From 1982d871475ffb8c2c160a96916a76fdcb6eb11c Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Sat, 18 Jan 2025 15:37:14 -0500 Subject: [PATCH 001/978] Merge commit '3383cfbd3572465febc7a8f816a46304373de46a' into sync-from-portable-simd-2025-01-18 --- .github/workflows/ci.yml | 125 +++++----- .github/workflows/doc.yml | 2 +- .gitignore | 1 + Cargo.toml | 6 + Cross.toml | 2 + crates/core_simd/Cargo.toml | 3 +- crates/core_simd/src/lane_count.rs | 8 +- crates/core_simd/src/lib.rs | 4 +- crates/core_simd/src/masks.rs | 42 ---- crates/core_simd/src/masks/bitmask.rs | 17 -- crates/core_simd/src/masks/full_masks.rs | 58 +---- crates/core_simd/src/ops.rs | 25 +- crates/core_simd/src/simd/cmp/eq.rs | 2 +- crates/core_simd/src/simd/num/float.rs | 30 ++- crates/core_simd/src/simd/num/int.rs | 43 +++- crates/core_simd/src/simd/num/uint.rs | 42 +++- crates/core_simd/src/simd/ptr/const_ptr.rs | 21 ++ crates/core_simd/src/simd/ptr/mut_ptr.rs | 21 ++ crates/core_simd/src/swizzle.rs | 257 ++++++++++++++++++++- crates/core_simd/src/swizzle_dyn.rs | 59 ++++- crates/core_simd/src/vector.rs | 43 +++- crates/core_simd/src/vendor.rs | 3 + crates/core_simd/src/vendor/loongarch64.rs | 31 +++ crates/core_simd/tests/layout.rs | 35 +++ crates/core_simd/tests/masks.rs | 43 ---- crates/core_simd/tests/ops_macros.rs | 38 +++ crates/core_simd/tests/swizzle.rs | 18 ++ crates/test_helpers/Cargo.toml | 3 - crates/test_helpers/src/lib.rs | 216 ++++++++--------- rust-toolchain.toml | 3 + subtree-sync.sh | 52 +++++ 31 files changed, 865 insertions(+), 388 deletions(-) create mode 100644 Cross.toml create mode 100644 crates/core_simd/src/vendor/loongarch64.rs create mode 100644 crates/core_simd/tests/layout.rs create mode 100644 rust-toolchain.toml create mode 100755 subtree-sync.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b292be2d6f99..3984d8f0d8d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,7 @@ on: env: CARGO_NET_RETRY: 10 RUSTUP_MAX_RETRIES: 10 + PROPTEST_CASES: 64 jobs: rustfmt: @@ -16,12 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Setup Rust - run: | - rustup update nightly --no-self-update - rustup default nightly - rustup component add rustfmt + - uses: actions/checkout@v4 - name: Run rustfmt run: cargo fmt --all -- --check @@ -37,7 +33,9 @@ jobs: - i686-unknown-linux-gnu - i586-unknown-linux-gnu - aarch64-unknown-linux-gnu + - arm64ec-pc-windows-msvc - armv7-unknown-linux-gnueabihf + - loongarch64-unknown-linux-gnu # non-nightly since https://github.com/rust-lang/rust/pull/113274 # - mips-unknown-linux-gnu # - mips64-unknown-linux-gnuabi64 @@ -49,13 +47,9 @@ jobs: - wasm32-unknown-unknown steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup Rust - run: | - rustup update nightly --no-self-update - rustup default nightly - rustup target add ${{ matrix.target }} - rustup component add clippy + run: rustup target add ${{ matrix.target }} - name: Run Clippy run: cargo clippy --all-targets --target ${{ matrix.target }} @@ -65,26 +59,19 @@ jobs: strategy: fail-fast: false matrix: - target: [x86_64-pc-windows-msvc, i686-pc-windows-msvc, i586-pc-windows-msvc, x86_64-unknown-linux-gnu, x86_64-apple-darwin] + target: [x86_64-pc-windows-msvc, i686-pc-windows-msvc, i586-pc-windows-msvc, x86_64-unknown-linux-gnu] # `default` means we use the default target config for the target, # `native` means we run with `-Ctarget-cpu=native`, and anything else is # an arg to `-Ctarget-feature` target_feature: [default, native, +sse3, +ssse3, +sse4.1, +sse4.2, +avx, +avx2] exclude: - # The macos runners seem to only reliably support up to `avx`. - - { target: x86_64-apple-darwin, target_feature: +avx2 } - # These features are statically known to be present for all 64 bit - # macs, and thus are covered by the `default` test - - { target: x86_64-apple-darwin, target_feature: +sse3 } - - { target: x86_64-apple-darwin, target_feature: +ssse3 } # -Ctarget-cpu=native sounds like bad-news if target != host - { target: i686-pc-windows-msvc, target_feature: native } - { target: i586-pc-windows-msvc, target_feature: native } include: # Populate the `matrix.os` field - - { target: x86_64-apple-darwin, os: macos-latest } - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest } - { target: x86_64-pc-windows-msvc, os: windows-latest } - { target: i686-pc-windows-msvc, os: windows-latest } @@ -98,12 +85,9 @@ jobs: # avx512vl, but occasionally doesn't. Maybe one day we can enable it. steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup Rust - run: | - rustup update nightly --no-self-update - rustup default nightly - rustup target add ${{ matrix.target }} + run: rustup target add ${{ matrix.target }} - name: Configure RUSTFLAGS shell: bash @@ -145,6 +129,35 @@ jobs: run: cargo doc --verbose --target=${{ matrix.target }} env: RUSTDOCFLAGS: -Dwarnings + + macos-tests: + name: ${{ matrix.target }} + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + target: + - aarch64-apple-darwin + - x86_64-apple-darwin + steps: + - uses: actions/checkout@v4 + - name: Setup Rust + run: rustup target add ${{ matrix.target }} + + - name: Configure RUSTFLAGS + shell: bash + run: echo "RUSTFLAGS=-Dwarnings" >> $GITHUB_ENV + + - name: Test (debug) + run: cargo test --verbose --target=${{ matrix.target }} + + - name: Test (release) + run: cargo test --verbose --target=${{ matrix.target }} --release + + - name: Generate docs + run: cargo doc --verbose --target=${{ matrix.target }} + env: + RUSTDOCFLAGS: -Dwarnings wasm-tests: name: "wasm (firefox, ${{ matrix.name }})" @@ -155,11 +168,7 @@ jobs: - { name: default, RUSTFLAGS: "" } - { name: simd128, RUSTFLAGS: "-C target-feature=+simd128" } steps: - - uses: actions/checkout@v2 - - name: Setup Rust - run: | - rustup update nightly --no-self-update - rustup default nightly + - uses: actions/checkout@v4 - name: Install wasm-pack run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - name: Test (debug) @@ -174,6 +183,8 @@ jobs: cross-tests: name: "${{ matrix.target_feature }} on ${{ matrix.target }} (via cross)" runs-on: ubuntu-latest + env: + PROPTEST_CASES: 16 strategy: fail-fast: false @@ -185,6 +196,7 @@ jobs: - powerpc-unknown-linux-gnu - powerpc64le-unknown-linux-gnu # includes altivec by default - riscv64gc-unknown-linux-gnu + - loongarch64-unknown-linux-gnu # MIPS uses a nonstandard binary representation for NaNs which makes it worth testing # non-nightly since https://github.com/rust-lang/rust/pull/113274 # - mips-unknown-linux-gnu @@ -201,24 +213,14 @@ jobs: # - { target: riscv64gc-unknown-linux-gnu, target_feature: "+v,+zvl128b" } steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup Rust - run: | - rustup update nightly --no-self-update - rustup default nightly - rustup target add ${{ matrix.target }} - rustup component add rust-src + run: rustup target add ${{ matrix.target }} - name: Install Cross - # Equivalent to `cargo install cross`, but downloading a prebuilt - # binary. Ideally we wouldn't hardcode a version, but the version number - # being part of the tarball means we can't just use the download/latest - # URL :( + # Install the latest git version for newer targets. run: | - CROSS_URL=https://github.com/cross-rs/cross/releases/download/v0.2.5/cross-x86_64-unknown-linux-gnu.tar.gz - mkdir -p "$HOME/.bin" - curl -sfSL --retry-delay 10 --retry 5 "${CROSS_URL}" | tar zxf - -C "$HOME/.bin" - echo "$HOME/.bin" >> $GITHUB_PATH + cargo install cross --git https://github.com/cross-rs/cross --rev 4090beca3cfffa44371a5bba524de3a578aa46c3 - name: Configure Emulated CPUs run: | @@ -242,34 +244,11 @@ jobs: - name: Test (release) run: cross test --verbose --target=${{ matrix.target }} --release - features: - name: "Test cargo features (${{ matrix.simd }} × ${{ matrix.features }})" + miri: runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - simd: - - "" - - "avx512" - features: - - "" - - "--features std" - - "--features all_lane_counts" - - "--all-features" - + env: + PROPTEST_CASES: 16 steps: - - uses: actions/checkout@v2 - - name: Setup Rust - run: | - rustup update nightly --no-self-update - rustup default nightly - - name: Detect AVX512 - run: echo "CPU_FEATURE=$(lscpu | grep -o avx512[a-z]* | sed s/avx/+avx/ | tr '\n' ',' )" >> $GITHUB_ENV - - name: Check build - if: ${{ matrix.simd == '' }} - run: RUSTFLAGS="-Dwarnings" cargo test --all-targets --no-default-features ${{ matrix.features }} - - name: Check AVX - if: ${{ matrix.simd == 'avx512' && contains(env.CPU_FEATURE, 'avx512') }} - run: | - echo "Found AVX features: $CPU_FEATURE" - RUSTFLAGS="-Dwarnings -Ctarget-feature=$CPU_FEATURE" cargo test --all-targets --no-default-features ${{ matrix.features }} + - uses: actions/checkout@v4 + - name: Test (Miri) + run: cargo miri test diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 9d1fa66ccb59..22c2cb3f67f1 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout Repository - uses: actions/checkout@v1 + uses: actions/checkout@v4 - name: Setup Rust run: | diff --git a/.gitignore b/.gitignore index ea8c4bf7f35f..9673e52dcadb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +git-subtree.sh diff --git a/Cargo.toml b/Cargo.toml index d1732aaec2f9..21d4584a9f4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,3 +5,9 @@ members = [ "crates/std_float", "crates/test_helpers", ] + +[profile.test.package."*"] +opt-level = 2 + +[profile.test.package.test_helpers] +opt-level = 2 diff --git a/Cross.toml b/Cross.toml new file mode 100644 index 000000000000..d21e76b92dd1 --- /dev/null +++ b/Cross.toml @@ -0,0 +1,2 @@ +[build.env] +passthrough = ["PROPTEST_CASES"] diff --git a/crates/core_simd/Cargo.toml b/crates/core_simd/Cargo.toml index b4a8fd70f4c0..a7a6d43b11d3 100644 --- a/crates/core_simd/Cargo.toml +++ b/crates/core_simd/Cargo.toml @@ -9,10 +9,9 @@ categories = ["hardware-support", "no-std"] license = "MIT OR Apache-2.0" [features] -default = ["as_crate"] +default = ["as_crate", "std"] as_crate = [] std = [] -all_lane_counts = [] [target.'cfg(target_arch = "wasm32")'.dev-dependencies] wasm-bindgen = "0.2" diff --git a/crates/core_simd/src/lane_count.rs b/crates/core_simd/src/lane_count.rs index 4cd7265ed671..280b27bc9bc6 100644 --- a/crates/core_simd/src/lane_count.rs +++ b/crates/core_simd/src/lane_count.rs @@ -33,10 +33,8 @@ macro_rules! supported_lane_count { }; } -supported_lane_count!(1, 2, 4, 8, 16, 32, 64); -#[cfg(feature = "all_lane_counts")] supported_lane_count!( - 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63 + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 ); diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs index 992a7705e3c5..7f57847c9c23 100644 --- a/crates/core_simd/src/lib.rs +++ b/crates/core_simd/src/lib.rs @@ -1,7 +1,6 @@ #![no_std] #![feature( - const_refs_to_cell, - const_mut_refs, + const_eval_select, convert_float_to_int, core_intrinsics, decl_macro, @@ -26,6 +25,7 @@ all(target_arch = "arm", target_feature = "v7"), feature(stdarch_arm_neon_intrinsics) )] +#![cfg_attr(target_arch = "loongarch64", feature(stdarch_loongarch))] #![cfg_attr( any(target_arch = "powerpc", target_arch = "powerpc64"), feature(stdarch_powerpc) diff --git a/crates/core_simd/src/masks.rs b/crates/core_simd/src/masks.rs index 04de3a968276..b763a7c75a5a 100644 --- a/crates/core_simd/src/masks.rs +++ b/crates/core_simd/src/masks.rs @@ -308,48 +308,6 @@ where Self(mask_impl::Mask::from_bitmask_integer(bitmask)) } - /// Creates a bitmask vector from a mask. - /// - /// Each bit is set if the corresponding element in the mask is `true`. - /// The remaining bits are unset. - /// - /// The bits are packed into the first N bits of the vector: - /// ``` - /// # #![feature(portable_simd)] - /// # #[cfg(feature = "as_crate")] use core_simd::simd; - /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::mask32x8; - /// let mask = mask32x8::from_array([true, false, true, false, false, false, true, false]); - /// assert_eq!(mask.to_bitmask_vector()[0], 0b01000101); - /// ``` - #[inline] - #[must_use = "method returns a new integer and does not mutate the original value"] - pub fn to_bitmask_vector(self) -> Simd { - self.0.to_bitmask_vector() - } - - /// Creates a mask from a bitmask vector. - /// - /// For each bit, if it is set, the corresponding element in the mask is set to `true`. - /// - /// The bits are packed into the first N bits of the vector: - /// ``` - /// # #![feature(portable_simd)] - /// # #[cfg(feature = "as_crate")] use core_simd::simd; - /// # #[cfg(not(feature = "as_crate"))] use core::simd; - /// # use simd::{mask32x8, u8x8}; - /// let bitmask = u8x8::from_array([0b01000101, 0, 0, 0, 0, 0, 0, 0]); - /// assert_eq!( - /// mask32x8::from_bitmask_vector(bitmask), - /// mask32x8::from_array([true, false, true, false, false, false, true, false]), - /// ); - /// ``` - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn from_bitmask_vector(bitmask: Simd) -> Self { - Self(mask_impl::Mask::from_bitmask_vector(bitmask)) - } - /// Finds the index of the first set element. /// /// ``` diff --git a/crates/core_simd/src/masks/bitmask.rs b/crates/core_simd/src/masks/bitmask.rs index 96c553426ee7..db4312d5bf88 100644 --- a/crates/core_simd/src/masks/bitmask.rs +++ b/crates/core_simd/src/masks/bitmask.rs @@ -122,23 +122,6 @@ where unsafe { Self(core::intrinsics::simd::simd_bitmask(value), PhantomData) } } - #[inline] - #[must_use = "method returns a new vector and does not mutate the original value"] - pub fn to_bitmask_vector(self) -> Simd { - let mut bitmask = Simd::splat(0); - bitmask.as_mut_array()[..self.0.as_ref().len()].copy_from_slice(self.0.as_ref()); - bitmask - } - - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn from_bitmask_vector(bitmask: Simd) -> Self { - let mut bytes = as SupportedLaneCount>::BitMask::default(); - let len = bytes.as_ref().len(); - bytes.as_mut().copy_from_slice(&bitmask.as_array()[..len]); - Self(bytes, PhantomData) - } - #[inline] pub fn to_bitmask_integer(self) -> u64 { let mut bitmask = [0u8; 8]; diff --git a/crates/core_simd/src/masks/full_masks.rs b/crates/core_simd/src/masks/full_masks.rs index 87f031a9f367..2d01946b5747 100644 --- a/crates/core_simd/src/masks/full_masks.rs +++ b/crates/core_simd/src/masks/full_masks.rs @@ -140,62 +140,6 @@ where unsafe { Mask(core::intrinsics::simd::simd_cast(self.0)) } } - #[inline] - #[must_use = "method returns a new vector and does not mutate the original value"] - pub fn to_bitmask_vector(self) -> Simd { - let mut bitmask = Simd::splat(0); - - // Safety: Bytes is the right size array - unsafe { - // Compute the bitmask - let mut bytes: as SupportedLaneCount>::BitMask = - core::intrinsics::simd::simd_bitmask(self.0); - - // LLVM assumes bit order should match endianness - if cfg!(target_endian = "big") { - for x in bytes.as_mut() { - *x = x.reverse_bits() - } - if N % 8 > 0 { - bytes.as_mut()[N / 8] >>= 8 - N % 8; - } - } - - bitmask.as_mut_array()[..bytes.as_ref().len()].copy_from_slice(bytes.as_ref()); - } - - bitmask - } - - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn from_bitmask_vector(bitmask: Simd) -> Self { - let mut bytes = as SupportedLaneCount>::BitMask::default(); - - // Safety: Bytes is the right size array - unsafe { - let len = bytes.as_ref().len(); - bytes.as_mut().copy_from_slice(&bitmask.as_array()[..len]); - - // LLVM assumes bit order should match endianness - if cfg!(target_endian = "big") { - for x in bytes.as_mut() { - *x = x.reverse_bits(); - } - if N % 8 > 0 { - bytes.as_mut()[N / 8] >>= 8 - N % 8; - } - } - - // Compute the regular mask - Self::from_int_unchecked(core::intrinsics::simd::simd_select_bitmask( - bytes, - Self::splat(true).to_int(), - Self::splat(false).to_int(), - )) - } - } - #[inline] unsafe fn to_bitmask_impl(self) -> U where @@ -283,7 +227,7 @@ where } #[inline] - #[must_use = "method returns a new vector and does not mutate the original value"] + #[must_use = "method returns a new bool and does not mutate the original value"] pub fn all(self) -> bool { // Safety: use `self` as an integer vector unsafe { core::intrinsics::simd::simd_reduce_all(self.to_int()) } diff --git a/crates/core_simd/src/ops.rs b/crates/core_simd/src/ops.rs index dd7303a97b19..d3bd14a34027 100644 --- a/crates/core_simd/src/ops.rs +++ b/crates/core_simd/src/ops.rs @@ -77,7 +77,7 @@ macro_rules! int_divrem_guard { ( $lhs:ident, $rhs:ident, { const PANIC_ZERO: &'static str = $zero:literal; - $simd_call:ident + $simd_call:ident, $op:tt }, $int:ident ) => { if $rhs.simd_eq(Simd::splat(0 as _)).any() { @@ -96,8 +96,23 @@ macro_rules! int_divrem_guard { // Nice base case to make it easy to const-fold away the other branch. $rhs }; - // Safety: $lhs and rhs are vectors - unsafe { core::intrinsics::simd::$simd_call($lhs, rhs) } + + // aarch64 div fails for arbitrary `v % 0`, mod fails when rhs is MIN, for non-powers-of-two + // these operations aren't vectorized on aarch64 anyway + #[cfg(target_arch = "aarch64")] + { + let mut out = Simd::splat(0 as _); + for i in 0..Self::LEN { + out[i] = $lhs[i] $op rhs[i]; + } + out + } + + #[cfg(not(target_arch = "aarch64"))] + { + // Safety: $lhs and rhs are vectors + unsafe { core::intrinsics::simd::$simd_call($lhs, rhs) } + } } }; } @@ -205,14 +220,14 @@ for_base_ops! { impl Div::div { int_divrem_guard { const PANIC_ZERO: &'static str = "attempt to divide by zero"; - simd_div + simd_div, / } } impl Rem::rem { int_divrem_guard { const PANIC_ZERO: &'static str = "attempt to calculate the remainder with a divisor of zero"; - simd_rem + simd_rem, % } } diff --git a/crates/core_simd/src/simd/cmp/eq.rs b/crates/core_simd/src/simd/cmp/eq.rs index 5b4615ce51d7..93989ce91b89 100644 --- a/crates/core_simd/src/simd/cmp/eq.rs +++ b/crates/core_simd/src/simd/cmp/eq.rs @@ -12,7 +12,7 @@ pub trait SimdPartialEq { #[must_use = "method returns a new mask and does not mutate the original value"] fn simd_eq(self, other: Self) -> Self::Mask; - /// Test if each element is equal to the corresponding element in `other`. + /// Test if each element is not equal to the corresponding element in `other`. #[must_use = "method returns a new mask and does not mutate the original value"] fn simd_ne(self, other: Self) -> Self::Mask; } diff --git a/crates/core_simd/src/simd/num/float.rs b/crates/core_simd/src/simd/num/float.rs index 59e43851ea8d..79954b937b39 100644 --- a/crates/core_simd/src/simd/num/float.rs +++ b/crates/core_simd/src/simd/num/float.rs @@ -255,6 +255,7 @@ macro_rules! impl_trait { type Bits = Simd<$bits_ty, N>; type Cast = Simd; + #[cfg(not(target_arch = "aarch64"))] #[inline] fn cast(self) -> Self::Cast { @@ -262,6 +263,33 @@ macro_rules! impl_trait { unsafe { core::intrinsics::simd::simd_as(self) } } + // https://github.com/llvm/llvm-project/issues/94694 + #[cfg(target_arch = "aarch64")] + #[inline] + fn cast(self) -> Self::Cast + { + const { assert!(N <= 64) }; + if N <= 2 || N == 4 || N == 8 || N == 16 || N == 32 || N == 64 { + // Safety: supported types are guaranteed by SimdCast + unsafe { core::intrinsics::simd::simd_as(self) } + } else if N < 4 { + let x = self.resize::<4>(Default::default()).cast(); + x.resize::(x[0]) + } else if N < 8 { + let x = self.resize::<8>(Default::default()).cast(); + x.resize::(x[0]) + } else if N < 16 { + let x = self.resize::<16>(Default::default()).cast(); + x.resize::(x[0]) + } else if N < 32 { + let x = self.resize::<32>(Default::default()).cast(); + x.resize::(x[0]) + } else { + let x = self.resize::<64>(Default::default()).cast(); + x.resize::(x[0]) + } + } + #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn to_int_unchecked(self) -> Self::Cast @@ -391,7 +419,7 @@ macro_rules! impl_trait { self.as_array().iter().sum() } else { // Safety: `self` is a float vector - unsafe { core::intrinsics::simd::simd_reduce_add_ordered(self, 0.) } + unsafe { core::intrinsics::simd::simd_reduce_add_ordered(self, -0.) } } } diff --git a/crates/core_simd/src/simd/num/int.rs b/crates/core_simd/src/simd/num/int.rs index d7598d9ceaf9..3a51235ff954 100644 --- a/crates/core_simd/src/simd/num/int.rs +++ b/crates/core_simd/src/simd/num/int.rs @@ -1,6 +1,6 @@ use super::sealed::Sealed; use crate::simd::{ - cmp::SimdPartialOrd, num::SimdUint, LaneCount, Mask, Simd, SimdCast, SimdElement, + cmp::SimdOrd, cmp::SimdPartialOrd, num::SimdUint, LaneCount, Mask, Simd, SimdCast, SimdElement, SupportedLaneCount, }; @@ -70,11 +70,27 @@ pub trait SimdInt: Copy + Sealed { /// # #[cfg(not(feature = "as_crate"))] use core::simd; /// # use simd::prelude::*; /// use core::i32::{MIN, MAX}; - /// let xs = Simd::from_array([MIN, MIN +1, -5, 0]); + /// let xs = Simd::from_array([MIN, MIN + 1, -5, 0]); /// assert_eq!(xs.abs(), Simd::from_array([MIN, MAX, 5, 0])); /// ``` fn abs(self) -> Self; + /// Lanewise absolute difference. + /// Every element becomes the absolute difference of `self` and `second`. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::prelude::*; + /// use core::i32::{MIN, MAX}; + /// let a = Simd::from_array([MIN, MAX, 100, -100]); + /// let b = Simd::from_array([MAX, MIN, -80, -120]); + /// assert_eq!(a.abs_diff(b), Simd::from_array([u32::MAX, u32::MAX, 180, 20])); + /// ``` + fn abs_diff(self, second: Self) -> Self::Unsigned; + /// Lanewise saturating absolute value, implemented in Rust. /// As abs(), except the MIN value becomes MAX instead of itself. /// @@ -203,6 +219,12 @@ pub trait SimdInt: Copy + Sealed { /// The least significant bit becomes the most significant bit, second least-significant bit becomes second most-significant bit, etc. fn reverse_bits(self) -> Self; + /// Returns the number of ones in the binary representation of each element. + fn count_ones(self) -> Self::Unsigned; + + /// Returns the number of zeros in the binary representation of each element. + fn count_zeros(self) -> Self::Unsigned; + /// Returns the number of leading zeros in the binary representation of each element. fn leading_zeros(self) -> Self::Unsigned; @@ -259,6 +281,13 @@ macro_rules! impl_trait { (self^m) - m } + #[inline] + fn abs_diff(self, second: Self) -> Self::Unsigned { + let max = self.simd_max(second); + let min = self.simd_min(second); + (max - min).cast() + } + #[inline] fn saturating_abs(self) -> Self { // arith shift for -1 or 0 mask based on sign bit, giving 2s complement @@ -344,6 +373,16 @@ macro_rules! impl_trait { unsafe { core::intrinsics::simd::simd_bitreverse(self) } } + #[inline] + fn count_ones(self) -> Self::Unsigned { + self.cast::<$unsigned>().count_ones() + } + + #[inline] + fn count_zeros(self) -> Self::Unsigned { + self.cast::<$unsigned>().count_zeros() + } + #[inline] fn leading_zeros(self) -> Self::Unsigned { self.cast::<$unsigned>().leading_zeros() diff --git a/crates/core_simd/src/simd/num/uint.rs b/crates/core_simd/src/simd/num/uint.rs index 53dd97f501c6..1ab2d8c7b731 100644 --- a/crates/core_simd/src/simd/num/uint.rs +++ b/crates/core_simd/src/simd/num/uint.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount}; +use crate::simd::{cmp::SimdOrd, LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount}; /// Operations on SIMD vectors of unsigned integers. pub trait SimdUint: Copy + Sealed { @@ -57,6 +57,22 @@ pub trait SimdUint: Copy + Sealed { /// assert_eq!(sat, Simd::splat(0)); fn saturating_sub(self, second: Self) -> Self; + /// Lanewise absolute difference. + /// Every element becomes the absolute difference of `self` and `second`. + /// + /// # Examples + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::prelude::*; + /// use core::u32::MAX; + /// let a = Simd::from_array([0, MAX, 100, 20]); + /// let b = Simd::from_array([MAX, 0, 80, 200]); + /// assert_eq!(a.abs_diff(b), Simd::from_array([MAX, MAX, 20, 180])); + /// ``` + fn abs_diff(self, second: Self) -> Self; + /// Returns the sum of the elements of the vector, with wrapping addition. fn reduce_sum(self) -> Self::Scalar; @@ -85,6 +101,12 @@ pub trait SimdUint: Copy + Sealed { /// The least significant bit becomes the most significant bit, second least-significant bit becomes second most-significant bit, etc. fn reverse_bits(self) -> Self; + /// Returns the number of ones in the binary representation of each element. + fn count_ones(self) -> Self; + + /// Returns the number of zeros in the binary representation of each element. + fn count_zeros(self) -> Self; + /// Returns the number of leading zeros in the binary representation of each element. fn leading_zeros(self) -> Self; @@ -138,6 +160,13 @@ macro_rules! impl_trait { unsafe { core::intrinsics::simd::simd_saturating_sub(self, second) } } + #[inline] + fn abs_diff(self, second: Self) -> Self { + let max = self.simd_max(second); + let min = self.simd_min(second); + max - min + } + #[inline] fn reduce_sum(self) -> Self::Scalar { // Safety: `self` is an integer vector @@ -192,6 +221,17 @@ macro_rules! impl_trait { unsafe { core::intrinsics::simd::simd_bitreverse(self) } } + #[inline] + fn count_ones(self) -> Self { + // Safety: `self` is an integer vector + unsafe { core::intrinsics::simd::simd_ctpop(self) } + } + + #[inline] + fn count_zeros(self) -> Self { + (!self).count_ones() + } + #[inline] fn leading_zeros(self) -> Self { // Safety: `self` is an integer vector diff --git a/crates/core_simd/src/simd/ptr/const_ptr.rs b/crates/core_simd/src/simd/ptr/const_ptr.rs index be635ea640b8..47383809ffba 100644 --- a/crates/core_simd/src/simd/ptr/const_ptr.rs +++ b/crates/core_simd/src/simd/ptr/const_ptr.rs @@ -42,6 +42,19 @@ pub trait SimdConstPtr: Copy + Sealed { /// Equivalent to calling [`pointer::addr`] on each element. fn addr(self) -> Self::Usize; + /// Converts an address to a pointer without giving it any provenance. + /// + /// Without provenance, this pointer is not associated with any actual allocation. Such a + /// no-provenance pointer may be used for zero-sized memory accesses (if suitably aligned), but + /// non-zero-sized memory accesses with a no-provenance pointer are UB. No-provenance pointers + /// are little more than a usize address in disguise. + /// + /// This is different from [`Self::with_exposed_provenance`], which creates a pointer that picks up a + /// previously exposed provenance. + /// + /// Equivalent to calling [`core::ptr::without_provenance`] on each element. + fn without_provenance(addr: Self::Usize) -> Self; + /// Creates a new pointer with the given address. /// /// This performs the same operation as a cast, but copies the *address-space* and @@ -118,6 +131,14 @@ where unsafe { core::mem::transmute_copy(&self) } } + #[inline] + fn without_provenance(addr: Self::Usize) -> Self { + // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + // SAFETY: Integer-to-pointer transmutes are valid (if you are okay with not getting any + // provenance). + unsafe { core::mem::transmute_copy(&addr) } + } + #[inline] fn with_addr(self, addr: Self::Usize) -> Self { // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. diff --git a/crates/core_simd/src/simd/ptr/mut_ptr.rs b/crates/core_simd/src/simd/ptr/mut_ptr.rs index f6823a949e32..3f20eef21a31 100644 --- a/crates/core_simd/src/simd/ptr/mut_ptr.rs +++ b/crates/core_simd/src/simd/ptr/mut_ptr.rs @@ -39,6 +39,19 @@ pub trait SimdMutPtr: Copy + Sealed { /// Equivalent to calling [`pointer::addr`] on each element. fn addr(self) -> Self::Usize; + /// Converts an address to a pointer without giving it any provenance. + /// + /// Without provenance, this pointer is not associated with any actual allocation. Such a + /// no-provenance pointer may be used for zero-sized memory accesses (if suitably aligned), but + /// non-zero-sized memory accesses with a no-provenance pointer are UB. No-provenance pointers + /// are little more than a usize address in disguise. + /// + /// This is different from [`Self::with_exposed_provenance`], which creates a pointer that picks up a + /// previously exposed provenance. + /// + /// Equivalent to calling [`core::ptr::without_provenance`] on each element. + fn without_provenance(addr: Self::Usize) -> Self; + /// Creates a new pointer with the given address. /// /// This performs the same operation as a cast, but copies the *address-space* and @@ -115,6 +128,14 @@ where unsafe { core::mem::transmute_copy(&self) } } + #[inline] + fn without_provenance(addr: Self::Usize) -> Self { + // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. + // SAFETY: Integer-to-pointer transmutes are valid (if you are okay with not getting any + // provenance). + unsafe { core::mem::transmute_copy(&addr) } + } + #[inline] fn with_addr(self, addr: Self::Usize) -> Self { // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. diff --git a/crates/core_simd/src/swizzle.rs b/crates/core_simd/src/swizzle.rs index d62642fb9061..42425ef37e50 100644 --- a/crates/core_simd/src/swizzle.rs +++ b/crates/core_simd/src/swizzle.rs @@ -155,8 +155,7 @@ pub trait Swizzle { /// Creates a new mask from the elements of `mask`. /// - /// Element `i` of the output is `concat[Self::INDEX[i]]`, where `concat` is the concatenation of - /// `first` and `second`. + /// Element `i` of the output is `mask[Self::INDEX[i]]`. #[inline] #[must_use = "method returns a new mask and does not mutate the original inputs"] fn swizzle_mask(mask: Mask) -> Mask @@ -260,6 +259,50 @@ where Rotate::::swizzle(self) } + /// Shifts the vector elements to the left by `OFFSET`, filling in with + /// `padding` from the right. + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + pub fn shift_elements_left(self, padding: T) -> Self { + struct Shift; + + impl Swizzle for Shift { + const INDEX: [usize; N] = const { + let mut index = [N; N]; + let mut i = 0; + while i + OFFSET < N { + index[i] = i + OFFSET; + i += 1; + } + index + }; + } + + Shift::::concat_swizzle(self, Simd::splat(padding)) + } + + /// Shifts the vector elements to the right by `OFFSET`, filling in with + /// `padding` from the left. + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + pub fn shift_elements_right(self, padding: T) -> Self { + struct Shift; + + impl Swizzle for Shift { + const INDEX: [usize; N] = const { + let mut index = [N; N]; + let mut i = OFFSET; + while i < N { + index[i] = i - OFFSET; + i += 1; + } + index + }; + } + + Shift::::concat_swizzle(self, Simd::splat(padding)) + } + /// Interleave two vectors. /// /// The resulting vectors contain elements taken alternatively from `self` and `other`, first @@ -320,7 +363,9 @@ where /// /// ``` /// # #![feature(portable_simd)] - /// # use core::simd::Simd; + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::Simd; /// let a = Simd::from_array([0, 4, 1, 5]); /// let b = Simd::from_array([2, 6, 3, 7]); /// let (x, y) = a.deinterleave(b); @@ -391,4 +436,210 @@ where } Resize::::concat_swizzle(self, Simd::splat(value)) } + + /// Extract a vector from another vector. + /// + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::u32x4; + /// let x = u32x4::from_array([0, 1, 2, 3]); + /// assert_eq!(x.extract::<1, 2>().to_array(), [1, 2]); + /// ``` + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + pub fn extract(self) -> Simd + where + LaneCount: SupportedLaneCount, + { + struct Extract; + impl Swizzle for Extract { + const INDEX: [usize; LEN] = const { + assert!(START + LEN <= N, "index out of bounds"); + let mut index = [0; LEN]; + let mut i = 0; + while i < LEN { + index[i] = START + i; + i += 1; + } + index + }; + } + Extract::::swizzle(self) + } +} + +impl Mask +where + T: MaskElement, + LaneCount: SupportedLaneCount, +{ + /// Reverse the order of the elements in the mask. + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + pub fn reverse(self) -> Self { + // Safety: swizzles are safe for masks + unsafe { Self::from_int_unchecked(self.to_int().reverse()) } + } + + /// Rotates the mask such that the first `OFFSET` elements of the slice move to the end + /// while the last `self.len() - OFFSET` elements move to the front. After calling `rotate_elements_left`, + /// the element previously at index `OFFSET` will become the first element in the slice. + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + pub fn rotate_elements_left(self) -> Self { + // Safety: swizzles are safe for masks + unsafe { Self::from_int_unchecked(self.to_int().rotate_elements_left::()) } + } + + /// Rotates the mask such that the first `self.len() - OFFSET` elements of the mask move to + /// the end while the last `OFFSET` elements move to the front. After calling `rotate_elements_right`, + /// the element previously at index `self.len() - OFFSET` will become the first element in the slice. + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + pub fn rotate_elements_right(self) -> Self { + // Safety: swizzles are safe for masks + unsafe { Self::from_int_unchecked(self.to_int().rotate_elements_right::()) } + } + + /// Shifts the mask elements to the left by `OFFSET`, filling in with + /// `padding` from the right. + #[inline] + #[must_use = "method returns a new mask and does not mutate the original inputs"] + pub fn shift_elements_left(self, padding: bool) -> Self { + // Safety: swizzles are safe for masks + unsafe { + Self::from_int_unchecked(self.to_int().shift_elements_left::(if padding { + T::TRUE + } else { + T::FALSE + })) + } + } + + /// Shifts the mask elements to the right by `OFFSET`, filling in with + /// `padding` from the left. + #[inline] + #[must_use = "method returns a new mask and does not mutate the original inputs"] + pub fn shift_elements_right(self, padding: bool) -> Self { + // Safety: swizzles are safe for masks + unsafe { + Self::from_int_unchecked(self.to_int().shift_elements_right::(if padding { + T::TRUE + } else { + T::FALSE + })) + } + } + + /// Interleave two masks. + /// + /// The resulting masks contain elements taken alternatively from `self` and `other`, first + /// filling the first result, and then the second. + /// + /// The reverse of this operation is [`Mask::deinterleave`]. + /// + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::mask32x4; + /// let a = mask32x4::from_array([false, true, false, true]); + /// let b = mask32x4::from_array([false, false, true, true]); + /// let (x, y) = a.interleave(b); + /// assert_eq!(x.to_array(), [false, false, true, false]); + /// assert_eq!(y.to_array(), [false, true, true, true]); + /// ``` + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + pub fn interleave(self, other: Self) -> (Self, Self) { + let (lo, hi) = self.to_int().interleave(other.to_int()); + // Safety: swizzles are safe for masks + unsafe { (Self::from_int_unchecked(lo), Self::from_int_unchecked(hi)) } + } + + /// Deinterleave two masks. + /// + /// The first result takes every other element of `self` and then `other`, starting with + /// the first element. + /// + /// The second result takes every other element of `self` and then `other`, starting with + /// the second element. + /// + /// The reverse of this operation is [`Mask::interleave`]. + /// + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::mask32x4; + /// let a = mask32x4::from_array([false, true, false, true]); + /// let b = mask32x4::from_array([false, false, true, true]); + /// let (x, y) = a.deinterleave(b); + /// assert_eq!(x.to_array(), [false, false, false, true]); + /// assert_eq!(y.to_array(), [true, true, false, true]); + /// ``` + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + pub fn deinterleave(self, other: Self) -> (Self, Self) { + let (even, odd) = self.to_int().deinterleave(other.to_int()); + // Safety: swizzles are safe for masks + unsafe { + ( + Self::from_int_unchecked(even), + Self::from_int_unchecked(odd), + ) + } + } + + /// Resize a mask. + /// + /// If `M` > `N`, extends the length of a mask, setting the new elements to `value`. + /// If `M` < `N`, truncates the mask to the first `M` elements. + /// + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::mask32x4; + /// let x = mask32x4::from_array([false, true, true, false]); + /// assert_eq!(x.resize::<8>(true).to_array(), [false, true, true, false, true, true, true, true]); + /// assert_eq!(x.resize::<2>(true).to_array(), [false, true]); + /// ``` + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + pub fn resize(self, value: bool) -> Mask + where + LaneCount: SupportedLaneCount, + { + // Safety: swizzles are safe for masks + unsafe { + Mask::::from_int_unchecked(self.to_int().resize::(if value { + T::TRUE + } else { + T::FALSE + })) + } + } + + /// Extract a vector from another vector. + /// + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd; + /// # use simd::mask32x4; + /// let x = mask32x4::from_array([false, true, true, false]); + /// assert_eq!(x.extract::<1, 2>().to_array(), [true, true]); + /// ``` + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + pub fn extract(self) -> Mask + where + LaneCount: SupportedLaneCount, + { + // Safety: swizzles are safe for masks + unsafe { Mask::::from_int_unchecked(self.to_int().extract::()) } + } } diff --git a/crates/core_simd/src/swizzle_dyn.rs b/crates/core_simd/src/swizzle_dyn.rs index 3b6388d0f275..773bd028bae0 100644 --- a/crates/core_simd/src/swizzle_dyn.rs +++ b/crates/core_simd/src/swizzle_dyn.rs @@ -59,15 +59,40 @@ where target_endian = "little" ))] 16 => transize(vqtbl1q_u8, self, idxs), + #[cfg(all( + target_arch = "arm", + target_feature = "v7", + target_feature = "neon", + target_endian = "little" + ))] + 16 => transize(armv7_neon_swizzle_u8x16, self, idxs), #[cfg(all(target_feature = "avx2", not(target_feature = "avx512vbmi")))] 32 => transize(avx2_pshufb, self, idxs), #[cfg(all(target_feature = "avx512vl", target_feature = "avx512vbmi"))] - 32 => transize(x86::_mm256_permutexvar_epi8, zeroing_idxs(idxs), self), - // Notable absence: avx512bw shuffle - // If avx512bw is available, odds of avx512vbmi are good - // FIXME: initial AVX512VBMI variant didn't actually pass muster - // #[cfg(target_feature = "avx512vbmi")] - // 64 => transize(x86::_mm512_permutexvar_epi8, self, idxs), + 32 => { + // Unlike vpshufb, vpermb doesn't zero out values in the result based on the index high bit + let swizzler = |bytes, idxs| { + let mask = x86::_mm256_cmp_epu8_mask::<{ x86::_MM_CMPINT_LT }>( + idxs, + Simd::::splat(N as u8).into(), + ); + x86::_mm256_maskz_permutexvar_epi8(mask, idxs, bytes) + }; + transize(swizzler, self, idxs) + } + // Notable absence: avx512bw pshufb shuffle + #[cfg(all(target_feature = "avx512vl", target_feature = "avx512vbmi"))] + 64 => { + // Unlike vpshufb, vpermb doesn't zero out values in the result based on the index high bit + let swizzler = |bytes, idxs| { + let mask = x86::_mm512_cmp_epu8_mask::<{ x86::_MM_CMPINT_LT }>( + idxs, + Simd::::splat(N as u8).into(), + ); + x86::_mm512_maskz_permutexvar_epi8(mask, idxs, bytes) + }; + transize(swizzler, self, idxs) + } _ => { let mut array = [0; N]; for (i, k) in idxs.to_array().into_iter().enumerate() { @@ -82,6 +107,28 @@ where } } +/// armv7 neon supports swizzling `u8x16` by swizzling two u8x8 blocks +/// with a u8x8x2 lookup table. +/// +/// # Safety +/// This requires armv7 neon to work +#[cfg(all( + target_arch = "arm", + target_feature = "v7", + target_feature = "neon", + target_endian = "little" +))] +unsafe fn armv7_neon_swizzle_u8x16(bytes: Simd, idxs: Simd) -> Simd { + use core::arch::arm::{uint8x8x2_t, vcombine_u8, vget_high_u8, vget_low_u8, vtbl2_u8}; + // SAFETY: Caller promised arm neon support + unsafe { + let bytes = uint8x8x2_t(vget_low_u8(bytes.into()), vget_high_u8(bytes.into())); + let lo = vtbl2_u8(bytes, vget_low_u8(idxs.into())); + let hi = vtbl2_u8(bytes, vget_high_u8(idxs.into())); + vcombine_u8(lo, hi).into() + } +} + /// "vpshufb like it was meant to be" on AVX2 /// /// # Safety diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs index 3e2391691496..9c4dd36c24fe 100644 --- a/crates/core_simd/src/vector.rs +++ b/crates/core_simd/src/vector.rs @@ -99,7 +99,7 @@ use crate::simd::{ // directly constructing an instance of the type (i.e. `let vector = Simd(array)`) should be // avoided, as it will likely become illegal on `#[repr(simd)]` structs in the future. It also // causes rustc to emit illegal LLVM IR in some cases. -#[repr(simd)] +#[repr(simd, packed)] pub struct Simd([T; N]) where LaneCount: SupportedLaneCount, @@ -144,14 +144,32 @@ where /// assert_eq!(v.as_array(), &[8, 8, 8, 8]); /// ``` #[inline] - pub fn splat(value: T) -> Self { - // This is preferred over `[value; N]`, since it's explicitly a splat: - // https://github.com/rust-lang/rust/issues/97804 - struct Splat; - impl Swizzle for Splat { - const INDEX: [usize; N] = [0; N]; + #[rustc_const_unstable(feature = "portable_simd", issue = "86656")] + pub const fn splat(value: T) -> Self { + const fn splat_const(value: T) -> Simd + where + T: SimdElement, + LaneCount: SupportedLaneCount, + { + Simd::from_array([value; N]) } - Splat::swizzle::(Simd::::from([value])) + + fn splat_rt(value: T) -> Simd + where + T: SimdElement, + LaneCount: SupportedLaneCount, + { + // This is preferred over `[value; N]`, since it's explicitly a splat: + // https://github.com/rust-lang/rust/issues/97804 + struct Splat; + impl Swizzle for Splat { + const INDEX: [usize; N] = [0; N]; + } + + Splat::swizzle::(Simd::::from([value])) + } + + core::intrinsics::const_eval_select((value,), splat_const, splat_rt) } /// Returns an array reference containing the entire SIMD vector. @@ -425,6 +443,9 @@ where /// /// When the element is disabled, that memory location is not accessed and the corresponding /// value from `or` is passed through. + /// + /// # Safety + /// Enabled loads must not exceed the length of `slice`. #[must_use] #[inline] pub unsafe fn load_select_unchecked( @@ -442,6 +463,9 @@ where /// /// When the element is disabled, that memory location is not accessed and the corresponding /// value from `or` is passed through. + /// + /// # Safety + /// Enabled `ptr` elements must be safe to read as if by `std::ptr::read`. #[must_use] #[inline] pub unsafe fn load_select_ptr( @@ -924,6 +948,7 @@ where } } +/// Lexicographic order. For the SIMD elementwise minimum and maximum, use simd_min and simd_max instead. impl PartialOrd for Simd where LaneCount: SupportedLaneCount, @@ -943,6 +968,7 @@ where { } +/// Lexicographic order. For the SIMD elementwise minimum and maximum, use simd_min and simd_max instead. impl Ord for Simd where LaneCount: SupportedLaneCount, @@ -1195,6 +1221,7 @@ fn lane_indices() -> Simd where LaneCount: SupportedLaneCount, { + #![allow(clippy::needless_range_loop)] let mut index = [0; N]; for i in 0..N { index[i] = i; diff --git a/crates/core_simd/src/vendor.rs b/crates/core_simd/src/vendor.rs index 1a34a3a8de5c..57536e4fc77d 100644 --- a/crates/core_simd/src/vendor.rs +++ b/crates/core_simd/src/vendor.rs @@ -29,3 +29,6 @@ mod arm; #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] mod powerpc; + +#[cfg(target_arch = "loongarch64")] +mod loongarch64; diff --git a/crates/core_simd/src/vendor/loongarch64.rs b/crates/core_simd/src/vendor/loongarch64.rs new file mode 100644 index 000000000000..1290bc166b2b --- /dev/null +++ b/crates/core_simd/src/vendor/loongarch64.rs @@ -0,0 +1,31 @@ +use crate::simd::*; +use core::arch::loongarch64::*; + +from_transmute! { unsafe u8x16 => v16u8 } +from_transmute! { unsafe u8x32 => v32u8 } +from_transmute! { unsafe i8x16 => v16i8 } +from_transmute! { unsafe i8x32 => v32i8 } + +from_transmute! { unsafe u16x8 => v8u16 } +from_transmute! { unsafe u16x16 => v16u16 } +from_transmute! { unsafe i16x8 => v8i16 } +from_transmute! { unsafe i16x16 => v16i16 } + +from_transmute! { unsafe u32x4 => v4u32 } +from_transmute! { unsafe u32x8 => v8u32 } +from_transmute! { unsafe i32x4 => v4i32 } +from_transmute! { unsafe i32x8 => v8i32 } +from_transmute! { unsafe f32x4 => v4f32 } +from_transmute! { unsafe f32x8 => v8f32 } + +from_transmute! { unsafe u64x2 => v2u64 } +from_transmute! { unsafe u64x4 => v4u64 } +from_transmute! { unsafe i64x2 => v2i64 } +from_transmute! { unsafe i64x4 => v4i64 } +from_transmute! { unsafe f64x2 => v2f64 } +from_transmute! { unsafe f64x4 => v4f64 } + +from_transmute! { unsafe usizex2 => v2u64 } +from_transmute! { unsafe usizex4 => v4u64 } +from_transmute! { unsafe isizex2 => v2i64 } +from_transmute! { unsafe isizex4 => v4i64 } diff --git a/crates/core_simd/tests/layout.rs b/crates/core_simd/tests/layout.rs new file mode 100644 index 000000000000..24114c2d261e --- /dev/null +++ b/crates/core_simd/tests/layout.rs @@ -0,0 +1,35 @@ +#![feature(portable_simd)] + +macro_rules! layout_tests { + { $($mod:ident, $ty:ty,)* } => { + $( + mod $mod { + test_helpers::test_lanes! { + fn no_padding() { + assert_eq!( + core::mem::size_of::>(), + core::mem::size_of::<[$ty; LANES]>(), + ); + } + } + } + )* + } +} + +layout_tests! { + i8, i8, + i16, i16, + i32, i32, + i64, i64, + isize, isize, + u8, u8, + u16, u16, + u32, u32, + u64, u64, + usize, usize, + f32, f32, + f64, f64, + mut_ptr, *mut (), + const_ptr, *const (), +} diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs index fc6a3476b7c6..48786d02440b 100644 --- a/crates/core_simd/tests/masks.rs +++ b/crates/core_simd/tests/masks.rs @@ -99,7 +99,6 @@ macro_rules! test_mask_api { assert_eq!(Mask::<$type, 2>::from_bitmask(bitmask), mask); } - #[cfg(feature = "all_lane_counts")] #[test] fn roundtrip_bitmask_conversion_odd() { let values = [ @@ -134,48 +133,6 @@ macro_rules! test_mask_api { cast_impl::(); cast_impl::(); } - - #[test] - fn roundtrip_bitmask_vector_conversion() { - use core_simd::simd::ToBytes; - let values = [ - true, false, false, true, false, false, true, false, - true, true, false, false, false, false, false, true, - ]; - let mask = Mask::<$type, 16>::from_array(values); - let bitmask = mask.to_bitmask_vector(); - assert_eq!(bitmask.resize::<2>(0).to_ne_bytes()[..2], [0b01001001, 0b10000011]); - assert_eq!(Mask::<$type, 16>::from_bitmask_vector(bitmask), mask); - } - - // rust-lang/portable-simd#379 - #[test] - fn roundtrip_bitmask_vector_conversion_small() { - use core_simd::simd::ToBytes; - let values = [ - true, false, true, true - ]; - let mask = Mask::<$type, 4>::from_array(values); - let bitmask = mask.to_bitmask_vector(); - assert_eq!(bitmask.resize::<1>(0).to_ne_bytes()[0], 0b00001101); - assert_eq!(Mask::<$type, 4>::from_bitmask_vector(bitmask), mask); - } - - /* FIXME doesn't work with non-powers-of-two, yet - // rust-lang/portable-simd#379 - #[cfg(feature = "all_lane_counts")] - #[test] - fn roundtrip_bitmask_vector_conversion_odd() { - use core_simd::simd::ToBytes; - let values = [ - true, false, true, false, true, true, false, false, false, true, true, - ]; - let mask = Mask::<$type, 11>::from_array(values); - let bitmask = mask.to_bitmask_vector(); - assert_eq!(bitmask.resize::<2>(0).to_ne_bytes()[..2], [0b00110101, 0b00000110]); - assert_eq!(Mask::<$type, 11>::from_bitmask_vector(bitmask), mask); - } - */ } } } diff --git a/crates/core_simd/tests/ops_macros.rs b/crates/core_simd/tests/ops_macros.rs index aa565a137527..6de78f51e59d 100644 --- a/crates/core_simd/tests/ops_macros.rs +++ b/crates/core_simd/tests/ops_macros.rs @@ -216,6 +216,22 @@ macro_rules! impl_common_integer_tests { ) } + fn count_ones() { + test_helpers::test_unary_elementwise( + &$vector::::count_ones, + &|x| x.count_ones() as _, + &|_| true, + ) + } + + fn count_zeros() { + test_helpers::test_unary_elementwise( + &$vector::::count_zeros, + &|x| x.count_zeros() as _, + &|_| true, + ) + } + fn leading_zeros() { test_helpers::test_unary_elementwise( &$vector::::leading_zeros, @@ -307,6 +323,14 @@ macro_rules! impl_signed_tests { assert_eq!(a % b, Vector::::splat(0)); } + fn abs_diff() { + test_helpers::test_binary_elementwise( + &Vector::::abs_diff, + &Scalar::abs_diff, + &|_, _| true, + ) + } + fn simd_min() { use core_simd::simd::cmp::SimdOrd; let a = Vector::::splat(Scalar::MIN); @@ -419,6 +443,14 @@ macro_rules! impl_unsigned_tests { &|_| true, ); } + + fn abs_diff() { + test_helpers::test_binary_elementwise( + &Vector::::abs_diff, + &Scalar::abs_diff, + &|_, _| true, + ) + } } impl_binary_op_test!(Scalar, Add::add, AddAssign::add_assign, Scalar::wrapping_add); @@ -495,6 +527,9 @@ macro_rules! impl_float_tests { } fn is_normal() { + // Arm v7 Neon violates float opsem re: subnormals, see + // https://github.com/rust-lang/portable-simd/issues/439 + #[cfg(not(target_arch = "arm"))] test_helpers::test_unary_mask_elementwise( &Vector::::is_normal, &Scalar::is_normal, @@ -503,6 +538,9 @@ macro_rules! impl_float_tests { } fn is_subnormal() { + // Arm v7 Neon violates float opsem re: subnormals, see + // https://github.com/rust-lang/portable-simd/issues/439 + #[cfg(not(target_arch = "arm"))] test_helpers::test_unary_mask_elementwise( &Vector::::is_subnormal, &Scalar::is_subnormal, diff --git a/crates/core_simd/tests/swizzle.rs b/crates/core_simd/tests/swizzle.rs index 522d71439b77..7001e5f6bf87 100644 --- a/crates/core_simd/tests/swizzle.rs +++ b/crates/core_simd/tests/swizzle.rs @@ -48,6 +48,24 @@ fn rotate() { assert_eq!(a.rotate_elements_right::<5>().to_array(), [4, 1, 2, 3]); } +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn shift() { + let a = Simd::from_array([1, 2, 3, 4]); + assert_eq!(a.shift_elements_left::<0>(0).to_array(), [1, 2, 3, 4]); + assert_eq!(a.shift_elements_left::<1>(0).to_array(), [2, 3, 4, 0]); + assert_eq!(a.shift_elements_left::<2>(9).to_array(), [3, 4, 9, 9]); + assert_eq!(a.shift_elements_left::<3>(8).to_array(), [4, 8, 8, 8]); + assert_eq!(a.shift_elements_left::<4>(7).to_array(), [7, 7, 7, 7]); + assert_eq!(a.shift_elements_left::<5>(6).to_array(), [6, 6, 6, 6]); + assert_eq!(a.shift_elements_right::<0>(0).to_array(), [1, 2, 3, 4]); + assert_eq!(a.shift_elements_right::<1>(0).to_array(), [0, 1, 2, 3]); + assert_eq!(a.shift_elements_right::<2>(-1).to_array(), [-1, -1, 1, 2]); + assert_eq!(a.shift_elements_right::<3>(-2).to_array(), [-2, -2, -2, 1]); + assert_eq!(a.shift_elements_right::<4>(-3).to_array(), [-3, -3, -3, -3]); + assert_eq!(a.shift_elements_right::<5>(-4).to_array(), [-4, -4, -4, -4]); +} + #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn interleave() { diff --git a/crates/test_helpers/Cargo.toml b/crates/test_helpers/Cargo.toml index 23dae7c93381..a5359b9abc84 100644 --- a/crates/test_helpers/Cargo.toml +++ b/crates/test_helpers/Cargo.toml @@ -6,6 +6,3 @@ publish = false [dependencies] proptest = { version = "0.10", default-features = false, features = ["alloc"] } - -[features] -all_lane_counts = [] diff --git a/crates/test_helpers/src/lib.rs b/crates/test_helpers/src/lib.rs index 51b860a86356..197c920e11ea 100644 --- a/crates/test_helpers/src/lib.rs +++ b/crates/test_helpers/src/lib.rs @@ -539,32 +539,22 @@ macro_rules! test_lanes { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]; lanes_1 1; lanes_2 2; - lanes_4 4; - ); - - #[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow - $crate::test_lanes_helper!( - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]; - lanes_8 8; - lanes_16 16; - lanes_32 32; - lanes_64 64; - ); - - #[cfg(feature = "all_lane_counts")] - $crate::test_lanes_helper!( - // test some odd and even non-power-of-2 lengths on miri - #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]; + // Cover an odd and an even non-power-of-2 length in Miri. + // (Even non-power-of-2 vectors have alignment between element + // and vector size, so we want to cover that case as well.) lanes_3 3; - lanes_5 5; + lanes_6 6; ); - #[cfg(feature = "all_lane_counts")] #[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow $crate::test_lanes_helper!( #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]; + lanes_4 4; + lanes_5 5; + lanes_7 7; + lanes_8 8; lanes_9 9; lanes_10 10; lanes_11 11; @@ -572,52 +562,55 @@ macro_rules! test_lanes { lanes_13 13; lanes_14 14; lanes_15 15; + lanes_16 16; lanes_17 17; - lanes_18 18; - lanes_19 19; - lanes_20 20; - lanes_21 21; - lanes_22 22; - lanes_23 23; + //lanes_18 18; + //lanes_19 19; + //lanes_20 20; + //lanes_21 21; + //lanes_22 22; + //lanes_23 23; lanes_24 24; - lanes_25 25; - lanes_26 26; - lanes_27 27; - lanes_28 28; - lanes_29 29; - lanes_30 30; - lanes_31 31; - lanes_33 33; - lanes_34 34; - lanes_35 35; - lanes_36 36; - lanes_37 37; - lanes_38 38; - lanes_39 39; - lanes_40 40; - lanes_41 41; - lanes_42 42; - lanes_43 43; - lanes_44 44; - lanes_45 45; - lanes_46 46; + //lanes_25 25; + //lanes_26 26; + //lanes_27 27; + //lanes_28 28; + //lanes_29 29; + //lanes_30 30; + //lanes_31 31; + lanes_32 32; + //lanes_33 33; + //lanes_34 34; + //lanes_35 35; + //lanes_36 36; + //lanes_37 37; + //lanes_38 38; + //lanes_39 39; + //lanes_40 40; + //lanes_41 41; + //lanes_42 42; + //lanes_43 43; + //lanes_44 44; + //lanes_45 45; + //lanes_46 46; lanes_47 47; - lanes_48 48; - lanes_49 49; - lanes_50 50; - lanes_51 51; - lanes_52 52; - lanes_53 53; - lanes_54 54; - lanes_55 55; + //lanes_48 48; + //lanes_49 49; + //lanes_50 50; + //lanes_51 51; + //lanes_52 52; + //lanes_53 53; + //lanes_54 54; + //lanes_55 55; lanes_56 56; lanes_57 57; - lanes_58 58; - lanes_59 59; - lanes_60 60; - lanes_61 61; - lanes_62 62; + //lanes_58 58; + //lanes_59 59; + //lanes_60 60; + //lanes_61 61; + //lanes_62 62; lanes_63 63; + lanes_64 64; ); } )* @@ -639,36 +632,24 @@ macro_rules! test_lanes_panic { core_simd::simd::LaneCount<$lanes>: core_simd::simd::SupportedLaneCount, $body + // test some odd and even non-power-of-2 lengths on miri $crate::test_lanes_helper!( #[should_panic]; lanes_1 1; lanes_2 2; - lanes_4 4; - ); - - #[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow - $crate::test_lanes_helper!( - #[should_panic]; - lanes_8 8; - lanes_16 16; - lanes_32 32; - lanes_64 64; - ); - - #[cfg(feature = "all_lane_counts")] - $crate::test_lanes_helper!( - // test some odd and even non-power-of-2 lengths on miri - #[should_panic]; lanes_3 3; - lanes_5 5; + lanes_6 6; ); - #[cfg(feature = "all_lane_counts")] #[cfg(not(miri))] // Miri intrinsic implementations are uniform and larger tests are sloooow $crate::test_lanes_helper!( #[should_panic]; + lanes_4 4; + lanes_5 5; + lanes_7 7; + lanes_8 8; lanes_9 9; lanes_10 10; lanes_11 11; @@ -676,52 +657,55 @@ macro_rules! test_lanes_panic { lanes_13 13; lanes_14 14; lanes_15 15; + lanes_16 16; lanes_17 17; - lanes_18 18; - lanes_19 19; - lanes_20 20; - lanes_21 21; - lanes_22 22; - lanes_23 23; + //lanes_18 18; + //lanes_19 19; + //lanes_20 20; + //lanes_21 21; + //lanes_22 22; + //lanes_23 23; lanes_24 24; - lanes_25 25; - lanes_26 26; - lanes_27 27; - lanes_28 28; - lanes_29 29; - lanes_30 30; - lanes_31 31; - lanes_33 33; - lanes_34 34; - lanes_35 35; - lanes_36 36; - lanes_37 37; - lanes_38 38; - lanes_39 39; - lanes_40 40; - lanes_41 41; - lanes_42 42; - lanes_43 43; - lanes_44 44; - lanes_45 45; - lanes_46 46; + //lanes_25 25; + //lanes_26 26; + //lanes_27 27; + //lanes_28 28; + //lanes_29 29; + //lanes_30 30; + //lanes_31 31; + lanes_32 32; + //lanes_33 33; + //lanes_34 34; + //lanes_35 35; + //lanes_36 36; + //lanes_37 37; + //lanes_38 38; + //lanes_39 39; + //lanes_40 40; + //lanes_41 41; + //lanes_42 42; + //lanes_43 43; + //lanes_44 44; + //lanes_45 45; + //lanes_46 46; lanes_47 47; - lanes_48 48; - lanes_49 49; - lanes_50 50; - lanes_51 51; - lanes_52 52; - lanes_53 53; - lanes_54 54; - lanes_55 55; + //lanes_48 48; + //lanes_49 49; + //lanes_50 50; + //lanes_51 51; + //lanes_52 52; + //lanes_53 53; + //lanes_54 54; + //lanes_55 55; lanes_56 56; lanes_57 57; - lanes_58 58; - lanes_59 59; - lanes_60 60; - lanes_61 61; - lanes_62 62; + //lanes_58 58; + //lanes_59 59; + //lanes_60 60; + //lanes_61 61; + //lanes_62 62; lanes_63 63; + lanes_64 64; ); } )* diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 000000000000..d17c6d2e8894 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "nightly-2025-01-16" +components = ["rustfmt", "clippy", "miri", "rust-src"] diff --git a/subtree-sync.sh b/subtree-sync.sh new file mode 100755 index 000000000000..18360077623b --- /dev/null +++ b/subtree-sync.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +set -eou pipefail + +git fetch origin +pushd $2 +git fetch origin +popd + +if [ "$(git rev-parse --show-prefix)" != "" ]; then + echo "Run this script from the git root" >&2 + exit 1 +fi + +if [ "$(git rev-parse HEAD)" != "$(git rev-parse origin/master)" ]; then + echo "$(pwd) is not at origin/master" >&2 + exit 1 +fi + +if [ ! -f library/portable-simd/git-subtree.sh ]; then + curl -sS https://raw.githubusercontent.com/bjorn3/git/tqc-subtree-portable/contrib/subtree/git-subtree.sh -o library/portable-simd/git-subtree.sh + chmod +x library/portable-simd/git-subtree.sh +fi + +today=$(date +%Y-%m-%d) + +case $1 in + "push") + upstream=rust-upstream-$today + merge=sync-from-rust-$today + + pushd $2 + git checkout master + git pull + popd + + library/portable-simd/git-subtree.sh push -P library/portable-simd $2 $upstream + + pushd $2 + git checkout -B $merge origin/master + git merge $upstream + popd + echo "Branch \`$merge\` created in \`$2\`. You may need to resolve merge conflicts." + ;; + "pull") + branch=sync-from-portable-simd-$today + + git checkout -B $branch + echo "Creating branch \`$branch\`... You may need to resolve merge conflicts." + library/portable-simd/git-subtree.sh pull -P library/portable-simd $2 origin/master + ;; +esac From 02a28b29e2d1ab50b8d80c18018c33402cefc054 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Wed, 12 Feb 2025 10:35:32 +0100 Subject: [PATCH 002/978] Remove ignored `#[must_use]` attributes from portable-simd The `#[must_use]` attribute has no effect when applied to methods in trait implementations. --- crates/core_simd/src/masks.rs | 13 ------------- crates/core_simd/src/masks/full_masks.rs | 5 ----- crates/core_simd/src/ops.rs | 1 - crates/core_simd/src/ops/deref.rs | 3 --- crates/core_simd/src/ops/unary.rs | 2 -- crates/core_simd/src/simd/num/float.rs | 1 - 6 files changed, 25 deletions(-) diff --git a/crates/core_simd/src/masks.rs b/crates/core_simd/src/masks.rs index b763a7c75a5a..19d45f4d3b31 100644 --- a/crates/core_simd/src/masks.rs +++ b/crates/core_simd/src/masks.rs @@ -401,7 +401,6 @@ where LaneCount: SupportedLaneCount, { #[inline] - #[must_use = "method returns a defaulted mask with all elements set to false (0)"] fn default() -> Self { Self::splat(false) } @@ -413,7 +412,6 @@ where LaneCount: SupportedLaneCount, { #[inline] - #[must_use = "method returns a new bool and does not mutate the original value"] fn eq(&self, other: &Self) -> bool { self.0 == other.0 } @@ -425,7 +423,6 @@ where LaneCount: SupportedLaneCount, { #[inline] - #[must_use = "method returns a new Ordering and does not mutate the original value"] fn partial_cmp(&self, other: &Self) -> Option { self.0.partial_cmp(&other.0) } @@ -451,7 +448,6 @@ where { type Output = Self; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn bitand(self, rhs: Self) -> Self { Self(self.0 & rhs.0) } @@ -464,7 +460,6 @@ where { type Output = Self; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn bitand(self, rhs: bool) -> Self { self & Self::splat(rhs) } @@ -477,7 +472,6 @@ where { type Output = Mask; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn bitand(self, rhs: Mask) -> Mask { Mask::splat(self) & rhs } @@ -490,7 +484,6 @@ where { type Output = Self; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn bitor(self, rhs: Self) -> Self { Self(self.0 | rhs.0) } @@ -503,7 +496,6 @@ where { type Output = Self; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn bitor(self, rhs: bool) -> Self { self | Self::splat(rhs) } @@ -516,7 +508,6 @@ where { type Output = Mask; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn bitor(self, rhs: Mask) -> Mask { Mask::splat(self) | rhs } @@ -529,7 +520,6 @@ where { type Output = Self; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn bitxor(self, rhs: Self) -> Self::Output { Self(self.0 ^ rhs.0) } @@ -542,7 +532,6 @@ where { type Output = Self; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn bitxor(self, rhs: bool) -> Self::Output { self ^ Self::splat(rhs) } @@ -555,7 +544,6 @@ where { type Output = Mask; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn bitxor(self, rhs: Mask) -> Self::Output { Mask::splat(self) ^ rhs } @@ -568,7 +556,6 @@ where { type Output = Mask; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn not(self) -> Self::Output { Self(!self.0) } diff --git a/crates/core_simd/src/masks/full_masks.rs b/crates/core_simd/src/masks/full_masks.rs index 2d01946b5747..387b508c4b4e 100644 --- a/crates/core_simd/src/masks/full_masks.rs +++ b/crates/core_simd/src/masks/full_masks.rs @@ -21,7 +21,6 @@ where LaneCount: SupportedLaneCount, { #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn clone(&self) -> Self { *self } @@ -252,7 +251,6 @@ where { type Output = Self; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn bitand(self, rhs: Self) -> Self { // Safety: `self` is an integer vector unsafe { Self(core::intrinsics::simd::simd_and(self.0, rhs.0)) } @@ -266,7 +264,6 @@ where { type Output = Self; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn bitor(self, rhs: Self) -> Self { // Safety: `self` is an integer vector unsafe { Self(core::intrinsics::simd::simd_or(self.0, rhs.0)) } @@ -280,7 +277,6 @@ where { type Output = Self; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn bitxor(self, rhs: Self) -> Self { // Safety: `self` is an integer vector unsafe { Self(core::intrinsics::simd::simd_xor(self.0, rhs.0)) } @@ -294,7 +290,6 @@ where { type Output = Self; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn not(self) -> Self::Output { Self::splat(true) ^ self } diff --git a/crates/core_simd/src/ops.rs b/crates/core_simd/src/ops.rs index d3bd14a34027..4ac64a253a3b 100644 --- a/crates/core_simd/src/ops.rs +++ b/crates/core_simd/src/ops.rs @@ -135,7 +135,6 @@ macro_rules! for_base_types { type Output = $out; #[inline] - #[must_use = "operator returns a new vector without mutating the inputs"] // TODO: only useful for int Div::div, but we hope that this // will essentially always get inlined anyway. #[track_caller] diff --git a/crates/core_simd/src/ops/deref.rs b/crates/core_simd/src/ops/deref.rs index 0ff76cfba39b..913cbbe977c4 100644 --- a/crates/core_simd/src/ops/deref.rs +++ b/crates/core_simd/src/ops/deref.rs @@ -18,7 +18,6 @@ macro_rules! deref_lhs { type Output = Simd; #[inline] - #[must_use = "operator returns a new vector without mutating the inputs"] fn $call(self, rhs: $simd) -> Self::Output { (*self).$call(rhs) } @@ -39,7 +38,6 @@ macro_rules! deref_rhs { type Output = Simd; #[inline] - #[must_use = "operator returns a new vector without mutating the inputs"] fn $call(self, rhs: &$simd) -> Self::Output { self.$call(*rhs) } @@ -71,7 +69,6 @@ macro_rules! deref_ops { type Output = $simd; #[inline] - #[must_use = "operator returns a new vector without mutating the inputs"] fn $call(self, rhs: &'rhs $simd) -> Self::Output { (*self).$call(*rhs) } diff --git a/crates/core_simd/src/ops/unary.rs b/crates/core_simd/src/ops/unary.rs index bdae96332a3a..412a5b801171 100644 --- a/crates/core_simd/src/ops/unary.rs +++ b/crates/core_simd/src/ops/unary.rs @@ -11,7 +11,6 @@ macro_rules! neg { type Output = Self; #[inline] - #[must_use = "operator returns a new vector without mutating the input"] fn neg(self) -> Self::Output { // Safety: `self` is a signed vector unsafe { core::intrinsics::simd::simd_neg(self) } @@ -46,7 +45,6 @@ macro_rules! not { type Output = Self; #[inline] - #[must_use = "operator returns a new vector without mutating the input"] fn not(self) -> Self::Output { self ^ (Simd::splat(!(0 as $scalar))) } diff --git a/crates/core_simd/src/simd/num/float.rs b/crates/core_simd/src/simd/num/float.rs index 79954b937b39..db705dfe2022 100644 --- a/crates/core_simd/src/simd/num/float.rs +++ b/crates/core_simd/src/simd/num/float.rs @@ -371,7 +371,6 @@ macro_rules! impl_trait { } #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn is_normal(self) -> Self::Mask { !(self.abs().simd_eq(Self::splat(0.0)) | self.is_nan() | self.is_subnormal() | self.is_infinite()) } From aaf8ff1f9ec9b7049a7896a3c278f9e990306cb8 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Wed, 19 Mar 2025 00:58:47 -0400 Subject: [PATCH 003/978] Merge commit 'c14f2fc3eb69c164d8bf8d36d91ebd60bd5261e6' into sync-from-portable-simd-2025-03-19 --- beginners-guide.md | 4 +- crates/core_simd/Cargo.toml | 2 +- crates/core_simd/src/lib.rs | 6 ++- crates/core_simd/src/masks/bitmask.rs | 22 +++++------ crates/core_simd/src/masks/full_masks.rs | 20 +++++----- crates/core_simd/src/ops.rs | 2 +- crates/core_simd/src/simd/cmp/eq.rs | 2 +- crates/core_simd/src/simd/cmp/ord.rs | 2 +- crates/core_simd/src/simd/num/float.rs | 9 +++-- crates/core_simd/src/simd/num/int.rs | 4 +- crates/core_simd/src/simd/num/uint.rs | 2 +- crates/core_simd/src/simd/prelude.rs | 3 +- crates/core_simd/src/simd/ptr/const_ptr.rs | 2 +- crates/core_simd/src/simd/ptr/mut_ptr.rs | 2 +- crates/core_simd/src/swizzle.rs | 44 ++++++++++++++++++++++ crates/core_simd/src/to_bytes.rs | 2 +- crates/core_simd/src/vector.rs | 4 +- crates/core_simd/tests/layout.rs | 4 +- crates/core_simd/tests/pointers.rs | 2 +- crates/core_simd/tests/round.rs | 2 +- crates/test_helpers/src/subnormals.rs | 2 +- 21 files changed, 96 insertions(+), 46 deletions(-) diff --git a/beginners-guide.md b/beginners-guide.md index 17ade06ae80f..dc08d847ced5 100644 --- a/beginners-guide.md +++ b/beginners-guide.md @@ -80,12 +80,12 @@ Most of the portable SIMD API is designed to allow the user to gloss over the de Fortunately, most SIMD types have a fairly predictable size. `i32x4` is bit-equivalent to `[i32; 4]` and so can be bitcast to it, e.g. using [`mem::transmute`], though the API usually offers a safe cast you can use instead. -However, this is not the same as alignment. Computer architectures generally prefer aligned accesses, especially when moving data between memory and vector registers, and while some support specialized operations that can bend the rules to help with this, unaligned access is still typically slow, or even undefined behavior. In addition, different architectures can require different alignments when interacting with their native SIMD types. For this reason, any `#[repr(simd)]` type has a non-portable alignment. If it is necessary to directly interact with the alignment of these types, it should be via [`mem::align_of`]. +However, this is not the same as alignment. Computer architectures generally prefer aligned accesses, especially when moving data between memory and vector registers, and while some support specialized operations that can bend the rules to help with this, unaligned access is still typically slow, or even undefined behavior. In addition, different architectures can require different alignments when interacting with their native SIMD types. For this reason, any `#[repr(simd)]` type has a non-portable alignment. If it is necessary to directly interact with the alignment of these types, it should be via [`align_of`]. When working with slices, data correctly aligned for SIMD can be acquired using the [`as_simd`] and [`as_simd_mut`] methods of the slice primitive. [`mem::transmute`]: https://doc.rust-lang.org/core/mem/fn.transmute.html -[`mem::align_of`]: https://doc.rust-lang.org/core/mem/fn.align_of.html +[`align_of`]: https://doc.rust-lang.org/core/mem/fn.align_of.html [`as_simd`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_simd [`as_simd_mut`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_simd_mut diff --git a/crates/core_simd/Cargo.toml b/crates/core_simd/Cargo.toml index a7a6d43b11d3..537ce459c07c 100644 --- a/crates/core_simd/Cargo.toml +++ b/crates/core_simd/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "core_simd" version = "0.1.0" -edition = "2021" +edition = "2024" homepage = "https://github.com/rust-lang/portable-simd" repository = "https://github.com/rust-lang/portable-simd" keywords = ["core", "simd", "intrinsics"] diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs index 7f57847c9c23..717b882b64ba 100644 --- a/crates/core_simd/src/lib.rs +++ b/crates/core_simd/src/lib.rs @@ -35,7 +35,11 @@ feature(stdarch_x86_avx512) )] #![warn(missing_docs, clippy::missing_inline_in_public_items)] // basically all items, really -#![deny(unsafe_op_in_unsafe_fn, clippy::undocumented_unsafe_blocks)] +#![deny( + unsafe_op_in_unsafe_fn, + unreachable_pub, + clippy::undocumented_unsafe_blocks +)] #![doc(test(attr(deny(warnings))))] #![allow(internal_features)] #![unstable(feature = "portable_simd", issue = "86656")] diff --git a/crates/core_simd/src/masks/bitmask.rs b/crates/core_simd/src/masks/bitmask.rs index db4312d5bf88..8221d8f17e90 100644 --- a/crates/core_simd/src/masks/bitmask.rs +++ b/crates/core_simd/src/masks/bitmask.rs @@ -5,7 +5,7 @@ use core::marker::PhantomData; /// A mask where each lane is represented by a single bit. #[repr(transparent)] -pub struct Mask( +pub(crate) struct Mask( as SupportedLaneCount>::BitMask, PhantomData, ) @@ -78,7 +78,7 @@ where { #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn splat(value: bool) -> Self { + pub(crate) fn splat(value: bool) -> Self { let mut mask = as SupportedLaneCount>::BitMask::default(); if value { mask.as_mut().fill(u8::MAX) @@ -93,12 +93,12 @@ where #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] - pub unsafe fn test_unchecked(&self, lane: usize) -> bool { + pub(crate) unsafe fn test_unchecked(&self, lane: usize) -> bool { (self.0.as_ref()[lane / 8] >> (lane % 8)) & 0x1 > 0 } #[inline] - pub unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { + pub(crate) unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { unsafe { self.0.as_mut()[lane / 8] ^= ((value ^ self.test_unchecked(lane)) as u8) << (lane % 8) } @@ -106,7 +106,7 @@ where #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - pub fn to_int(self) -> Simd { + pub(crate) fn to_int(self) -> Simd { unsafe { core::intrinsics::simd::simd_select_bitmask( self.0, @@ -118,19 +118,19 @@ where #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub unsafe fn from_int_unchecked(value: Simd) -> Self { + pub(crate) unsafe fn from_int_unchecked(value: Simd) -> Self { unsafe { Self(core::intrinsics::simd::simd_bitmask(value), PhantomData) } } #[inline] - pub fn to_bitmask_integer(self) -> u64 { + pub(crate) fn to_bitmask_integer(self) -> u64 { let mut bitmask = [0u8; 8]; bitmask[..self.0.as_ref().len()].copy_from_slice(self.0.as_ref()); u64::from_ne_bytes(bitmask) } #[inline] - pub fn from_bitmask_integer(bitmask: u64) -> Self { + pub(crate) fn from_bitmask_integer(bitmask: u64) -> Self { let mut bytes = as SupportedLaneCount>::BitMask::default(); let len = bytes.as_mut().len(); bytes @@ -141,7 +141,7 @@ where #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn convert(self) -> Mask + pub(crate) fn convert(self) -> Mask where U: MaskElement, { @@ -151,13 +151,13 @@ where #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] - pub fn any(self) -> bool { + pub(crate) fn any(self) -> bool { self != Self::splat(false) } #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] - pub fn all(self) -> bool { + pub(crate) fn all(self) -> bool { self == Self::splat(true) } } diff --git a/crates/core_simd/src/masks/full_masks.rs b/crates/core_simd/src/masks/full_masks.rs index 387b508c4b4e..4e98db4070a9 100644 --- a/crates/core_simd/src/masks/full_masks.rs +++ b/crates/core_simd/src/masks/full_masks.rs @@ -3,7 +3,7 @@ use crate::simd::{LaneCount, MaskElement, Simd, SupportedLaneCount}; #[repr(transparent)] -pub struct Mask(Simd) +pub(crate) struct Mask(Simd) where T: MaskElement, LaneCount: SupportedLaneCount; @@ -80,7 +80,7 @@ macro_rules! impl_reverse_bits { #[inline(always)] fn reverse_bits(self, n: usize) -> Self { let rev = <$int>::reverse_bits(self); - let bitsize = core::mem::size_of::<$int>() * 8; + let bitsize = size_of::<$int>() * 8; if n < bitsize { // Shift things back to the right rev >> (bitsize - n) @@ -102,36 +102,36 @@ where { #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn splat(value: bool) -> Self { + pub(crate) fn splat(value: bool) -> Self { Self(Simd::splat(if value { T::TRUE } else { T::FALSE })) } #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] - pub unsafe fn test_unchecked(&self, lane: usize) -> bool { + pub(crate) unsafe fn test_unchecked(&self, lane: usize) -> bool { T::eq(self.0[lane], T::TRUE) } #[inline] - pub unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { + pub(crate) unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { self.0[lane] = if value { T::TRUE } else { T::FALSE } } #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - pub fn to_int(self) -> Simd { + pub(crate) fn to_int(self) -> Simd { self.0 } #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub unsafe fn from_int_unchecked(value: Simd) -> Self { + pub(crate) unsafe fn from_int_unchecked(value: Simd) -> Self { Self(value) } #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn convert(self) -> Mask + pub(crate) fn convert(self) -> Mask where U: MaskElement, { @@ -220,14 +220,14 @@ where #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] - pub fn any(self) -> bool { + pub(crate) fn any(self) -> bool { // Safety: use `self` as an integer vector unsafe { core::intrinsics::simd::simd_reduce_any(self.to_int()) } } #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] - pub fn all(self) -> bool { + pub(crate) fn all(self) -> bool { // Safety: use `self` as an integer vector unsafe { core::intrinsics::simd::simd_reduce_all(self.to_int()) } } diff --git a/crates/core_simd/src/ops.rs b/crates/core_simd/src/ops.rs index 4ac64a253a3b..f36e8d01a73b 100644 --- a/crates/core_simd/src/ops.rs +++ b/crates/core_simd/src/ops.rs @@ -1,4 +1,4 @@ -use crate::simd::{cmp::SimdPartialEq, LaneCount, Simd, SimdElement, SupportedLaneCount}; +use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount, cmp::SimdPartialEq}; use core::ops::{Add, Mul}; use core::ops::{BitAnd, BitOr, BitXor}; use core::ops::{Div, Rem, Sub}; diff --git a/crates/core_simd/src/simd/cmp/eq.rs b/crates/core_simd/src/simd/cmp/eq.rs index 93989ce91b89..2312ba401fa7 100644 --- a/crates/core_simd/src/simd/cmp/eq.rs +++ b/crates/core_simd/src/simd/cmp/eq.rs @@ -1,6 +1,6 @@ use crate::simd::{ - ptr::{SimdConstPtr, SimdMutPtr}, LaneCount, Mask, Simd, SimdElement, SupportedLaneCount, + ptr::{SimdConstPtr, SimdMutPtr}, }; /// Parallel `PartialEq`. diff --git a/crates/core_simd/src/simd/cmp/ord.rs b/crates/core_simd/src/simd/cmp/ord.rs index 899f00a83164..e813e7613032 100644 --- a/crates/core_simd/src/simd/cmp/ord.rs +++ b/crates/core_simd/src/simd/cmp/ord.rs @@ -1,7 +1,7 @@ use crate::simd::{ + LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, ptr::{SimdConstPtr, SimdMutPtr}, - LaneCount, Mask, Simd, SupportedLaneCount, }; /// Parallel `PartialOrd`. diff --git a/crates/core_simd/src/simd/num/float.rs b/crates/core_simd/src/simd/num/float.rs index db705dfe2022..b5972c47373b 100644 --- a/crates/core_simd/src/simd/num/float.rs +++ b/crates/core_simd/src/simd/num/float.rs @@ -1,7 +1,7 @@ use super::sealed::Sealed; use crate::simd::{ - cmp::{SimdPartialEq, SimdPartialOrd}, LaneCount, Mask, Simd, SimdCast, SimdElement, SupportedLaneCount, + cmp::{SimdPartialEq, SimdPartialOrd}, }; /// Operations on SIMD vectors of floats. @@ -263,7 +263,8 @@ macro_rules! impl_trait { unsafe { core::intrinsics::simd::simd_as(self) } } - // https://github.com/llvm/llvm-project/issues/94694 + // workaround for https://github.com/llvm/llvm-project/issues/94694 (fixed in LLVM 20) + // tracked in: https://github.com/rust-lang/rust/issues/135982 #[cfg(target_arch = "aarch64")] #[inline] fn cast(self) -> Self::Cast @@ -302,14 +303,14 @@ macro_rules! impl_trait { #[inline] fn to_bits(self) -> Simd<$bits_ty, N> { - assert_eq!(core::mem::size_of::(), core::mem::size_of::()); + assert_eq!(size_of::(), size_of::()); // Safety: transmuting between vector types is safe unsafe { core::mem::transmute_copy(&self) } } #[inline] fn from_bits(bits: Simd<$bits_ty, N>) -> Self { - assert_eq!(core::mem::size_of::(), core::mem::size_of::()); + assert_eq!(size_of::(), size_of::()); // Safety: transmuting between vector types is safe unsafe { core::mem::transmute_copy(&bits) } } diff --git a/crates/core_simd/src/simd/num/int.rs b/crates/core_simd/src/simd/num/int.rs index 3a51235ff954..d25050c3e4b4 100644 --- a/crates/core_simd/src/simd/num/int.rs +++ b/crates/core_simd/src/simd/num/int.rs @@ -1,7 +1,7 @@ use super::sealed::Sealed; use crate::simd::{ - cmp::SimdOrd, cmp::SimdPartialOrd, num::SimdUint, LaneCount, Mask, Simd, SimdCast, SimdElement, - SupportedLaneCount, + LaneCount, Mask, Simd, SimdCast, SimdElement, SupportedLaneCount, cmp::SimdOrd, + cmp::SimdPartialOrd, num::SimdUint, }; /// Operations on SIMD vectors of signed integers. diff --git a/crates/core_simd/src/simd/num/uint.rs b/crates/core_simd/src/simd/num/uint.rs index 1ab2d8c7b731..45d978068b66 100644 --- a/crates/core_simd/src/simd/num/uint.rs +++ b/crates/core_simd/src/simd/num/uint.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{cmp::SimdOrd, LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount}; +use crate::simd::{LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount, cmp::SimdOrd}; /// Operations on SIMD vectors of unsigned integers. pub trait SimdUint: Copy + Sealed { diff --git a/crates/core_simd/src/simd/prelude.rs b/crates/core_simd/src/simd/prelude.rs index 4b7c744c0132..e5d7a2aeb73d 100644 --- a/crates/core_simd/src/simd/prelude.rs +++ b/crates/core_simd/src/simd/prelude.rs @@ -7,10 +7,11 @@ #[doc(no_inline)] pub use super::{ + Mask, Simd, cmp::{SimdOrd, SimdPartialEq, SimdPartialOrd}, num::{SimdFloat, SimdInt, SimdUint}, ptr::{SimdConstPtr, SimdMutPtr}, - simd_swizzle, Mask, Simd, + simd_swizzle, }; #[rustfmt::skip] diff --git a/crates/core_simd/src/simd/ptr/const_ptr.rs b/crates/core_simd/src/simd/ptr/const_ptr.rs index 47383809ffba..36452e7ae920 100644 --- a/crates/core_simd/src/simd/ptr/const_ptr.rs +++ b/crates/core_simd/src/simd/ptr/const_ptr.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{cmp::SimdPartialEq, num::SimdUint, LaneCount, Mask, Simd, SupportedLaneCount}; +use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, num::SimdUint}; /// Operations on SIMD vectors of constant pointers. pub trait SimdConstPtr: Copy + Sealed { diff --git a/crates/core_simd/src/simd/ptr/mut_ptr.rs b/crates/core_simd/src/simd/ptr/mut_ptr.rs index 3f20eef21a31..c644f390c20a 100644 --- a/crates/core_simd/src/simd/ptr/mut_ptr.rs +++ b/crates/core_simd/src/simd/ptr/mut_ptr.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{cmp::SimdPartialEq, num::SimdUint, LaneCount, Mask, Simd, SupportedLaneCount}; +use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, num::SimdUint}; /// Operations on SIMD vectors of mutable pointers. pub trait SimdMutPtr: Copy + Sealed { diff --git a/crates/core_simd/src/swizzle.rs b/crates/core_simd/src/swizzle.rs index 42425ef37e50..dbdd6ef40eba 100644 --- a/crates/core_simd/src/swizzle.rs +++ b/crates/core_simd/src/swizzle.rs @@ -214,6 +214,17 @@ where /// Rotates the vector such that the first `OFFSET` elements of the slice move to the end /// while the last `self.len() - OFFSET` elements move to the front. After calling `rotate_elements_left`, /// the element previously at index `OFFSET` will become the first element in the slice. + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd::Simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd::Simd; + /// let a = Simd::from_array([0, 1, 2, 3]); + /// let x = a.rotate_elements_left::<3>(); + /// assert_eq!(x.to_array(), [3, 0, 1, 2]); + /// + /// let y = a.rotate_elements_left::<7>(); + /// assert_eq!(y.to_array(), [3, 0, 1, 2]); + /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn rotate_elements_left(self) -> Self { @@ -238,6 +249,17 @@ where /// Rotates the vector such that the first `self.len() - OFFSET` elements of the vector move to /// the end while the last `OFFSET` elements move to the front. After calling `rotate_elements_right`, /// the element previously at index `self.len() - OFFSET` will become the first element in the slice. + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd::Simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd::Simd; + /// let a = Simd::from_array([0, 1, 2, 3]); + /// let x = a.rotate_elements_right::<3>(); + /// assert_eq!(x.to_array(), [1, 2, 3, 0]); + /// + /// let y = a.rotate_elements_right::<7>(); + /// assert_eq!(y.to_array(), [1, 2, 3, 0]); + /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn rotate_elements_right(self) -> Self { @@ -261,6 +283,17 @@ where /// Shifts the vector elements to the left by `OFFSET`, filling in with /// `padding` from the right. + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd::Simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd::Simd; + /// let a = Simd::from_array([0, 1, 2, 3]); + /// let x = a.shift_elements_left::<3>(255); + /// assert_eq!(x.to_array(), [3, 255, 255, 255]); + /// + /// let y = a.shift_elements_left::<7>(255); + /// assert_eq!(y.to_array(), [255, 255, 255, 255]); + /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn shift_elements_left(self, padding: T) -> Self { @@ -283,6 +316,17 @@ where /// Shifts the vector elements to the right by `OFFSET`, filling in with /// `padding` from the left. + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd::Simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd::Simd; + /// let a = Simd::from_array([0, 1, 2, 3]); + /// let x = a.shift_elements_right::<3>(255); + /// assert_eq!(x.to_array(), [255, 255, 255, 0]); + /// + /// let y = a.shift_elements_right::<7>(255); + /// assert_eq!(y.to_array(), [255, 255, 255, 255]); + /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn shift_elements_right(self, padding: T) -> Self { diff --git a/crates/core_simd/src/to_bytes.rs b/crates/core_simd/src/to_bytes.rs index 4833ea9e1136..fee2cc06c5b0 100644 --- a/crates/core_simd/src/to_bytes.rs +++ b/crates/core_simd/src/to_bytes.rs @@ -1,6 +1,6 @@ use crate::simd::{ - num::{SimdFloat, SimdInt, SimdUint}, LaneCount, Simd, SimdElement, SupportedLaneCount, + num::{SimdFloat, SimdInt, SimdUint}, }; mod sealed { diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs index 9c4dd36c24fe..d76a6cd52bfc 100644 --- a/crates/core_simd/src/vector.rs +++ b/crates/core_simd/src/vector.rs @@ -1,8 +1,8 @@ use crate::simd::{ + LaneCount, Mask, MaskElement, SupportedLaneCount, Swizzle, cmp::SimdPartialOrd, num::SimdUint, ptr::{SimdConstPtr, SimdMutPtr}, - LaneCount, Mask, MaskElement, SupportedLaneCount, Swizzle, }; /// A SIMD vector with the shape of `[T; N]` but the operations of `T`. @@ -83,7 +83,7 @@ use crate::simd::{ /// converting `[T]` to `[Simd]`, and allows soundly operating on an aligned SIMD body, /// but it may cost more time when handling the scalar head and tail. /// If these are not enough, it is most ideal to design data structures to be already aligned -/// to `mem::align_of::>()` before using `unsafe` Rust to read or write. +/// to `align_of::>()` before using `unsafe` Rust to read or write. /// Other ways to compensate for these facts, like materializing `Simd` to or from an array first, /// are handled by safe methods like [`Simd::from_array`] and [`Simd::from_slice`]. /// diff --git a/crates/core_simd/tests/layout.rs b/crates/core_simd/tests/layout.rs index 24114c2d261e..3b4666249b0d 100644 --- a/crates/core_simd/tests/layout.rs +++ b/crates/core_simd/tests/layout.rs @@ -7,8 +7,8 @@ macro_rules! layout_tests { test_helpers::test_lanes! { fn no_padding() { assert_eq!( - core::mem::size_of::>(), - core::mem::size_of::<[$ty; LANES]>(), + size_of::>(), + size_of::<[$ty; LANES]>(), ); } } diff --git a/crates/core_simd/tests/pointers.rs b/crates/core_simd/tests/pointers.rs index d7db4e82b3ca..6e74c2d18b1e 100644 --- a/crates/core_simd/tests/pointers.rs +++ b/crates/core_simd/tests/pointers.rs @@ -1,8 +1,8 @@ #![feature(portable_simd)] use core_simd::simd::{ - ptr::{SimdConstPtr, SimdMutPtr}, Simd, + ptr::{SimdConstPtr, SimdMutPtr}, }; macro_rules! common_tests { diff --git a/crates/core_simd/tests/round.rs b/crates/core_simd/tests/round.rs index 847766ec41ed..4c1ac3c36f89 100644 --- a/crates/core_simd/tests/round.rs +++ b/crates/core_simd/tests/round.rs @@ -58,7 +58,7 @@ macro_rules! float_rounding_test { // all of the mantissa digits set to 1, pushed up to the MSB. const ALL_MANTISSA_BITS: IntScalar = ((1 << ::MANTISSA_DIGITS) - 1); const MAX_REPRESENTABLE_VALUE: Scalar = - (ALL_MANTISSA_BITS << (core::mem::size_of::() * 8 - ::MANTISSA_DIGITS as usize - 1)) as Scalar; + (ALL_MANTISSA_BITS << (size_of::() * 8 - ::MANTISSA_DIGITS as usize - 1)) as Scalar; let mut runner = test_helpers::make_runner(); runner.run( diff --git a/crates/test_helpers/src/subnormals.rs b/crates/test_helpers/src/subnormals.rs index ec0f1fb24b93..b5f19ba47b81 100644 --- a/crates/test_helpers/src/subnormals.rs +++ b/crates/test_helpers/src/subnormals.rs @@ -12,7 +12,7 @@ macro_rules! impl_float { $( impl FlushSubnormals for $ty { fn flush(self) -> Self { - let is_f32 = core::mem::size_of::() == 4; + let is_f32 = size_of::() == 4; let ppc_flush = is_f32 && cfg!(all( any(target_arch = "powerpc", all(target_arch = "powerpc64", target_endian = "big")), target_feature = "altivec", From cdac23c86a06003d37ad102edbdc74c8d3d9f933 Mon Sep 17 00:00:00 2001 From: Cornelius Roemer Date: Mon, 7 Apr 2025 18:13:32 +0200 Subject: [PATCH 004/978] Fix grammar in beginners-guide.md --- beginners-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beginners-guide.md b/beginners-guide.md index dc08d847ced5..4250a18315a6 100644 --- a/beginners-guide.md +++ b/beginners-guide.md @@ -25,7 +25,7 @@ SIMD has a few special vocabulary terms you should know: * **Scalar:** "Scalar" in mathematical contexts refers to values that can be represented as a single element, mostly numbers like 6, 3.14, or -2. It can also be used to describe "scalar operations" that use strictly scalar values, like addition. This term is mostly used to differentiate between vectorized operations that use SIMD instructions and scalar operations that don't. -* **Lane:** A single element position within a vector is called a lane. If you have `N` lanes available then they're numbered from `0` to `N-1` when referring to them, again like an array. The biggest difference between an array element and a vector lane is that in general is *relatively costly* to access an individual lane value. On most architectures, the vector has to be pushed out of the SIMD register onto the stack, then an individual lane is accessed while it's on the stack (and possibly the stack value is read back into a register). For this reason, when working with SIMD you should avoid reading or writing the value of an individual lane during hot loops. +* **Lane:** A single element position within a vector is called a lane. If you have `N` lanes available then they're numbered from `0` to `N-1` when referring to them, again like an array. The biggest difference between an array element and a vector lane is that in general it is *relatively costly* to access an individual lane value. On most architectures, the vector has to be pushed out of the SIMD register onto the stack, then an individual lane is accessed while it's on the stack (and possibly the stack value is read back into a register). For this reason, when working with SIMD you should avoid reading or writing the value of an individual lane during hot loops. * **Bit Widths:** When talking about SIMD, the bit widths used are the bit size of the vectors involved, *not* the individual elements. So "128-bit SIMD" has 128-bit vectors, and that might be `f32x4`, `i32x4`, `i16x8`, or other variations. While 128-bit SIMD is the most common, there's also 64-bit, 256-bit, and even 512-bit on the newest CPUs. From 6951b685b8d8bd42b88765432e125959cb5fbdd8 Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Wed, 11 Jun 2025 17:45:38 -0400 Subject: [PATCH 005/978] Remove usize/isize `From` impls for vendor vector types Remove usize/isize impls from - `loongarch64.rs` - `wasm32.rs` - `x86.rs` --- crates/core_simd/src/vendor/loongarch64.rs | 5 ----- crates/core_simd/src/vendor/wasm32.rs | 14 -------------- crates/core_simd/src/vendor/x86.rs | 22 ---------------------- 3 files changed, 41 deletions(-) diff --git a/crates/core_simd/src/vendor/loongarch64.rs b/crates/core_simd/src/vendor/loongarch64.rs index 1290bc166b2b..13dda4769aba 100644 --- a/crates/core_simd/src/vendor/loongarch64.rs +++ b/crates/core_simd/src/vendor/loongarch64.rs @@ -24,8 +24,3 @@ from_transmute! { unsafe i64x2 => v2i64 } from_transmute! { unsafe i64x4 => v4i64 } from_transmute! { unsafe f64x2 => v2f64 } from_transmute! { unsafe f64x4 => v4f64 } - -from_transmute! { unsafe usizex2 => v2u64 } -from_transmute! { unsafe usizex4 => v4u64 } -from_transmute! { unsafe isizex2 => v2i64 } -from_transmute! { unsafe isizex4 => v4i64 } diff --git a/crates/core_simd/src/vendor/wasm32.rs b/crates/core_simd/src/vendor/wasm32.rs index ef3baf885b0f..1fdb2bc86d34 100644 --- a/crates/core_simd/src/vendor/wasm32.rs +++ b/crates/core_simd/src/vendor/wasm32.rs @@ -14,17 +14,3 @@ from_transmute! { unsafe f32x4 => v128 } from_transmute! { unsafe u64x2 => v128 } from_transmute! { unsafe i64x2 => v128 } from_transmute! { unsafe f64x2 => v128 } - -#[cfg(target_pointer_width = "32")] -mod p32 { - use super::*; - from_transmute! { unsafe usizex4 => v128 } - from_transmute! { unsafe isizex4 => v128 } -} - -#[cfg(target_pointer_width = "64")] -mod p64 { - use super::*; - from_transmute! { unsafe usizex2 => v128 } - from_transmute! { unsafe isizex2 => v128 } -} diff --git a/crates/core_simd/src/vendor/x86.rs b/crates/core_simd/src/vendor/x86.rs index 66aaf90eef59..eae42e6fd0d0 100644 --- a/crates/core_simd/src/vendor/x86.rs +++ b/crates/core_simd/src/vendor/x86.rs @@ -39,25 +39,3 @@ from_transmute! { unsafe i64x8 => __m512i } from_transmute! { unsafe f64x2 => __m128d } from_transmute! { unsafe f64x4 => __m256d } from_transmute! { unsafe f64x8 => __m512d } - -#[cfg(target_pointer_width = "32")] -mod p32 { - use super::*; - from_transmute! { unsafe usizex4 => __m128i } - from_transmute! { unsafe usizex8 => __m256i } - from_transmute! { unsafe Simd => __m512i } - from_transmute! { unsafe isizex4 => __m128i } - from_transmute! { unsafe isizex8 => __m256i } - from_transmute! { unsafe Simd => __m512i } -} - -#[cfg(target_pointer_width = "64")] -mod p64 { - use super::*; - from_transmute! { unsafe usizex2 => __m128i } - from_transmute! { unsafe usizex4 => __m256i } - from_transmute! { unsafe usizex8 => __m512i } - from_transmute! { unsafe isizex2 => __m128i } - from_transmute! { unsafe isizex4 => __m256i } - from_transmute! { unsafe isizex8 => __m512i } -} From 97a3a5008470239510262f378350132da358edaf Mon Sep 17 00:00:00 2001 From: ltdk Date: Thu, 12 Jun 2025 12:03:40 -0400 Subject: [PATCH 006/978] Add const to as_mut_array, copy_to_slice --- crates/core_simd/src/vector.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs index d76a6cd52bfc..984a356c6552 100644 --- a/crates/core_simd/src/vector.rs +++ b/crates/core_simd/src/vector.rs @@ -195,7 +195,7 @@ where /// Returns a mutable array reference containing the entire SIMD vector. #[inline] - pub fn as_mut_array(&mut self) -> &mut [T; N] { + pub const fn as_mut_array(&mut self) -> &mut [T; N] { // SAFETY: `Simd` is just an overaligned `[T; N]` with // potential padding at the end, so pointer casting to a // `&mut [T; N]` is safe. @@ -324,7 +324,7 @@ where /// ``` #[inline] #[track_caller] - pub fn copy_to_slice(self, slice: &mut [T]) { + pub const fn copy_to_slice(self, slice: &mut [T]) { assert!( slice.len() >= Self::LEN, "slice length must be at least the number of elements" From a85790961605af9967fe5b76c45671c37c17f56b Mon Sep 17 00:00:00 2001 From: ltdk Date: Fri, 13 Jun 2025 00:38:09 -0400 Subject: [PATCH 007/978] Make Mask::splat const --- crates/core_simd/src/lane_count.rs | 15 ++++++++++++++- crates/core_simd/src/masks.rs | 3 ++- crates/core_simd/src/masks/bitmask.rs | 23 +++++++++++------------ crates/core_simd/src/masks/full_masks.rs | 3 ++- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/crates/core_simd/src/lane_count.rs b/crates/core_simd/src/lane_count.rs index 280b27bc9bc6..c62b9d3b7d9b 100644 --- a/crates/core_simd/src/lane_count.rs +++ b/crates/core_simd/src/lane_count.rs @@ -18,7 +18,11 @@ impl LaneCount { /// Only SIMD vectors with supported lane counts are constructable. pub trait SupportedLaneCount: Sealed { #[doc(hidden)] - type BitMask: Copy + Default + AsRef<[u8]> + AsMut<[u8]>; + type BitMask: Copy + AsRef<[u8]> + AsMut<[u8]>; + #[doc(hidden)] + const EMPTY_BIT_MASK: Self::BitMask; + #[doc(hidden)] + const FULL_BIT_MASK: Self::BitMask; } impl Sealed for LaneCount {} @@ -28,6 +32,15 @@ macro_rules! supported_lane_count { $( impl SupportedLaneCount for LaneCount<$lanes> { type BitMask = [u8; ($lanes + 7) / 8]; + const EMPTY_BIT_MASK: Self::BitMask = [0; ($lanes + 7) / 8]; + const FULL_BIT_MASK: Self::BitMask = { + const LEN: usize = ($lanes + 7) / 8; + let mut array = [!0u8; LEN]; + if $lanes % 8 > 0 { + array[LEN - 1] = (!0) >> (8 - $lanes % 8); + } + array + }; } )+ }; diff --git a/crates/core_simd/src/masks.rs b/crates/core_simd/src/masks.rs index 19d45f4d3b31..2b6be3676279 100644 --- a/crates/core_simd/src/masks.rs +++ b/crates/core_simd/src/masks.rs @@ -139,7 +139,8 @@ where { /// Constructs a mask by setting all elements to the given value. #[inline] - pub fn splat(value: bool) -> Self { + #[rustc_const_unstable(feature = "portable_simd", issue = "86656")] + pub const fn splat(value: bool) -> Self { Self(mask_impl::Mask::splat(value)) } diff --git a/crates/core_simd/src/masks/bitmask.rs b/crates/core_simd/src/masks/bitmask.rs index 8221d8f17e90..ef03ec7f7159 100644 --- a/crates/core_simd/src/masks/bitmask.rs +++ b/crates/core_simd/src/masks/bitmask.rs @@ -78,17 +78,16 @@ where { #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub(crate) fn splat(value: bool) -> Self { - let mut mask = as SupportedLaneCount>::BitMask::default(); - if value { - mask.as_mut().fill(u8::MAX) - } else { - mask.as_mut().fill(u8::MIN) - } - if N % 8 > 0 { - *mask.as_mut().last_mut().unwrap() &= u8::MAX >> (8 - N % 8); - } - Self(mask, PhantomData) + #[rustc_const_unstable(feature = "portable_simd", issue = "86656")] + pub(crate) const fn splat(value: bool) -> Self { + Self( + if value { + as SupportedLaneCount>::FULL_BIT_MASK + } else { + as SupportedLaneCount>::EMPTY_BIT_MASK + }, + PhantomData, + ) } #[inline] @@ -131,7 +130,7 @@ where #[inline] pub(crate) fn from_bitmask_integer(bitmask: u64) -> Self { - let mut bytes = as SupportedLaneCount>::BitMask::default(); + let mut bytes = as SupportedLaneCount>::BitMask::EMPTY_BIT_MASK; let len = bytes.as_mut().len(); bytes .as_mut() diff --git a/crates/core_simd/src/masks/full_masks.rs b/crates/core_simd/src/masks/full_masks.rs index 4e98db4070a9..ddd7fb69b189 100644 --- a/crates/core_simd/src/masks/full_masks.rs +++ b/crates/core_simd/src/masks/full_masks.rs @@ -102,7 +102,8 @@ where { #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub(crate) fn splat(value: bool) -> Self { + #[rustc_const_unstable(feature = "portable_simd", issue = "86656")] + pub(crate) const fn splat(value: bool) -> Self { Self(Simd::splat(if value { T::TRUE } else { T::FALSE })) } From b47a091b7df34d0a95913974419076c67a91643d Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Fri, 4 Jul 2025 14:22:09 +0000 Subject: [PATCH 008/978] clippy fix: use div_ceil --- crates/core_simd/src/lane_count.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/core_simd/src/lane_count.rs b/crates/core_simd/src/lane_count.rs index c62b9d3b7d9b..839195c38eda 100644 --- a/crates/core_simd/src/lane_count.rs +++ b/crates/core_simd/src/lane_count.rs @@ -8,7 +8,7 @@ pub struct LaneCount; impl LaneCount { /// The number of bytes in a bitmask with this many lanes. - pub const BITMASK_LEN: usize = (N + 7) / 8; + pub const BITMASK_LEN: usize = N.div_ceil(8); } /// Statically guarantees that a lane count is marked as supported. @@ -31,13 +31,12 @@ macro_rules! supported_lane_count { ($($lanes:literal),+) => { $( impl SupportedLaneCount for LaneCount<$lanes> { - type BitMask = [u8; ($lanes + 7) / 8]; - const EMPTY_BIT_MASK: Self::BitMask = [0; ($lanes + 7) / 8]; + type BitMask = [u8; Self::BITMASK_LEN]; + const EMPTY_BIT_MASK: Self::BitMask = [0; Self::BITMASK_LEN]; const FULL_BIT_MASK: Self::BitMask = { - const LEN: usize = ($lanes + 7) / 8; - let mut array = [!0u8; LEN]; + let mut array = [!0u8; Self::BITMASK_LEN]; if $lanes % 8 > 0 { - array[LEN - 1] = (!0) >> (8 - $lanes % 8); + array[Self::BITMASK_LEN - 1] = (!0) >> (8 - $lanes % 8); } array }; From 5a26848a5aa9fbaf75eed785acb40fc0010a38ba Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 5 Jul 2025 08:36:27 +0200 Subject: [PATCH 009/978] use `div_ceil` instead of manual logic --- crates/core_simd/src/lane_count.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/core_simd/src/lane_count.rs b/crates/core_simd/src/lane_count.rs index 280b27bc9bc6..bbdfd5f5f3ed 100644 --- a/crates/core_simd/src/lane_count.rs +++ b/crates/core_simd/src/lane_count.rs @@ -8,7 +8,7 @@ pub struct LaneCount; impl LaneCount { /// The number of bytes in a bitmask with this many lanes. - pub const BITMASK_LEN: usize = (N + 7) / 8; + pub const BITMASK_LEN: usize = N.div_ceil(8); } /// Statically guarantees that a lane count is marked as supported. From 3a0909c7677e0903145fb84a66683d5989eb7b69 Mon Sep 17 00:00:00 2001 From: burgerindividual Date: Mon, 4 Aug 2025 11:29:22 -0400 Subject: [PATCH 010/978] Fix incorrect reference to EMPTY_BIT_MASK --- crates/core_simd/src/masks/bitmask.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/core_simd/src/masks/bitmask.rs b/crates/core_simd/src/masks/bitmask.rs index ef03ec7f7159..780162c5b4bb 100644 --- a/crates/core_simd/src/masks/bitmask.rs +++ b/crates/core_simd/src/masks/bitmask.rs @@ -130,7 +130,7 @@ where #[inline] pub(crate) fn from_bitmask_integer(bitmask: u64) -> Self { - let mut bytes = as SupportedLaneCount>::BitMask::EMPTY_BIT_MASK; + let mut bytes = as SupportedLaneCount>::EMPTY_BIT_MASK; let len = bytes.as_mut().len(); bytes .as_mut() From b8955c5656e0805847549ac6043d6ae89f7fc0cc Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 8 Jul 2025 14:09:34 -0500 Subject: [PATCH 011/978] core: add Option::get_or_try_insert_with Co-authored-by: kennytm --- library/core/src/option.rs | 45 +++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index ed070fbd2274..da753f36b16a 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -578,7 +578,7 @@ use crate::iter::{self, FusedIterator, TrustedLen}; use crate::marker::Destruct; -use crate::ops::{self, ControlFlow, Deref, DerefMut}; +use crate::ops::{self, ControlFlow, Deref, DerefMut, Residual, Try}; use crate::panicking::{panic, panic_display}; use crate::pin::Pin; use crate::{cmp, convert, hint, mem, slice}; @@ -1807,6 +1807,49 @@ impl Option { unsafe { self.as_mut().unwrap_unchecked() } } + /// If the option is `None`, calls the closure and inserts its output if successful. + /// + /// If the closure returns a residual value such as `Err` or `None`, + /// that residual value is returned and nothing is inserted. + /// + /// If the option is `Some`, nothing is inserted. + /// + /// Unless a residual is returned, a mutable reference to the value + /// of the option will be output. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_get_or_try_insert_with)] + /// let mut o1: Option = None; + /// let mut o2: Option = None; + /// + /// let number = "12345"; + /// + /// assert_eq!(o1.get_or_try_insert_with(|| number.parse()).copied(), Ok(12345)); + /// assert!(o2.get_or_try_insert_with(|| number.parse()).is_err()); + /// assert_eq!(o1, Some(12345)); + /// assert_eq!(o2, None); + /// ``` + #[inline] + #[unstable(feature = "option_get_or_try_insert_with", issue = "143648")] + pub fn get_or_try_insert_with<'a, R, F>( + &'a mut self, + f: F, + ) -> >::TryType + where + F: FnOnce() -> R, + R: Try>, + { + if let None = self { + *self = Some(f()?); + } + // SAFETY: a `None` variant for `self` would have been replaced by a `Some` + // variant in the code above. + + Try::from_output(unsafe { self.as_mut().unwrap_unchecked() }) + } + ///////////////////////////////////////////////////////////////////////// // Misc ///////////////////////////////////////////////////////////////////////// From 3f01c753fd24607e20de083a407a5e9275f1ec78 Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Sun, 17 Aug 2025 20:36:53 -0400 Subject: [PATCH 012/978] Update nightly toolchain and fix broken examples Update examples to remove features that have been stabilized --- crates/core_simd/examples/dot_product.rs | 34 ++++++++++++------- crates/core_simd/examples/matrix_inversion.rs | 2 +- rust-toolchain.toml | 2 +- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/crates/core_simd/examples/dot_product.rs b/crates/core_simd/examples/dot_product.rs index 75d152ae7f0e..4ef32bfa60b5 100644 --- a/crates/core_simd/examples/dot_product.rs +++ b/crates/core_simd/examples/dot_product.rs @@ -1,8 +1,6 @@ //! Code taken from the `packed_simd` crate. //! Run this code with `cargo test --example dot_product`. -#![feature(array_chunks)] -#![feature(slice_as_chunks)] // Add these imports to use the stdsimd library #![feature(portable_simd)] use core_simd::simd::prelude::*; @@ -33,7 +31,7 @@ pub fn dot_prod_scalar_1(a: &[f32], b: &[f32]) -> f32 { } // We now move on to the SIMD implementations: notice the following constructs: -// `array_chunks::<4>`: mapping this over the vector will let use construct SIMD vectors +// `as_chunks::<4>`: mapping this over the vector will let us construct SIMD vectors // `f32x4::from_array`: construct the SIMD vector from a slice // `(a * b).reduce_sum()`: Multiply both f32x4 vectors together, and then reduce them. // This approach essentially uses SIMD to produce a vector of length N/4 of all the products, @@ -42,9 +40,11 @@ pub fn dot_prod_scalar_1(a: &[f32], b: &[f32]) -> f32 { pub fn dot_prod_simd_0(a: &[f32], b: &[f32]) -> f32 { assert_eq!(a.len(), b.len()); // TODO handle remainder when a.len() % 4 != 0 - a.array_chunks::<4>() + a.as_chunks::<4>() + .0 + .iter() .map(|&a| f32x4::from_array(a)) - .zip(b.array_chunks::<4>().map(|&b| f32x4::from_array(b))) + .zip(b.as_chunks::<4>().0.iter().map(|&b| f32x4::from_array(b))) .map(|(a, b)| (a * b).reduce_sum()) .sum() } @@ -60,9 +60,11 @@ pub fn dot_prod_simd_0(a: &[f32], b: &[f32]) -> f32 { pub fn dot_prod_simd_1(a: &[f32], b: &[f32]) -> f32 { assert_eq!(a.len(), b.len()); // TODO handle remainder when a.len() % 4 != 0 - a.array_chunks::<4>() + a.as_chunks::<4>() + .0 + .iter() .map(|&a| f32x4::from_array(a)) - .zip(b.array_chunks::<4>().map(|&b| f32x4::from_array(b))) + .zip(b.as_chunks::<4>().0.iter().map(|&b| f32x4::from_array(b))) .fold(f32x4::splat(0.0), |acc, zipped| acc + zipped.0 * zipped.1) .reduce_sum() } @@ -74,9 +76,11 @@ pub fn dot_prod_simd_2(a: &[f32], b: &[f32]) -> f32 { assert_eq!(a.len(), b.len()); // TODO handle remainder when a.len() % 4 != 0 let mut res = f32x4::splat(0.0); - a.array_chunks::<4>() + a.as_chunks::<4>() + .0 + .iter() .map(|&a| f32x4::from_array(a)) - .zip(b.array_chunks::<4>().map(|&b| f32x4::from_array(b))) + .zip(b.as_chunks::<4>().0.iter().map(|&b| f32x4::from_array(b))) .for_each(|(a, b)| { res = a.mul_add(b, res); }); @@ -113,9 +117,11 @@ pub fn dot_prod_simd_3(a: &[f32], b: &[f32]) -> f32 { // next example. pub fn dot_prod_simd_4(a: &[f32], b: &[f32]) -> f32 { let mut sum = a - .array_chunks::<4>() + .as_chunks::<4>() + .0 + .iter() .map(|&a| f32x4::from_array(a)) - .zip(b.array_chunks::<4>().map(|&b| f32x4::from_array(b))) + .zip(b.as_chunks::<4>().0.iter().map(|&b| f32x4::from_array(b))) .map(|(a, b)| a * b) .fold(f32x4::splat(0.0), std::ops::Add::add) .reduce_sum(); @@ -131,9 +137,11 @@ pub fn dot_prod_simd_4(a: &[f32], b: &[f32]) -> f32 { // This version allocates a single `XMM` register for accumulation, and the folds don't allocate on top of that. // Notice the use of `mul_add`, which can do a multiply and an add operation ber iteration. pub fn dot_prod_simd_5(a: &[f32], b: &[f32]) -> f32 { - a.array_chunks::<4>() + a.as_chunks::<4>() + .0 + .iter() .map(|&a| f32x4::from_array(a)) - .zip(b.array_chunks::<4>().map(|&b| f32x4::from_array(b))) + .zip(b.as_chunks::<4>().0.iter().map(|&b| f32x4::from_array(b))) .fold(f32x4::splat(0.), |acc, (a, b)| a.mul_add(b, acc)) .reduce_sum() } diff --git a/crates/core_simd/examples/matrix_inversion.rs b/crates/core_simd/examples/matrix_inversion.rs index bad86414401d..ad2eea9153e0 100644 --- a/crates/core_simd/examples/matrix_inversion.rs +++ b/crates/core_simd/examples/matrix_inversion.rs @@ -1,7 +1,7 @@ //! 4x4 matrix inverse // Code ported from the `packed_simd` crate // Run this code with `cargo test --example matrix_inversion` -#![feature(array_chunks, portable_simd)] +#![feature(portable_simd)] use core_simd::simd::prelude::*; // Gotta define our own 4x4 matrix since Rust doesn't ship multidim arrays yet :^) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index d17c6d2e8894..df4bd75ecfe2 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-01-16" +channel = "nightly-2025-08-17" components = ["rustfmt", "clippy", "miri", "rust-src"] From 28e79b143328822ac43d9d72f5f0fbf60479c0a5 Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Sun, 17 Aug 2025 21:42:22 -0400 Subject: [PATCH 013/978] Update Cargo.lock --- Cargo.lock | 267 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 206 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1584c704fb22..d7accf71ab69 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,12 +1,12 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "autocfg" -version = "1.1.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bitflags" @@ -16,31 +16,30 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "core_simd" @@ -55,45 +54,59 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "log" -version = "0.4.20" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "minicov" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" +dependencies = [ + "cc", + "walkdir", +] [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -114,9 +127,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -167,10 +180,25 @@ dependencies = [ ] [[package]] -name = "scoped-tls" -version = "1.0.1" +name = "rustversion" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "std_float" @@ -184,9 +212,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.29" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -202,29 +230,40 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -233,21 +272,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -255,9 +295,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -268,19 +308,21 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "wasm-bindgen-test" -version = "0.3.37" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e6e302a7ea94f83a6d09e78e7dc7d9ca7b186bc2829c24a22d0753efd680671" +checksum = "66c8d5e33ca3b6d9fa3b4676d774c5778031d27a578c2b007f905acf816152c3" dependencies = [ - "console_error_panic_hook", "js-sys", - "scoped-tls", + "minicov", "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-test-macro", @@ -288,20 +330,123 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.37" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecb993dd8c836930ed130e020e77d9b2e65dd0fbab1b67c790b0f5d80b11a575" +checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b" dependencies = [ "proc-macro2", "quote", + "syn", ] [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", ] + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] From 07e9de0f6d73d5c9ffc87dbdc496687fc2ad7200 Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Sun, 17 Aug 2025 21:46:26 -0400 Subject: [PATCH 014/978] Remove `i586-pc-windows-msvc` from CI --- .github/workflows/ci.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3984d8f0d8d9..96881687af05 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,7 +59,7 @@ jobs: strategy: fail-fast: false matrix: - target: [x86_64-pc-windows-msvc, i686-pc-windows-msvc, i586-pc-windows-msvc, x86_64-unknown-linux-gnu] + target: [x86_64-pc-windows-msvc, i686-pc-windows-msvc, x86_64-unknown-linux-gnu] # `default` means we use the default target config for the target, # `native` means we run with `-Ctarget-cpu=native`, and anything else is # an arg to `-Ctarget-feature` @@ -68,18 +68,12 @@ jobs: exclude: # -Ctarget-cpu=native sounds like bad-news if target != host - { target: i686-pc-windows-msvc, target_feature: native } - - { target: i586-pc-windows-msvc, target_feature: native } include: # Populate the `matrix.os` field - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest } - { target: x86_64-pc-windows-msvc, os: windows-latest } - { target: i686-pc-windows-msvc, os: windows-latest } - - { target: i586-pc-windows-msvc, os: windows-latest } - - # These are globally available on all the other targets. - - { target: i586-pc-windows-msvc, target_feature: +sse, os: windows-latest } - - { target: i586-pc-windows-msvc, target_feature: +sse2, os: windows-latest } # Annoyingly, the x86_64-unknown-linux-gnu runner *almost* always has # avx512vl, but occasionally doesn't. Maybe one day we can enable it. @@ -129,7 +123,7 @@ jobs: run: cargo doc --verbose --target=${{ matrix.target }} env: RUSTDOCFLAGS: -Dwarnings - + macos-tests: name: ${{ matrix.target }} runs-on: macos-latest From 323484c8278886ffe58e8d355107a5b59ffd85cd Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Mon, 18 Aug 2025 00:42:20 -0400 Subject: [PATCH 015/978] Add no-extra-rounding-error flag to Miri CI config --- .github/workflows/ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96881687af05..5344efe1db0e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -244,5 +244,10 @@ jobs: PROPTEST_CASES: 16 steps: - uses: actions/checkout@v4 + - name: Download and install nightly + run: | + rustup toolchain install nightly --component miri,rust-src + rustup override set nightly + cargo miri setup - name: Test (Miri) - run: cargo miri test + run: MIRIFLAGS="-Zmiri-no-extra-rounding-error" cargo miri test From c43c8d25a8c4f7035d4265e672f41848effbe615 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Mon, 18 Aug 2025 01:31:25 -0400 Subject: [PATCH 016/978] Check some float ops approximately --- Cargo.lock | 10 +++ crates/std_float/tests/float.rs | 29 +++++++- crates/test_helpers/Cargo.toml | 1 + crates/test_helpers/src/approxeq.rs | 110 ++++++++++++++++++++++++++++ crates/test_helpers/src/lib.rs | 76 +++++++++++++++++++ 5 files changed, 222 insertions(+), 4 deletions(-) create mode 100644 crates/test_helpers/src/approxeq.rs diff --git a/Cargo.lock b/Cargo.lock index d7accf71ab69..5a5f0d8907ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,6 +52,15 @@ dependencies = [ "wasm-bindgen-test", ] +[[package]] +name = "float-cmp" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" +dependencies = [ + "num-traits", +] + [[package]] name = "js-sys" version = "0.3.77" @@ -225,6 +234,7 @@ dependencies = [ name = "test_helpers" version = "0.1.0" dependencies = [ + "float-cmp", "proptest", ] diff --git a/crates/std_float/tests/float.rs b/crates/std_float/tests/float.rs index c66c968f8c66..c608ba49564e 100644 --- a/crates/std_float/tests/float.rs +++ b/crates/std_float/tests/float.rs @@ -16,15 +16,33 @@ macro_rules! unary_test { } } -macro_rules! binary_test { +macro_rules! unary_approx_test { { $scalar:tt, $($func:tt),+ } => { test_helpers::test_lanes! { $( fn $func() { - test_helpers::test_binary_elementwise( + test_helpers::test_unary_elementwise_approx( + &core_simd::simd::Simd::<$scalar, LANES>::$func, + &$scalar::$func, + &|_| true, + 8, + ) + } + )* + } + } +} + +macro_rules! binary_approx_test { + { $scalar:tt, $($func:tt),+ } => { + test_helpers::test_lanes! { + $( + fn $func() { + test_helpers::test_binary_elementwise_approx( &core_simd::simd::Simd::<$scalar, LANES>::$func, &$scalar::$func, &|_, _| true, + 16, ) } )* @@ -53,10 +71,13 @@ macro_rules! impl_tests { mod $scalar { use std_float::StdFloat; - unary_test! { $scalar, sqrt, sin, cos, exp, exp2, ln, log2, log10, ceil, floor, round, trunc } - binary_test! { $scalar, log } + unary_test! { $scalar, sqrt, ceil, floor, round, trunc } ternary_test! { $scalar, mul_add } + // https://github.com/rust-lang/miri/issues/3555 + unary_approx_test! { $scalar, sin, cos, exp, exp2, ln, log2, log10 } + binary_approx_test! { $scalar, log } + test_helpers::test_lanes! { fn fract() { test_helpers::test_unary_elementwise_flush_subnormals( diff --git a/crates/test_helpers/Cargo.toml b/crates/test_helpers/Cargo.toml index a5359b9abc84..408bb04c7aa4 100644 --- a/crates/test_helpers/Cargo.toml +++ b/crates/test_helpers/Cargo.toml @@ -6,3 +6,4 @@ publish = false [dependencies] proptest = { version = "0.10", default-features = false, features = ["alloc"] } +float-cmp = "0.10" diff --git a/crates/test_helpers/src/approxeq.rs b/crates/test_helpers/src/approxeq.rs new file mode 100644 index 000000000000..57b43a16bc6f --- /dev/null +++ b/crates/test_helpers/src/approxeq.rs @@ -0,0 +1,110 @@ +//! Compare numeric types approximately. + +use float_cmp::Ulps; + +pub trait ApproxEq { + fn approxeq(&self, other: &Self, _ulps: i64) -> bool; + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result; +} + +impl ApproxEq for bool { + fn approxeq(&self, other: &Self, _ulps: i64) -> bool { + self == other + } + + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{:?}", self) + } +} + +macro_rules! impl_integer_approxeq { + { $($type:ty),* } => { + $( + impl ApproxEq for $type { + fn approxeq(&self, other: &Self, _ulps: i64) -> bool { + self == other + } + + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{:?} ({:x})", self, self) + } + } + )* + }; +} + +impl_integer_approxeq! { u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize } + +macro_rules! impl_float_approxeq { + { $($type:ty),* } => { + $( + impl ApproxEq for $type { + fn approxeq(&self, other: &Self, ulps: i64) -> bool { + if self.is_nan() && other.is_nan() { + true + } else { + (self.ulps(other) as i64).abs() <= ulps + } + } + + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{:?} ({:x})", self, self.to_bits()) + } + } + )* + }; +} + +impl_float_approxeq! { f32, f64 } + +impl ApproxEq for [T; N] { + fn approxeq(&self, other: &Self, ulps: i64) -> bool { + self.iter() + .zip(other.iter()) + .fold(true, |value, (left, right)| { + value && left.approxeq(right, ulps) + }) + } + + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + #[repr(transparent)] + struct Wrapper<'a, T: ApproxEq>(&'a T); + + impl core::fmt::Debug for Wrapper<'_, T> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + self.0.fmt(f) + } + } + + f.debug_list() + .entries(self.iter().map(|x| Wrapper(x))) + .finish() + } +} + +#[doc(hidden)] +pub struct ApproxEqWrapper<'a, T>(pub &'a T, pub i64); + +impl PartialEq for ApproxEqWrapper<'_, T> { + fn eq(&self, other: &T) -> bool { + self.0.approxeq(other, self.1) + } +} + +impl core::fmt::Debug for ApproxEqWrapper<'_, T> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + self.0.fmt(f) + } +} + +#[macro_export] +macro_rules! prop_assert_approxeq { + { $a:expr, $b:expr, $ulps:expr $(,)? } => { + { + use $crate::approxeq::ApproxEqWrapper; + let a = $a; + let b = $b; + proptest::prop_assert_eq!(ApproxEqWrapper(&a, $ulps), b); + } + }; +} diff --git a/crates/test_helpers/src/lib.rs b/crates/test_helpers/src/lib.rs index 197c920e11ea..35401a9ddb40 100644 --- a/crates/test_helpers/src/lib.rs +++ b/crates/test_helpers/src/lib.rs @@ -12,6 +12,9 @@ pub mod wasm; #[macro_use] pub mod biteq; +#[macro_use] +pub mod approxeq; + pub mod subnormals; use subnormals::FlushSubnormals; @@ -185,6 +188,41 @@ pub fn test_unary_elementwise( + fv: &dyn Fn(Vector) -> VectorResult, + fs: &dyn Fn(Scalar) -> ScalarResult, + check: &dyn Fn([Scalar; LANES]) -> bool, + ulps: i64, +) where + Scalar: Copy + core::fmt::Debug + DefaultStrategy, + ScalarResult: Copy + approxeq::ApproxEq + core::fmt::Debug + DefaultStrategy, + Vector: Into<[Scalar; LANES]> + From<[Scalar; LANES]> + Copy, + VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy, +{ + test_1(&|x: [Scalar; LANES]| { + proptest::prop_assume!(check(x)); + let result_1: [ScalarResult; LANES] = fv(x.into()).into(); + let result_2: [ScalarResult; LANES] = x + .iter() + .copied() + .map(fs) + .collect::>() + .try_into() + .unwrap(); + crate::prop_assert_approxeq!(result_1, result_2, ulps); + Ok(()) + }); +} + /// Test a unary vector function against a unary scalar function, applied elementwise. /// /// Where subnormals are flushed, use approximate equality. @@ -290,6 +328,44 @@ pub fn test_binary_elementwise< }); } +/// Test a binary vector function against a binary scalar function, applied elementwise. +pub fn test_binary_elementwise_approx< + Scalar1, + Scalar2, + ScalarResult, + Vector1, + Vector2, + VectorResult, + const LANES: usize, +>( + fv: &dyn Fn(Vector1, Vector2) -> VectorResult, + fs: &dyn Fn(Scalar1, Scalar2) -> ScalarResult, + check: &dyn Fn([Scalar1; LANES], [Scalar2; LANES]) -> bool, + ulps: i64, +) where + Scalar1: Copy + core::fmt::Debug + DefaultStrategy, + Scalar2: Copy + core::fmt::Debug + DefaultStrategy, + ScalarResult: Copy + approxeq::ApproxEq + core::fmt::Debug + DefaultStrategy, + Vector1: Into<[Scalar1; LANES]> + From<[Scalar1; LANES]> + Copy, + Vector2: Into<[Scalar2; LANES]> + From<[Scalar2; LANES]> + Copy, + VectorResult: Into<[ScalarResult; LANES]> + From<[ScalarResult; LANES]> + Copy, +{ + test_2(&|x: [Scalar1; LANES], y: [Scalar2; LANES]| { + proptest::prop_assume!(check(x, y)); + let result_1: [ScalarResult; LANES] = fv(x.into(), y.into()).into(); + let result_2: [ScalarResult; LANES] = x + .iter() + .copied() + .zip(y.iter().copied()) + .map(|(x, y)| fs(x, y)) + .collect::>() + .try_into() + .unwrap(); + crate::prop_assert_approxeq!(result_1, result_2, ulps); + Ok(()) + }); +} + /// Test a binary vector function against a binary scalar function, applied elementwise. /// /// Where subnormals are flushed, use approximate equality. From b902397bc20e1d0fa5ffe2939b3b9082f2f5b658 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Mon, 18 Aug 2025 01:33:28 -0400 Subject: [PATCH 017/978] Clippy isn't aware of repr(simd, packed) --- crates/core_simd/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs index 717b882b64ba..9d7dfd2ab351 100644 --- a/crates/core_simd/src/lib.rs +++ b/crates/core_simd/src/lib.rs @@ -41,7 +41,7 @@ clippy::undocumented_unsafe_blocks )] #![doc(test(attr(deny(warnings))))] -#![allow(internal_features)] +#![allow(internal_features, clippy::repr_packed_without_abi)] #![unstable(feature = "portable_simd", issue = "86656")] //! Portable SIMD module. From 1ce33dd37dd87dc566e0f9ea5b2e15e17c458ee5 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Mon, 18 Aug 2025 01:34:11 -0400 Subject: [PATCH 018/978] Revert "Add no-extra-rounding-error flag to Miri CI config" This reverts commit 323484c8278886ffe58e8d355107a5b59ffd85cd. --- .github/workflows/ci.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5344efe1db0e..96881687af05 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -244,10 +244,5 @@ jobs: PROPTEST_CASES: 16 steps: - uses: actions/checkout@v4 - - name: Download and install nightly - run: | - rustup toolchain install nightly --component miri,rust-src - rustup override set nightly - cargo miri setup - name: Test (Miri) - run: MIRIFLAGS="-Zmiri-no-extra-rounding-error" cargo miri test + run: cargo miri test From 61c45c164a7a9ebf3107eb6d8735514ee3221053 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Fri, 8 Aug 2025 16:31:47 +0800 Subject: [PATCH 019/978] loongarch64: Use unified data types for SIMD intrinsics --- crates/core_simd/src/vendor/loongarch64.rs | 40 +++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/crates/core_simd/src/vendor/loongarch64.rs b/crates/core_simd/src/vendor/loongarch64.rs index 13dda4769aba..1f84cdb971ec 100644 --- a/crates/core_simd/src/vendor/loongarch64.rs +++ b/crates/core_simd/src/vendor/loongarch64.rs @@ -1,26 +1,26 @@ use crate::simd::*; use core::arch::loongarch64::*; -from_transmute! { unsafe u8x16 => v16u8 } -from_transmute! { unsafe u8x32 => v32u8 } -from_transmute! { unsafe i8x16 => v16i8 } -from_transmute! { unsafe i8x32 => v32i8 } +from_transmute! { unsafe u8x16 => m128i } +from_transmute! { unsafe u8x32 => m256i } +from_transmute! { unsafe i8x16 => m128i } +from_transmute! { unsafe i8x32 => m256i } -from_transmute! { unsafe u16x8 => v8u16 } -from_transmute! { unsafe u16x16 => v16u16 } -from_transmute! { unsafe i16x8 => v8i16 } -from_transmute! { unsafe i16x16 => v16i16 } +from_transmute! { unsafe u16x8 => m128i } +from_transmute! { unsafe u16x16 => m256i } +from_transmute! { unsafe i16x8 => m128i } +from_transmute! { unsafe i16x16 => m256i } -from_transmute! { unsafe u32x4 => v4u32 } -from_transmute! { unsafe u32x8 => v8u32 } -from_transmute! { unsafe i32x4 => v4i32 } -from_transmute! { unsafe i32x8 => v8i32 } -from_transmute! { unsafe f32x4 => v4f32 } -from_transmute! { unsafe f32x8 => v8f32 } +from_transmute! { unsafe u32x4 => m128i } +from_transmute! { unsafe u32x8 => m256i } +from_transmute! { unsafe i32x4 => m128i } +from_transmute! { unsafe i32x8 => m256i } +from_transmute! { unsafe f32x4 => m128 } +from_transmute! { unsafe f32x8 => m256 } -from_transmute! { unsafe u64x2 => v2u64 } -from_transmute! { unsafe u64x4 => v4u64 } -from_transmute! { unsafe i64x2 => v2i64 } -from_transmute! { unsafe i64x4 => v4i64 } -from_transmute! { unsafe f64x2 => v2f64 } -from_transmute! { unsafe f64x4 => v4f64 } +from_transmute! { unsafe u64x2 => m128i } +from_transmute! { unsafe u64x4 => m256i } +from_transmute! { unsafe i64x2 => m128i } +from_transmute! { unsafe i64x4 => m256i } +from_transmute! { unsafe f64x2 => m128d } +from_transmute! { unsafe f64x4 => m256d } From 402c045f7a8f2085dd6552e63d4b6ae26049e9f9 Mon Sep 17 00:00:00 2001 From: AudaciousAxiom <179637270+AudaciousAxiom@users.noreply.github.com> Date: Tue, 2 Sep 2025 21:34:04 +0200 Subject: [PATCH 020/978] docs(std): add missing closing code block fences in doc comments --- crates/core_simd/src/simd/num/int.rs | 1 + crates/core_simd/src/simd/num/uint.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/crates/core_simd/src/simd/num/int.rs b/crates/core_simd/src/simd/num/int.rs index d25050c3e4b4..e7253313f036 100644 --- a/crates/core_simd/src/simd/num/int.rs +++ b/crates/core_simd/src/simd/num/int.rs @@ -58,6 +58,7 @@ pub trait SimdInt: Copy + Sealed { /// let sat = x.saturating_sub(max); /// assert_eq!(unsat, Simd::from_array([1, MAX, MIN, 0])); /// assert_eq!(sat, Simd::from_array([MIN, MIN, MIN, 0])); + /// ``` fn saturating_sub(self, second: Self) -> Self; /// Lanewise absolute value, implemented in Rust. diff --git a/crates/core_simd/src/simd/num/uint.rs b/crates/core_simd/src/simd/num/uint.rs index 45d978068b66..e3ba8658bd80 100644 --- a/crates/core_simd/src/simd/num/uint.rs +++ b/crates/core_simd/src/simd/num/uint.rs @@ -55,6 +55,7 @@ pub trait SimdUint: Copy + Sealed { /// let sat = x.saturating_sub(max); /// assert_eq!(unsat, Simd::from_array([3, 2, 1, 0])); /// assert_eq!(sat, Simd::splat(0)); + /// ``` fn saturating_sub(self, second: Self) -> Self; /// Lanewise absolute difference. From 1e62d4c87cec532abf267cd5a7cb0342f8369ed1 Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Fri, 5 Sep 2025 14:29:26 -0400 Subject: [PATCH 021/978] Rename `Mask::to_int` to `Mask::to_simd` --- crates/core_simd/src/masks.rs | 8 ++++---- crates/core_simd/src/masks/bitmask.rs | 2 +- crates/core_simd/src/masks/full_masks.rs | 8 ++++---- crates/core_simd/src/select.rs | 2 +- crates/core_simd/src/simd/cmp/eq.rs | 4 ++-- crates/core_simd/src/simd/cmp/ord.rs | 8 ++++---- crates/core_simd/src/swizzle.rs | 22 +++++++++++----------- crates/core_simd/src/vector.rs | 8 ++++---- crates/core_simd/tests/masks.rs | 2 +- 9 files changed, 32 insertions(+), 32 deletions(-) diff --git a/crates/core_simd/src/masks.rs b/crates/core_simd/src/masks.rs index 2b6be3676279..b42cca7c977d 100644 --- a/crates/core_simd/src/masks.rs +++ b/crates/core_simd/src/masks.rs @@ -175,7 +175,7 @@ where // This would be hypothetically valid as an "in-place" transmute, // but these are "dependently-sized" types, so copy elision it is! unsafe { - let mut bytes: Simd = core::intrinsics::simd::simd_cast(self.to_int()); + let mut bytes: Simd = core::intrinsics::simd::simd_cast(self.to_simd()); bytes &= Simd::splat(1i8); mem::transmute_copy(&bytes) } @@ -214,8 +214,8 @@ where /// represents `true`. #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - pub fn to_int(self) -> Simd { - self.0.to_int() + pub fn to_simd(self) -> Simd { + self.0.to_simd() } /// Converts the mask to a mask of any other element size. @@ -352,7 +352,7 @@ where // Safety: the input and output are integer vectors let index: Simd = unsafe { core::intrinsics::simd::simd_cast(index) }; - let masked_index = self.select(index, Self::splat(true).to_int()); + let masked_index = self.select(index, Self::splat(true).to_simd()); // Safety: the input and output are integer vectors let masked_index: Simd = diff --git a/crates/core_simd/src/masks/bitmask.rs b/crates/core_simd/src/masks/bitmask.rs index 780162c5b4bb..4211789da708 100644 --- a/crates/core_simd/src/masks/bitmask.rs +++ b/crates/core_simd/src/masks/bitmask.rs @@ -105,7 +105,7 @@ where #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - pub(crate) fn to_int(self) -> Simd { + pub(crate) fn to_simd(self) -> Simd { unsafe { core::intrinsics::simd::simd_select_bitmask( self.0, diff --git a/crates/core_simd/src/masks/full_masks.rs b/crates/core_simd/src/masks/full_masks.rs index ddd7fb69b189..a5382f0ff739 100644 --- a/crates/core_simd/src/masks/full_masks.rs +++ b/crates/core_simd/src/masks/full_masks.rs @@ -120,7 +120,7 @@ where #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - pub(crate) fn to_int(self) -> Simd { + pub(crate) fn to_simd(self) -> Simd { self.0 } @@ -145,7 +145,7 @@ where where LaneCount: SupportedLaneCount, { - let resized = self.to_int().resize::(T::FALSE); + let resized = self.to_simd().resize::(T::FALSE); // Safety: `resized` is an integer vector with length M, which must match T let bitmask: U = unsafe { core::intrinsics::simd::simd_bitmask(resized) }; @@ -223,14 +223,14 @@ where #[must_use = "method returns a new bool and does not mutate the original value"] pub(crate) fn any(self) -> bool { // Safety: use `self` as an integer vector - unsafe { core::intrinsics::simd::simd_reduce_any(self.to_int()) } + unsafe { core::intrinsics::simd::simd_reduce_any(self.to_simd()) } } #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] pub(crate) fn all(self) -> bool { // Safety: use `self` as an integer vector - unsafe { core::intrinsics::simd::simd_reduce_all(self.to_int()) } + unsafe { core::intrinsics::simd::simd_reduce_all(self.to_simd()) } } } diff --git a/crates/core_simd/src/select.rs b/crates/core_simd/src/select.rs index f33aa261a928..a2db455a5268 100644 --- a/crates/core_simd/src/select.rs +++ b/crates/core_simd/src/select.rs @@ -28,7 +28,7 @@ where { // Safety: The mask has been cast to a vector of integers, // and the operands to select between are vectors of the same type and length. - unsafe { core::intrinsics::simd::simd_select(self.to_int(), true_values, false_values) } + unsafe { core::intrinsics::simd::simd_select(self.to_simd(), true_values, false_values) } } /// Choose elements from two masks. diff --git a/crates/core_simd/src/simd/cmp/eq.rs b/crates/core_simd/src/simd/cmp/eq.rs index 2312ba401fa7..3c483f3f94a3 100644 --- a/crates/core_simd/src/simd/cmp/eq.rs +++ b/crates/core_simd/src/simd/cmp/eq.rs @@ -59,14 +59,14 @@ macro_rules! impl_mask { fn simd_eq(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_eq(self.to_int(), other.to_int())) } + unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_eq(self.to_simd(), other.to_simd())) } } #[inline] fn simd_ne(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_ne(self.to_int(), other.to_int())) } + unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_ne(self.to_simd(), other.to_simd())) } } } )* diff --git a/crates/core_simd/src/simd/cmp/ord.rs b/crates/core_simd/src/simd/cmp/ord.rs index e813e7613032..6eb3e360bdeb 100644 --- a/crates/core_simd/src/simd/cmp/ord.rs +++ b/crates/core_simd/src/simd/cmp/ord.rs @@ -163,28 +163,28 @@ macro_rules! impl_mask { fn simd_lt(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_lt(self.to_int(), other.to_int())) } + unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_lt(self.to_simd(), other.to_simd())) } } #[inline] fn simd_le(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_le(self.to_int(), other.to_int())) } + unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_le(self.to_simd(), other.to_simd())) } } #[inline] fn simd_gt(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_gt(self.to_int(), other.to_int())) } + unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_gt(self.to_simd(), other.to_simd())) } } #[inline] fn simd_ge(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_ge(self.to_int(), other.to_int())) } + unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_ge(self.to_simd(), other.to_simd())) } } } diff --git a/crates/core_simd/src/swizzle.rs b/crates/core_simd/src/swizzle.rs index dbdd6ef40eba..b6af2ded1cce 100644 --- a/crates/core_simd/src/swizzle.rs +++ b/crates/core_simd/src/swizzle.rs @@ -165,7 +165,7 @@ pub trait Swizzle { LaneCount: SupportedLaneCount, { // SAFETY: all elements of this mask come from another mask - unsafe { Mask::from_int_unchecked(Self::swizzle(mask.to_int())) } + unsafe { Mask::from_int_unchecked(Self::swizzle(mask.to_simd())) } } /// Creates a new mask from the elements of `first` and `second`. @@ -181,7 +181,7 @@ pub trait Swizzle { LaneCount: SupportedLaneCount, { // SAFETY: all elements of this mask come from another mask - unsafe { Mask::from_int_unchecked(Self::concat_swizzle(first.to_int(), second.to_int())) } + unsafe { Mask::from_int_unchecked(Self::concat_swizzle(first.to_simd(), second.to_simd())) } } } @@ -524,7 +524,7 @@ where #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn reverse(self) -> Self { // Safety: swizzles are safe for masks - unsafe { Self::from_int_unchecked(self.to_int().reverse()) } + unsafe { Self::from_int_unchecked(self.to_simd().reverse()) } } /// Rotates the mask such that the first `OFFSET` elements of the slice move to the end @@ -534,7 +534,7 @@ where #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn rotate_elements_left(self) -> Self { // Safety: swizzles are safe for masks - unsafe { Self::from_int_unchecked(self.to_int().rotate_elements_left::()) } + unsafe { Self::from_int_unchecked(self.to_simd().rotate_elements_left::()) } } /// Rotates the mask such that the first `self.len() - OFFSET` elements of the mask move to @@ -544,7 +544,7 @@ where #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn rotate_elements_right(self) -> Self { // Safety: swizzles are safe for masks - unsafe { Self::from_int_unchecked(self.to_int().rotate_elements_right::()) } + unsafe { Self::from_int_unchecked(self.to_simd().rotate_elements_right::()) } } /// Shifts the mask elements to the left by `OFFSET`, filling in with @@ -554,7 +554,7 @@ where pub fn shift_elements_left(self, padding: bool) -> Self { // Safety: swizzles are safe for masks unsafe { - Self::from_int_unchecked(self.to_int().shift_elements_left::(if padding { + Self::from_int_unchecked(self.to_simd().shift_elements_left::(if padding { T::TRUE } else { T::FALSE @@ -569,7 +569,7 @@ where pub fn shift_elements_right(self, padding: bool) -> Self { // Safety: swizzles are safe for masks unsafe { - Self::from_int_unchecked(self.to_int().shift_elements_right::(if padding { + Self::from_int_unchecked(self.to_simd().shift_elements_right::(if padding { T::TRUE } else { T::FALSE @@ -598,7 +598,7 @@ where #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn interleave(self, other: Self) -> (Self, Self) { - let (lo, hi) = self.to_int().interleave(other.to_int()); + let (lo, hi) = self.to_simd().interleave(other.to_simd()); // Safety: swizzles are safe for masks unsafe { (Self::from_int_unchecked(lo), Self::from_int_unchecked(hi)) } } @@ -627,7 +627,7 @@ where #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn deinterleave(self, other: Self) -> (Self, Self) { - let (even, odd) = self.to_int().deinterleave(other.to_int()); + let (even, odd) = self.to_simd().deinterleave(other.to_simd()); // Safety: swizzles are safe for masks unsafe { ( @@ -659,7 +659,7 @@ where { // Safety: swizzles are safe for masks unsafe { - Mask::::from_int_unchecked(self.to_int().resize::(if value { + Mask::::from_int_unchecked(self.to_simd().resize::(if value { T::TRUE } else { T::FALSE @@ -684,6 +684,6 @@ where LaneCount: SupportedLaneCount, { // Safety: swizzles are safe for masks - unsafe { Mask::::from_int_unchecked(self.to_int().extract::()) } + unsafe { Mask::::from_int_unchecked(self.to_simd().extract::()) } } } diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs index 984a356c6552..1f15c9f85c71 100644 --- a/crates/core_simd/src/vector.rs +++ b/crates/core_simd/src/vector.rs @@ -474,7 +474,7 @@ where or: Self, ) -> Self { // SAFETY: The safety of reading elements through `ptr` is ensured by the caller. - unsafe { core::intrinsics::simd::simd_masked_load(enable.to_int(), ptr, or) } + unsafe { core::intrinsics::simd::simd_masked_load(enable.to_simd(), ptr, or) } } /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector. @@ -652,7 +652,7 @@ where or: Self, ) -> Self { // Safety: The caller is responsible for upholding all invariants - unsafe { core::intrinsics::simd::simd_gather(or, source, enable.to_int()) } + unsafe { core::intrinsics::simd::simd_gather(or, source, enable.to_simd()) } } /// Conditionally write contiguous elements to `slice`. The `enable` mask controls @@ -723,7 +723,7 @@ where #[inline] pub unsafe fn store_select_ptr(self, ptr: *mut T, enable: Mask<::Mask, N>) { // SAFETY: The safety of writing elements through `ptr` is ensured by the caller. - unsafe { core::intrinsics::simd::simd_masked_store(enable.to_int(), ptr, self) } + unsafe { core::intrinsics::simd::simd_masked_store(enable.to_simd(), ptr, self) } } /// Writes the values in a SIMD vector to potentially discontiguous indices in `slice`. @@ -882,7 +882,7 @@ where #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn scatter_select_ptr(self, dest: Simd<*mut T, N>, enable: Mask) { // Safety: The caller is responsible for upholding all invariants - unsafe { core::intrinsics::simd::simd_scatter(self, dest, enable.to_int()) } + unsafe { core::intrinsics::simd::simd_scatter(self, dest, enable.to_simd()) } } } diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs index 48786d02440b..be7c5a27e86f 100644 --- a/crates/core_simd/tests/masks.rs +++ b/crates/core_simd/tests/masks.rs @@ -65,7 +65,7 @@ macro_rules! test_mask_api { fn roundtrip_int_conversion() { let values = [true, false, false, true, false, false, true, false]; let mask = Mask::<$type, 8>::from_array(values); - let int = mask.to_int(); + let int = mask.to_simd(); assert_eq!(int.to_array(), [-1, 0, 0, -1, 0, 0, -1, 0]); assert_eq!(Mask::<$type, 8>::from_int(int), mask); } From 42409f05bf162f4fac8e7010892c08539ccfa034 Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Fri, 5 Sep 2025 14:30:44 -0400 Subject: [PATCH 022/978] Rename `Mask::from_int` to `Mask::from_simd` --- crates/core_simd/src/masks.rs | 2 +- crates/core_simd/tests/masks.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/core_simd/src/masks.rs b/crates/core_simd/src/masks.rs index b42cca7c977d..022003ef4dcc 100644 --- a/crates/core_simd/src/masks.rs +++ b/crates/core_simd/src/masks.rs @@ -204,7 +204,7 @@ where #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] #[track_caller] - pub fn from_int(value: Simd) -> Self { + pub fn from_simd(value: Simd) -> Self { assert!(T::valid(value), "all values must be either 0 or -1",); // Safety: the validity has been checked unsafe { Self::from_int_unchecked(value) } diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs index be7c5a27e86f..53fb2367b605 100644 --- a/crates/core_simd/tests/masks.rs +++ b/crates/core_simd/tests/masks.rs @@ -67,7 +67,7 @@ macro_rules! test_mask_api { let mask = Mask::<$type, 8>::from_array(values); let int = mask.to_simd(); assert_eq!(int.to_array(), [-1, 0, 0, -1, 0, 0, -1, 0]); - assert_eq!(Mask::<$type, 8>::from_int(int), mask); + assert_eq!(Mask::<$type, 8>::from_simd(int), mask); } #[test] From 3a70dd6a69e0eb4b7d72e812cf32204ba2e7669c Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Fri, 5 Sep 2025 14:32:40 -0400 Subject: [PATCH 023/978] Rename `Mask::from_int_unchecked` to `Mask::from_simd_unchecked` --- crates/core_simd/src/masks.rs | 8 ++++---- crates/core_simd/src/masks/bitmask.rs | 2 +- crates/core_simd/src/masks/full_masks.rs | 4 ++-- crates/core_simd/src/simd/cmp/eq.rs | 8 ++++---- crates/core_simd/src/simd/cmp/ord.rs | 24 +++++++++++----------- crates/core_simd/src/swizzle.rs | 26 +++++++++++++----------- crates/core_simd/src/vector.rs | 4 ++-- 7 files changed, 39 insertions(+), 37 deletions(-) diff --git a/crates/core_simd/src/masks.rs b/crates/core_simd/src/masks.rs index 022003ef4dcc..ca1e3db8b46f 100644 --- a/crates/core_simd/src/masks.rs +++ b/crates/core_simd/src/masks.rs @@ -157,7 +157,7 @@ where let bytes: [u8; N] = mem::transmute_copy(&array); let bools: Simd = core::intrinsics::simd::simd_ne(Simd::from_array(bytes), Simd::splat(0u8)); - Mask::from_int_unchecked(core::intrinsics::simd::simd_cast(bools)) + Mask::from_simd_unchecked(core::intrinsics::simd::simd_cast(bools)) } } @@ -188,11 +188,11 @@ where /// All elements must be either 0 or -1. #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub unsafe fn from_int_unchecked(value: Simd) -> Self { + pub unsafe fn from_simd_unchecked(value: Simd) -> Self { // Safety: the caller must confirm this invariant unsafe { core::intrinsics::assume(::valid(value)); - Self(mask_impl::Mask::from_int_unchecked(value)) + Self(mask_impl::Mask::from_simd_unchecked(value)) } } @@ -207,7 +207,7 @@ where pub fn from_simd(value: Simd) -> Self { assert!(T::valid(value), "all values must be either 0 or -1",); // Safety: the validity has been checked - unsafe { Self::from_int_unchecked(value) } + unsafe { Self::from_simd_unchecked(value) } } /// Converts the mask to a vector of integers, where 0 represents `false` and -1 diff --git a/crates/core_simd/src/masks/bitmask.rs b/crates/core_simd/src/masks/bitmask.rs index 4211789da708..83ee88c372ab 100644 --- a/crates/core_simd/src/masks/bitmask.rs +++ b/crates/core_simd/src/masks/bitmask.rs @@ -117,7 +117,7 @@ where #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub(crate) unsafe fn from_int_unchecked(value: Simd) -> Self { + pub(crate) unsafe fn from_simd_unchecked(value: Simd) -> Self { unsafe { Self(core::intrinsics::simd::simd_bitmask(value), PhantomData) } } diff --git a/crates/core_simd/src/masks/full_masks.rs b/crates/core_simd/src/masks/full_masks.rs index a5382f0ff739..5ad2c1d1eaf6 100644 --- a/crates/core_simd/src/masks/full_masks.rs +++ b/crates/core_simd/src/masks/full_masks.rs @@ -126,7 +126,7 @@ where #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub(crate) unsafe fn from_int_unchecked(value: Simd) -> Self { + pub(crate) unsafe fn from_simd_unchecked(value: Simd) -> Self { Self(value) } @@ -180,7 +180,7 @@ where }; // SAFETY: `mask` only contains `T::TRUE` or `T::FALSE` - unsafe { Self::from_int_unchecked(mask.resize::(T::FALSE)) } + unsafe { Self::from_simd_unchecked(mask.resize::(T::FALSE)) } } #[inline] diff --git a/crates/core_simd/src/simd/cmp/eq.rs b/crates/core_simd/src/simd/cmp/eq.rs index 3c483f3f94a3..789fc0bb9424 100644 --- a/crates/core_simd/src/simd/cmp/eq.rs +++ b/crates/core_simd/src/simd/cmp/eq.rs @@ -30,14 +30,14 @@ macro_rules! impl_number { fn simd_eq(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_eq(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_eq(self, other)) } } #[inline] fn simd_ne(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_ne(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_ne(self, other)) } } } )* @@ -59,14 +59,14 @@ macro_rules! impl_mask { fn simd_eq(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_eq(self.to_simd(), other.to_simd())) } + unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_eq(self.to_simd(), other.to_simd())) } } #[inline] fn simd_ne(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_ne(self.to_simd(), other.to_simd())) } + unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_ne(self.to_simd(), other.to_simd())) } } } )* diff --git a/crates/core_simd/src/simd/cmp/ord.rs b/crates/core_simd/src/simd/cmp/ord.rs index 6eb3e360bdeb..4b2d0b55feba 100644 --- a/crates/core_simd/src/simd/cmp/ord.rs +++ b/crates/core_simd/src/simd/cmp/ord.rs @@ -56,28 +56,28 @@ macro_rules! impl_integer { fn simd_lt(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_lt(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_lt(self, other)) } } #[inline] fn simd_le(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_le(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_le(self, other)) } } #[inline] fn simd_gt(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_gt(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_gt(self, other)) } } #[inline] fn simd_ge(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_ge(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_ge(self, other)) } } } @@ -122,28 +122,28 @@ macro_rules! impl_float { fn simd_lt(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_lt(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_lt(self, other)) } } #[inline] fn simd_le(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_le(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_le(self, other)) } } #[inline] fn simd_gt(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_gt(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_gt(self, other)) } } #[inline] fn simd_ge(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Mask::from_int_unchecked(core::intrinsics::simd::simd_ge(self, other)) } + unsafe { Mask::from_simd_unchecked(core::intrinsics::simd::simd_ge(self, other)) } } } )* @@ -163,28 +163,28 @@ macro_rules! impl_mask { fn simd_lt(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_lt(self.to_simd(), other.to_simd())) } + unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_lt(self.to_simd(), other.to_simd())) } } #[inline] fn simd_le(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_le(self.to_simd(), other.to_simd())) } + unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_le(self.to_simd(), other.to_simd())) } } #[inline] fn simd_gt(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_gt(self.to_simd(), other.to_simd())) } + unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_gt(self.to_simd(), other.to_simd())) } } #[inline] fn simd_ge(self, other: Self) -> Self::Mask { // Safety: `self` is a vector, and the result of the comparison // is always a valid mask. - unsafe { Self::from_int_unchecked(core::intrinsics::simd::simd_ge(self.to_simd(), other.to_simd())) } + unsafe { Self::from_simd_unchecked(core::intrinsics::simd::simd_ge(self.to_simd(), other.to_simd())) } } } diff --git a/crates/core_simd/src/swizzle.rs b/crates/core_simd/src/swizzle.rs index b6af2ded1cce..81085a9ee4a3 100644 --- a/crates/core_simd/src/swizzle.rs +++ b/crates/core_simd/src/swizzle.rs @@ -165,7 +165,7 @@ pub trait Swizzle { LaneCount: SupportedLaneCount, { // SAFETY: all elements of this mask come from another mask - unsafe { Mask::from_int_unchecked(Self::swizzle(mask.to_simd())) } + unsafe { Mask::from_simd_unchecked(Self::swizzle(mask.to_simd())) } } /// Creates a new mask from the elements of `first` and `second`. @@ -181,7 +181,9 @@ pub trait Swizzle { LaneCount: SupportedLaneCount, { // SAFETY: all elements of this mask come from another mask - unsafe { Mask::from_int_unchecked(Self::concat_swizzle(first.to_simd(), second.to_simd())) } + unsafe { + Mask::from_simd_unchecked(Self::concat_swizzle(first.to_simd(), second.to_simd())) + } } } @@ -524,7 +526,7 @@ where #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn reverse(self) -> Self { // Safety: swizzles are safe for masks - unsafe { Self::from_int_unchecked(self.to_simd().reverse()) } + unsafe { Self::from_simd_unchecked(self.to_simd().reverse()) } } /// Rotates the mask such that the first `OFFSET` elements of the slice move to the end @@ -534,7 +536,7 @@ where #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn rotate_elements_left(self) -> Self { // Safety: swizzles are safe for masks - unsafe { Self::from_int_unchecked(self.to_simd().rotate_elements_left::()) } + unsafe { Self::from_simd_unchecked(self.to_simd().rotate_elements_left::()) } } /// Rotates the mask such that the first `self.len() - OFFSET` elements of the mask move to @@ -544,7 +546,7 @@ where #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn rotate_elements_right(self) -> Self { // Safety: swizzles are safe for masks - unsafe { Self::from_int_unchecked(self.to_simd().rotate_elements_right::()) } + unsafe { Self::from_simd_unchecked(self.to_simd().rotate_elements_right::()) } } /// Shifts the mask elements to the left by `OFFSET`, filling in with @@ -554,7 +556,7 @@ where pub fn shift_elements_left(self, padding: bool) -> Self { // Safety: swizzles are safe for masks unsafe { - Self::from_int_unchecked(self.to_simd().shift_elements_left::(if padding { + Self::from_simd_unchecked(self.to_simd().shift_elements_left::(if padding { T::TRUE } else { T::FALSE @@ -569,7 +571,7 @@ where pub fn shift_elements_right(self, padding: bool) -> Self { // Safety: swizzles are safe for masks unsafe { - Self::from_int_unchecked(self.to_simd().shift_elements_right::(if padding { + Self::from_simd_unchecked(self.to_simd().shift_elements_right::(if padding { T::TRUE } else { T::FALSE @@ -600,7 +602,7 @@ where pub fn interleave(self, other: Self) -> (Self, Self) { let (lo, hi) = self.to_simd().interleave(other.to_simd()); // Safety: swizzles are safe for masks - unsafe { (Self::from_int_unchecked(lo), Self::from_int_unchecked(hi)) } + unsafe { (Self::from_simd_unchecked(lo), Self::from_simd_unchecked(hi)) } } /// Deinterleave two masks. @@ -631,8 +633,8 @@ where // Safety: swizzles are safe for masks unsafe { ( - Self::from_int_unchecked(even), - Self::from_int_unchecked(odd), + Self::from_simd_unchecked(even), + Self::from_simd_unchecked(odd), ) } } @@ -659,7 +661,7 @@ where { // Safety: swizzles are safe for masks unsafe { - Mask::::from_int_unchecked(self.to_simd().resize::(if value { + Mask::::from_simd_unchecked(self.to_simd().resize::(if value { T::TRUE } else { T::FALSE @@ -684,6 +686,6 @@ where LaneCount: SupportedLaneCount, { // Safety: swizzles are safe for masks - unsafe { Mask::::from_int_unchecked(self.to_simd().extract::()) } + unsafe { Mask::::from_simd_unchecked(self.to_simd().extract::()) } } } diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs index 1f15c9f85c71..c00cfcdd41ff 100644 --- a/crates/core_simd/src/vector.rs +++ b/crates/core_simd/src/vector.rs @@ -926,7 +926,7 @@ where let mask = unsafe { let tfvec: Simd<::Mask, N> = core::intrinsics::simd::simd_eq(*self, *other); - Mask::from_int_unchecked(tfvec) + Mask::from_simd_unchecked(tfvec) }; // Two vectors are equal if all elements are equal when compared elementwise @@ -940,7 +940,7 @@ where let mask = unsafe { let tfvec: Simd<::Mask, N> = core::intrinsics::simd::simd_ne(*self, *other); - Mask::from_int_unchecked(tfvec) + Mask::from_simd_unchecked(tfvec) }; // Two vectors are non-equal if any elements are non-equal when compared elementwise From 32ba8edf03c233640569c1f9a0bf4529c3a6608c Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Fri, 12 Sep 2025 22:03:51 -0400 Subject: [PATCH 024/978] Remove poor-performing bitmasks, add Select trait, and enable select on integer bitmasks (#482) --- crates/core_simd/src/masks.rs | 123 +++++++--- crates/core_simd/src/masks/bitmask.rs | 231 ------------------ crates/core_simd/src/masks/full_masks.rs | 297 ----------------------- crates/core_simd/src/mod.rs | 1 + crates/core_simd/src/ops.rs | 2 +- crates/core_simd/src/select.rs | 199 +++++++++++---- crates/core_simd/src/simd/cmp/ord.rs | 6 +- crates/core_simd/src/simd/num/float.rs | 2 +- crates/core_simd/src/simd/num/int.rs | 2 +- crates/core_simd/src/swizzle_dyn.rs | 4 +- 10 files changed, 248 insertions(+), 619 deletions(-) delete mode 100644 crates/core_simd/src/masks/bitmask.rs delete mode 100644 crates/core_simd/src/masks/full_masks.rs diff --git a/crates/core_simd/src/masks.rs b/crates/core_simd/src/masks.rs index ca1e3db8b46f..7baa96475910 100644 --- a/crates/core_simd/src/masks.rs +++ b/crates/core_simd/src/masks.rs @@ -2,20 +2,33 @@ //! Types representing #![allow(non_camel_case_types)] -#[cfg_attr( - not(all(target_arch = "x86_64", target_feature = "avx512f")), - path = "masks/full_masks.rs" -)] -#[cfg_attr( - all(target_arch = "x86_64", target_feature = "avx512f"), - path = "masks/bitmask.rs" -)] -mod mask_impl; - -use crate::simd::{LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount}; +use crate::simd::{LaneCount, Select, Simd, SimdCast, SimdElement, SupportedLaneCount}; use core::cmp::Ordering; use core::{fmt, mem}; +pub(crate) trait FixEndianness { + fn fix_endianness(self) -> Self; +} + +macro_rules! impl_fix_endianness { + { $($int:ty),* } => { + $( + impl FixEndianness for $int { + #[inline(always)] + fn fix_endianness(self) -> Self { + if cfg!(target_endian = "big") { + <$int>::reverse_bits(self) + } else { + self + } + } + } + )* + } +} + +impl_fix_endianness! { u8, u16, u32, u64 } + mod sealed { use super::*; @@ -109,7 +122,7 @@ impl_element! { isize, usize } /// and/or Rust versions, and code should not assume that it is equivalent to /// `[T; N]`. #[repr(transparent)] -pub struct Mask(mask_impl::Mask) +pub struct Mask(Simd) where T: MaskElement, LaneCount: SupportedLaneCount; @@ -141,7 +154,7 @@ where #[inline] #[rustc_const_unstable(feature = "portable_simd", issue = "86656")] pub const fn splat(value: bool) -> Self { - Self(mask_impl::Mask::splat(value)) + Self(Simd::splat(if value { T::TRUE } else { T::FALSE })) } /// Converts an array of bools to a SIMD mask. @@ -192,8 +205,8 @@ where // Safety: the caller must confirm this invariant unsafe { core::intrinsics::assume(::valid(value)); - Self(mask_impl::Mask::from_simd_unchecked(value)) } + Self(value) } /// Converts a vector of integers to a mask, where 0 represents `false` and -1 @@ -215,14 +228,15 @@ where #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] pub fn to_simd(self) -> Simd { - self.0.to_simd() + self.0 } /// Converts the mask to a mask of any other element size. #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] pub fn cast(self) -> Mask { - Mask(self.0.convert()) + // Safety: mask elements are integers + unsafe { Mask(core::intrinsics::simd::simd_as(self.0)) } } /// Tests the value of the specified element. @@ -233,7 +247,7 @@ where #[must_use = "method returns a new bool and does not mutate the original value"] pub unsafe fn test_unchecked(&self, index: usize) -> bool { // Safety: the caller must confirm this invariant - unsafe { self.0.test_unchecked(index) } + unsafe { T::eq(*self.0.as_array().get_unchecked(index), T::TRUE) } } /// Tests the value of the specified element. @@ -244,9 +258,7 @@ where #[must_use = "method returns a new bool and does not mutate the original value"] #[track_caller] pub fn test(&self, index: usize) -> bool { - assert!(index < N, "element index out of range"); - // Safety: the element index has been checked - unsafe { self.test_unchecked(index) } + T::eq(self.0[index], T::TRUE) } /// Sets the value of the specified element. @@ -257,7 +269,7 @@ where pub unsafe fn set_unchecked(&mut self, index: usize, value: bool) { // Safety: the caller must confirm this invariant unsafe { - self.0.set_unchecked(index, value); + *self.0.as_mut_array().get_unchecked_mut(index) = if value { T::TRUE } else { T::FALSE } } } @@ -268,35 +280,67 @@ where #[inline] #[track_caller] pub fn set(&mut self, index: usize, value: bool) { - assert!(index < N, "element index out of range"); - // Safety: the element index has been checked - unsafe { - self.set_unchecked(index, value); - } + self.0[index] = if value { T::TRUE } else { T::FALSE } } /// Returns true if any element is set, or false otherwise. #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] pub fn any(self) -> bool { - self.0.any() + // Safety: `self` is a mask vector + unsafe { core::intrinsics::simd::simd_reduce_any(self.0) } } /// Returns true if all elements are set, or false otherwise. #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] pub fn all(self) -> bool { - self.0.all() + // Safety: `self` is a mask vector + unsafe { core::intrinsics::simd::simd_reduce_all(self.0) } } /// Creates a bitmask from a mask. /// /// Each bit is set if the corresponding element in the mask is `true`. - /// If the mask contains more than 64 elements, the bitmask is truncated to the first 64. #[inline] #[must_use = "method returns a new integer and does not mutate the original value"] pub fn to_bitmask(self) -> u64 { - self.0.to_bitmask_integer() + const { + assert!(N <= 64, "number of elements can't be greater than 64"); + } + + #[inline] + unsafe fn to_bitmask_impl( + mask: Mask, + ) -> U + where + T: MaskElement, + LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, + { + let resized = mask.resize::(false); + + // Safety: `resized` is an integer vector with length M, which must match T + let bitmask: U = unsafe { core::intrinsics::simd::simd_bitmask(resized.0) }; + + // LLVM assumes bit order should match endianness + bitmask.fix_endianness() + } + + // TODO modify simd_bitmask to zero-extend output, making this unnecessary + if N <= 8 { + // Safety: bitmask matches length + unsafe { to_bitmask_impl::(self) as u64 } + } else if N <= 16 { + // Safety: bitmask matches length + unsafe { to_bitmask_impl::(self) as u64 } + } else if N <= 32 { + // Safety: bitmask matches length + unsafe { to_bitmask_impl::(self) as u64 } + } else { + // Safety: bitmask matches length + unsafe { to_bitmask_impl::(self) } + } } /// Creates a mask from a bitmask. @@ -306,7 +350,7 @@ where #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] pub fn from_bitmask(bitmask: u64) -> Self { - Self(mask_impl::Mask::from_bitmask_integer(bitmask)) + Self(bitmask.select(Simd::splat(T::TRUE), Simd::splat(T::FALSE))) } /// Finds the index of the first set element. @@ -450,7 +494,8 @@ where type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { - Self(self.0 & rhs.0) + // Safety: `self` is an integer vector + unsafe { Self(core::intrinsics::simd::simd_and(self.0, rhs.0)) } } } @@ -486,7 +531,8 @@ where type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { - Self(self.0 | rhs.0) + // Safety: `self` is an integer vector + unsafe { Self(core::intrinsics::simd::simd_or(self.0, rhs.0)) } } } @@ -522,7 +568,8 @@ where type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self::Output { - Self(self.0 ^ rhs.0) + // Safety: `self` is an integer vector + unsafe { Self(core::intrinsics::simd::simd_xor(self.0, rhs.0)) } } } @@ -558,7 +605,7 @@ where type Output = Mask; #[inline] fn not(self) -> Self::Output { - Self(!self.0) + Self::splat(true) ^ self } } @@ -569,7 +616,7 @@ where { #[inline] fn bitand_assign(&mut self, rhs: Self) { - self.0 = self.0 & rhs.0; + *self = *self & rhs; } } @@ -591,7 +638,7 @@ where { #[inline] fn bitor_assign(&mut self, rhs: Self) { - self.0 = self.0 | rhs.0; + *self = *self | rhs; } } @@ -613,7 +660,7 @@ where { #[inline] fn bitxor_assign(&mut self, rhs: Self) { - self.0 = self.0 ^ rhs.0; + *self = *self ^ rhs; } } diff --git a/crates/core_simd/src/masks/bitmask.rs b/crates/core_simd/src/masks/bitmask.rs deleted file mode 100644 index 83ee88c372ab..000000000000 --- a/crates/core_simd/src/masks/bitmask.rs +++ /dev/null @@ -1,231 +0,0 @@ -#![allow(unused_imports)] -use super::MaskElement; -use crate::simd::{LaneCount, Simd, SupportedLaneCount}; -use core::marker::PhantomData; - -/// A mask where each lane is represented by a single bit. -#[repr(transparent)] -pub(crate) struct Mask( - as SupportedLaneCount>::BitMask, - PhantomData, -) -where - T: MaskElement, - LaneCount: SupportedLaneCount; - -impl Copy for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ -} - -impl Clone for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn clone(&self) -> Self { - *self - } -} - -impl PartialEq for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn eq(&self, other: &Self) -> bool { - self.0.as_ref() == other.0.as_ref() - } -} - -impl PartialOrd for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn partial_cmp(&self, other: &Self) -> Option { - self.0.as_ref().partial_cmp(other.0.as_ref()) - } -} - -impl Eq for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ -} - -impl Ord for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn cmp(&self, other: &Self) -> core::cmp::Ordering { - self.0.as_ref().cmp(other.0.as_ref()) - } -} - -impl Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - #[rustc_const_unstable(feature = "portable_simd", issue = "86656")] - pub(crate) const fn splat(value: bool) -> Self { - Self( - if value { - as SupportedLaneCount>::FULL_BIT_MASK - } else { - as SupportedLaneCount>::EMPTY_BIT_MASK - }, - PhantomData, - ) - } - - #[inline] - #[must_use = "method returns a new bool and does not mutate the original value"] - pub(crate) unsafe fn test_unchecked(&self, lane: usize) -> bool { - (self.0.as_ref()[lane / 8] >> (lane % 8)) & 0x1 > 0 - } - - #[inline] - pub(crate) unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { - unsafe { - self.0.as_mut()[lane / 8] ^= ((value ^ self.test_unchecked(lane)) as u8) << (lane % 8) - } - } - - #[inline] - #[must_use = "method returns a new vector and does not mutate the original value"] - pub(crate) fn to_simd(self) -> Simd { - unsafe { - core::intrinsics::simd::simd_select_bitmask( - self.0, - Simd::splat(T::TRUE), - Simd::splat(T::FALSE), - ) - } - } - - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - pub(crate) unsafe fn from_simd_unchecked(value: Simd) -> Self { - unsafe { Self(core::intrinsics::simd::simd_bitmask(value), PhantomData) } - } - - #[inline] - pub(crate) fn to_bitmask_integer(self) -> u64 { - let mut bitmask = [0u8; 8]; - bitmask[..self.0.as_ref().len()].copy_from_slice(self.0.as_ref()); - u64::from_ne_bytes(bitmask) - } - - #[inline] - pub(crate) fn from_bitmask_integer(bitmask: u64) -> Self { - let mut bytes = as SupportedLaneCount>::EMPTY_BIT_MASK; - let len = bytes.as_mut().len(); - bytes - .as_mut() - .copy_from_slice(&bitmask.to_ne_bytes()[..len]); - Self(bytes, PhantomData) - } - - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - pub(crate) fn convert(self) -> Mask - where - U: MaskElement, - { - // Safety: bitmask layout does not depend on the element width - unsafe { core::mem::transmute_copy(&self) } - } - - #[inline] - #[must_use = "method returns a new bool and does not mutate the original value"] - pub(crate) fn any(self) -> bool { - self != Self::splat(false) - } - - #[inline] - #[must_use = "method returns a new bool and does not mutate the original value"] - pub(crate) fn all(self) -> bool { - self == Self::splat(true) - } -} - -impl core::ops::BitAnd for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, - as SupportedLaneCount>::BitMask: AsRef<[u8]> + AsMut<[u8]>, -{ - type Output = Self; - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - fn bitand(mut self, rhs: Self) -> Self { - for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) { - *l &= r; - } - self - } -} - -impl core::ops::BitOr for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, - as SupportedLaneCount>::BitMask: AsRef<[u8]> + AsMut<[u8]>, -{ - type Output = Self; - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - fn bitor(mut self, rhs: Self) -> Self { - for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) { - *l |= r; - } - self - } -} - -impl core::ops::BitXor for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - type Output = Self; - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - fn bitxor(mut self, rhs: Self) -> Self::Output { - for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) { - *l ^= r; - } - self - } -} - -impl core::ops::Not for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - type Output = Self; - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - fn not(mut self) -> Self::Output { - for x in self.0.as_mut() { - *x = !*x; - } - if N % 8 > 0 { - *self.0.as_mut().last_mut().unwrap() &= u8::MAX >> (8 - N % 8); - } - self - } -} diff --git a/crates/core_simd/src/masks/full_masks.rs b/crates/core_simd/src/masks/full_masks.rs deleted file mode 100644 index 5ad2c1d1eaf6..000000000000 --- a/crates/core_simd/src/masks/full_masks.rs +++ /dev/null @@ -1,297 +0,0 @@ -//! Masks that take up full SIMD vector registers. - -use crate::simd::{LaneCount, MaskElement, Simd, SupportedLaneCount}; - -#[repr(transparent)] -pub(crate) struct Mask(Simd) -where - T: MaskElement, - LaneCount: SupportedLaneCount; - -impl Copy for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ -} - -impl Clone for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn clone(&self) -> Self { - *self - } -} - -impl PartialEq for Mask -where - T: MaskElement + PartialEq, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn eq(&self, other: &Self) -> bool { - self.0.eq(&other.0) - } -} - -impl PartialOrd for Mask -where - T: MaskElement + PartialOrd, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn partial_cmp(&self, other: &Self) -> Option { - self.0.partial_cmp(&other.0) - } -} - -impl Eq for Mask -where - T: MaskElement + Eq, - LaneCount: SupportedLaneCount, -{ -} - -impl Ord for Mask -where - T: MaskElement + Ord, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn cmp(&self, other: &Self) -> core::cmp::Ordering { - self.0.cmp(&other.0) - } -} - -// Used for bitmask bit order workaround -pub(crate) trait ReverseBits { - // Reverse the least significant `n` bits of `self`. - // (Remaining bits must be 0.) - fn reverse_bits(self, n: usize) -> Self; -} - -macro_rules! impl_reverse_bits { - { $($int:ty),* } => { - $( - impl ReverseBits for $int { - #[inline(always)] - fn reverse_bits(self, n: usize) -> Self { - let rev = <$int>::reverse_bits(self); - let bitsize = size_of::<$int>() * 8; - if n < bitsize { - // Shift things back to the right - rev >> (bitsize - n) - } else { - rev - } - } - } - )* - } -} - -impl_reverse_bits! { u8, u16, u32, u64 } - -impl Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - #[rustc_const_unstable(feature = "portable_simd", issue = "86656")] - pub(crate) const fn splat(value: bool) -> Self { - Self(Simd::splat(if value { T::TRUE } else { T::FALSE })) - } - - #[inline] - #[must_use = "method returns a new bool and does not mutate the original value"] - pub(crate) unsafe fn test_unchecked(&self, lane: usize) -> bool { - T::eq(self.0[lane], T::TRUE) - } - - #[inline] - pub(crate) unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { - self.0[lane] = if value { T::TRUE } else { T::FALSE } - } - - #[inline] - #[must_use = "method returns a new vector and does not mutate the original value"] - pub(crate) fn to_simd(self) -> Simd { - self.0 - } - - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - pub(crate) unsafe fn from_simd_unchecked(value: Simd) -> Self { - Self(value) - } - - #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] - pub(crate) fn convert(self) -> Mask - where - U: MaskElement, - { - // Safety: masks are simply integer vectors of 0 and -1, and we can cast the element type. - unsafe { Mask(core::intrinsics::simd::simd_cast(self.0)) } - } - - #[inline] - unsafe fn to_bitmask_impl(self) -> U - where - LaneCount: SupportedLaneCount, - { - let resized = self.to_simd().resize::(T::FALSE); - - // Safety: `resized` is an integer vector with length M, which must match T - let bitmask: U = unsafe { core::intrinsics::simd::simd_bitmask(resized) }; - - // LLVM assumes bit order should match endianness - if cfg!(target_endian = "big") { - bitmask.reverse_bits(M) - } else { - bitmask - } - } - - #[inline] - unsafe fn from_bitmask_impl(bitmask: U) -> Self - where - LaneCount: SupportedLaneCount, - { - // LLVM assumes bit order should match endianness - let bitmask = if cfg!(target_endian = "big") { - bitmask.reverse_bits(M) - } else { - bitmask - }; - - // SAFETY: `mask` is the correct bitmask type for a u64 bitmask - let mask: Simd = unsafe { - core::intrinsics::simd::simd_select_bitmask( - bitmask, - Simd::::splat(T::TRUE), - Simd::::splat(T::FALSE), - ) - }; - - // SAFETY: `mask` only contains `T::TRUE` or `T::FALSE` - unsafe { Self::from_simd_unchecked(mask.resize::(T::FALSE)) } - } - - #[inline] - pub(crate) fn to_bitmask_integer(self) -> u64 { - // TODO modify simd_bitmask to zero-extend output, making this unnecessary - if N <= 8 { - // Safety: bitmask matches length - unsafe { self.to_bitmask_impl::() as u64 } - } else if N <= 16 { - // Safety: bitmask matches length - unsafe { self.to_bitmask_impl::() as u64 } - } else if N <= 32 { - // Safety: bitmask matches length - unsafe { self.to_bitmask_impl::() as u64 } - } else { - // Safety: bitmask matches length - unsafe { self.to_bitmask_impl::() } - } - } - - #[inline] - pub(crate) fn from_bitmask_integer(bitmask: u64) -> Self { - // TODO modify simd_bitmask_select to truncate input, making this unnecessary - if N <= 8 { - // Safety: bitmask matches length - unsafe { Self::from_bitmask_impl::(bitmask as u8) } - } else if N <= 16 { - // Safety: bitmask matches length - unsafe { Self::from_bitmask_impl::(bitmask as u16) } - } else if N <= 32 { - // Safety: bitmask matches length - unsafe { Self::from_bitmask_impl::(bitmask as u32) } - } else { - // Safety: bitmask matches length - unsafe { Self::from_bitmask_impl::(bitmask) } - } - } - - #[inline] - #[must_use = "method returns a new bool and does not mutate the original value"] - pub(crate) fn any(self) -> bool { - // Safety: use `self` as an integer vector - unsafe { core::intrinsics::simd::simd_reduce_any(self.to_simd()) } - } - - #[inline] - #[must_use = "method returns a new bool and does not mutate the original value"] - pub(crate) fn all(self) -> bool { - // Safety: use `self` as an integer vector - unsafe { core::intrinsics::simd::simd_reduce_all(self.to_simd()) } - } -} - -impl From> for Simd -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn from(value: Mask) -> Self { - value.0 - } -} - -impl core::ops::BitAnd for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - type Output = Self; - #[inline] - fn bitand(self, rhs: Self) -> Self { - // Safety: `self` is an integer vector - unsafe { Self(core::intrinsics::simd::simd_and(self.0, rhs.0)) } - } -} - -impl core::ops::BitOr for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - type Output = Self; - #[inline] - fn bitor(self, rhs: Self) -> Self { - // Safety: `self` is an integer vector - unsafe { Self(core::intrinsics::simd::simd_or(self.0, rhs.0)) } - } -} - -impl core::ops::BitXor for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - type Output = Self; - #[inline] - fn bitxor(self, rhs: Self) -> Self { - // Safety: `self` is an integer vector - unsafe { Self(core::intrinsics::simd::simd_xor(self.0, rhs.0)) } - } -} - -impl core::ops::Not for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - type Output = Self; - #[inline] - fn not(self) -> Self::Output { - Self::splat(true) ^ self - } -} diff --git a/crates/core_simd/src/mod.rs b/crates/core_simd/src/mod.rs index 45b1a0f97514..14fe70df4ed1 100644 --- a/crates/core_simd/src/mod.rs +++ b/crates/core_simd/src/mod.rs @@ -29,6 +29,7 @@ pub mod simd { pub use crate::core_simd::cast::*; pub use crate::core_simd::lane_count::{LaneCount, SupportedLaneCount}; pub use crate::core_simd::masks::*; + pub use crate::core_simd::select::*; pub use crate::core_simd::swizzle::*; pub use crate::core_simd::to_bytes::ToBytes; pub use crate::core_simd::vector::*; diff --git a/crates/core_simd/src/ops.rs b/crates/core_simd/src/ops.rs index f36e8d01a73b..f36e360fadf9 100644 --- a/crates/core_simd/src/ops.rs +++ b/crates/core_simd/src/ops.rs @@ -1,4 +1,4 @@ -use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount, cmp::SimdPartialEq}; +use crate::simd::{LaneCount, Select, Simd, SimdElement, SupportedLaneCount, cmp::SimdPartialEq}; use core::ops::{Add, Mul}; use core::ops::{BitAnd, BitOr, BitXor}; use core::ops::{Div, Rem, Sub}; diff --git a/crates/core_simd/src/select.rs b/crates/core_simd/src/select.rs index a2db455a5268..5240b9b0c716 100644 --- a/crates/core_simd/src/select.rs +++ b/crates/core_simd/src/select.rs @@ -1,54 +1,163 @@ -use crate::simd::{LaneCount, Mask, MaskElement, Simd, SimdElement, SupportedLaneCount}; +use crate::simd::{ + FixEndianness, LaneCount, Mask, MaskElement, Simd, SimdElement, SupportedLaneCount, +}; -impl Mask +/// Choose elements from two vectors using a mask. +/// +/// For each element in the mask, choose the corresponding element from `true_values` if +/// that element mask is true, and `false_values` if that element mask is false. +/// +/// If the mask is `u64`, it's treated as a bitmask with the least significant bit +/// corresponding to the first element. +/// +/// # Examples +/// +/// ## Selecting values from `Simd` +/// ``` +/// # #![feature(portable_simd)] +/// # #[cfg(feature = "as_crate")] use core_simd::simd; +/// # #[cfg(not(feature = "as_crate"))] use core::simd; +/// # use simd::{Simd, Mask, Select}; +/// let a = Simd::from_array([0, 1, 2, 3]); +/// let b = Simd::from_array([4, 5, 6, 7]); +/// let mask = Mask::::from_array([true, false, false, true]); +/// let c = mask.select(a, b); +/// assert_eq!(c.to_array(), [0, 5, 6, 3]); +/// ``` +/// +/// ## Selecting values from `Mask` +/// ``` +/// # #![feature(portable_simd)] +/// # #[cfg(feature = "as_crate")] use core_simd::simd; +/// # #[cfg(not(feature = "as_crate"))] use core::simd; +/// # use simd::{Mask, Select}; +/// let a = Mask::::from_array([true, true, false, false]); +/// let b = Mask::::from_array([false, false, true, true]); +/// let mask = Mask::::from_array([true, false, false, true]); +/// let c = mask.select(a, b); +/// assert_eq!(c.to_array(), [true, false, true, false]); +/// ``` +/// +/// ## Selecting with a bitmask +/// ``` +/// # #![feature(portable_simd)] +/// # #[cfg(feature = "as_crate")] use core_simd::simd; +/// # #[cfg(not(feature = "as_crate"))] use core::simd; +/// # use simd::{Mask, Select}; +/// let a = Mask::::from_array([true, true, false, false]); +/// let b = Mask::::from_array([false, false, true, true]); +/// let mask = 0b1001; +/// let c = mask.select(a, b); +/// assert_eq!(c.to_array(), [true, false, true, false]); +/// ``` +pub trait Select { + /// Choose elements + fn select(self, true_values: T, false_values: T) -> T; +} + +impl Select> for Mask +where + T: SimdElement, + U: MaskElement, + LaneCount: SupportedLaneCount, +{ + #[inline] + fn select(self, true_values: Simd, false_values: Simd) -> Simd { + // Safety: + // simd_as between masks is always safe (they're vectors of ints). + // simd_select uses a mask that matches the width and number of elements + unsafe { + let mask: Simd = core::intrinsics::simd::simd_as(self.to_simd()); + core::intrinsics::simd::simd_select(mask, true_values, false_values) + } + } +} + +impl Select> for u64 +where + T: SimdElement, + LaneCount: SupportedLaneCount, +{ + #[inline] + fn select(self, true_values: Simd, false_values: Simd) -> Simd { + const { + assert!(N <= 64, "number of elements can't be greater than 64"); + } + + #[inline] + unsafe fn select_impl( + bitmask: U, + true_values: Simd, + false_values: Simd, + ) -> Simd + where + T: SimdElement, + LaneCount: SupportedLaneCount, + LaneCount: SupportedLaneCount, + { + let default = true_values[0]; + let true_values = true_values.resize::(default); + let false_values = false_values.resize::(default); + + // LLVM assumes bit order should match endianness + let bitmask = bitmask.fix_endianness(); + + // Safety: the caller guarantees that the size of U matches M + let selected = unsafe { + core::intrinsics::simd::simd_select_bitmask(bitmask, true_values, false_values) + }; + + selected.resize::(default) + } + + // TODO modify simd_bitmask_select to truncate input, making this unnecessary + if N <= 8 { + let bitmask = self as u8; + // Safety: bitmask matches length + unsafe { select_impl::(bitmask, true_values, false_values) } + } else if N <= 16 { + let bitmask = self as u16; + // Safety: bitmask matches length + unsafe { select_impl::(bitmask, true_values, false_values) } + } else if N <= 32 { + let bitmask = self as u32; + // Safety: bitmask matches length + unsafe { select_impl::(bitmask, true_values, false_values) } + } else { + let bitmask = self; + // Safety: bitmask matches length + unsafe { select_impl::(bitmask, true_values, false_values) } + } + } +} + +impl Select> for Mask +where + T: MaskElement, + U: MaskElement, + LaneCount: SupportedLaneCount, +{ + #[inline] + fn select(self, true_values: Mask, false_values: Mask) -> Mask { + let selected: Simd = + Select::select(self, true_values.to_simd(), false_values.to_simd()); + + // Safety: all values come from masks + unsafe { Mask::from_simd_unchecked(selected) } + } +} + +impl Select> for u64 where T: MaskElement, LaneCount: SupportedLaneCount, { - /// Choose elements from two vectors. - /// - /// For each element in the mask, choose the corresponding element from `true_values` if - /// that element mask is true, and `false_values` if that element mask is false. - /// - /// # Examples - /// ``` - /// # #![feature(portable_simd)] - /// # use core::simd::{Simd, Mask}; - /// let a = Simd::from_array([0, 1, 2, 3]); - /// let b = Simd::from_array([4, 5, 6, 7]); - /// let mask = Mask::from_array([true, false, false, true]); - /// let c = mask.select(a, b); - /// assert_eq!(c.to_array(), [0, 5, 6, 3]); - /// ``` #[inline] - #[must_use = "method returns a new vector and does not mutate the original inputs"] - pub fn select(self, true_values: Simd, false_values: Simd) -> Simd - where - U: SimdElement, - { - // Safety: The mask has been cast to a vector of integers, - // and the operands to select between are vectors of the same type and length. - unsafe { core::intrinsics::simd::simd_select(self.to_simd(), true_values, false_values) } - } + fn select(self, true_values: Mask, false_values: Mask) -> Mask { + let selected: Simd = + Select::select(self, true_values.to_simd(), false_values.to_simd()); - /// Choose elements from two masks. - /// - /// For each element in the mask, choose the corresponding element from `true_values` if - /// that element mask is true, and `false_values` if that element mask is false. - /// - /// # Examples - /// ``` - /// # #![feature(portable_simd)] - /// # use core::simd::Mask; - /// let a = Mask::::from_array([true, true, false, false]); - /// let b = Mask::::from_array([false, false, true, true]); - /// let mask = Mask::::from_array([true, false, false, true]); - /// let c = mask.select_mask(a, b); - /// assert_eq!(c.to_array(), [true, false, true, false]); - /// ``` - #[inline] - #[must_use = "method returns a new mask and does not mutate the original inputs"] - pub fn select_mask(self, true_values: Self, false_values: Self) -> Self { - self & true_values | !self & false_values + // Safety: all values come from masks + unsafe { Mask::from_simd_unchecked(selected) } } } diff --git a/crates/core_simd/src/simd/cmp/ord.rs b/crates/core_simd/src/simd/cmp/ord.rs index 4b2d0b55feba..1b1c689ad458 100644 --- a/crates/core_simd/src/simd/cmp/ord.rs +++ b/crates/core_simd/src/simd/cmp/ord.rs @@ -1,5 +1,5 @@ use crate::simd::{ - LaneCount, Mask, Simd, SupportedLaneCount, + LaneCount, Mask, Select, Simd, SupportedLaneCount, cmp::SimdPartialEq, ptr::{SimdConstPtr, SimdMutPtr}, }; @@ -194,12 +194,12 @@ macro_rules! impl_mask { { #[inline] fn simd_max(self, other: Self) -> Self { - self.simd_gt(other).select_mask(other, self) + self.simd_gt(other).select(other, self) } #[inline] fn simd_min(self, other: Self) -> Self { - self.simd_lt(other).select_mask(other, self) + self.simd_lt(other).select(other, self) } #[inline] diff --git a/crates/core_simd/src/simd/num/float.rs b/crates/core_simd/src/simd/num/float.rs index b5972c47373b..76ab5748c638 100644 --- a/crates/core_simd/src/simd/num/float.rs +++ b/crates/core_simd/src/simd/num/float.rs @@ -1,6 +1,6 @@ use super::sealed::Sealed; use crate::simd::{ - LaneCount, Mask, Simd, SimdCast, SimdElement, SupportedLaneCount, + LaneCount, Mask, Select, Simd, SimdCast, SimdElement, SupportedLaneCount, cmp::{SimdPartialEq, SimdPartialOrd}, }; diff --git a/crates/core_simd/src/simd/num/int.rs b/crates/core_simd/src/simd/num/int.rs index d25050c3e4b4..5a292407d050 100644 --- a/crates/core_simd/src/simd/num/int.rs +++ b/crates/core_simd/src/simd/num/int.rs @@ -1,6 +1,6 @@ use super::sealed::Sealed; use crate::simd::{ - LaneCount, Mask, Simd, SimdCast, SimdElement, SupportedLaneCount, cmp::SimdOrd, + LaneCount, Mask, Select, Simd, SimdCast, SimdElement, SupportedLaneCount, cmp::SimdOrd, cmp::SimdPartialOrd, num::SimdUint, }; diff --git a/crates/core_simd/src/swizzle_dyn.rs b/crates/core_simd/src/swizzle_dyn.rs index 773bd028bae0..73b18595d0a1 100644 --- a/crates/core_simd/src/swizzle_dyn.rs +++ b/crates/core_simd/src/swizzle_dyn.rs @@ -139,7 +139,7 @@ unsafe fn armv7_neon_swizzle_u8x16(bytes: Simd, idxs: Simd) -> S #[inline] #[allow(clippy::let_and_return)] unsafe fn avx2_pshufb(bytes: Simd, idxs: Simd) -> Simd { - use crate::simd::cmp::SimdPartialOrd; + use crate::simd::{Select, cmp::SimdPartialOrd}; #[cfg(target_arch = "x86")] use core::arch::x86; #[cfg(target_arch = "x86_64")] @@ -200,7 +200,7 @@ fn zeroing_idxs(idxs: Simd) -> Simd where LaneCount: SupportedLaneCount, { - use crate::simd::cmp::SimdPartialOrd; + use crate::simd::{Select, cmp::SimdPartialOrd}; idxs.simd_lt(Simd::splat(N as u8)) .select(idxs, Simd::splat(u8::MAX)) } From 8ce88bcb509e1f7d7b6b76724a6fcb827d9a78ac Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Tue, 7 Oct 2025 10:16:49 -0400 Subject: [PATCH 025/978] Remove LaneCount in favor of #[rustc_simd_monomorphize_lane_limit] attribute (#485) * Remove LaneCount in favor of #[rustc_simd_monomorphize_lane_limit] attribute * Document allowed vector lengths --- crates/core_simd/src/fmt.rs | 3 +- crates/core_simd/src/iter.rs | 10 +---- crates/core_simd/src/lane_count.rs | 52 ---------------------- crates/core_simd/src/lib.rs | 3 +- crates/core_simd/src/masks.rs | 46 +++---------------- crates/core_simd/src/mod.rs | 2 - crates/core_simd/src/ops.rs | 5 +-- crates/core_simd/src/ops/assign.rs | 1 - crates/core_simd/src/ops/deref.rs | 3 -- crates/core_simd/src/ops/shift_scalar.rs | 10 +---- crates/core_simd/src/ops/unary.rs | 4 +- crates/core_simd/src/select.rs | 10 +---- crates/core_simd/src/simd/cmp/eq.rs | 16 ++----- crates/core_simd/src/simd/cmp/ord.rs | 32 +++---------- crates/core_simd/src/simd/num/float.rs | 10 +---- crates/core_simd/src/simd/num/int.rs | 14 ++---- crates/core_simd/src/simd/num/uint.rs | 10 +---- crates/core_simd/src/simd/ptr/const_ptr.rs | 9 ++-- crates/core_simd/src/simd/ptr/mut_ptr.rs | 9 ++-- crates/core_simd/src/swizzle.rs | 32 +++---------- crates/core_simd/src/swizzle_dyn.rs | 17 ++----- crates/core_simd/src/to_bytes.rs | 4 +- crates/core_simd/src/vector.rs | 43 +++--------------- crates/std_float/src/lib.rs | 10 ++--- crates/test_helpers/src/lib.rs | 4 -- rust-toolchain.toml | 2 +- 26 files changed, 57 insertions(+), 304 deletions(-) delete mode 100644 crates/core_simd/src/lane_count.rs diff --git a/crates/core_simd/src/fmt.rs b/crates/core_simd/src/fmt.rs index 3a540f5a0490..90c520e75bb3 100644 --- a/crates/core_simd/src/fmt.rs +++ b/crates/core_simd/src/fmt.rs @@ -1,9 +1,8 @@ -use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; +use crate::simd::{Simd, SimdElement}; use core::fmt; impl fmt::Debug for Simd where - LaneCount: SupportedLaneCount, T: SimdElement + fmt::Debug, { /// A `Simd` has a debug format like the one for `[T]`: diff --git a/crates/core_simd/src/iter.rs b/crates/core_simd/src/iter.rs index b3732fd74d5f..fdc458efeda4 100644 --- a/crates/core_simd/src/iter.rs +++ b/crates/core_simd/src/iter.rs @@ -1,4 +1,4 @@ -use crate::simd::{LaneCount, Simd, SupportedLaneCount}; +use crate::simd::Simd; use core::{ iter::{Product, Sum}, ops::{Add, Mul}, @@ -7,8 +7,6 @@ use core::{ macro_rules! impl_traits { { $type:ty } => { impl Sum for Simd<$type, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn sum>(iter: I) -> Self { @@ -17,8 +15,6 @@ macro_rules! impl_traits { } impl Product for Simd<$type, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn product>(iter: I) -> Self { @@ -27,8 +23,6 @@ macro_rules! impl_traits { } impl<'a, const N: usize> Sum<&'a Self> for Simd<$type, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn sum>(iter: I) -> Self { @@ -37,8 +31,6 @@ macro_rules! impl_traits { } impl<'a, const N: usize> Product<&'a Self> for Simd<$type, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn product>(iter: I) -> Self { diff --git a/crates/core_simd/src/lane_count.rs b/crates/core_simd/src/lane_count.rs deleted file mode 100644 index 839195c38eda..000000000000 --- a/crates/core_simd/src/lane_count.rs +++ /dev/null @@ -1,52 +0,0 @@ -mod sealed { - pub trait Sealed {} -} -use sealed::Sealed; - -/// Specifies the number of lanes in a SIMD vector as a type. -pub struct LaneCount; - -impl LaneCount { - /// The number of bytes in a bitmask with this many lanes. - pub const BITMASK_LEN: usize = N.div_ceil(8); -} - -/// Statically guarantees that a lane count is marked as supported. -/// -/// This trait is *sealed*: the list of implementors below is total. -/// Users do not have the ability to mark additional `LaneCount` values as supported. -/// Only SIMD vectors with supported lane counts are constructable. -pub trait SupportedLaneCount: Sealed { - #[doc(hidden)] - type BitMask: Copy + AsRef<[u8]> + AsMut<[u8]>; - #[doc(hidden)] - const EMPTY_BIT_MASK: Self::BitMask; - #[doc(hidden)] - const FULL_BIT_MASK: Self::BitMask; -} - -impl Sealed for LaneCount {} - -macro_rules! supported_lane_count { - ($($lanes:literal),+) => { - $( - impl SupportedLaneCount for LaneCount<$lanes> { - type BitMask = [u8; Self::BITMASK_LEN]; - const EMPTY_BIT_MASK: Self::BitMask = [0; Self::BITMASK_LEN]; - const FULL_BIT_MASK: Self::BitMask = { - let mut array = [!0u8; Self::BITMASK_LEN]; - if $lanes % 8 > 0 { - array[Self::BITMASK_LEN - 1] = (!0) >> (8 - $lanes % 8); - } - array - }; - } - )+ - }; -} - -supported_lane_count!( - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 -); diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs index 9d7dfd2ab351..3e5ebe19e4db 100644 --- a/crates/core_simd/src/lib.rs +++ b/crates/core_simd/src/lib.rs @@ -9,7 +9,8 @@ simd_ffi, staged_api, prelude_import, - ptr_metadata + ptr_metadata, + rustc_attrs )] #![cfg_attr( all( diff --git a/crates/core_simd/src/masks.rs b/crates/core_simd/src/masks.rs index 7baa96475910..3e2209556b66 100644 --- a/crates/core_simd/src/masks.rs +++ b/crates/core_simd/src/masks.rs @@ -2,7 +2,7 @@ //! Types representing #![allow(non_camel_case_types)] -use crate::simd::{LaneCount, Select, Simd, SimdCast, SimdElement, SupportedLaneCount}; +use crate::simd::{Select, Simd, SimdCast, SimdElement}; use core::cmp::Ordering; use core::{fmt, mem}; @@ -41,7 +41,6 @@ mod sealed { pub trait Sealed { fn valid(values: Simd) -> bool where - LaneCount: SupportedLaneCount, Self: SimdElement; fn eq(self, other: Self) -> bool; @@ -69,8 +68,6 @@ macro_rules! impl_element { impl Sealed for $ty { #[inline] fn valid(value: Simd) -> bool - where - LaneCount: SupportedLaneCount, { // We can't use `Simd` directly, because `Simd`'s functions call this function and // we will end up with an infinite loop. @@ -121,23 +118,19 @@ impl_element! { isize, usize } /// The layout of this type is unspecified, and may change between platforms /// and/or Rust versions, and code should not assume that it is equivalent to /// `[T; N]`. +/// +/// `N` cannot be 0 and may be at most 64. This limit may be increased in +/// the future. #[repr(transparent)] pub struct Mask(Simd) where - T: MaskElement, - LaneCount: SupportedLaneCount; + T: MaskElement; -impl Copy for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ -} +impl Copy for Mask where T: MaskElement {} impl Clone for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn clone(&self) -> Self { @@ -148,7 +141,6 @@ where impl Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { /// Constructs a mask by setting all elements to the given value. #[inline] @@ -315,8 +307,6 @@ where ) -> U where T: MaskElement, - LaneCount: SupportedLaneCount, - LaneCount: SupportedLaneCount, { let resized = mask.resize::(false); @@ -421,7 +411,6 @@ where impl From<[bool; N]> for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn from(array: [bool; N]) -> Self { @@ -432,7 +421,6 @@ where impl From> for [bool; N] where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn from(vector: Mask) -> Self { @@ -443,7 +431,6 @@ where impl Default for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn default() -> Self { @@ -454,7 +441,6 @@ where impl PartialEq for Mask where T: MaskElement + PartialEq, - LaneCount: SupportedLaneCount, { #[inline] fn eq(&self, other: &Self) -> bool { @@ -465,7 +451,6 @@ where impl PartialOrd for Mask where T: MaskElement + PartialOrd, - LaneCount: SupportedLaneCount, { #[inline] fn partial_cmp(&self, other: &Self) -> Option { @@ -476,7 +461,6 @@ where impl fmt::Debug for Mask where T: MaskElement + fmt::Debug, - LaneCount: SupportedLaneCount, { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -489,7 +473,6 @@ where impl core::ops::BitAnd for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -502,7 +485,6 @@ where impl core::ops::BitAnd for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -514,7 +496,6 @@ where impl core::ops::BitAnd> for bool where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Mask; #[inline] @@ -526,7 +507,6 @@ where impl core::ops::BitOr for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -539,7 +519,6 @@ where impl core::ops::BitOr for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -551,7 +530,6 @@ where impl core::ops::BitOr> for bool where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Mask; #[inline] @@ -563,7 +541,6 @@ where impl core::ops::BitXor for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -576,7 +553,6 @@ where impl core::ops::BitXor for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -588,7 +564,6 @@ where impl core::ops::BitXor> for bool where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Mask; #[inline] @@ -600,7 +575,6 @@ where impl core::ops::Not for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { type Output = Mask; #[inline] @@ -612,7 +586,6 @@ where impl core::ops::BitAndAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn bitand_assign(&mut self, rhs: Self) { @@ -623,7 +596,6 @@ where impl core::ops::BitAndAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn bitand_assign(&mut self, rhs: bool) { @@ -634,7 +606,6 @@ where impl core::ops::BitOrAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn bitor_assign(&mut self, rhs: Self) { @@ -645,7 +616,6 @@ where impl core::ops::BitOrAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn bitor_assign(&mut self, rhs: bool) { @@ -656,7 +626,6 @@ where impl core::ops::BitXorAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn bitxor_assign(&mut self, rhs: Self) { @@ -667,7 +636,6 @@ where impl core::ops::BitXorAssign for Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn bitxor_assign(&mut self, rhs: bool) { @@ -679,8 +647,6 @@ macro_rules! impl_from { { $from:ty => $($to:ty),* } => { $( impl From> for Mask<$to, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn from(value: Mask<$from, N>) -> Self { diff --git a/crates/core_simd/src/mod.rs b/crates/core_simd/src/mod.rs index 14fe70df4ed1..5f635d80a178 100644 --- a/crates/core_simd/src/mod.rs +++ b/crates/core_simd/src/mod.rs @@ -5,7 +5,6 @@ mod alias; mod cast; mod fmt; mod iter; -mod lane_count; mod masks; mod ops; mod select; @@ -27,7 +26,6 @@ pub mod simd { pub use crate::core_simd::alias::*; pub use crate::core_simd::cast::*; - pub use crate::core_simd::lane_count::{LaneCount, SupportedLaneCount}; pub use crate::core_simd::masks::*; pub use crate::core_simd::select::*; pub use crate::core_simd::swizzle::*; diff --git a/crates/core_simd/src/ops.rs b/crates/core_simd/src/ops.rs index f36e360fadf9..eb6601f73483 100644 --- a/crates/core_simd/src/ops.rs +++ b/crates/core_simd/src/ops.rs @@ -1,4 +1,4 @@ -use crate::simd::{LaneCount, Select, Simd, SimdElement, SupportedLaneCount, cmp::SimdPartialEq}; +use crate::simd::{Select, Simd, SimdElement, cmp::SimdPartialEq}; use core::ops::{Add, Mul}; use core::ops::{BitAnd, BitOr, BitXor}; use core::ops::{Div, Rem, Sub}; @@ -12,7 +12,6 @@ mod unary; impl core::ops::Index for Simd where T: SimdElement, - LaneCount: SupportedLaneCount, I: core::slice::SliceIndex<[T]>, { type Output = I::Output; @@ -25,7 +24,6 @@ where impl core::ops::IndexMut for Simd where T: SimdElement, - LaneCount: SupportedLaneCount, I: core::slice::SliceIndex<[T]>, { #[inline] @@ -130,7 +128,6 @@ macro_rules! for_base_types { impl $op for Simd<$scalar, N> where $scalar: SimdElement, - LaneCount: SupportedLaneCount, { type Output = $out; diff --git a/crates/core_simd/src/ops/assign.rs b/crates/core_simd/src/ops/assign.rs index d21d867de26d..c1830c35df77 100644 --- a/crates/core_simd/src/ops/assign.rs +++ b/crates/core_simd/src/ops/assign.rs @@ -21,7 +21,6 @@ macro_rules! assign_ops { where Self: $trait, T: SimdElement, - LaneCount: SupportedLaneCount, { #[inline] fn $assign_call(&mut self, rhs: U) { diff --git a/crates/core_simd/src/ops/deref.rs b/crates/core_simd/src/ops/deref.rs index 913cbbe977c4..360b83c40346 100644 --- a/crates/core_simd/src/ops/deref.rs +++ b/crates/core_simd/src/ops/deref.rs @@ -13,7 +13,6 @@ macro_rules! deref_lhs { where T: SimdElement, $simd: $trait<$simd, Output = $simd>, - LaneCount: SupportedLaneCount, { type Output = Simd; @@ -33,7 +32,6 @@ macro_rules! deref_rhs { where T: SimdElement, $simd: $trait<$simd, Output = $simd>, - LaneCount: SupportedLaneCount, { type Output = Simd; @@ -64,7 +62,6 @@ macro_rules! deref_ops { where T: SimdElement, $simd: $trait<$simd, Output = $simd>, - LaneCount: SupportedLaneCount, { type Output = $simd; diff --git a/crates/core_simd/src/ops/shift_scalar.rs b/crates/core_simd/src/ops/shift_scalar.rs index f5115a5a5e93..7ca83dc40f61 100644 --- a/crates/core_simd/src/ops/shift_scalar.rs +++ b/crates/core_simd/src/ops/shift_scalar.rs @@ -1,13 +1,11 @@ // Shift operations uniquely typically only have a scalar on the right-hand side. // Here, we implement shifts for scalar RHS arguments. -use crate::simd::{LaneCount, Simd, SupportedLaneCount}; +use crate::simd::Simd; macro_rules! impl_splatted_shifts { { impl $trait:ident :: $trait_fn:ident for $ty:ty } => { impl core::ops::$trait<$ty> for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -17,8 +15,6 @@ macro_rules! impl_splatted_shifts { } impl core::ops::$trait<&$ty> for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, { type Output = Self; #[inline] @@ -28,8 +24,6 @@ macro_rules! impl_splatted_shifts { } impl<'lhs, const N: usize> core::ops::$trait<$ty> for &'lhs Simd<$ty, N> - where - LaneCount: SupportedLaneCount, { type Output = Simd<$ty, N>; #[inline] @@ -39,8 +33,6 @@ macro_rules! impl_splatted_shifts { } impl<'lhs, const N: usize> core::ops::$trait<&$ty> for &'lhs Simd<$ty, N> - where - LaneCount: SupportedLaneCount, { type Output = Simd<$ty, N>; #[inline] diff --git a/crates/core_simd/src/ops/unary.rs b/crates/core_simd/src/ops/unary.rs index 412a5b801171..e1c06167f979 100644 --- a/crates/core_simd/src/ops/unary.rs +++ b/crates/core_simd/src/ops/unary.rs @@ -1,4 +1,4 @@ -use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; +use crate::simd::{Simd, SimdElement}; use core::ops::{Neg, Not}; // unary ops macro_rules! neg { @@ -6,7 +6,6 @@ macro_rules! neg { $(impl Neg for Simd<$scalar, N> where $scalar: SimdElement, - LaneCount: SupportedLaneCount, { type Output = Self; @@ -40,7 +39,6 @@ macro_rules! not { $(impl Not for Simd<$scalar, N> where $scalar: SimdElement, - LaneCount: SupportedLaneCount, { type Output = Self; diff --git a/crates/core_simd/src/select.rs b/crates/core_simd/src/select.rs index 5240b9b0c716..404f54d8f382 100644 --- a/crates/core_simd/src/select.rs +++ b/crates/core_simd/src/select.rs @@ -1,6 +1,4 @@ -use crate::simd::{ - FixEndianness, LaneCount, Mask, MaskElement, Simd, SimdElement, SupportedLaneCount, -}; +use crate::simd::{FixEndianness, Mask, MaskElement, Simd, SimdElement}; /// Choose elements from two vectors using a mask. /// @@ -59,7 +57,6 @@ impl Select> for Mask where T: SimdElement, U: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn select(self, true_values: Simd, false_values: Simd) -> Simd { @@ -76,7 +73,6 @@ where impl Select> for u64 where T: SimdElement, - LaneCount: SupportedLaneCount, { #[inline] fn select(self, true_values: Simd, false_values: Simd) -> Simd { @@ -92,8 +88,6 @@ where ) -> Simd where T: SimdElement, - LaneCount: SupportedLaneCount, - LaneCount: SupportedLaneCount, { let default = true_values[0]; let true_values = true_values.resize::(default); @@ -135,7 +129,6 @@ impl Select> for Mask where T: MaskElement, U: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn select(self, true_values: Mask, false_values: Mask) -> Mask { @@ -150,7 +143,6 @@ where impl Select> for u64 where T: MaskElement, - LaneCount: SupportedLaneCount, { #[inline] fn select(self, true_values: Mask, false_values: Mask) -> Mask { diff --git a/crates/core_simd/src/simd/cmp/eq.rs b/crates/core_simd/src/simd/cmp/eq.rs index 789fc0bb9424..d553d6c040c9 100644 --- a/crates/core_simd/src/simd/cmp/eq.rs +++ b/crates/core_simd/src/simd/cmp/eq.rs @@ -1,5 +1,5 @@ use crate::simd::{ - LaneCount, Mask, Simd, SimdElement, SupportedLaneCount, + Mask, Simd, SimdElement, ptr::{SimdConstPtr, SimdMutPtr}, }; @@ -21,8 +21,6 @@ macro_rules! impl_number { { $($number:ty),* } => { $( impl SimdPartialEq for Simd<$number, N> - where - LaneCount: SupportedLaneCount, { type Mask = Mask<<$number as SimdElement>::Mask, N>; @@ -50,8 +48,6 @@ macro_rules! impl_mask { { $($integer:ty),* } => { $( impl SimdPartialEq for Mask<$integer, N> - where - LaneCount: SupportedLaneCount, { type Mask = Self; @@ -75,10 +71,7 @@ macro_rules! impl_mask { impl_mask! { i8, i16, i32, i64, isize } -impl SimdPartialEq for Simd<*const T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdPartialEq for Simd<*const T, N> { type Mask = Mask; #[inline] @@ -92,10 +85,7 @@ where } } -impl SimdPartialEq for Simd<*mut T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdPartialEq for Simd<*mut T, N> { type Mask = Mask; #[inline] diff --git a/crates/core_simd/src/simd/cmp/ord.rs b/crates/core_simd/src/simd/cmp/ord.rs index 1b1c689ad458..5672fbbf54ca 100644 --- a/crates/core_simd/src/simd/cmp/ord.rs +++ b/crates/core_simd/src/simd/cmp/ord.rs @@ -1,5 +1,5 @@ use crate::simd::{ - LaneCount, Mask, Select, Simd, SupportedLaneCount, + Mask, Select, Simd, cmp::SimdPartialEq, ptr::{SimdConstPtr, SimdMutPtr}, }; @@ -49,8 +49,6 @@ macro_rules! impl_integer { { $($integer:ty),* } => { $( impl SimdPartialOrd for Simd<$integer, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn simd_lt(self, other: Self) -> Self::Mask { @@ -82,8 +80,6 @@ macro_rules! impl_integer { } impl SimdOrd for Simd<$integer, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn simd_max(self, other: Self) -> Self { @@ -115,8 +111,6 @@ macro_rules! impl_float { { $($float:ty),* } => { $( impl SimdPartialOrd for Simd<$float, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn simd_lt(self, other: Self) -> Self::Mask { @@ -156,8 +150,6 @@ macro_rules! impl_mask { { $($integer:ty),* } => { $( impl SimdPartialOrd for Mask<$integer, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn simd_lt(self, other: Self) -> Self::Mask { @@ -189,8 +181,6 @@ macro_rules! impl_mask { } impl SimdOrd for Mask<$integer, N> - where - LaneCount: SupportedLaneCount, { #[inline] fn simd_max(self, other: Self) -> Self { @@ -218,10 +208,7 @@ macro_rules! impl_mask { impl_mask! { i8, i16, i32, i64, isize } -impl SimdPartialOrd for Simd<*const T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdPartialOrd for Simd<*const T, N> { #[inline] fn simd_lt(self, other: Self) -> Self::Mask { self.addr().simd_lt(other.addr()) @@ -243,10 +230,7 @@ where } } -impl SimdOrd for Simd<*const T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdOrd for Simd<*const T, N> { #[inline] fn simd_max(self, other: Self) -> Self { self.simd_lt(other).select(other, self) @@ -268,10 +252,7 @@ where } } -impl SimdPartialOrd for Simd<*mut T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdPartialOrd for Simd<*mut T, N> { #[inline] fn simd_lt(self, other: Self) -> Self::Mask { self.addr().simd_lt(other.addr()) @@ -293,10 +274,7 @@ where } } -impl SimdOrd for Simd<*mut T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdOrd for Simd<*mut T, N> { #[inline] fn simd_max(self, other: Self) -> Self { self.simd_lt(other).select(other, self) diff --git a/crates/core_simd/src/simd/num/float.rs b/crates/core_simd/src/simd/num/float.rs index 76ab5748c638..efd7c2469512 100644 --- a/crates/core_simd/src/simd/num/float.rs +++ b/crates/core_simd/src/simd/num/float.rs @@ -1,6 +1,6 @@ use super::sealed::Sealed; use crate::simd::{ - LaneCount, Mask, Select, Simd, SimdCast, SimdElement, SupportedLaneCount, + Mask, Select, Simd, SimdCast, SimdElement, cmp::{SimdPartialEq, SimdPartialOrd}, }; @@ -240,15 +240,9 @@ pub trait SimdFloat: Copy + Sealed { macro_rules! impl_trait { { $($ty:ty { bits: $bits_ty:ty, mask: $mask_ty:ty }),* } => { $( - impl Sealed for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, - { - } + impl Sealed for Simd<$ty, N> {} impl SimdFloat for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, { type Mask = Mask<<$mask_ty as SimdElement>::Mask, N>; type Scalar = $ty; diff --git a/crates/core_simd/src/simd/num/int.rs b/crates/core_simd/src/simd/num/int.rs index 5a292407d050..6ebf0ba397c6 100644 --- a/crates/core_simd/src/simd/num/int.rs +++ b/crates/core_simd/src/simd/num/int.rs @@ -1,7 +1,6 @@ use super::sealed::Sealed; use crate::simd::{ - LaneCount, Mask, Select, Simd, SimdCast, SimdElement, SupportedLaneCount, cmp::SimdOrd, - cmp::SimdPartialOrd, num::SimdUint, + Mask, Select, Simd, SimdCast, SimdElement, cmp::SimdOrd, cmp::SimdPartialOrd, num::SimdUint, }; /// Operations on SIMD vectors of signed integers. @@ -241,16 +240,9 @@ pub trait SimdInt: Copy + Sealed { macro_rules! impl_trait { { $($ty:ident ($unsigned:ident)),* } => { $( - impl Sealed for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, - { - } + impl Sealed for Simd<$ty, N> {} - impl SimdInt for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, - { + impl SimdInt for Simd<$ty, N> { type Mask = Mask<<$ty as SimdElement>::Mask, N>; type Scalar = $ty; type Unsigned = Simd<$unsigned, N>; diff --git a/crates/core_simd/src/simd/num/uint.rs b/crates/core_simd/src/simd/num/uint.rs index 45d978068b66..f8a40f8ec565 100644 --- a/crates/core_simd/src/simd/num/uint.rs +++ b/crates/core_simd/src/simd/num/uint.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount, cmp::SimdOrd}; +use crate::simd::{Simd, SimdCast, SimdElement, cmp::SimdOrd}; /// Operations on SIMD vectors of unsigned integers. pub trait SimdUint: Copy + Sealed { @@ -123,15 +123,9 @@ pub trait SimdUint: Copy + Sealed { macro_rules! impl_trait { { $($ty:ident ($signed:ident)),* } => { $( - impl Sealed for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, - { - } + impl Sealed for Simd<$ty, N> {} impl SimdUint for Simd<$ty, N> - where - LaneCount: SupportedLaneCount, { type Scalar = $ty; type Cast = Simd; diff --git a/crates/core_simd/src/simd/ptr/const_ptr.rs b/crates/core_simd/src/simd/ptr/const_ptr.rs index 36452e7ae920..7ef9dc21373e 100644 --- a/crates/core_simd/src/simd/ptr/const_ptr.rs +++ b/crates/core_simd/src/simd/ptr/const_ptr.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, num::SimdUint}; +use crate::simd::{Mask, Simd, cmp::SimdPartialEq, num::SimdUint}; /// Operations on SIMD vectors of constant pointers. pub trait SimdConstPtr: Copy + Sealed { @@ -88,12 +88,9 @@ pub trait SimdConstPtr: Copy + Sealed { fn wrapping_sub(self, count: Self::Usize) -> Self; } -impl Sealed for Simd<*const T, N> where LaneCount: SupportedLaneCount {} +impl Sealed for Simd<*const T, N> {} -impl SimdConstPtr for Simd<*const T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdConstPtr for Simd<*const T, N> { type Usize = Simd; type Isize = Simd; type CastPtr = Simd<*const U, N>; diff --git a/crates/core_simd/src/simd/ptr/mut_ptr.rs b/crates/core_simd/src/simd/ptr/mut_ptr.rs index c644f390c20a..3b9b75ddf566 100644 --- a/crates/core_simd/src/simd/ptr/mut_ptr.rs +++ b/crates/core_simd/src/simd/ptr/mut_ptr.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, num::SimdUint}; +use crate::simd::{Mask, Simd, cmp::SimdPartialEq, num::SimdUint}; /// Operations on SIMD vectors of mutable pointers. pub trait SimdMutPtr: Copy + Sealed { @@ -85,12 +85,9 @@ pub trait SimdMutPtr: Copy + Sealed { fn wrapping_sub(self, count: Self::Usize) -> Self; } -impl Sealed for Simd<*mut T, N> where LaneCount: SupportedLaneCount {} +impl Sealed for Simd<*mut T, N> {} -impl SimdMutPtr for Simd<*mut T, N> -where - LaneCount: SupportedLaneCount, -{ +impl SimdMutPtr for Simd<*mut T, N> { type Usize = Simd; type Isize = Simd; type CastPtr = Simd<*mut U, N>; diff --git a/crates/core_simd/src/swizzle.rs b/crates/core_simd/src/swizzle.rs index 81085a9ee4a3..02dcd71356dd 100644 --- a/crates/core_simd/src/swizzle.rs +++ b/crates/core_simd/src/swizzle.rs @@ -1,4 +1,4 @@ -use crate::simd::{LaneCount, Mask, MaskElement, Simd, SimdElement, SupportedLaneCount}; +use crate::simd::{Mask, MaskElement, Simd, SimdElement}; /// Constructs a new SIMD vector by copying elements from selected elements in other vectors. /// @@ -82,8 +82,6 @@ pub trait Swizzle { fn swizzle(vector: Simd) -> Simd where T: SimdElement, - LaneCount: SupportedLaneCount, - LaneCount: SupportedLaneCount, { // Safety: `vector` is a vector, and the index is a const vector of u32. unsafe { @@ -122,8 +120,6 @@ pub trait Swizzle { fn concat_swizzle(first: Simd, second: Simd) -> Simd where T: SimdElement, - LaneCount: SupportedLaneCount, - LaneCount: SupportedLaneCount, { // Safety: `first` and `second` are vectors, and the index is a const vector of u32. unsafe { @@ -161,8 +157,6 @@ pub trait Swizzle { fn swizzle_mask(mask: Mask) -> Mask where T: MaskElement, - LaneCount: SupportedLaneCount, - LaneCount: SupportedLaneCount, { // SAFETY: all elements of this mask come from another mask unsafe { Mask::from_simd_unchecked(Self::swizzle(mask.to_simd())) } @@ -177,8 +171,6 @@ pub trait Swizzle { fn concat_swizzle_mask(first: Mask, second: Mask) -> Mask where T: MaskElement, - LaneCount: SupportedLaneCount, - LaneCount: SupportedLaneCount, { // SAFETY: all elements of this mask come from another mask unsafe { @@ -190,7 +182,6 @@ pub trait Swizzle { impl Simd where T: SimdElement, - LaneCount: SupportedLaneCount, { /// Reverse the order of the elements in the vector. #[inline] @@ -464,10 +455,7 @@ where /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] - pub fn resize(self, value: T) -> Simd - where - LaneCount: SupportedLaneCount, - { + pub fn resize(self, value: T) -> Simd { struct Resize; impl Swizzle for Resize { const INDEX: [usize; M] = const { @@ -495,10 +483,7 @@ where /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] - pub fn extract(self) -> Simd - where - LaneCount: SupportedLaneCount, - { + pub fn extract(self) -> Simd { struct Extract; impl Swizzle for Extract { const INDEX: [usize; LEN] = const { @@ -519,7 +504,6 @@ where impl Mask where T: MaskElement, - LaneCount: SupportedLaneCount, { /// Reverse the order of the elements in the mask. #[inline] @@ -655,10 +639,7 @@ where /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] - pub fn resize(self, value: bool) -> Mask - where - LaneCount: SupportedLaneCount, - { + pub fn resize(self, value: bool) -> Mask { // Safety: swizzles are safe for masks unsafe { Mask::::from_simd_unchecked(self.to_simd().resize::(if value { @@ -681,10 +662,7 @@ where /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] - pub fn extract(self) -> Mask - where - LaneCount: SupportedLaneCount, - { + pub fn extract(self) -> Mask { // Safety: swizzles are safe for masks unsafe { Mask::::from_simd_unchecked(self.to_simd().extract::()) } } diff --git a/crates/core_simd/src/swizzle_dyn.rs b/crates/core_simd/src/swizzle_dyn.rs index 73b18595d0a1..ae0b174973da 100644 --- a/crates/core_simd/src/swizzle_dyn.rs +++ b/crates/core_simd/src/swizzle_dyn.rs @@ -1,10 +1,7 @@ -use crate::simd::{LaneCount, Simd, SupportedLaneCount}; +use crate::simd::Simd; use core::mem; -impl Simd -where - LaneCount: SupportedLaneCount, -{ +impl Simd { /// Swizzle a vector of bytes according to the index vector. /// Indices within range select the appropriate byte. /// Indices "out of bounds" instead select 0. @@ -184,10 +181,7 @@ unsafe fn transize( f: unsafe fn(T, T) -> T, a: Simd, b: Simd, -) -> Simd -where - LaneCount: SupportedLaneCount, -{ +) -> Simd { // SAFETY: Same obligation to use this function as to use mem::transmute_copy. unsafe { mem::transmute_copy(&f(mem::transmute_copy(&a), mem::transmute_copy(&b))) } } @@ -196,10 +190,7 @@ where #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] #[allow(unused)] #[inline(always)] -fn zeroing_idxs(idxs: Simd) -> Simd -where - LaneCount: SupportedLaneCount, -{ +fn zeroing_idxs(idxs: Simd) -> Simd { use crate::simd::{Select, cmp::SimdPartialOrd}; idxs.simd_lt(Simd::splat(N as u8)) .select(idxs, Simd::splat(u8::MAX)) diff --git a/crates/core_simd/src/to_bytes.rs b/crates/core_simd/src/to_bytes.rs index fee2cc06c5b0..1fd285e457db 100644 --- a/crates/core_simd/src/to_bytes.rs +++ b/crates/core_simd/src/to_bytes.rs @@ -1,12 +1,12 @@ use crate::simd::{ - LaneCount, Simd, SimdElement, SupportedLaneCount, + Simd, SimdElement, num::{SimdFloat, SimdInt, SimdUint}, }; mod sealed { use super::*; pub trait Sealed {} - impl Sealed for Simd where LaneCount: SupportedLaneCount {} + impl Sealed for Simd {} } use sealed::Sealed; diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs index c00cfcdd41ff..2dba5c83e112 100644 --- a/crates/core_simd/src/vector.rs +++ b/crates/core_simd/src/vector.rs @@ -1,5 +1,5 @@ use crate::simd::{ - LaneCount, Mask, MaskElement, SupportedLaneCount, Swizzle, + Mask, MaskElement, Swizzle, cmp::SimdPartialOrd, num::SimdUint, ptr::{SimdConstPtr, SimdMutPtr}, @@ -51,6 +51,8 @@ use crate::simd::{ /// Thus it is sound to [`transmute`] `Simd` to `[T; N]` and should optimize to "zero cost", /// but the reverse transmutation may require a copy the compiler cannot simply elide. /// +/// `N` cannot be 0 and may be at most 64. This limit may be increased in the future. +/// /// # ABI "Features" /// Due to Rust's safety guarantees, `Simd` is currently passed and returned via memory, /// not SIMD registers, except as an optimization. Using `#[inline]` on functions that accept @@ -100,14 +102,13 @@ use crate::simd::{ // avoided, as it will likely become illegal on `#[repr(simd)]` structs in the future. It also // causes rustc to emit illegal LLVM IR in some cases. #[repr(simd, packed)] +#[rustc_simd_monomorphize_lane_limit = "64"] pub struct Simd([T; N]) where - LaneCount: SupportedLaneCount, T: SimdElement; impl Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { /// Number of elements in this vector. @@ -149,7 +150,6 @@ where const fn splat_const(value: T) -> Simd where T: SimdElement, - LaneCount: SupportedLaneCount, { Simd::from_array([value; N]) } @@ -157,7 +157,6 @@ where fn splat_rt(value: T) -> Simd where T: SimdElement, - LaneCount: SupportedLaneCount, { // This is preferred over `[value; N]`, since it's explicitly a splat: // https://github.com/rust-lang/rust/issues/97804 @@ -886,16 +885,10 @@ where } } -impl Copy for Simd -where - LaneCount: SupportedLaneCount, - T: SimdElement, -{ -} +impl Copy for Simd where T: SimdElement {} impl Clone for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { #[inline] @@ -906,7 +899,6 @@ where impl Default for Simd where - LaneCount: SupportedLaneCount, T: SimdElement + Default, { #[inline] @@ -917,7 +909,6 @@ where impl PartialEq for Simd where - LaneCount: SupportedLaneCount, T: SimdElement + PartialEq, { #[inline] @@ -951,7 +942,6 @@ where /// Lexicographic order. For the SIMD elementwise minimum and maximum, use simd_min and simd_max instead. impl PartialOrd for Simd where - LaneCount: SupportedLaneCount, T: SimdElement + PartialOrd, { #[inline] @@ -961,17 +951,11 @@ where } } -impl Eq for Simd -where - LaneCount: SupportedLaneCount, - T: SimdElement + Eq, -{ -} +impl Eq for Simd where T: SimdElement + Eq {} /// Lexicographic order. For the SIMD elementwise minimum and maximum, use simd_min and simd_max instead. impl Ord for Simd where - LaneCount: SupportedLaneCount, T: SimdElement + Ord, { #[inline] @@ -983,7 +967,6 @@ where impl core::hash::Hash for Simd where - LaneCount: SupportedLaneCount, T: SimdElement + core::hash::Hash, { #[inline] @@ -998,7 +981,6 @@ where // array references impl AsRef<[T; N]> for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { #[inline] @@ -1009,7 +991,6 @@ where impl AsMut<[T; N]> for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { #[inline] @@ -1021,7 +1002,6 @@ where // slice references impl AsRef<[T]> for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { #[inline] @@ -1032,7 +1012,6 @@ where impl AsMut<[T]> for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { #[inline] @@ -1044,7 +1023,6 @@ where // vector/array conversion impl From<[T; N]> for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { #[inline] @@ -1055,7 +1033,6 @@ where impl From> for [T; N] where - LaneCount: SupportedLaneCount, T: SimdElement, { #[inline] @@ -1066,7 +1043,6 @@ where impl TryFrom<&[T]> for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { type Error = core::array::TryFromSliceError; @@ -1079,7 +1055,6 @@ where impl TryFrom<&mut [T]> for Simd where - LaneCount: SupportedLaneCount, T: SimdElement, { type Error = core::array::TryFromSliceError; @@ -1217,10 +1192,7 @@ where } #[inline] -fn lane_indices() -> Simd -where - LaneCount: SupportedLaneCount, -{ +fn lane_indices() -> Simd { #![allow(clippy::needless_range_loop)] let mut index = [0; N]; for i in 0..N { @@ -1232,7 +1204,6 @@ where #[inline] fn mask_up_to(len: usize) -> Mask where - LaneCount: SupportedLaneCount, M: MaskElement, { let index = lane_indices::(); diff --git a/crates/std_float/src/lib.rs b/crates/std_float/src/lib.rs index 148aa5f9f177..c3c9b76e50b8 100644 --- a/crates/std_float/src/lib.rs +++ b/crates/std_float/src/lib.rs @@ -11,7 +11,7 @@ use core_simd::simd; use core::intrinsics::simd as intrinsics; -use simd::{LaneCount, Simd, SupportedLaneCount}; +use simd::Simd; #[cfg(feature = "as_crate")] mod experimental { @@ -140,16 +140,14 @@ pub trait StdFloat: Sealed + Sized { fn fract(self) -> Self; } -impl Sealed for Simd where LaneCount: SupportedLaneCount {} -impl Sealed for Simd where LaneCount: SupportedLaneCount {} +impl Sealed for Simd {} +impl Sealed for Simd {} macro_rules! impl_float { { $($fn:ident: $intrinsic:ident,)* } => { impl StdFloat for Simd - where - LaneCount: SupportedLaneCount, { #[inline] fn fract(self) -> Self { @@ -165,8 +163,6 @@ macro_rules! impl_float { } impl StdFloat for Simd - where - LaneCount: SupportedLaneCount, { #[inline] fn fract(self) -> Self { diff --git a/crates/test_helpers/src/lib.rs b/crates/test_helpers/src/lib.rs index 35401a9ddb40..eb3d3f68bc2e 100644 --- a/crates/test_helpers/src/lib.rs +++ b/crates/test_helpers/src/lib.rs @@ -604,8 +604,6 @@ macro_rules! test_lanes { use super::*; fn implementation() - where - core_simd::simd::LaneCount<$lanes>: core_simd::simd::SupportedLaneCount, $body #[cfg(target_arch = "wasm32")] @@ -704,8 +702,6 @@ macro_rules! test_lanes_panic { use super::*; fn implementation() - where - core_simd::simd::LaneCount<$lanes>: core_simd::simd::SupportedLaneCount, $body // test some odd and even non-power-of-2 lengths on miri diff --git a/rust-toolchain.toml b/rust-toolchain.toml index df4bd75ecfe2..ed4d7e8a801e 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-08-17" +channel = "nightly-2025-09-30" components = ["rustfmt", "clippy", "miri", "rust-src"] From 061617bdbcaa49bb5c4456c0c5264d0849afe4b1 Mon Sep 17 00:00:00 2001 From: sayantn Date: Wed, 8 Oct 2025 08:12:09 +0530 Subject: [PATCH 026/978] Add alignment parameter to `simd_masked_{load,store}` --- crates/core_simd/src/vector.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs index d76a6cd52bfc..f40031f8c4da 100644 --- a/crates/core_simd/src/vector.rs +++ b/crates/core_simd/src/vector.rs @@ -474,7 +474,14 @@ where or: Self, ) -> Self { // SAFETY: The safety of reading elements through `ptr` is ensured by the caller. - unsafe { core::intrinsics::simd::simd_masked_load(enable.to_int(), ptr, or) } + unsafe { + core::intrinsics::simd::simd_masked_load::< + _, + _, + _, + { core::intrinsics::simd::SimdAlign::Element }, + >(enable.to_int(), ptr, or) + } } /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector. @@ -723,7 +730,14 @@ where #[inline] pub unsafe fn store_select_ptr(self, ptr: *mut T, enable: Mask<::Mask, N>) { // SAFETY: The safety of writing elements through `ptr` is ensured by the caller. - unsafe { core::intrinsics::simd::simd_masked_store(enable.to_int(), ptr, self) } + unsafe { + core::intrinsics::simd::simd_masked_store::< + _, + _, + _, + { core::intrinsics::simd::SimdAlign::Element }, + >(enable.to_int(), ptr, self) + } } /// Writes the values in a SIMD vector to potentially discontiguous indices in `slice`. From 242b4b5dc96472858438338642635091dfd3ec99 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 11 Nov 2025 13:25:22 -0800 Subject: [PATCH 027/978] Remove more #[must_use] from portable-simd warning: `#[must_use]` attribute cannot be used on trait methods in impl blocks --> crates/core_simd/src/masks/bitmask.rs:173:5 | 173 | #[must_use = "method returns a new mask and does not mutate the original value"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[must_use]` can be applied to data types, foreign functions, functions, inherent methods, provided trait methods, required trait methods, traits, and unions = note: `#[warn(unused_attributes)]` (part of `#[warn(unused)]`) on by default warning: `#[must_use]` attribute cannot be used on trait methods in impl blocks --> crates/core_simd/src/masks/bitmask.rs:190:5 | 190 | #[must_use = "method returns a new mask and does not mutate the original value"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[must_use]` can be applied to data types, foreign functions, functions, inherent methods, provided trait methods, required trait methods, traits, and unions warning: `#[must_use]` attribute cannot be used on trait methods in impl blocks --> crates/core_simd/src/masks/bitmask.rs:206:5 | 206 | #[must_use = "method returns a new mask and does not mutate the original value"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[must_use]` can be applied to data types, foreign functions, functions, inherent methods, provided trait methods, required trait methods, traits, and unions warning: `#[must_use]` attribute cannot be used on trait methods in impl blocks --> crates/core_simd/src/masks/bitmask.rs:222:5 | 222 | #[must_use = "method returns a new mask and does not mutate the original value"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[must_use]` can be applied to data types, foreign functions, functions, inherent methods, provided trait methods, required trait methods, traits, and unions --- crates/core_simd/src/masks/bitmask.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/core_simd/src/masks/bitmask.rs b/crates/core_simd/src/masks/bitmask.rs index 8221d8f17e90..32d37b553392 100644 --- a/crates/core_simd/src/masks/bitmask.rs +++ b/crates/core_simd/src/masks/bitmask.rs @@ -170,7 +170,6 @@ where { type Output = Self; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn bitand(mut self, rhs: Self) -> Self { for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) { *l &= r; @@ -187,7 +186,6 @@ where { type Output = Self; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn bitor(mut self, rhs: Self) -> Self { for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) { *l |= r; @@ -203,7 +201,6 @@ where { type Output = Self; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn bitxor(mut self, rhs: Self) -> Self::Output { for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) { *l ^= r; @@ -219,7 +216,6 @@ where { type Output = Self; #[inline] - #[must_use = "method returns a new mask and does not mutate the original value"] fn not(mut self) -> Self::Output { for x in self.0.as_mut() { *x = !*x; From 055cd2717fe298a567c130204743cc0cc06a08e0 Mon Sep 17 00:00:00 2001 From: Voxell Paladynee Date: Wed, 19 Nov 2025 21:17:40 +0100 Subject: [PATCH 028/978] ptr_cast_slice: add new methods to raw pointers --- library/core/src/ptr/const_ptr.rs | 37 +++++++++++++++++++++++++ library/core/src/ptr/mut_ptr.rs | 45 +++++++++++++++++++++++++++++++ library/core/src/ptr/non_null.rs | 29 ++++++++++++++++++++ 3 files changed, 111 insertions(+) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 84a6982d5680..e4d2f7436f13 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1386,6 +1386,43 @@ impl *const T { pub const fn cast_uninit(self) -> *const MaybeUninit { self as _ } + + /// Forms a raw slice from a pointer and a length. + /// + /// The `len` argument is the number of **elements**, not the number of bytes. + /// + /// This function is safe, but actually using the return value is unsafe. + /// See the documentation of [`slice::from_raw_parts`] for slice safety requirements. + /// + /// [`slice::from_raw_parts`]: crate::slice::from_raw_parts + /// + /// # Examples + /// + /// ```rust + /// #![feature(ptr_cast_slice)] + /// // create a slice pointer when starting out with a pointer to the first element + /// let x = [5, 6, 7]; + /// let raw_pointer = x.as_ptr(); + /// let slice = raw_pointer.cast_slice(3); + /// assert_eq!(unsafe { &*slice }[2], 7); + /// ``` + /// + /// You must ensure that the pointer is valid and not null before dereferencing + /// the raw slice. A slice reference must never have a null pointer, even if it's empty. + /// + /// ```rust,should_panic + /// #![feature(ptr_cast_slice)] + /// use std::ptr; + /// let danger: *const [u8] = ptr::null::().cast_slice(0); + /// unsafe { + /// danger.as_ref().expect("references must not be null"); + /// } + /// ``` + #[inline] + #[unstable(feature = "ptr_cast_slice", issue = "149103")] + pub const fn cast_slice(self, len: usize) -> *const [T] { + slice_from_raw_parts(self, len) + } } impl *const MaybeUninit { /// Casts from a maybe-uninitialized type to its initialized version. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 85d54b4d3b9b..edcd0cd2d932 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1655,6 +1655,51 @@ impl *mut T { pub const fn cast_uninit(self) -> *mut MaybeUninit { self as _ } + + /// Forms a raw mutable slice from a pointer and a length. + /// + /// The `len` argument is the number of **elements**, not the number of bytes. + /// + /// Performs the same functionality as [`cast_slice`] on a `*const T`, except that a + /// raw mutable slice is returned, as opposed to a raw immutable slice. + /// + /// This function is safe, but actually using the return value is unsafe. + /// See the documentation of [`slice::from_raw_parts_mut`] for slice safety requirements. + /// + /// [`slice::from_raw_parts_mut`]: crate::slice::from_raw_parts_mut + /// [`cast_slice`]: pointer::cast_slice + /// + /// # Examples + /// + /// ```rust + /// #![feature(ptr_cast_slice)] + /// + /// let x = &mut [5, 6, 7]; + /// let slice = x.as_mut_ptr().cast_slice(3); + /// + /// unsafe { + /// (*slice)[2] = 99; // assign a value at an index in the slice + /// }; + /// + /// assert_eq!(unsafe { &*slice }[2], 99); + /// ``` + /// + /// You must ensure that the pointer is valid and not null before dereferencing + /// the raw slice. A slice reference must never have a null pointer, even if it's empty. + /// + /// ```rust,should_panic + /// #![feature(ptr_cast_slice)] + /// use std::ptr; + /// let danger: *mut [u8] = ptr::null_mut::().cast_slice(0); + /// unsafe { + /// danger.as_mut().expect("references must not be null"); + /// } + /// ``` + #[inline] + #[unstable(feature = "ptr_cast_slice", issue = "149103")] + pub const fn cast_slice(self, len: usize) -> *mut [T] { + slice_from_raw_parts_mut(self, len) + } } impl *mut MaybeUninit { /// Casts from a maybe-uninitialized type to its initialized version. diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index aa3af2f18528..2cefc41017f4 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1377,6 +1377,35 @@ impl NonNull { pub const fn cast_uninit(self) -> NonNull> { self.cast() } + + /// Creates a non-null raw slice from a thin pointer and a length. + /// + /// The `len` argument is the number of **elements**, not the number of bytes. + /// + /// This function is safe, but dereferencing the return value is unsafe. + /// See the documentation of [`slice::from_raw_parts`] for slice safety requirements. + /// + /// # Examples + /// + /// ```rust + /// #![feature(ptr_cast_slice)] + /// use std::ptr::NonNull; + /// + /// // create a slice pointer when starting out with a pointer to the first element + /// let mut x = [5, 6, 7]; + /// let nonnull_pointer = NonNull::new(x.as_mut_ptr()).unwrap(); + /// let slice = nonnull_pointer.cast_slice(3); + /// assert_eq!(unsafe { slice.as_ref()[2] }, 7); + /// ``` + /// + /// (Note that this example artificially demonstrates a use of this method, + /// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.) + #[inline] + #[must_use] + #[unstable(feature = "ptr_cast_slice", issue = "149103")] + pub const fn cast_slice(self, len: usize) -> NonNull<[T]> { + NonNull::slice_from_raw_parts(self, len) + } } impl NonNull> { /// Casts from a maybe-uninitialized type to its initialized version. From 67c61cefaf87cb842b2248935dcc481faad21b14 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 23 Oct 2025 09:39:13 +0000 Subject: [PATCH 029/978] Remove opts field from CodegenContext --- src/back/lto.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index 404064fb7a06..08c36d2b7318 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -290,7 +290,7 @@ pub(crate) fn run_thin( let dcx = cgcx.create_dcx(); let dcx = dcx.handle(); let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx); - if cgcx.opts.cg.linker_plugin_lto.enabled() { + if cgcx.use_linker_plugin_lto { unreachable!( "We should never reach this case if the LTO step \ is deferred to the linker" From 385590e9dc85761402f278c61fd081c24c184cb6 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 21 Nov 2025 15:08:09 +0000 Subject: [PATCH 030/978] Remove SharedEmitter from CodegenContext --- src/back/lto.rs | 12 +++++------- src/back/write.rs | 8 ++++++-- src/lib.rs | 14 +++++++++----- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index 08c36d2b7318..24be3ee4c34d 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -26,11 +26,11 @@ use std::sync::atomic::Ordering; use gccjit::{Context, OutputKind}; use object::read::archive::ArchiveFile; use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared}; -use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput}; +use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, SharedEmitter}; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file}; use rustc_data_structures::memmap::Mmap; -use rustc_errors::DiagCtxtHandle; +use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_log::tracing::info; use rustc_middle::bug; use rustc_middle::dep_graph::WorkProduct; @@ -112,10 +112,11 @@ fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> { /// for further optimization. pub(crate) fn run_fat( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> ModuleCodegen { - let dcx = cgcx.create_dcx(); + let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx); /*let symbols_below_threshold = @@ -283,12 +284,11 @@ impl ModuleBufferMethods for ModuleBuffer { /// can simply be copied over from the incr. comp. cache. pub(crate) fn run_thin( cgcx: &CodegenContext, + dcx: DiagCtxtHandle<'_>, each_linked_rlib_for_lto: &[PathBuf], modules: Vec<(String, ThinBuffer)>, cached_modules: Vec<(SerializedModule, WorkProduct)>, ) -> (Vec>, Vec) { - let dcx = cgcx.create_dcx(); - let dcx = dcx.handle(); let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx); if cgcx.use_linker_plugin_lto { unreachable!( @@ -522,8 +522,6 @@ pub fn optimize_thin_module( thin_module: ThinModule, _cgcx: &CodegenContext, ) -> ModuleCodegen { - //let dcx = cgcx.create_dcx(); - //let module_name = &thin_module.shared.module_names[thin_module.idx]; /*let tm_factory_config = TargetMachineFactoryConfig::new(cgcx, module_name.to_str().unwrap()); let tm = (cgcx.tm_factory)(tm_factory_config).map_err(|e| write::llvm_err(&dcx, e))?;*/ diff --git a/src/back/write.rs b/src/back/write.rs index eae0f2aa00f6..b6223c5be370 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -2,8 +2,11 @@ use std::{env, fs}; use gccjit::{Context, OutputKind}; use rustc_codegen_ssa::back::link::ensure_removed; -use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig}; +use rustc_codegen_ssa::back::write::{ + BitcodeSection, CodegenContext, EmitObj, ModuleConfig, SharedEmitter, +}; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; +use rustc_errors::DiagCtxt; use rustc_fs_util::link_or_copy; use rustc_log::tracing::debug; use rustc_session::config::OutputType; @@ -15,10 +18,11 @@ use crate::{GccCodegenBackend, GccContext, LtoMode}; pub(crate) fn codegen( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, ) -> CompiledModule { - let dcx = cgcx.create_dcx(); + let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); let dcx = dcx.handle(); let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen", &*module.name); diff --git a/src/lib.rs b/src/lib.rs index 409b7886740a..5a2ec0a2fc68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,7 +82,7 @@ use gccjit::{TargetInfo, Version}; use rustc_ast::expand::allocator::AllocatorMethod; use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule}; use rustc_codegen_ssa::back::write::{ - CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn, + CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryFn, }; use rustc_codegen_ssa::base::codegen_crate; use rustc_codegen_ssa::target_features::cfg_target_feature; @@ -371,23 +371,25 @@ impl WriteBackendMethods for GccCodegenBackend { fn run_and_optimize_fat_lto( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, // FIXME(bjorn3): Limit LTO exports to these symbols _exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> ModuleCodegen { - back::lto::run_fat(cgcx, each_linked_rlib_for_lto, modules) + back::lto::run_fat(cgcx, shared_emitter, each_linked_rlib_for_lto, modules) } fn run_thin_lto( cgcx: &CodegenContext, + dcx: DiagCtxtHandle<'_>, // FIXME(bjorn3): Limit LTO exports to these symbols _exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], modules: Vec<(String, Self::ThinBuffer)>, cached_modules: Vec<(SerializedModule, WorkProduct)>, ) -> (Vec>, Vec) { - back::lto::run_thin(cgcx, each_linked_rlib_for_lto, modules, cached_modules) + back::lto::run_thin(cgcx, dcx, each_linked_rlib_for_lto, modules, cached_modules) } fn print_pass_timings(&self) { @@ -400,7 +402,7 @@ impl WriteBackendMethods for GccCodegenBackend { fn optimize( _cgcx: &CodegenContext, - _dcx: DiagCtxtHandle<'_>, + _shared_emitter: &SharedEmitter, module: &mut ModuleCodegen, config: &ModuleConfig, ) { @@ -409,6 +411,7 @@ impl WriteBackendMethods for GccCodegenBackend { fn optimize_thin( cgcx: &CodegenContext, + _shared_emitter: &SharedEmitter, thin: ThinModule, ) -> ModuleCodegen { back::lto::optimize_thin_module(thin, cgcx) @@ -416,10 +419,11 @@ impl WriteBackendMethods for GccCodegenBackend { fn codegen( cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, module: ModuleCodegen, config: &ModuleConfig, ) -> CompiledModule { - back::write::codegen(cgcx, module, config) + back::write::codegen(cgcx, shared_emitter, module, config) } fn prepare_thin(module: ModuleCodegen) -> (String, Self::ThinBuffer) { From 09f774da8eccc725f54b38715c88cf7d52315361 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Sun, 23 Nov 2025 01:56:15 -0500 Subject: [PATCH 031/978] Mark all arms as being from a desugaring when lowering `?` and for loops. --- compiler/rustc_ast_lowering/src/expr.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 524f8b054cb4..0ab3191f23be 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -941,14 +941,14 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); this.arena.alloc(this.expr(gen_future_span, expr_break)) }); - self.arm(ready_pat, break_x) + self.arm(ready_pat, break_x, span) }; // `::std::task::Poll::Pending => {}` let pending_arm = { let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]); let empty_block = self.expr_block_empty(span); - self.arm(pending_pat, empty_block) + self.arm(pending_pat, empty_block, span) }; let inner_match_stmt = { @@ -1002,7 +1002,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }); // mut __awaitee => loop { ... } - let awaitee_arm = self.arm(awaitee_pat, loop_expr); + let awaitee_arm = self.arm(awaitee_pat, loop_expr, span); // `match ::std::future::IntoFuture::into_future() { ... }` let into_future_expr = match await_kind { @@ -1788,7 +1788,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let break_expr = self.with_loop_scope(loop_hir_id, |this| this.expr_break_alloc(for_span)); let pat = self.pat_none(for_span); - self.arm(pat, break_expr) + self.arm(pat, break_expr, for_span) }; // Some() => , @@ -1797,7 +1797,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let body_block = self.with_loop_scope(loop_hir_id, |this| this.lower_block(body, false)); let body_expr = self.arena.alloc(self.expr_block(body_block)); - self.arm(some_pat, body_expr) + self.arm(some_pat, body_expr, for_span) }; // `mut iter` @@ -1856,7 +1856,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let loop_expr = self.arena.alloc(hir::Expr { hir_id: loop_hir_id, kind, span: for_span }); // `mut iter => { ... }` - let iter_arm = self.arm(iter_pat, loop_expr); + let iter_arm = self.arm(iter_pat, loop_expr, for_span); let match_expr = match loop_kind { ForLoopKind::For => { @@ -1901,7 +1901,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::LangItem::IntoAsyncIterIntoIter, arena_vec![self; head], ); - let iter_arm = self.arm(async_iter_pat, inner_match_expr); + let iter_arm = self.arm(async_iter_pat, inner_match_expr, for_span); self.arena.alloc(self.expr_match( for_span, iter, @@ -1968,7 +1968,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let val_expr = self.expr_ident(span, val_ident, val_pat_nid); self.lower_attrs(val_expr.hir_id, &attrs, span, Target::Expression); let continue_pat = self.pat_cf_continue(unstable_span, val_pat); - self.arm(continue_pat, val_expr) + self.arm(continue_pat, val_expr, try_span) }; // `ControlFlow::Break(residual) => @@ -2004,7 +2004,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_attrs(ret_expr.hir_id, &attrs, span, Target::Expression); let break_pat = self.pat_cf_break(try_span, residual_local); - self.arm(break_pat, ret_expr) + self.arm(break_pat, ret_expr, try_span) }; hir::ExprKind::Match( @@ -2329,12 +2329,13 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, pat: &'hir hir::Pat<'hir>, expr: &'hir hir::Expr<'hir>, + span: Span, ) -> hir::Arm<'hir> { hir::Arm { hir_id: self.next_id(), pat, guard: None, - span: self.lower_span(expr.span), + span: self.lower_span(span), body: expr, } } From 1deb487076519970fdba20742cc10c380962d2c3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 30 Nov 2025 14:21:08 +0100 Subject: [PATCH 032/978] thread::scope: document how join interacts with TLS destructors --- library/std/src/thread/join_handle.rs | 2 ++ library/std/src/thread/scoped.rs | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/library/std/src/thread/join_handle.rs b/library/std/src/thread/join_handle.rs index 8714ceeb4f46..bb3759cd3a07 100644 --- a/library/std/src/thread/join_handle.rs +++ b/library/std/src/thread/join_handle.rs @@ -102,6 +102,8 @@ impl JoinHandle { /// Waits for the associated thread to finish. /// /// This function will return immediately if the associated thread has already finished. + /// Otherwise, it fully waits for the thread to finish, including all destructors + /// for thread-local variables that might be running after the main function of the thread. /// /// In terms of [atomic memory orderings], the completion of the associated /// thread synchronizes with this function returning. In other words, all diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs index 301f5e949cac..368fb819962b 100644 --- a/library/std/src/thread/scoped.rs +++ b/library/std/src/thread/scoped.rs @@ -80,6 +80,9 @@ impl ScopeData { /// /// All threads spawned within the scope that haven't been manually joined /// will be automatically joined before this function returns. +/// However, note that joining will only wait for the main function of these threads to finish; even +/// when this function returns, destructors of thread-local variables in these threads might still +/// be running. /// /// # Panics /// @@ -292,6 +295,8 @@ impl<'scope, T> ScopedJoinHandle<'scope, T> { /// Waits for the associated thread to finish. /// /// This function will return immediately if the associated thread has already finished. + /// Otherwise, it fully waits for the thread to finish, including all destructors + /// for thread-local variables that might be running after the main function of the thread. /// /// In terms of [atomic memory orderings], the completion of the associated /// thread synchronizes with this function returning. From a8ffa1cbb035ddeb6e5c6326ffca26f58e7bb2b6 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sat, 6 Dec 2025 15:12:20 +0800 Subject: [PATCH 033/978] docs: update default branch name of `rust-lang/rust` --- book/src/development/infrastructure/sync.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/book/src/development/infrastructure/sync.md b/book/src/development/infrastructure/sync.md index 2bbdf47a8358..4506ff15d8ff 100644 --- a/book/src/development/infrastructure/sync.md +++ b/book/src/development/infrastructure/sync.md @@ -79,7 +79,7 @@ to be run inside the `rust` directory): ```bash git fetch upstream # assuming upstream is the rust-lang/rust remote git switch rustup - git merge upstream/master --no-ff + git merge upstream/main --no-ff ``` > Note: This is one of the few instances where a merge commit is allowed in > a PR. @@ -99,7 +99,7 @@ to be run inside the `rust` directory): All the following commands have to be run inside the `rust` directory. -1. Make sure you have checked out the latest `master` of `rust-lang/rust`. +1. Make sure you have checked out the latest `main` of `rust-lang/rust`. 2. Sync the `rust-lang/rust-clippy` master to the rust-copy of Clippy: ```bash git switch -c clippy-subtree-update From 4215b7228d28cb84016e8f0e41c0a5e0935a222f Mon Sep 17 00:00:00 2001 From: Andrew Cherry Date: Thu, 11 Dec 2025 13:58:40 +0000 Subject: [PATCH 034/978] removal of aarch64 special-casing (#497) --- crates/std_float/src/lib.rs | 98 ++++++++++++++----------------------- 1 file changed, 37 insertions(+), 61 deletions(-) diff --git a/crates/std_float/src/lib.rs b/crates/std_float/src/lib.rs index c3c9b76e50b8..b269efc9b1d7 100644 --- a/crates/std_float/src/lib.rs +++ b/crates/std_float/src/lib.rs @@ -66,28 +66,43 @@ pub trait StdFloat: Sealed + Sized { /// Produces a vector where every element has the sine of the value /// in the equivalently-indexed element in `self`. + #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - fn sin(self) -> Self; + fn sin(self) -> Self { + unsafe { intrinsics::simd_fsin(self) } + } /// Produces a vector where every element has the cosine of the value /// in the equivalently-indexed element in `self`. + #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - fn cos(self) -> Self; + fn cos(self) -> Self { + unsafe { intrinsics::simd_fcos(self) } + } /// Produces a vector where every element has the exponential (base e) of the value /// in the equivalently-indexed element in `self`. + #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - fn exp(self) -> Self; + fn exp(self) -> Self { + unsafe { intrinsics::simd_fexp(self) } + } /// Produces a vector where every element has the exponential (base 2) of the value /// in the equivalently-indexed element in `self`. + #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - fn exp2(self) -> Self; + fn exp2(self) -> Self { + unsafe { intrinsics::simd_fexp2(self) } + } /// Produces a vector where every element has the natural logarithm of the value /// in the equivalently-indexed element in `self`. + #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - fn ln(self) -> Self; + fn ln(self) -> Self { + unsafe { intrinsics::simd_flog(self) } + } /// Produces a vector where every element has the logarithm with respect to an arbitrary /// in the equivalently-indexed elements in `self` and `base`. @@ -99,13 +114,19 @@ pub trait StdFloat: Sealed + Sized { /// Produces a vector where every element has the base-2 logarithm of the value /// in the equivalently-indexed element in `self`. + #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - fn log2(self) -> Self; + fn log2(self) -> Self { + unsafe { intrinsics::simd_flog2(self) } + } /// Produces a vector where every element has the base-10 logarithm of the value /// in the equivalently-indexed element in `self`. + #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - fn log10(self) -> Self; + fn log10(self) -> Self { + unsafe { intrinsics::simd_flog10(self) } + } /// Returns the smallest integer greater than or equal to each element. #[must_use = "method returns a new vector and does not mutate the original value"] @@ -143,61 +164,16 @@ pub trait StdFloat: Sealed + Sized { impl Sealed for Simd {} impl Sealed for Simd {} -macro_rules! impl_float { - { - $($fn:ident: $intrinsic:ident,)* - } => { - impl StdFloat for Simd - { - #[inline] - fn fract(self) -> Self { - self - self.trunc() - } - - $( - #[inline] - fn $fn(self) -> Self { - unsafe { intrinsics::$intrinsic(self) } - } - )* - } - - impl StdFloat for Simd - { - #[inline] - fn fract(self) -> Self { - self - self.trunc() - } - - $( - #[inline] - fn $fn(self) -> Self { - // https://github.com/llvm/llvm-project/issues/83729 - #[cfg(target_arch = "aarch64")] - { - let mut ln = Self::splat(0f64); - for i in 0..N { - ln[i] = self[i].$fn() - } - ln - } - - #[cfg(not(target_arch = "aarch64"))] - { - unsafe { intrinsics::$intrinsic(self) } - } - } - )* - } +impl StdFloat for Simd { + #[inline] + fn fract(self) -> Self { + self - self.trunc() } } -impl_float! { - sin: simd_fsin, - cos: simd_fcos, - exp: simd_fexp, - exp2: simd_fexp2, - ln: simd_flog, - log2: simd_flog2, - log10: simd_flog10, +impl StdFloat for Simd { + #[inline] + fn fract(self) -> Self { + self - self.trunc() + } } From bf5283cf6fe637fba494f81793be5a40acf93e1f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 21 Dec 2025 00:13:38 +0100 Subject: [PATCH 035/978] Merge commit '02f889aec5dc9b4e51d4cfd86c67ce5e4a0bbf72' --- build_system/src/build.rs | 12 +++- rust-toolchain | 2 +- src/intrinsic/archs.rs | 123 +++++++++++++++++++++++++++++-------- tests/failing-ui-tests.txt | 9 +++ triagebot.toml | 3 - 5 files changed, 118 insertions(+), 31 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 27476465d740..9b7ee8380ca5 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -111,14 +111,20 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu // Symlink libgccjit.so to sysroot. let lib_path = start_dir.join("sysroot").join("lib"); + let rustlib_target_path = lib_path + .join("rustlib") + .join(&config.host_triple) + .join("codegen-backends") + .join("lib") + .join(&config.target_triple); let libgccjit_path = PathBuf::from(config.gcc_path.as_ref().expect("libgccjit should be set by this point")) .join("libgccjit.so"); - let libgccjit_in_sysroot_path = lib_path.join("libgccjit.so"); + let libgccjit_in_sysroot_path = rustlib_target_path.join("libgccjit.so"); // First remove the file to be able to create the symlink even when the file already exists. let _ = fs::remove_file(&libgccjit_in_sysroot_path); - create_dir(&lib_path)?; - symlink(libgccjit_path, libgccjit_in_sysroot_path) + create_dir(&rustlib_target_path)?; + symlink(libgccjit_path, &libgccjit_in_sysroot_path) .map_err(|error| format!("Cannot create symlink for libgccjit.so: {}", error))?; let library_dir = start_dir.join("sysroot_src").join("library"); diff --git a/rust-toolchain b/rust-toolchain index f9645451e964..86ae738d4483 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-11-24" +channel = "nightly-2025-12-20" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index bb8bcbf66f38..43e7c352c34a 100644 --- a/src/intrinsic/archs.rs +++ b/src/intrinsic/archs.rs @@ -70,10 +70,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sve.sm4e" => "__builtin_sve_svsm4e_u32", "sve.sm4ekey" => "__builtin_sve_svsm4ekey_u32", "sve.wrffr" => "__builtin_sve_svwrffr", - "tcancel" => "__builtin_arm_tcancel", - "tcommit" => "__builtin_arm_tcommit", - "tstart" => "__builtin_arm_tstart", - "ttest" => "__builtin_arm_ttest", _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } @@ -1632,6 +1628,14 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "V6.vabs.f8.128B" => "__builtin_HEXAGON_V6_vabs_f8_128B", "V6.vabs.hf" => "__builtin_HEXAGON_V6_vabs_hf", "V6.vabs.hf.128B" => "__builtin_HEXAGON_V6_vabs_hf_128B", + "V6.vabs.qf16.hf" => "__builtin_HEXAGON_V6_vabs_qf16_hf", + "V6.vabs.qf16.hf.128B" => "__builtin_HEXAGON_V6_vabs_qf16_hf_128B", + "V6.vabs.qf16.qf16" => "__builtin_HEXAGON_V6_vabs_qf16_qf16", + "V6.vabs.qf16.qf16.128B" => "__builtin_HEXAGON_V6_vabs_qf16_qf16_128B", + "V6.vabs.qf32.qf32" => "__builtin_HEXAGON_V6_vabs_qf32_qf32", + "V6.vabs.qf32.qf32.128B" => "__builtin_HEXAGON_V6_vabs_qf32_qf32_128B", + "V6.vabs.qf32.sf" => "__builtin_HEXAGON_V6_vabs_qf32_sf", + "V6.vabs.qf32.sf.128B" => "__builtin_HEXAGON_V6_vabs_qf32_sf_128B", "V6.vabs.sf" => "__builtin_HEXAGON_V6_vabs_sf", "V6.vabs.sf.128B" => "__builtin_HEXAGON_V6_vabs_sf_128B", "V6.vabsb" => "__builtin_HEXAGON_V6_vabsb", @@ -1744,6 +1748,8 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "V6.vaddwsat.128B" => "__builtin_HEXAGON_V6_vaddwsat_128B", "V6.vaddwsat.dv" => "__builtin_HEXAGON_V6_vaddwsat_dv", "V6.vaddwsat.dv.128B" => "__builtin_HEXAGON_V6_vaddwsat_dv_128B", + "V6.valign4" => "__builtin_HEXAGON_V6_valign4", + "V6.valign4.128B" => "__builtin_HEXAGON_V6_valign4_128B", "V6.valignb" => "__builtin_HEXAGON_V6_valignb", "V6.valignb.128B" => "__builtin_HEXAGON_V6_valignb_128B", "V6.valignbi" => "__builtin_HEXAGON_V6_valignbi", @@ -1862,14 +1868,30 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "V6.vcl0w.128B" => "__builtin_HEXAGON_V6_vcl0w_128B", "V6.vcombine" => "__builtin_HEXAGON_V6_vcombine", "V6.vcombine.128B" => "__builtin_HEXAGON_V6_vcombine_128B", + "V6.vconv.bf.qf32" => "__builtin_HEXAGON_V6_vconv_bf_qf32", + "V6.vconv.bf.qf32.128B" => "__builtin_HEXAGON_V6_vconv_bf_qf32_128B", + "V6.vconv.f8.qf16" => "__builtin_HEXAGON_V6_vconv_f8_qf16", + "V6.vconv.f8.qf16.128B" => "__builtin_HEXAGON_V6_vconv_f8_qf16_128B", "V6.vconv.h.hf" => "__builtin_HEXAGON_V6_vconv_h_hf", "V6.vconv.h.hf.128B" => "__builtin_HEXAGON_V6_vconv_h_hf_128B", + "V6.vconv.h.hf.rnd" => "__builtin_HEXAGON_V6_vconv_h_hf_rnd", + "V6.vconv.h.hf.rnd.128B" => "__builtin_HEXAGON_V6_vconv_h_hf_rnd_128B", "V6.vconv.hf.h" => "__builtin_HEXAGON_V6_vconv_hf_h", "V6.vconv.hf.h.128B" => "__builtin_HEXAGON_V6_vconv_hf_h_128B", "V6.vconv.hf.qf16" => "__builtin_HEXAGON_V6_vconv_hf_qf16", "V6.vconv.hf.qf16.128B" => "__builtin_HEXAGON_V6_vconv_hf_qf16_128B", "V6.vconv.hf.qf32" => "__builtin_HEXAGON_V6_vconv_hf_qf32", "V6.vconv.hf.qf32.128B" => "__builtin_HEXAGON_V6_vconv_hf_qf32_128B", + "V6.vconv.qf16.f8" => "__builtin_HEXAGON_V6_vconv_qf16_f8", + "V6.vconv.qf16.f8.128B" => "__builtin_HEXAGON_V6_vconv_qf16_f8_128B", + "V6.vconv.qf16.hf" => "__builtin_HEXAGON_V6_vconv_qf16_hf", + "V6.vconv.qf16.hf.128B" => "__builtin_HEXAGON_V6_vconv_qf16_hf_128B", + "V6.vconv.qf16.qf16" => "__builtin_HEXAGON_V6_vconv_qf16_qf16", + "V6.vconv.qf16.qf16.128B" => "__builtin_HEXAGON_V6_vconv_qf16_qf16_128B", + "V6.vconv.qf32.qf32" => "__builtin_HEXAGON_V6_vconv_qf32_qf32", + "V6.vconv.qf32.qf32.128B" => "__builtin_HEXAGON_V6_vconv_qf32_qf32_128B", + "V6.vconv.qf32.sf" => "__builtin_HEXAGON_V6_vconv_qf32_sf", + "V6.vconv.qf32.sf.128B" => "__builtin_HEXAGON_V6_vconv_qf32_sf_128B", "V6.vconv.sf.qf32" => "__builtin_HEXAGON_V6_vconv_sf_qf32", "V6.vconv.sf.qf32.128B" => "__builtin_HEXAGON_V6_vconv_sf_qf32_128B", "V6.vconv.sf.w" => "__builtin_HEXAGON_V6_vconv_sf_w", @@ -1984,6 +2006,22 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "V6.veqh.or.128B" => "__builtin_HEXAGON_V6_veqh_or_128B", "V6.veqh.xor" => "__builtin_HEXAGON_V6_veqh_xor", "V6.veqh.xor.128B" => "__builtin_HEXAGON_V6_veqh_xor_128B", + "V6.veqhf" => "__builtin_HEXAGON_V6_veqhf", + "V6.veqhf.128B" => "__builtin_HEXAGON_V6_veqhf_128B", + "V6.veqhf.and" => "__builtin_HEXAGON_V6_veqhf_and", + "V6.veqhf.and.128B" => "__builtin_HEXAGON_V6_veqhf_and_128B", + "V6.veqhf.or" => "__builtin_HEXAGON_V6_veqhf_or", + "V6.veqhf.or.128B" => "__builtin_HEXAGON_V6_veqhf_or_128B", + "V6.veqhf.xor" => "__builtin_HEXAGON_V6_veqhf_xor", + "V6.veqhf.xor.128B" => "__builtin_HEXAGON_V6_veqhf_xor_128B", + "V6.veqsf" => "__builtin_HEXAGON_V6_veqsf", + "V6.veqsf.128B" => "__builtin_HEXAGON_V6_veqsf_128B", + "V6.veqsf.and" => "__builtin_HEXAGON_V6_veqsf_and", + "V6.veqsf.and.128B" => "__builtin_HEXAGON_V6_veqsf_and_128B", + "V6.veqsf.or" => "__builtin_HEXAGON_V6_veqsf_or", + "V6.veqsf.or.128B" => "__builtin_HEXAGON_V6_veqsf_or_128B", + "V6.veqsf.xor" => "__builtin_HEXAGON_V6_veqsf_xor", + "V6.veqsf.xor.128B" => "__builtin_HEXAGON_V6_veqsf_xor_128B", "V6.veqw" => "__builtin_HEXAGON_V6_veqw", "V6.veqw.128B" => "__builtin_HEXAGON_V6_veqw_128B", "V6.veqw.and" => "__builtin_HEXAGON_V6_veqw_and", @@ -2096,6 +2134,14 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "V6.vgtw.or.128B" => "__builtin_HEXAGON_V6_vgtw_or_128B", "V6.vgtw.xor" => "__builtin_HEXAGON_V6_vgtw_xor", "V6.vgtw.xor.128B" => "__builtin_HEXAGON_V6_vgtw_xor_128B", + "V6.vilog2.hf" => "__builtin_HEXAGON_V6_vilog2_hf", + "V6.vilog2.hf.128B" => "__builtin_HEXAGON_V6_vilog2_hf_128B", + "V6.vilog2.qf16" => "__builtin_HEXAGON_V6_vilog2_qf16", + "V6.vilog2.qf16.128B" => "__builtin_HEXAGON_V6_vilog2_qf16_128B", + "V6.vilog2.qf32" => "__builtin_HEXAGON_V6_vilog2_qf32", + "V6.vilog2.qf32.128B" => "__builtin_HEXAGON_V6_vilog2_qf32_128B", + "V6.vilog2.sf" => "__builtin_HEXAGON_V6_vilog2_sf", + "V6.vilog2.sf.128B" => "__builtin_HEXAGON_V6_vilog2_sf_128B", "V6.vinsertwr" => "__builtin_HEXAGON_V6_vinsertwr", "V6.vinsertwr.128B" => "__builtin_HEXAGON_V6_vinsertwr_128B", "V6.vlalignb" => "__builtin_HEXAGON_V6_vlalignb", @@ -2350,6 +2396,14 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "V6.vnavgub.128B" => "__builtin_HEXAGON_V6_vnavgub_128B", "V6.vnavgw" => "__builtin_HEXAGON_V6_vnavgw", "V6.vnavgw.128B" => "__builtin_HEXAGON_V6_vnavgw_128B", + "V6.vneg.qf16.hf" => "__builtin_HEXAGON_V6_vneg_qf16_hf", + "V6.vneg.qf16.hf.128B" => "__builtin_HEXAGON_V6_vneg_qf16_hf_128B", + "V6.vneg.qf16.qf16" => "__builtin_HEXAGON_V6_vneg_qf16_qf16", + "V6.vneg.qf16.qf16.128B" => "__builtin_HEXAGON_V6_vneg_qf16_qf16_128B", + "V6.vneg.qf32.qf32" => "__builtin_HEXAGON_V6_vneg_qf32_qf32", + "V6.vneg.qf32.qf32.128B" => "__builtin_HEXAGON_V6_vneg_qf32_qf32_128B", + "V6.vneg.qf32.sf" => "__builtin_HEXAGON_V6_vneg_qf32_sf", + "V6.vneg.qf32.sf.128B" => "__builtin_HEXAGON_V6_vneg_qf32_sf_128B", "V6.vnormamth" => "__builtin_HEXAGON_V6_vnormamth", "V6.vnormamth.128B" => "__builtin_HEXAGON_V6_vnormamth_128B", "V6.vnormamtw" => "__builtin_HEXAGON_V6_vnormamtw", @@ -2684,6 +2738,24 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "iocsrwr.d" => "__builtin_loongarch_iocsrwr_d", "iocsrwr.h" => "__builtin_loongarch_iocsrwr_h", "iocsrwr.w" => "__builtin_loongarch_iocsrwr_w", + "lasx.cast.128" => "__builtin_lasx_cast_128", + "lasx.cast.128.d" => "__builtin_lasx_cast_128_d", + "lasx.cast.128.s" => "__builtin_lasx_cast_128_s", + "lasx.concat.128" => "__builtin_lasx_concat_128", + "lasx.concat.128.d" => "__builtin_lasx_concat_128_d", + "lasx.concat.128.s" => "__builtin_lasx_concat_128_s", + "lasx.extract.128.hi" => "__builtin_lasx_extract_128_hi", + "lasx.extract.128.hi.d" => "__builtin_lasx_extract_128_hi_d", + "lasx.extract.128.hi.s" => "__builtin_lasx_extract_128_hi_s", + "lasx.extract.128.lo" => "__builtin_lasx_extract_128_lo", + "lasx.extract.128.lo.d" => "__builtin_lasx_extract_128_lo_d", + "lasx.extract.128.lo.s" => "__builtin_lasx_extract_128_lo_s", + "lasx.insert.128.hi" => "__builtin_lasx_insert_128_hi", + "lasx.insert.128.hi.d" => "__builtin_lasx_insert_128_hi_d", + "lasx.insert.128.hi.s" => "__builtin_lasx_insert_128_hi_s", + "lasx.insert.128.lo" => "__builtin_lasx_insert_128_lo", + "lasx.insert.128.lo.d" => "__builtin_lasx_insert_128_lo_d", + "lasx.insert.128.lo.s" => "__builtin_lasx_insert_128_lo_s", "lasx.vext2xv.d.b" => "__builtin_lasx_vext2xv_d_b", "lasx.vext2xv.d.h" => "__builtin_lasx_vext2xv_d_h", "lasx.vext2xv.d.w" => "__builtin_lasx_vext2xv_d_w", @@ -4950,8 +5022,20 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "f16x2.to.e5m2x2.rn.relu" => "__nvvm_f16x2_to_e5m2x2_rn_relu", "f2bf16.rn" => "__nvvm_f2bf16_rn", "f2bf16.rn.relu" => "__nvvm_f2bf16_rn_relu", + "f2bf16.rn.relu.satfinite" => "__nvvm_f2bf16_rn_relu_satfinite", + "f2bf16.rn.satfinite" => "__nvvm_f2bf16_rn_satfinite", "f2bf16.rz" => "__nvvm_f2bf16_rz", "f2bf16.rz.relu" => "__nvvm_f2bf16_rz_relu", + "f2bf16.rz.relu.satfinite" => "__nvvm_f2bf16_rz_relu_satfinite", + "f2bf16.rz.satfinite" => "__nvvm_f2bf16_rz_satfinite", + "f2f16.rn" => "__nvvm_f2f16_rn", + "f2f16.rn.relu" => "__nvvm_f2f16_rn_relu", + "f2f16.rn.relu.satfinite" => "__nvvm_f2f16_rn_relu_satfinite", + "f2f16.rn.satfinite" => "__nvvm_f2f16_rn_satfinite", + "f2f16.rz" => "__nvvm_f2f16_rz", + "f2f16.rz.relu" => "__nvvm_f2f16_rz_relu", + "f2f16.rz.relu.satfinite" => "__nvvm_f2f16_rz_relu_satfinite", + "f2f16.rz.satfinite" => "__nvvm_f2f16_rz_satfinite", "f2h.rn" => "__nvvm_f2h_rn", "f2h.rn.ftz" => "__nvvm_f2h_rn_ftz", "f2i.rm" => "__nvvm_f2i_rm", @@ -5035,20 +5119,28 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "ff.to.ue8m0x2.rz.satfinite" => "__nvvm_ff_to_ue8m0x2_rz_satfinite", "ff2bf16x2.rn" => "__nvvm_ff2bf16x2_rn", "ff2bf16x2.rn.relu" => "__nvvm_ff2bf16x2_rn_relu", + "ff2bf16x2.rn.relu.satfinite" => "__nvvm_ff2bf16x2_rn_relu_satfinite", + "ff2bf16x2.rn.satfinite" => "__nvvm_ff2bf16x2_rn_satfinite", "ff2bf16x2.rs" => "__nvvm_ff2bf16x2_rs", "ff2bf16x2.rs.relu" => "__nvvm_ff2bf16x2_rs_relu", "ff2bf16x2.rs.relu.satfinite" => "__nvvm_ff2bf16x2_rs_relu_satfinite", "ff2bf16x2.rs.satfinite" => "__nvvm_ff2bf16x2_rs_satfinite", "ff2bf16x2.rz" => "__nvvm_ff2bf16x2_rz", "ff2bf16x2.rz.relu" => "__nvvm_ff2bf16x2_rz_relu", + "ff2bf16x2.rz.relu.satfinite" => "__nvvm_ff2bf16x2_rz_relu_satfinite", + "ff2bf16x2.rz.satfinite" => "__nvvm_ff2bf16x2_rz_satfinite", "ff2f16x2.rn" => "__nvvm_ff2f16x2_rn", "ff2f16x2.rn.relu" => "__nvvm_ff2f16x2_rn_relu", + "ff2f16x2.rn.relu.satfinite" => "__nvvm_ff2f16x2_rn_relu_satfinite", + "ff2f16x2.rn.satfinite" => "__nvvm_ff2f16x2_rn_satfinite", "ff2f16x2.rs" => "__nvvm_ff2f16x2_rs", "ff2f16x2.rs.relu" => "__nvvm_ff2f16x2_rs_relu", "ff2f16x2.rs.relu.satfinite" => "__nvvm_ff2f16x2_rs_relu_satfinite", "ff2f16x2.rs.satfinite" => "__nvvm_ff2f16x2_rs_satfinite", "ff2f16x2.rz" => "__nvvm_ff2f16x2_rz", "ff2f16x2.rz.relu" => "__nvvm_ff2f16x2_rz_relu", + "ff2f16x2.rz.relu.satfinite" => "__nvvm_ff2f16x2_rz_relu_satfinite", + "ff2f16x2.rz.satfinite" => "__nvvm_ff2f16x2_rz_satfinite", "floor.d" => "__nvvm_floor_d", "floor.f" => "__nvvm_floor_f", "floor.ftz.f" => "__nvvm_floor_ftz_f", @@ -5942,6 +6034,8 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "altivec.vupklsb" => "__builtin_altivec_vupklsb", "altivec.vupklsh" => "__builtin_altivec_vupklsh", "altivec.vupklsw" => "__builtin_altivec_vupklsw", + "amo.ldat" => "__builtin_amo_ldat", + "amo.lwat" => "__builtin_amo_lwat", "bcdadd" => "__builtin_ppc_bcdadd", "bcdadd.p" => "__builtin_ppc_bcdadd_p", "bcdcopysign" => "__builtin_ppc_bcdcopysign", @@ -6202,6 +6296,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "vsx.xvminsp" => "__builtin_vsx_xvminsp", "vsx.xvredp" => "__builtin_vsx_xvredp", "vsx.xvresp" => "__builtin_vsx_xvresp", + "vsx.xvrlw" => "__builtin_vsx_xvrlw", "vsx.xvrsqrtedp" => "__builtin_vsx_xvrsqrtedp", "vsx.xvrsqrtesp" => "__builtin_vsx_xvrsqrtesp", "vsx.xvtdivdp" => "__builtin_vsx_xvtdivdp", @@ -10158,24 +10253,16 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "stui" => "__builtin_ia32_stui", "subborrow.u32" => "__builtin_ia32_subborrow_u32", "subborrow.u64" => "__builtin_ia32_subborrow_u64", - "t2rpntlvwz0" => "__builtin_ia32_t2rpntlvwz0", "t2rpntlvwz0rs" => "__builtin_ia32_t2rpntlvwz0rs", "t2rpntlvwz0rst1" => "__builtin_ia32_t2rpntlvwz0rst1", - "t2rpntlvwz0t1" => "__builtin_ia32_t2rpntlvwz0t1", - "t2rpntlvwz1" => "__builtin_ia32_t2rpntlvwz1", "t2rpntlvwz1rs" => "__builtin_ia32_t2rpntlvwz1rs", "t2rpntlvwz1rst1" => "__builtin_ia32_t2rpntlvwz1rst1", - "t2rpntlvwz1t1" => "__builtin_ia32_t2rpntlvwz1t1", "tbm.bextri.u32" => "__builtin_ia32_bextri_u32", "tbm.bextri.u64" => "__builtin_ia32_bextri_u64", "tcmmimfp16ps" => "__builtin_ia32_tcmmimfp16ps", "tcmmimfp16ps.internal" => "__builtin_ia32_tcmmimfp16ps_internal", "tcmmrlfp16ps" => "__builtin_ia32_tcmmrlfp16ps", "tcmmrlfp16ps.internal" => "__builtin_ia32_tcmmrlfp16ps_internal", - "tconjtcmmimfp16ps" => "__builtin_ia32_tconjtcmmimfp16ps", - "tconjtcmmimfp16ps.internal" => "__builtin_ia32_tconjtcmmimfp16ps_internal", - "tconjtfp16" => "__builtin_ia32_tconjtfp16", - "tconjtfp16.internal" => "__builtin_ia32_tconjtfp16_internal", "tcvtrowd2ps" => "__builtin_ia32_tcvtrowd2ps", "tcvtrowd2ps.internal" => "__builtin_ia32_tcvtrowd2ps_internal", "tcvtrowps2bf16h" => "__builtin_ia32_tcvtrowps2bf16h", @@ -10225,18 +10312,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "tmmultf32ps" => "__builtin_ia32_tmmultf32ps", "tmmultf32ps.internal" => "__builtin_ia32_tmmultf32ps_internal", "tpause" => "__builtin_ia32_tpause", - "ttcmmimfp16ps" => "__builtin_ia32_ttcmmimfp16ps", - "ttcmmimfp16ps.internal" => "__builtin_ia32_ttcmmimfp16ps_internal", - "ttcmmrlfp16ps" => "__builtin_ia32_ttcmmrlfp16ps", - "ttcmmrlfp16ps.internal" => "__builtin_ia32_ttcmmrlfp16ps_internal", - "ttdpbf16ps" => "__builtin_ia32_ttdpbf16ps", - "ttdpbf16ps.internal" => "__builtin_ia32_ttdpbf16ps_internal", - "ttdpfp16ps" => "__builtin_ia32_ttdpfp16ps", - "ttdpfp16ps.internal" => "__builtin_ia32_ttdpfp16ps_internal", - "ttmmultf32ps" => "__builtin_ia32_ttmmultf32ps", - "ttmmultf32ps.internal" => "__builtin_ia32_ttmmultf32ps_internal", - "ttransposed" => "__builtin_ia32_ttransposed", - "ttransposed.internal" => "__builtin_ia32_ttransposed_internal", "umonitor" => "__builtin_ia32_umonitor", "umwait" => "__builtin_ia32_umwait", "urdmsr" => "__builtin_ia32_urdmsr", diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 2380bd0fc137..99a80fa7e4f4 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -88,3 +88,12 @@ tests/ui/test-attrs/test-panic-while-printing.rs tests/ui/thir-print/offset_of.rs tests/ui/iterators/rangefrom-overflow-debug.rs tests/ui/iterators/rangefrom-overflow-overflow-checks.rs +tests/ui/iterators/iter-filter-count-debug-check.rs +tests/ui/eii/codegen_single_crate.rs +tests/ui/eii/codegen_cross_crate.rs +tests/ui/eii/default/local_crate.rs +tests/ui/eii/multiple_impls.rs +tests/ui/eii/default/call_default.rs +tests/ui/eii/same-symbol.rs +tests/ui/eii/privacy1.rs +tests/ui/eii/default/call_impl.rs diff --git a/triagebot.toml b/triagebot.toml index 13da0a87def3..eb0c7b011f60 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -2,6 +2,3 @@ # Prevents un-canonicalized issue links (to avoid wrong issues being linked in r-l/rust) [issue-links] - -# Prevents mentions in commits to avoid users being spammed -[no-mentions] From df25df1af84487b9ce9e793834e91bbf1485cecf Mon Sep 17 00:00:00 2001 From: EFanZh Date: Sat, 27 Dec 2025 12:29:19 +0800 Subject: [PATCH 036/978] Constify `fmt::from_fn` --- library/core/src/fmt/builders.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 197cddd3fa9d..7550dac45cd0 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -1227,8 +1227,9 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// assert_eq!(format!("{:?}", wrapped), "'a'"); /// ``` #[stable(feature = "fmt_from_fn", since = "1.93.0")] +#[rustc_const_stable(feature = "const_fmt_from_fn", since = "CURRENT_RUSTC_VERSION")] #[must_use = "returns a type implementing Debug and Display, which do not have any effects unless they are used"] -pub fn from_fn) -> fmt::Result>(f: F) -> FromFn { +pub const fn from_fn) -> fmt::Result>(f: F) -> FromFn { FromFn(f) } From 9ba3ed5423d409cf92ab85a80c9b49dd9a148c92 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 18 Sep 2025 13:25:01 +0000 Subject: [PATCH 037/978] Move llvm intrinsic call to backend --- src/intrinsic/mod.rs | 52 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index d2714ba7914f..75ea39c23114 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -9,7 +9,7 @@ use gccjit::Type; use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp}; #[cfg(feature = "master")] use rustc_abi::ExternAbi; -use rustc_abi::{BackendRepr, HasDataLayout}; +use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; @@ -20,7 +20,7 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; use rustc_codegen_ssa::traits::MiscCodegenMethods; use rustc_codegen_ssa::traits::{ ArgAbiBuilderMethods, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, - IntrinsicCallBuilderMethods, + IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods, }; use rustc_middle::bug; #[cfg(feature = "master")] @@ -609,6 +609,54 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc Ok(()) } + fn codegen_llvm_intrinsic_call( + &mut self, + instance: ty::Instance<'tcx>, + args: &[OperandRef<'tcx, Self::Value>], + is_cleanup: bool, + ) -> Self::Value { + let fn_ptr = self.get_fn_addr(instance); + let fn_ty = fn_ptr.get_type(); + + let mut llargs = vec![]; + + for arg in args { + match arg.val { + OperandValue::ZeroSized => {} + OperandValue::Immediate(_) => llargs.push(arg.immediate()), + OperandValue::Pair(a, b) => { + llargs.push(a); + llargs.push(b); + } + OperandValue::Ref(op_place_val) => { + let mut llval = op_place_val.llval; + // We can't use `PlaceRef::load` here because the argument + // may have a type we don't treat as immediate, but the ABI + // used for this call is passing it by-value. In that case, + // the load would just produce `OperandValue::Ref` instead + // of the `OperandValue::Immediate` we need for the call. + llval = self.load(self.backend_type(arg.layout), llval, op_place_val.align); + if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr { + if scalar.is_bool() { + self.range_metadata(llval, WrappingRange { start: 0, end: 1 }); + } + // We store bools as `i8` so we need to truncate to `i1`. + llval = self.to_immediate_scalar(llval, scalar); + } + llargs.push(llval); + } + } + } + + // FIXME directly use the llvm intrinsic adjustment functions here + let llret = self.call(fn_ty, None, None, fn_ptr, &llargs, None, None); + if is_cleanup { + self.apply_attrs_to_cleanup_callsite(llret); + } + + llret + } + fn abort(&mut self) { let func = self.context.get_builtin_function("abort"); let func: RValue<'gcc> = unsafe { std::mem::transmute(func) }; From 0462ce9934e6b66e44c5f4ab673ff3fde52395b7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:03:25 +0100 Subject: [PATCH 038/978] Don't assume get_fn is only called from codegen_mir in cg_gcc --- src/builder.rs | 1 + src/context.rs | 4 +--- src/declare.rs | 8 ++------ 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 79228c20d292..f57c50eb64d1 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -514,6 +514,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { type CodegenCx = CodegenCx<'gcc, 'tcx>; fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Builder<'a, 'gcc, 'tcx> { + *cx.current_func.borrow_mut() = Some(block.get_function()); Builder::with_cx(cx, block) } diff --git a/src/context.rs b/src/context.rs index dbb89a4ff7db..67bec261cc2e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -391,9 +391,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn get_fn(&self, instance: Instance<'tcx>) -> Function<'gcc> { - let func = get_fn(self, instance); - *self.current_func.borrow_mut() = Some(func); - func + get_fn(self, instance) } fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> { diff --git a/src/declare.rs b/src/declare.rs index 42d6fb17a88b..fec7d9d0a403 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -100,18 +100,14 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let return_type = self.type_i32(); let variadic = false; self.linkage.set(FunctionType::Exported); - let func = declare_raw_fn( + declare_raw_fn( self, name, callconv, return_type, &[self.type_i32(), const_string], variadic, - ); - // NOTE: it is needed to set the current_func here as well, because get_fn() is not called - // for the main function. - *self.current_func.borrow_mut() = Some(func); - func + ) } pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> { From 56be08eb45c2a1e0169470a3f0644fe296d1b534 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:14:03 +0100 Subject: [PATCH 039/978] Pass Function to Builder::function_call in cg_gcc --- src/builder.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index f57c50eb64d1..8b4a8de94bf3 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -316,12 +316,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fn function_call( &mut self, - func: RValue<'gcc>, + func: Function<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>, ) -> RValue<'gcc> { - // TODO(antoyo): remove when the API supports a different type for functions. - let func: Function<'gcc> = self.cx.rvalue_as_function(func); let args = self.check_call("call", func, args); // gccjit requires to use the result of functions, even when it's not used. @@ -1766,6 +1764,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // FIXME(antoyo): remove when having a proper API. let gcc_func = unsafe { std::mem::transmute::, Function<'gcc>>(func) }; let call = if self.functions.borrow().values().any(|value| *value == gcc_func) { + // TODO(antoyo): remove when the API supports a different type for functions. + let func: Function<'gcc> = self.cx.rvalue_as_function(func); self.function_call(func, args, funclet) } else { // If it's a not function that was defined, it's a function pointer. From 5bcd472b8688437b4967bcba077c4089572a17ea Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 10 Nov 2025 13:42:32 +0000 Subject: [PATCH 040/978] Partially inline get_fn_addr/get_fn in codegen_llvm_intrinsic_call This moves all LLVM intrinsic handling out of the regular call path for cg_gcc and makes it easier to hook into this code for future cg_llvm changes. --- src/builder.rs | 2 +- src/context.rs | 7 ++++--- src/declare.rs | 14 -------------- src/intrinsic/mod.rs | 42 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 8b4a8de94bf3..3def9a5c015c 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -314,7 +314,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.block.get_function() } - fn function_call( + pub fn function_call( &mut self, func: Function<'gcc>, args: &[RValue<'gcc>], diff --git a/src/context.rs b/src/context.rs index 67bec261cc2e..d200d5319a93 100644 --- a/src/context.rs +++ b/src/context.rs @@ -92,6 +92,8 @@ pub struct CodegenCx<'gcc, 'tcx> { pub instances: RefCell, LValue<'gcc>>>, /// Cache function instances of monomorphic and polymorphic items pub function_instances: RefCell, Function<'gcc>>>, + /// Cache function instances of intrinsics + pub intrinsic_instances: RefCell, Function<'gcc>>>, /// Cache generated vtables pub vtables: RefCell, Option>), RValue<'gcc>>>, @@ -280,6 +282,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { linkage: Cell::new(FunctionType::Internal), instances: Default::default(), function_instances: Default::default(), + intrinsic_instances: Default::default(), on_stack_params: Default::default(), on_stack_function_params: Default::default(), vtables: Default::default(), @@ -397,9 +400,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> { let func_name = self.tcx.symbol_name(instance).name; - let func = if self.intrinsics.borrow().contains_key(func_name) { - self.intrinsics.borrow()[func_name] - } else if let Some(variable) = self.get_declared_value(func_name) { + let func = if let Some(variable) = self.get_declared_value(func_name) { return variable; } else { get_fn(self, instance) diff --git a/src/declare.rs b/src/declare.rs index fec7d9d0a403..e4130b221ee3 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -8,7 +8,6 @@ use rustc_target::callconv::FnAbi; use crate::abi::{FnAbiGcc, FnAbiGccExt}; use crate::context::CodegenCx; -use crate::intrinsic::llvm; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { pub fn get_or_insert_global( @@ -162,19 +161,6 @@ fn declare_raw_fn<'gcc>( param_types: &[Type<'gcc>], variadic: bool, ) -> Function<'gcc> { - if name.starts_with("llvm.") { - let intrinsic = match name { - "llvm.fma.f16" => { - // fma is not a target builtin, but a normal builtin, so we handle it differently - // here. - cx.context.get_builtin_function("fma") - } - _ => llvm::intrinsic(name, cx), - }; - - cx.intrinsics.borrow_mut().insert(name.to_string(), intrinsic); - return intrinsic; - } let func = if cx.functions.borrow().contains_key(name) { cx.functions.borrow()[name] } else { diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 75ea39c23114..77b88a969084 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -615,7 +615,47 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc args: &[OperandRef<'tcx, Self::Value>], is_cleanup: bool, ) -> Self::Value { - let fn_ptr = self.get_fn_addr(instance); + let func = if let Some(&func) = self.intrinsic_instances.borrow().get(&instance) { + func + } else { + let sym = self.tcx.symbol_name(instance).name; + + let func = if let Some(func) = self.intrinsics.borrow().get(sym) { + *func + } else { + self.linkage.set(FunctionType::Extern); + let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); + let fn_ty = fn_abi.gcc_type(self); + + let func = match sym { + "llvm.fma.f16" => { + // fma is not a target builtin, but a normal builtin, so we handle it differently + // here. + self.context.get_builtin_function("fma") + } + _ => llvm::intrinsic(sym, self), + }; + + self.intrinsics.borrow_mut().insert(sym.to_string(), func); + + self.on_stack_function_params + .borrow_mut() + .insert(func, fn_ty.on_stack_param_indices); + #[cfg(feature = "master")] + for fn_attr in fn_ty.fn_attributes { + func.add_attribute(fn_attr); + } + + crate::attributes::from_fn_attrs(self, func, instance); + + func + }; + + self.intrinsic_instances.borrow_mut().insert(instance, func); + + func + }; + let fn_ptr = func.get_address(None); let fn_ty = fn_ptr.get_type(); let mut llargs = vec![]; From ea8f037c760f1eb0099521230c87318d028d8e49 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 27 Dec 2025 08:49:59 +0000 Subject: [PATCH 041/978] Fix compilation of cg_gcc with master feature disabled --- src/intrinsic/mod.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 77b88a969084..36ea76cbc51a 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -23,16 +23,12 @@ use rustc_codegen_ssa::traits::{ IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods, }; use rustc_middle::bug; -#[cfg(feature = "master")] -use rustc_middle::ty::layout::FnAbiOf; -use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::{Span, Symbol, sym}; use rustc_target::callconv::{ArgAbi, PassMode}; -#[cfg(feature = "master")] -use crate::abi::FnAbiGccExt; -use crate::abi::GccType; +use crate::abi::{FnAbiGccExt, GccType}; use crate::builder::Builder; use crate::common::{SignType, TypeReflection}; use crate::context::CodegenCx; From 57e44f5046058d467b9f8731f4c49885a8664d8e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 2 Jan 2026 18:39:06 +0100 Subject: [PATCH 042/978] skip codegen for intrinsics with big fallback bodies if backend does not need them --- compiler/rustc_codegen_llvm/src/lib.rs | 6 +++++- compiler/rustc_codegen_ssa/src/traits/backend.rs | 6 ++++++ compiler/rustc_interface/src/interface.rs | 1 + compiler/rustc_monomorphize/src/collector.rs | 9 +++++---- compiler/rustc_session/src/session.rs | 7 ++++++- tests/codegen-llvm/intrinsics/carrying_mul_add.rs | 5 ++--- 6 files changed, 25 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 095274744993..875b60ef6ddb 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -42,7 +42,7 @@ use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_session::Session; use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest}; -use rustc_span::Symbol; +use rustc_span::{Symbol, sym}; use rustc_target::spec::{RelocModel, TlsModel}; use crate::llvm::ToLlvmBool; @@ -333,6 +333,10 @@ impl CodegenBackend for LlvmCodegenBackend { target_config(sess) } + fn replaced_intrinsics(&self) -> Vec { + vec![sym::unchecked_funnel_shl, sym::unchecked_funnel_shr, sym::carrying_mul_add] + } + fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box { Box::new(rustc_codegen_ssa::base::codegen_crate( LlvmCodegenBackend(()), diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index cb74e2e46d65..2ca24836d046 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -78,6 +78,12 @@ pub trait CodegenBackend { fn print_version(&self) {} + /// Returns a list of all intrinsics that this backend definitely + /// replaces, which means their fallback bodies do not need to be monomorphized. + fn replaced_intrinsics(&self) -> Vec { + vec![] + } + /// Value printed by `--print=backend-has-zstd`. /// /// Used by compiletest to determine whether tests involving zstd compression diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index c0f8f33692e8..c60cf9b8992a 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -496,6 +496,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se ); codegen_backend.init(&sess); + sess.replaced_intrinsics = FxHashSet::from_iter(codegen_backend.replaced_intrinsics()); let cfg = parse_cfg(sess.dcx(), config.crate_cfg); let mut cfg = config::build_configuration(&sess, cfg); diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 4b2f8e03afc1..622fdeb4e81c 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1001,11 +1001,12 @@ fn visit_instance_use<'tcx>( if tcx.should_codegen_locally(panic_instance) { output.push(create_fn_mono_item(tcx, panic_instance, source)); } - } else if !intrinsic.must_be_overridden { + } else if !intrinsic.must_be_overridden + && !tcx.sess.replaced_intrinsics.contains(&intrinsic.name) + { // Codegen the fallback body of intrinsics with fallback bodies. - // We explicitly skip this otherwise to ensure we get a linker error - // if anyone tries to call this intrinsic and the codegen backend did not - // override the implementation. + // We have to skip this otherwise as there's no body to codegen. + // We also skip intrinsics the backend handles, to reduce monomorphizations. let instance = ty::Instance::new_raw(instance.def_id(), instance.args); if tcx.should_codegen_locally(instance) { output.push(create_fn_mono_item(tcx, instance, source)); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 1a0ec600af47..b3027d902b4c 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -8,7 +8,7 @@ use std::{env, io}; use rand::{RngCore, rng}; use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN}; use rustc_data_structures::flock; -use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; use rustc_data_structures::sync::{DynSend, DynSync, Lock, MappedReadGuard, ReadGuard, RwLock}; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter; @@ -154,6 +154,10 @@ pub struct Session { /// preserved with a flag like `-C save-temps`, since these files may be /// hard linked. pub invocation_temp: Option, + + /// The names of intrinsics that the current codegen backend replaces + /// with its own implementations. + pub replaced_intrinsics: FxHashSet, } #[derive(Clone, Copy)] @@ -1091,6 +1095,7 @@ pub fn build_session( target_filesearch, host_filesearch, invocation_temp, + replaced_intrinsics: FxHashSet::default(), // filled by `run_compiler` }; validate_commandline_args_with_session_available(&sess); diff --git a/tests/codegen-llvm/intrinsics/carrying_mul_add.rs b/tests/codegen-llvm/intrinsics/carrying_mul_add.rs index 21fb49a3786a..844f4f6cff64 100644 --- a/tests/codegen-llvm/intrinsics/carrying_mul_add.rs +++ b/tests/codegen-llvm/intrinsics/carrying_mul_add.rs @@ -11,10 +11,9 @@ use std::intrinsics::{carrying_mul_add, fallback}; -// The fallbacks are emitted even when they're never used, but optimize out. +// The fallbacks should not be emitted. -// RAW: wide_mul_u128 -// OPT-NOT: wide_mul_u128 +// NOT: wide_mul_u128 // CHECK-LABEL: @cma_u8 #[no_mangle] From ebd4bc9224a5de37ce151745b00cb8039fef4385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 27 Dec 2025 20:56:37 +0000 Subject: [PATCH 043/978] Support long diff conflict markers git can be configured to use more than 7 characters for conflict markers, and jj automatically uses longer conflict markers when the text contains any char sequence that could be confused with conflict markers. Ensure that we only point at markers that are consistent with the start marker's length. Ensure that we only consider char sequences at the beginning of a line as a diff marker. --- .../rustc_parse/src/parser/diagnostics.rs | 54 +++++++++++++++---- .../diff-markers/long-conflict-markers.rs | 11 ++++ .../diff-markers/long-conflict-markers.stderr | 20 +++++++ 3 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 tests/ui/parser/diff-markers/long-conflict-markers.rs create mode 100644 tests/ui/parser/diff-markers/long-conflict-markers.stderr diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 70ec80a50812..9c4895e391d2 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -3037,27 +3037,53 @@ impl<'a> Parser<'a> { long_kind: &TokenKind, short_kind: &TokenKind, ) -> bool { - (0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind)) - && self.look_ahead(3, |tok| tok == short_kind) + if long_kind == short_kind { + // For conflict marker chars like `%` and `\`. + (0..7).all(|i| self.look_ahead(i, |tok| tok == long_kind)) + } else { + // For conflict marker chars like `<` and `|`. + (0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind)) + && self.look_ahead(3, |tok| tok == short_kind || tok == long_kind) + } } - fn conflict_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> Option { + fn conflict_marker( + &mut self, + long_kind: &TokenKind, + short_kind: &TokenKind, + expected: Option, + ) -> Option<(Span, usize)> { if self.is_vcs_conflict_marker(long_kind, short_kind) { let lo = self.token.span; - for _ in 0..4 { - self.bump(); + if self.psess.source_map().span_to_margin(lo) != Some(0) { + return None; } - return Some(lo.to(self.prev_token.span)); + let mut len = 0; + while self.token.kind == *long_kind || self.token.kind == *short_kind { + if self.token.kind.break_two_token_op(1).is_some() { + len += 2; + } else { + len += 1; + } + self.bump(); + if expected == Some(len) { + break; + } + } + if expected.is_some() && expected != Some(len) { + return None; + } + return Some((lo.to(self.prev_token.span), len)); } None } pub(super) fn recover_vcs_conflict_marker(&mut self) { // <<<<<<< - let Some(start) = self.conflict_marker(&TokenKind::Shl, &TokenKind::Lt) else { + let Some((start, len)) = self.conflict_marker(&TokenKind::Shl, &TokenKind::Lt, None) else { return; }; - let mut spans = Vec::with_capacity(3); + let mut spans = Vec::with_capacity(2); spans.push(start); // ||||||| let mut middlediff3 = None; @@ -3069,13 +3095,19 @@ impl<'a> Parser<'a> { if self.token == TokenKind::Eof { break; } - if let Some(span) = self.conflict_marker(&TokenKind::OrOr, &TokenKind::Or) { + if let Some((span, _)) = + self.conflict_marker(&TokenKind::OrOr, &TokenKind::Or, Some(len)) + { middlediff3 = Some(span); } - if let Some(span) = self.conflict_marker(&TokenKind::EqEq, &TokenKind::Eq) { + if let Some((span, _)) = + self.conflict_marker(&TokenKind::EqEq, &TokenKind::Eq, Some(len)) + { middle = Some(span); } - if let Some(span) = self.conflict_marker(&TokenKind::Shr, &TokenKind::Gt) { + if let Some((span, _)) = + self.conflict_marker(&TokenKind::Shr, &TokenKind::Gt, Some(len)) + { spans.push(span); end = Some(span); break; diff --git a/tests/ui/parser/diff-markers/long-conflict-markers.rs b/tests/ui/parser/diff-markers/long-conflict-markers.rs new file mode 100644 index 000000000000..f92615fb75b4 --- /dev/null +++ b/tests/ui/parser/diff-markers/long-conflict-markers.rs @@ -0,0 +1,11 @@ +enum E { + Foo { +<<<<<<<<< HEAD //~ ERROR encountered diff marker + x: u8, +||||||| + z: (), +========= + y: i8, +>>>>>>>>> branch + } +} diff --git a/tests/ui/parser/diff-markers/long-conflict-markers.stderr b/tests/ui/parser/diff-markers/long-conflict-markers.stderr new file mode 100644 index 000000000000..c83aaf16b741 --- /dev/null +++ b/tests/ui/parser/diff-markers/long-conflict-markers.stderr @@ -0,0 +1,20 @@ +error: encountered diff marker + --> $DIR/long-conflict-markers.rs:3:1 + | +LL | <<<<<<<<< HEAD + | ^^^^^^^^^ between this marker and `=======` is the code that you are merging into +... +LL | ========= + | --------- between this marker and `>>>>>>>` is the incoming code +LL | y: i8, +LL | >>>>>>>>> branch + | ^^^^^^^^^ this marker concludes the conflict region + | + = note: conflict markers indicate that a merge was started but could not be completed due to merge conflicts + to resolve a conflict, keep only the code you want and then delete the lines containing conflict markers + = help: if you are in a merge, the top section is the code you already had checked out and the bottom section is the new code + if you are in a rebase, the top section is the code being rebased onto and the bottom section is the code you had checked out which is being rebased + = note: for an explanation on these markers from the `git` documentation, visit + +error: aborting due to 1 previous error + From acc8c0bd65a057c7e61d3e70556e66b66d3f45b7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 28 Dec 2025 13:05:09 +0000 Subject: [PATCH 044/978] Reduce usage of FnAbi in codegen_llvm_intrinsic_call --- .../rustc_codegen_gcc/src/intrinsic/mod.rs | 88 ++++++++++++++++++- compiler/rustc_codegen_llvm/src/intrinsic.rs | 30 ++++++- 2 files changed, 111 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 36ea76cbc51a..f138b87d3405 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -4,10 +4,10 @@ mod simd; #[cfg(feature = "master")] use std::iter; -#[cfg(feature = "master")] -use gccjit::Type; use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp}; #[cfg(feature = "master")] +use gccjit::{FnAttribute, Type}; +#[cfg(feature = "master")] use rustc_abi::ExternAbi; use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::MemFlags; @@ -22,13 +22,18 @@ use rustc_codegen_ssa::traits::{ ArgAbiBuilderMethods, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods, }; +use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::{self, Instance, Ty}; +#[cfg(feature = "master")] +use rustc_session::config; use rustc_span::{Span, Symbol, sym}; +#[cfg(feature = "master")] +use rustc_target::callconv::ArgAttributes; use rustc_target::callconv::{ArgAbi, PassMode}; -use crate::abi::{FnAbiGccExt, GccType}; +use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType}; use crate::builder::Builder; use crate::common::{SignType, TypeReflection}; use crate::context::CodegenCx; @@ -621,7 +626,82 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } else { self.linkage.set(FunctionType::Extern); let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); - let fn_ty = fn_abi.gcc_type(self); + assert!(!fn_abi.ret.is_indirect()); + assert!(!fn_abi.c_variadic); + + let return_type = match fn_abi.ret.mode { + PassMode::Ignore => self.type_void(), + PassMode::Direct(_) | PassMode::Pair(..) => { + fn_abi.ret.layout.immediate_gcc_type(self) + } + PassMode::Cast { .. } | PassMode::Indirect { .. } => { + unreachable!() + } + }; + + #[cfg(feature = "master")] + let mut non_null_args = Vec::new(); + + #[cfg(feature = "master")] + let mut apply_attrs = + |mut ty: Type<'gcc>, attrs: &ArgAttributes, arg_index: usize| { + if self.sess().opts.optimize == config::OptLevel::No { + return ty; + } + if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NoAlias) { + ty = ty.make_restrict() + } + if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) { + non_null_args.push(arg_index as i32 + 1); + } + ty + }; + #[cfg(not(feature = "master"))] + let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| ty; + + let mut argument_tys = Vec::with_capacity(fn_abi.args.len()); + for arg in fn_abi.args.iter() { + match arg.mode { + PassMode::Ignore => {} + PassMode::Pair(a, b) => { + let arg_pos = argument_tys.len(); + argument_tys.push(apply_attrs( + arg.layout.scalar_pair_element_gcc_type(self, 0), + &a, + arg_pos, + )); + argument_tys.push(apply_attrs( + arg.layout.scalar_pair_element_gcc_type(self, 1), + &b, + arg_pos + 1, + )); + } + PassMode::Direct(attrs) => argument_tys.push(apply_attrs( + arg.layout.immediate_gcc_type(self), + &attrs, + argument_tys.len(), + )), + PassMode::Indirect { .. } | PassMode::Cast { .. } => { + unreachable!() + } + } + } + + #[cfg(feature = "master")] + let fn_attrs = if non_null_args.is_empty() { + Vec::new() + } else { + vec![FnAttribute::NonNull(non_null_args)] + }; + + let fn_ty = FnAbiGcc { + return_type, + arguments_type: argument_tys, + is_c_variadic: false, + on_stack_param_indices: FxHashSet::default(), + #[cfg(feature = "master")] + fn_attributes: fn_attrs, + }; let func = match sym { "llvm.fma.f16" => { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 481f75f337d6..7327137fbbdd 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -649,7 +649,32 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { // FIXME remove usage of fn_abi let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); assert!(!fn_abi.ret.is_indirect()); - let fn_ty = fn_abi.llvm_type(self); + assert!(!fn_abi.c_variadic); + + let llreturn_ty = match &fn_abi.ret.mode { + PassMode::Ignore => self.type_void(), + PassMode::Direct(_) | PassMode::Pair(..) => fn_abi.ret.layout.immediate_llvm_type(self), + PassMode::Cast { .. } | PassMode::Indirect { .. } => { + unreachable!() + } + }; + + let mut llargument_tys = Vec::with_capacity(fn_abi.args.len()); + for arg in &fn_abi.args { + match &arg.mode { + PassMode::Ignore => {} + PassMode::Direct(_) => llargument_tys.push(arg.layout.immediate_llvm_type(self)), + PassMode::Pair(..) => { + llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(self, 0, true)); + llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(self, 1, true)); + } + PassMode::Indirect { .. } | PassMode::Cast { .. } => { + unreachable!() + } + }; + } + + let fn_ty = self.type_func(&llargument_tys, llreturn_ty); let fn_ptr = if let Some(&llfn) = self.intrinsic_instances.borrow().get(&instance) { llfn @@ -665,12 +690,11 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let llfn = declare_raw_fn( self, sym, - fn_abi.llvm_cconv(self), + llvm::CCallConv, llvm::UnnamedAddr::Global, llvm::Visibility::Default, fn_ty, ); - fn_abi.apply_attrs_llfn(self, llfn, Some(instance)); llfn }; From f004b3eb19b988a9066ca9dc9b2a63919f504ada Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 28 Dec 2025 13:05:09 +0000 Subject: [PATCH 045/978] Reduce usage of FnAbi in codegen_llvm_intrinsic_call --- src/intrinsic/mod.rs | 88 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 4 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 36ea76cbc51a..f138b87d3405 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -4,10 +4,10 @@ mod simd; #[cfg(feature = "master")] use std::iter; -#[cfg(feature = "master")] -use gccjit::Type; use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp}; #[cfg(feature = "master")] +use gccjit::{FnAttribute, Type}; +#[cfg(feature = "master")] use rustc_abi::ExternAbi; use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::MemFlags; @@ -22,13 +22,18 @@ use rustc_codegen_ssa::traits::{ ArgAbiBuilderMethods, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods, }; +use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::{self, Instance, Ty}; +#[cfg(feature = "master")] +use rustc_session::config; use rustc_span::{Span, Symbol, sym}; +#[cfg(feature = "master")] +use rustc_target::callconv::ArgAttributes; use rustc_target::callconv::{ArgAbi, PassMode}; -use crate::abi::{FnAbiGccExt, GccType}; +use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType}; use crate::builder::Builder; use crate::common::{SignType, TypeReflection}; use crate::context::CodegenCx; @@ -621,7 +626,82 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } else { self.linkage.set(FunctionType::Extern); let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); - let fn_ty = fn_abi.gcc_type(self); + assert!(!fn_abi.ret.is_indirect()); + assert!(!fn_abi.c_variadic); + + let return_type = match fn_abi.ret.mode { + PassMode::Ignore => self.type_void(), + PassMode::Direct(_) | PassMode::Pair(..) => { + fn_abi.ret.layout.immediate_gcc_type(self) + } + PassMode::Cast { .. } | PassMode::Indirect { .. } => { + unreachable!() + } + }; + + #[cfg(feature = "master")] + let mut non_null_args = Vec::new(); + + #[cfg(feature = "master")] + let mut apply_attrs = + |mut ty: Type<'gcc>, attrs: &ArgAttributes, arg_index: usize| { + if self.sess().opts.optimize == config::OptLevel::No { + return ty; + } + if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NoAlias) { + ty = ty.make_restrict() + } + if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) { + non_null_args.push(arg_index as i32 + 1); + } + ty + }; + #[cfg(not(feature = "master"))] + let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| ty; + + let mut argument_tys = Vec::with_capacity(fn_abi.args.len()); + for arg in fn_abi.args.iter() { + match arg.mode { + PassMode::Ignore => {} + PassMode::Pair(a, b) => { + let arg_pos = argument_tys.len(); + argument_tys.push(apply_attrs( + arg.layout.scalar_pair_element_gcc_type(self, 0), + &a, + arg_pos, + )); + argument_tys.push(apply_attrs( + arg.layout.scalar_pair_element_gcc_type(self, 1), + &b, + arg_pos + 1, + )); + } + PassMode::Direct(attrs) => argument_tys.push(apply_attrs( + arg.layout.immediate_gcc_type(self), + &attrs, + argument_tys.len(), + )), + PassMode::Indirect { .. } | PassMode::Cast { .. } => { + unreachable!() + } + } + } + + #[cfg(feature = "master")] + let fn_attrs = if non_null_args.is_empty() { + Vec::new() + } else { + vec![FnAttribute::NonNull(non_null_args)] + }; + + let fn_ty = FnAbiGcc { + return_type, + arguments_type: argument_tys, + is_c_variadic: false, + on_stack_param_indices: FxHashSet::default(), + #[cfg(feature = "master")] + fn_attributes: fn_attrs, + }; let func = match sym { "llvm.fma.f16" => { From f1ab0036585e64bffbdc8ac20e7b0a5fb9507e95 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 8 Jan 2026 10:47:29 +0000 Subject: [PATCH 046/978] Don't compute FnAbi for LLVM intrinsics in backends --- .../rustc_codegen_gcc/src/intrinsic/mod.rs | 101 ++---------------- compiler/rustc_codegen_llvm/src/intrinsic.rs | 48 +++++---- 2 files changed, 34 insertions(+), 115 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index f138b87d3405..de262994fa45 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -4,9 +4,9 @@ mod simd; #[cfg(feature = "master")] use std::iter; -use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp}; #[cfg(feature = "master")] -use gccjit::{FnAttribute, Type}; +use gccjit::Type; +use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp}; #[cfg(feature = "master")] use rustc_abi::ExternAbi; use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange}; @@ -24,16 +24,16 @@ use rustc_codegen_ssa::traits::{ }; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; -use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; +#[cfg(feature = "master")] +use rustc_middle::ty::layout::FnAbiOf; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance, Ty}; -#[cfg(feature = "master")] -use rustc_session::config; use rustc_span::{Span, Symbol, sym}; -#[cfg(feature = "master")] -use rustc_target::callconv::ArgAttributes; use rustc_target::callconv::{ArgAbi, PassMode}; -use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType}; +#[cfg(feature = "master")] +use crate::abi::FnAbiGccExt; +use crate::abi::GccType; use crate::builder::Builder; use crate::common::{SignType, TypeReflection}; use crate::context::CodegenCx; @@ -625,83 +625,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc *func } else { self.linkage.set(FunctionType::Extern); - let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); - assert!(!fn_abi.ret.is_indirect()); - assert!(!fn_abi.c_variadic); - - let return_type = match fn_abi.ret.mode { - PassMode::Ignore => self.type_void(), - PassMode::Direct(_) | PassMode::Pair(..) => { - fn_abi.ret.layout.immediate_gcc_type(self) - } - PassMode::Cast { .. } | PassMode::Indirect { .. } => { - unreachable!() - } - }; - - #[cfg(feature = "master")] - let mut non_null_args = Vec::new(); - - #[cfg(feature = "master")] - let mut apply_attrs = - |mut ty: Type<'gcc>, attrs: &ArgAttributes, arg_index: usize| { - if self.sess().opts.optimize == config::OptLevel::No { - return ty; - } - if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NoAlias) { - ty = ty.make_restrict() - } - if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) { - non_null_args.push(arg_index as i32 + 1); - } - ty - }; - #[cfg(not(feature = "master"))] - let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| ty; - - let mut argument_tys = Vec::with_capacity(fn_abi.args.len()); - for arg in fn_abi.args.iter() { - match arg.mode { - PassMode::Ignore => {} - PassMode::Pair(a, b) => { - let arg_pos = argument_tys.len(); - argument_tys.push(apply_attrs( - arg.layout.scalar_pair_element_gcc_type(self, 0), - &a, - arg_pos, - )); - argument_tys.push(apply_attrs( - arg.layout.scalar_pair_element_gcc_type(self, 1), - &b, - arg_pos + 1, - )); - } - PassMode::Direct(attrs) => argument_tys.push(apply_attrs( - arg.layout.immediate_gcc_type(self), - &attrs, - argument_tys.len(), - )), - PassMode::Indirect { .. } | PassMode::Cast { .. } => { - unreachable!() - } - } - } - - #[cfg(feature = "master")] - let fn_attrs = if non_null_args.is_empty() { - Vec::new() - } else { - vec![FnAttribute::NonNull(non_null_args)] - }; - - let fn_ty = FnAbiGcc { - return_type, - arguments_type: argument_tys, - is_c_variadic: false, - on_stack_param_indices: FxHashSet::default(), - #[cfg(feature = "master")] - fn_attributes: fn_attrs, - }; let func = match sym { "llvm.fma.f16" => { @@ -714,13 +637,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc self.intrinsics.borrow_mut().insert(sym.to_string(), func); - self.on_stack_function_params - .borrow_mut() - .insert(func, fn_ty.on_stack_param_indices); - #[cfg(feature = "master")] - for fn_attr in fn_ty.fn_attributes { - func.add_attribute(fn_attr); - } + self.on_stack_function_params.borrow_mut().insert(func, FxHashSet::default()); crate::attributes::from_fn_attrs(self, func, instance); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 7327137fbbdd..13402edd13e2 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -646,32 +646,34 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { ) -> Self::Value { let tcx = self.tcx(); - // FIXME remove usage of fn_abi - let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); - assert!(!fn_abi.ret.is_indirect()); - assert!(!fn_abi.c_variadic); - - let llreturn_ty = match &fn_abi.ret.mode { - PassMode::Ignore => self.type_void(), - PassMode::Direct(_) | PassMode::Pair(..) => fn_abi.ret.layout.immediate_llvm_type(self), - PassMode::Cast { .. } | PassMode::Indirect { .. } => { - unreachable!() + let fn_ty = instance.ty(tcx, self.typing_env()); + let fn_sig = match *fn_ty.kind() { + ty::FnDef(def_id, args) => { + tcx.instantiate_bound_regions_with_erased(tcx.fn_sig(def_id).instantiate(tcx, args)) } + _ => unreachable!(), + }; + assert!(!fn_sig.c_variadic); + + let ret_layout = self.layout_of(fn_sig.output()); + let llreturn_ty = if ret_layout.is_zst() { + self.type_void() + } else { + ret_layout.immediate_llvm_type(self) }; - let mut llargument_tys = Vec::with_capacity(fn_abi.args.len()); - for arg in &fn_abi.args { - match &arg.mode { - PassMode::Ignore => {} - PassMode::Direct(_) => llargument_tys.push(arg.layout.immediate_llvm_type(self)), - PassMode::Pair(..) => { - llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(self, 0, true)); - llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(self, 1, true)); - } - PassMode::Indirect { .. } | PassMode::Cast { .. } => { - unreachable!() - } - }; + let mut llargument_tys = Vec::with_capacity(fn_sig.inputs().len()); + for &arg in fn_sig.inputs() { + let arg_layout = self.layout_of(arg); + if arg_layout.is_zst() { + continue; + } + if let BackendRepr::ScalarPair(_, _) = arg_layout.backend_repr { + llargument_tys.push(arg_layout.scalar_pair_element_llvm_type(self, 0, true)); + llargument_tys.push(arg_layout.scalar_pair_element_llvm_type(self, 1, true)); + continue; + } + llargument_tys.push(arg_layout.immediate_llvm_type(self)); } let fn_ty = self.type_func(&llargument_tys, llreturn_ty); From e90414f6224b95662c2f52fcfc508a316f54db09 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 8 Jan 2026 10:47:29 +0000 Subject: [PATCH 047/978] Don't compute FnAbi for LLVM intrinsics in backends --- src/intrinsic/mod.rs | 101 ++++--------------------------------------- 1 file changed, 9 insertions(+), 92 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index f138b87d3405..de262994fa45 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -4,9 +4,9 @@ mod simd; #[cfg(feature = "master")] use std::iter; -use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp}; #[cfg(feature = "master")] -use gccjit::{FnAttribute, Type}; +use gccjit::Type; +use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, UnaryOp}; #[cfg(feature = "master")] use rustc_abi::ExternAbi; use rustc_abi::{BackendRepr, HasDataLayout, WrappingRange}; @@ -24,16 +24,16 @@ use rustc_codegen_ssa::traits::{ }; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; -use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; +#[cfg(feature = "master")] +use rustc_middle::ty::layout::FnAbiOf; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance, Ty}; -#[cfg(feature = "master")] -use rustc_session::config; use rustc_span::{Span, Symbol, sym}; -#[cfg(feature = "master")] -use rustc_target::callconv::ArgAttributes; use rustc_target::callconv::{ArgAbi, PassMode}; -use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType}; +#[cfg(feature = "master")] +use crate::abi::FnAbiGccExt; +use crate::abi::GccType; use crate::builder::Builder; use crate::common::{SignType, TypeReflection}; use crate::context::CodegenCx; @@ -625,83 +625,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc *func } else { self.linkage.set(FunctionType::Extern); - let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); - assert!(!fn_abi.ret.is_indirect()); - assert!(!fn_abi.c_variadic); - - let return_type = match fn_abi.ret.mode { - PassMode::Ignore => self.type_void(), - PassMode::Direct(_) | PassMode::Pair(..) => { - fn_abi.ret.layout.immediate_gcc_type(self) - } - PassMode::Cast { .. } | PassMode::Indirect { .. } => { - unreachable!() - } - }; - - #[cfg(feature = "master")] - let mut non_null_args = Vec::new(); - - #[cfg(feature = "master")] - let mut apply_attrs = - |mut ty: Type<'gcc>, attrs: &ArgAttributes, arg_index: usize| { - if self.sess().opts.optimize == config::OptLevel::No { - return ty; - } - if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NoAlias) { - ty = ty.make_restrict() - } - if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) { - non_null_args.push(arg_index as i32 + 1); - } - ty - }; - #[cfg(not(feature = "master"))] - let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| ty; - - let mut argument_tys = Vec::with_capacity(fn_abi.args.len()); - for arg in fn_abi.args.iter() { - match arg.mode { - PassMode::Ignore => {} - PassMode::Pair(a, b) => { - let arg_pos = argument_tys.len(); - argument_tys.push(apply_attrs( - arg.layout.scalar_pair_element_gcc_type(self, 0), - &a, - arg_pos, - )); - argument_tys.push(apply_attrs( - arg.layout.scalar_pair_element_gcc_type(self, 1), - &b, - arg_pos + 1, - )); - } - PassMode::Direct(attrs) => argument_tys.push(apply_attrs( - arg.layout.immediate_gcc_type(self), - &attrs, - argument_tys.len(), - )), - PassMode::Indirect { .. } | PassMode::Cast { .. } => { - unreachable!() - } - } - } - - #[cfg(feature = "master")] - let fn_attrs = if non_null_args.is_empty() { - Vec::new() - } else { - vec![FnAttribute::NonNull(non_null_args)] - }; - - let fn_ty = FnAbiGcc { - return_type, - arguments_type: argument_tys, - is_c_variadic: false, - on_stack_param_indices: FxHashSet::default(), - #[cfg(feature = "master")] - fn_attributes: fn_attrs, - }; let func = match sym { "llvm.fma.f16" => { @@ -714,13 +637,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc self.intrinsics.borrow_mut().insert(sym.to_string(), func); - self.on_stack_function_params - .borrow_mut() - .insert(func, fn_ty.on_stack_param_indices); - #[cfg(feature = "master")] - for fn_attr in fn_ty.fn_attributes { - func.add_attribute(fn_attr); - } + self.on_stack_function_params.borrow_mut().insert(func, FxHashSet::default()); crate::attributes::from_fn_attrs(self, func, instance); From fe0facf0f6f021f0c5d597fb214d96ae48571c91 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Thu, 1 Jan 2026 10:47:22 +0100 Subject: [PATCH 048/978] Finish transition from `semitransparent` to `semiopaque` for `rustc_macro_transparency` --- example/mini_core.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 64a5b431bd07..0aba44a88c5a 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -748,25 +748,25 @@ extern "C" { pub struct VaList<'a>(&'a mut VaListImpl); #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[rustc_macro_transparency = "semiopaque"] pub macro stringify($($t:tt)*) { /* compiler built-in */ } #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[rustc_macro_transparency = "semiopaque"] pub macro file() { /* compiler built-in */ } #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[rustc_macro_transparency = "semiopaque"] pub macro line() { /* compiler built-in */ } #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[rustc_macro_transparency = "semiopaque"] pub macro cfg() { /* compiler built-in */ } From fe9715b5e8fb9e425fa14ce2830a3faafd3adf78 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 8 Jan 2026 18:44:38 +0000 Subject: [PATCH 049/978] Remove support for ScalarPair unadjusted arguments --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 13402edd13e2..d7a928f492f0 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -668,11 +668,6 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { if arg_layout.is_zst() { continue; } - if let BackendRepr::ScalarPair(_, _) = arg_layout.backend_repr { - llargument_tys.push(arg_layout.scalar_pair_element_llvm_type(self, 0, true)); - llargument_tys.push(arg_layout.scalar_pair_element_llvm_type(self, 1, true)); - continue; - } llargument_tys.push(arg_layout.immediate_llvm_type(self)); } From cd6c41283838023ee3b22709106d666869ec9a6f Mon Sep 17 00:00:00 2001 From: Zachary S Date: Tue, 13 Jan 2026 22:40:12 -0600 Subject: [PATCH 050/978] Add test for feature-gating `mut ref` patterns in struct field shorthand. --- tests/ui/feature-gates/feature-gate-mut-ref.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/ui/feature-gates/feature-gate-mut-ref.rs b/tests/ui/feature-gates/feature-gate-mut-ref.rs index 752ae35d8a9a..eac2a59002e2 100644 --- a/tests/ui/feature-gates/feature-gate-mut-ref.rs +++ b/tests/ui/feature-gates/feature-gate-mut-ref.rs @@ -10,4 +10,7 @@ fn main() { let mut ref x = 10; //~ ERROR [E0658] #[cfg(false)] let mut ref mut y = 10; //~ ERROR [E0658] + + struct Foo { x: i32 } + let Foo { mut ref x } = Foo { x: 10 }; } From f809e332d895bc80d28d8d2cb10297a3fe9ca4f2 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Tue, 13 Jan 2026 12:57:04 -0600 Subject: [PATCH 051/978] Feature-gate `mut ref` patterns in struct field shorthand. --- compiler/rustc_parse/src/parser/pat.rs | 6 ++++++ tests/ui/feature-gates/feature-gate-mut-ref.rs | 2 +- tests/ui/feature-gates/feature-gate-mut-ref.stderr | 12 +++++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index d7f3a36122e5..f3e12d48a6a5 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1750,6 +1750,12 @@ impl<'a> Parser<'a> { hi = self.prev_token.span; let ann = BindingMode(by_ref, mutability); let fieldpat = self.mk_pat_ident(boxed_span.to(hi), ann, fieldname); + if matches!( + fieldpat.kind, + PatKind::Ident(BindingMode(ByRef::Yes(..), Mutability::Mut), ..) + ) { + self.psess.gated_spans.gate(sym::mut_ref, fieldpat.span); + } let subpat = if is_box { self.mk_pat(lo.to(hi), PatKind::Box(Box::new(fieldpat))) } else { diff --git a/tests/ui/feature-gates/feature-gate-mut-ref.rs b/tests/ui/feature-gates/feature-gate-mut-ref.rs index eac2a59002e2..74b1fba5dfea 100644 --- a/tests/ui/feature-gates/feature-gate-mut-ref.rs +++ b/tests/ui/feature-gates/feature-gate-mut-ref.rs @@ -12,5 +12,5 @@ fn main() { let mut ref mut y = 10; //~ ERROR [E0658] struct Foo { x: i32 } - let Foo { mut ref x } = Foo { x: 10 }; + let Foo { mut ref x } = Foo { x: 10 }; //~ ERROR [E0658] } diff --git a/tests/ui/feature-gates/feature-gate-mut-ref.stderr b/tests/ui/feature-gates/feature-gate-mut-ref.stderr index d3eb674e92de..921ff878bf4d 100644 --- a/tests/ui/feature-gates/feature-gate-mut-ref.stderr +++ b/tests/ui/feature-gates/feature-gate-mut-ref.stderr @@ -38,6 +38,16 @@ LL | let mut ref mut y = 10; = help: add `#![feature(mut_ref)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 4 previous errors +error[E0658]: mutable by-reference bindings are experimental + --> $DIR/feature-gate-mut-ref.rs:15:15 + | +LL | let Foo { mut ref x } = Foo { x: 10 }; + | ^^^^^^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0658`. From c9a063ced93ec7dce1dfaca57f818dba5334cfca Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 14 Jan 2026 10:30:08 +1100 Subject: [PATCH 052/978] Remove `Deref`/`DerefMut` impl for `Providers`. It's described as a "backwards compatibility hack to keep the diff small". Removing it requires only a modest amount of churn, and the resulting code is clearer without the invisible derefs. --- src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 96d3a0024f41..cf1be1806235 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -286,7 +286,8 @@ impl CodegenBackend for GccCodegenBackend { } fn provide(&self, providers: &mut Providers) { - providers.global_backend_features = |tcx, ()| gcc_util::global_gcc_features(tcx.sess) + providers.queries.global_backend_features = + |tcx, ()| gcc_util::global_gcc_features(tcx.sess) } fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box { From 628bacac3312357af71816b0875174062b310a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sun, 4 Jan 2026 04:22:55 +0100 Subject: [PATCH 053/978] add tests for emergent behavior of partial captures --- .../auxiliary/partial_move_drop_order_lib.rs | 11 ++ .../match/auxiliary/partial_move_lib.rs | 4 + .../match/partial-move-drop-order.rs | 83 ++++++++++++ .../match/partial-move-drop-order.run.stdout | 23 ++++ .../match/partial-move.rs | 118 +++++++++++++++++ .../match/partial-move.stderr | 123 ++++++++++++++++++ 6 files changed, 362 insertions(+) create mode 100644 tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_drop_order_lib.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_lib.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout create mode 100644 tests/ui/closures/2229_closure_analysis/match/partial-move.rs create mode 100644 tests/ui/closures/2229_closure_analysis/match/partial-move.stderr diff --git a/tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_drop_order_lib.rs b/tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_drop_order_lib.rs new file mode 100644 index 000000000000..8cf25c6ba7b2 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_drop_order_lib.rs @@ -0,0 +1,11 @@ +pub struct LoudDrop(pub &'static str); +impl Drop for LoudDrop { + fn drop(&mut self) { + println!("dropping {}", self.0); + } +} + +#[non_exhaustive] +pub enum ExtNonExhaustive { + One(i32, LoudDrop), +} diff --git a/tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_lib.rs b/tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_lib.rs new file mode 100644 index 000000000000..b0646f1d0032 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/auxiliary/partial_move_lib.rs @@ -0,0 +1,4 @@ +#[non_exhaustive] +pub enum ExtNonExhaustive { + A(u32, String), +} diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs new file mode 100644 index 000000000000..1c178bd3f684 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs @@ -0,0 +1,83 @@ +//@ edition:2021 +//@ run-pass +//@ check-run-results +//@ aux-build:partial_move_drop_order_lib.rs + +extern crate partial_move_drop_order_lib; +use partial_move_drop_order_lib::{LoudDrop, ExtNonExhaustive}; + +pub enum OneVariant { + One(i32, LoudDrop), +} + +pub enum TwoVariants { + One(i32, LoudDrop), + Two, +} + +#[non_exhaustive] +pub enum NonExhaustive { + One(i32, LoudDrop), +} + +#[allow(unused)] +fn one_variant() { + println!("one variant:"); + let mut thing = OneVariant::One(0, LoudDrop("a")); + let closure = move || match thing { + OneVariant::One(x, _) => {} + _ => unreachable!(), + }; + println!("before assign"); + thing = OneVariant::One(1, LoudDrop("b")); + println!("after assign"); +} + +#[allow(unused)] +fn two_variants() { + println!("two variants:"); + let mut thing = TwoVariants::One(0, LoudDrop("a")); + let closure = move || match thing { + TwoVariants::One(x, _) => {} + _ => unreachable!(), + }; + println!("before assign"); + thing = TwoVariants::One(1, LoudDrop("b")); + println!("after assign"); +} + +#[allow(unused)] +fn non_exhaustive() { + println!("non exhaustive:"); + let mut thing = NonExhaustive::One(0, LoudDrop("a")); + let closure = move || match thing { + NonExhaustive::One(x, _) => {} + _ => unreachable!(), + }; + println!("before assign"); + thing = NonExhaustive::One(1, LoudDrop("b")); + println!("after assign"); +} + +#[allow(unused)] +fn ext_non_exhaustive() { + println!("external non exhaustive:"); + let mut thing = ExtNonExhaustive::One(0, LoudDrop("a")); + let closure = move || match thing { + ExtNonExhaustive::One(x, _) => {} + _ => unreachable!(), + }; + println!("before assign"); + thing = ExtNonExhaustive::One(1, LoudDrop("b")); + println!("after assign"); +} + +fn main() { + one_variant(); + println!(); + two_variants(); + println!(); + non_exhaustive(); + println!(); + ext_non_exhaustive(); +} diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout new file mode 100644 index 000000000000..e0d83dd99549 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout @@ -0,0 +1,23 @@ +one variant: +before assign +dropping a +after assign +dropping b + +two variants: +before assign +after assign +dropping a +dropping b + +non exhaustive: +before assign +dropping a +after assign +dropping b + +external non exhaustive: +before assign +after assign +dropping a +dropping b diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move.rs b/tests/ui/closures/2229_closure_analysis/match/partial-move.rs new file mode 100644 index 000000000000..62d1b362cb83 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move.rs @@ -0,0 +1,118 @@ +// This test measures the effect of matching-induced partial captures on the borrow checker. +// In particular, in each of the cases below, the closure either captures the entire enum/struct, +// or each field separately. +// +// If the entire ADT gets captured, it'll happen by move, and the closure will live for 'static. +// On the other hand, if each field gets captured separately, the u32 field, being Copy, will only +// get captured by an immutable borrow, resulting in a borrow checker error. +// +// See rust-lang/rust#147722 +// +//@ edition:2021 +//@ aux-build:partial_move_lib.rs +pub struct Struct(u32, String); + +pub enum Enum { + A(u32, String), +} + +pub enum TwoVariants { + A(u32, String), + B, +} + +#[non_exhaustive] +pub enum NonExhaustive { + A(u32, String), +} + +extern crate partial_move_lib; +use partial_move_lib::ExtNonExhaustive; + +// First, let's assert that the additional wildcard arm is not a source of any behavior +// differences: +pub fn test_enum1(x: Enum) -> impl FnOnce() { + || { + //~^ ERROR: closure may outlive the current function, but it borrows `x.0` + match x { + Enum::A(a, b) => { + drop((a, b)); + } + _ => unreachable!(), + } + } +} + +pub fn test_enum2(x: Enum) -> impl FnOnce() { + || { + //~^ ERROR: closure may outlive the current function, but it borrows `x.0` + match x { + Enum::A(a, b) => { + drop((a, b)); + } + } + } +} + +// The behavior for single-variant enums matches what happens for a struct +pub fn test_struct(x: Struct) -> impl FnOnce() { + || { + //~^ ERROR: closure may outlive the current function, but it borrows `x.0` + match x { + Struct(a, b) => { + drop((a, b)); + } + } + } +} + +// If we have two variants, the entire enum gets moved into the closure +pub fn test_two_variants(x: TwoVariants) -> impl FnOnce() { + || { + match x { + TwoVariants::A(a, b) => { + drop((a, b)); + } + _ => unreachable!(), + } + } +} + +// ...and single-variant, non-exhaustive enums *should* behave as if they had multiple variants +pub fn test_non_exhaustive1(x: NonExhaustive) -> impl FnOnce() { + || { + //~^ ERROR: closure may outlive the current function, but it borrows `x.0` + match x { + NonExhaustive::A(a, b) => { + drop((a, b)); + } + _ => unreachable!(), + } + } +} + +// (again, wildcard branch or not) +pub fn test_non_exhaustive2(x: NonExhaustive) -> impl FnOnce() { + || { + //~^ ERROR: closure may outlive the current function, but it borrows `x.0` + match x { + NonExhaustive::A(a, b) => { + drop((a, b)); + } + } + } +} + +// ...regardless of whether the enum is defined in the current, or in another crate +pub fn test_ext(x: ExtNonExhaustive) -> impl FnOnce() { + || { + match x { + ExtNonExhaustive::A(a, b) => { + drop((a, b)); + } + _ => unreachable!(), + } + } +} + +fn main() {} diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move.stderr b/tests/ui/closures/2229_closure_analysis/match/partial-move.stderr new file mode 100644 index 000000000000..36adcc6717ed --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move.stderr @@ -0,0 +1,123 @@ +error[E0373]: closure may outlive the current function, but it borrows `x.0`, which is owned by the current function + --> $DIR/partial-move.rs:35:5 + | +LL | || { + | ^^ may outlive borrowed value `x.0` +LL | +LL | match x { + | - `x.0` is borrowed here + | +note: closure is returned here + --> $DIR/partial-move.rs:35:5 + | +LL | / || { +LL | | +LL | | match x { +LL | | Enum::A(a, b) => { +... | +LL | | } + | |_____^ +help: to force the closure to take ownership of `x.0` (and any other referenced variables), use the `move` keyword + | +LL | move || { + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x.0`, which is owned by the current function + --> $DIR/partial-move.rs:47:5 + | +LL | || { + | ^^ may outlive borrowed value `x.0` +LL | +LL | match x { + | - `x.0` is borrowed here + | +note: closure is returned here + --> $DIR/partial-move.rs:47:5 + | +LL | / || { +LL | | +LL | | match x { +LL | | Enum::A(a, b) => { +... | +LL | | } + | |_____^ +help: to force the closure to take ownership of `x.0` (and any other referenced variables), use the `move` keyword + | +LL | move || { + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x.0`, which is owned by the current function + --> $DIR/partial-move.rs:59:5 + | +LL | || { + | ^^ may outlive borrowed value `x.0` +LL | +LL | match x { + | - `x.0` is borrowed here + | +note: closure is returned here + --> $DIR/partial-move.rs:59:5 + | +LL | / || { +LL | | +LL | | match x { +LL | | Struct(a, b) => { +... | +LL | | } + | |_____^ +help: to force the closure to take ownership of `x.0` (and any other referenced variables), use the `move` keyword + | +LL | move || { + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x.0`, which is owned by the current function + --> $DIR/partial-move.rs:83:5 + | +LL | || { + | ^^ may outlive borrowed value `x.0` +LL | +LL | match x { + | - `x.0` is borrowed here + | +note: closure is returned here + --> $DIR/partial-move.rs:83:5 + | +LL | / || { +LL | | +LL | | match x { +LL | | NonExhaustive::A(a, b) => { +... | +LL | | } + | |_____^ +help: to force the closure to take ownership of `x.0` (and any other referenced variables), use the `move` keyword + | +LL | move || { + | ++++ + +error[E0373]: closure may outlive the current function, but it borrows `x.0`, which is owned by the current function + --> $DIR/partial-move.rs:96:5 + | +LL | || { + | ^^ may outlive borrowed value `x.0` +LL | +LL | match x { + | - `x.0` is borrowed here + | +note: closure is returned here + --> $DIR/partial-move.rs:96:5 + | +LL | / || { +LL | | +LL | | match x { +LL | | NonExhaustive::A(a, b) => { +... | +LL | | } + | |_____^ +help: to force the closure to take ownership of `x.0` (and any other referenced variables), use the `move` keyword + | +LL | move || { + | ++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0373`. From 3c175080dca2a60eb42a28d46ecc416d3a6f8879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sun, 4 Jan 2026 19:34:37 +0100 Subject: [PATCH 054/978] add tests for discriminant read borrowck --- tests/ui/match/borrowck-uninhabited.rs | 53 +++++++++++++++++++ tests/ui/match/borrowck-uninhabited.stderr | 14 +++++ tests/ui/match/uninhabited-granular-moves.rs | 46 ++++++++++++++++ .../match/uninhabited-granular-moves.stderr | 18 +++++++ 4 files changed, 131 insertions(+) create mode 100644 tests/ui/match/borrowck-uninhabited.rs create mode 100644 tests/ui/match/borrowck-uninhabited.stderr create mode 100644 tests/ui/match/uninhabited-granular-moves.rs create mode 100644 tests/ui/match/uninhabited-granular-moves.stderr diff --git a/tests/ui/match/borrowck-uninhabited.rs b/tests/ui/match/borrowck-uninhabited.rs new file mode 100644 index 000000000000..93838ede2793 --- /dev/null +++ b/tests/ui/match/borrowck-uninhabited.rs @@ -0,0 +1,53 @@ +// See: rust-lang/rust#146590 + +enum Never {} + +// baseline +fn both_inhabited(x: &mut Result) { + match x { + &mut Ok(ref mut y) => match x { + //~^ ERROR: cannot use `*x` because it was mutably borrowed + &mut Err(ref mut z) => { + let _y = y; + let _z = z; + } + _ => {} + }, + _ => {} + }; +} + +fn ref_uninhabited(x: &mut Result) { + match x { + &mut Ok(ref mut y) => match x { + &mut Err(ref mut z) => { + let _y = y; + let _z = z; + } + _ => {} + }, + _ => {} + }; +} + +enum Single { + V(String, String), +} + +// arguably this should be rejected as well, but currently it is still accepted +fn single_variant(x: &mut Single) { + match x { + &mut Single::V(ref mut y, _) => { + match x { + &mut Single::V(_, ref mut z) => { + let _y = y; + let _z = z; + } + _ => {} + } + }, + _ => {} + }; +} + +fn main() {} diff --git a/tests/ui/match/borrowck-uninhabited.stderr b/tests/ui/match/borrowck-uninhabited.stderr new file mode 100644 index 000000000000..ee3b814da9f4 --- /dev/null +++ b/tests/ui/match/borrowck-uninhabited.stderr @@ -0,0 +1,14 @@ +error[E0503]: cannot use `*x` because it was mutably borrowed + --> $DIR/borrowck-uninhabited.rs:8:37 + | +LL | &mut Ok(ref mut y) => match x { + | --------- ^ use of borrowed `x.0` + | | + | `x.0` is borrowed here +... +LL | let _y = y; + | - borrow later used here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/match/uninhabited-granular-moves.rs b/tests/ui/match/uninhabited-granular-moves.rs new file mode 100644 index 000000000000..9d04fcb3259e --- /dev/null +++ b/tests/ui/match/uninhabited-granular-moves.rs @@ -0,0 +1,46 @@ +// See rust-lang/rust#146590, as well as Zulip discussion: +// +// https://rust-lang.zulipchat.com/#narrow/channel/513289-t-patterns/topic/Question.20about.20patterns.20and.20moves/with/558638455 +// +// Whether pattern matching performs a discriminant read shouldn't depend on whether +// you explicitly write down an uninhabited branch, or leave it implicit. + +enum Emp { } + +enum Foo { + Bar(A), + Qux(Emp), +} + +fn test1(thefoo: Foo<(Box, Box)>) { + match thefoo { + Foo::Bar((a, _)) => { } + } + + match thefoo { + Foo::Bar((_, a)) => { } + } +} + +fn test2(thefoo: Foo<(Box, Box)>) { + match thefoo { + Foo::Bar((a, _)) => { } + Foo::Qux(_) => { } + } + match thefoo { //~ ERROR: use of partially moved value: `thefoo` + Foo::Bar((_, a)) => { } + Foo::Qux(_) => { } + } +} + +fn test3(thefoo: Foo<(Box, Box)>) { + match thefoo { + Foo::Bar((a, _)) => { } + Foo::Qux(_) => { } + } + match thefoo { + Foo::Bar((_, a)) => { } + } +} + +fn main() {} diff --git a/tests/ui/match/uninhabited-granular-moves.stderr b/tests/ui/match/uninhabited-granular-moves.stderr new file mode 100644 index 000000000000..d32f935d3d55 --- /dev/null +++ b/tests/ui/match/uninhabited-granular-moves.stderr @@ -0,0 +1,18 @@ +error[E0382]: use of partially moved value: `thefoo` + --> $DIR/uninhabited-granular-moves.rs:30:11 + | +LL | Foo::Bar((a, _)) => { } + | - value partially moved here +... +LL | match thefoo { + | ^^^^^^ value used here after partial move + | + = note: partial move occurs because value has type `Box`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | Foo::Bar((ref a, _)) => { } + | +++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. From ee1a6f4e88bb71d964864de1d7c935d53a3d0cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sun, 4 Jan 2026 04:22:55 +0100 Subject: [PATCH 055/978] match in closure: capture non_exhaustive even if defined in current crate --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 29 +++-------- .../match/non-exhaustive-match.rs | 16 +++--- .../match/non-exhaustive-match.stderr | 19 +++++-- .../match/partial-move-drop-order.rs | 5 ++ .../match/partial-move-drop-order.run.stdout | 2 +- .../match/partial-move.rs | 4 +- .../match/partial-move.stderr | 50 +------------------ 7 files changed, 39 insertions(+), 86 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index ad34994526ed..9e9b511b9b23 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -818,14 +818,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx /// The core driver for walking a pattern /// /// This should mirror how pattern-matching gets lowered to MIR, as - /// otherwise lowering will ICE when trying to resolve the upvars. + /// otherwise said lowering will ICE when trying to resolve the upvars. /// /// However, it is okay to approximate it here by doing *more* accesses than /// the actual MIR builder will, which is useful when some checks are too - /// cumbersome to perform here. For example, if after typeck it becomes - /// clear that only one variant of an enum is inhabited, and therefore a - /// read of the discriminant is not necessary, `walk_pat` will have - /// over-approximated the necessary upvar capture granularity. + /// cumbersome to perform here, because e.g. they require more typeck results + /// than available. /// /// Do note that discrepancies like these do still create obscure corners /// in the semantics of the language, and should be avoided if possible. @@ -1852,26 +1850,13 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } /// Checks whether a type has multiple variants, and therefore, whether a - /// read of the discriminant might be necessary. Note that the actual MIR - /// builder code does a more specific check, filtering out variants that - /// happen to be uninhabited. - /// - /// Here, it is not practical to perform such a check, because inhabitedness - /// queries require typeck results, and typeck requires closure capture analysis. - /// - /// Moreover, the language is moving towards uninhabited variants still semantically - /// causing a discriminant read, so we *shouldn't* perform any such check. - /// - /// FIXME(never_patterns): update this comment once the aforementioned MIR builder - /// code is changed to be insensitive to inhhabitedness. + /// read of the discriminant might be necessary. #[instrument(skip(self, span), level = "debug")] fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool { if let ty::Adt(def, _) = self.cx.structurally_resolve_type(span, ty).kind() { - // Note that if a non-exhaustive SingleVariant is defined in another crate, we need - // to assume that more cases will be added to the variant in the future. This mean - // that we should handle non-exhaustive SingleVariant the same way we would handle - // a MultiVariant. - def.variants().len() > 1 || def.variant_list_has_applicable_non_exhaustive() + // We treat non-exhaustive enums the same independent of the crate they are + // defined in, to avoid differences in the operational semantics between crates. + def.variants().len() > 1 || def.is_variant_list_non_exhaustive() } else { false } diff --git a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs index 5b7259c6c2cc..f47d70b52f20 100644 --- a/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs +++ b/tests/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs @@ -28,12 +28,6 @@ fn main() { let _b = || { match l1 { L1::A => () } }; //~^ ERROR: non-exhaustive patterns: `L1::B` not covered [E0004] - // l2 should not be captured as it is a non-exhaustive SingleVariant - // defined in this crate - let _c = || { match l2 { L2::C => (), _ => () } }; - let mut mut_l2 = l2; - _c(); - // E1 is not visibly uninhabited from here let (e1, e2, e3, e4) = bar(); let _d = || { match e1 {} }; @@ -42,8 +36,14 @@ fn main() { //~^ ERROR: non-exhaustive patterns: `_` not covered [E0004] let _f = || { match e2 { E2::A => (), E2::B => (), _ => () } }; - // e3 should be captured as it is a non-exhaustive SingleVariant - // defined in another crate + // non-exhaustive enums should always be captured, regardless if they + // are defined in the current crate: + let _c = || { match l2 { L2::C => (), _ => () } }; + let mut mut_l2 = l2; + //~^ ERROR: cannot move out of `l2` because it is borrowed + _c(); + + // ...or in another crate: let _g = || { match e3 { E3::C => (), _ => () } }; let mut mut_e3 = e3; //~^ ERROR: cannot move out of `e3` because it is borrowed 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 99d33b05429e..e34d1889803a 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 @@ -16,7 +16,7 @@ LL | let _b = || { match l1 { L1::A => (), L1::B => todo!() } }; | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: type `E1` is non-empty - --> $DIR/non-exhaustive-match.rs:39:25 + --> $DIR/non-exhaustive-match.rs:33:25 | LL | let _d = || { match e1 {} }; | ^^ @@ -35,7 +35,7 @@ LL ~ } }; | error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/non-exhaustive-match.rs:41:25 + --> $DIR/non-exhaustive-match.rs:35:25 | LL | let _e = || { match e2 { E2::A => (), E2::B => () } }; | ^^ pattern `_` not covered @@ -52,6 +52,19 @@ help: ensure that all possible cases are being handled by adding a match arm wit LL | let _e = || { match e2 { E2::A => (), E2::B => (), _ => todo!() } }; | ++++++++++++++ +error[E0505]: cannot move out of `l2` because it is borrowed + --> $DIR/non-exhaustive-match.rs:42:22 + | +LL | let _c = || { match l2 { L2::C => (), _ => () } }; + | -- -- borrow occurs due to use in closure + | | + | borrow of `l2` occurs here +LL | let mut mut_l2 = l2; + | ^^ move out of `l2` occurs here +LL | +LL | _c(); + | -- borrow later used here + error[E0505]: cannot move out of `e3` because it is borrowed --> $DIR/non-exhaustive-match.rs:48:22 | @@ -65,7 +78,7 @@ LL | LL | _g(); | -- borrow later used here -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0004, E0505. For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs index 1c178bd3f684..348d558dd980 100644 --- a/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.rs @@ -1,3 +1,8 @@ +// Make sure that #[non_exhaustive] cannot cause drop order to depend on which +// crate the code is in. +// +// See rust-lang/rust#147722 +// //@ edition:2021 //@ run-pass //@ check-run-results diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout index e0d83dd99549..3fa346d87b07 100644 --- a/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move-drop-order.run.stdout @@ -12,8 +12,8 @@ dropping b non exhaustive: before assign -dropping a after assign +dropping a dropping b external non exhaustive: diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move.rs b/tests/ui/closures/2229_closure_analysis/match/partial-move.rs index 62d1b362cb83..7bd435bd1856 100644 --- a/tests/ui/closures/2229_closure_analysis/match/partial-move.rs +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move.rs @@ -78,10 +78,9 @@ pub fn test_two_variants(x: TwoVariants) -> impl FnOnce() { } } -// ...and single-variant, non-exhaustive enums *should* behave as if they had multiple variants +// ...and single-variant, non-exhaustive enums behave as if they had multiple variants pub fn test_non_exhaustive1(x: NonExhaustive) -> impl FnOnce() { || { - //~^ ERROR: closure may outlive the current function, but it borrows `x.0` match x { NonExhaustive::A(a, b) => { drop((a, b)); @@ -94,7 +93,6 @@ pub fn test_non_exhaustive1(x: NonExhaustive) -> impl FnOnce() { // (again, wildcard branch or not) pub fn test_non_exhaustive2(x: NonExhaustive) -> impl FnOnce() { || { - //~^ ERROR: closure may outlive the current function, but it borrows `x.0` match x { NonExhaustive::A(a, b) => { drop((a, b)); diff --git a/tests/ui/closures/2229_closure_analysis/match/partial-move.stderr b/tests/ui/closures/2229_closure_analysis/match/partial-move.stderr index 36adcc6717ed..09f9adf95d5b 100644 --- a/tests/ui/closures/2229_closure_analysis/match/partial-move.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/partial-move.stderr @@ -70,54 +70,6 @@ help: to force the closure to take ownership of `x.0` (and any other referenced LL | move || { | ++++ -error[E0373]: closure may outlive the current function, but it borrows `x.0`, which is owned by the current function - --> $DIR/partial-move.rs:83:5 - | -LL | || { - | ^^ may outlive borrowed value `x.0` -LL | -LL | match x { - | - `x.0` is borrowed here - | -note: closure is returned here - --> $DIR/partial-move.rs:83:5 - | -LL | / || { -LL | | -LL | | match x { -LL | | NonExhaustive::A(a, b) => { -... | -LL | | } - | |_____^ -help: to force the closure to take ownership of `x.0` (and any other referenced variables), use the `move` keyword - | -LL | move || { - | ++++ - -error[E0373]: closure may outlive the current function, but it borrows `x.0`, which is owned by the current function - --> $DIR/partial-move.rs:96:5 - | -LL | || { - | ^^ may outlive borrowed value `x.0` -LL | -LL | match x { - | - `x.0` is borrowed here - | -note: closure is returned here - --> $DIR/partial-move.rs:96:5 - | -LL | / || { -LL | | -LL | | match x { -LL | | NonExhaustive::A(a, b) => { -... | -LL | | } - | |_____^ -help: to force the closure to take ownership of `x.0` (and any other referenced variables), use the `move` keyword - | -LL | move || { - | ++++ - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0373`. From 3387a58bc777d31493f37160cdd1f57223f0bc0c Mon Sep 17 00:00:00 2001 From: James Hendry Date: Wed, 14 Jan 2026 10:48:24 +0000 Subject: [PATCH 056/978] fN::BITS constants for feature float_bits_const Also enables the feature for compiler_builtins as otherwise this causes a warning and conflicts with the Float extension trait Explicitly use Float trait BITS in miri tests to prevent warnings against upcoming BITS field for floats --- library/compiler-builtins/compiler-builtins/src/lib.rs | 1 + library/core/src/num/f128.rs | 5 +++++ library/core/src/num/f16.rs | 5 +++++ library/core/src/num/f32.rs | 4 ++++ library/core/src/num/f64.rs | 4 ++++ src/tools/miri/tests/pass/float.rs | 6 +++--- src/tools/test-float-parse/src/traits.rs | 2 +- 7 files changed, 23 insertions(+), 4 deletions(-) diff --git a/library/compiler-builtins/compiler-builtins/src/lib.rs b/library/compiler-builtins/compiler-builtins/src/lib.rs index c993209699be..342427aca9c7 100644 --- a/library/compiler-builtins/compiler-builtins/src/lib.rs +++ b/library/compiler-builtins/compiler-builtins/src/lib.rs @@ -11,6 +11,7 @@ #![feature(repr_simd)] #![feature(macro_metavar_expr_concat)] #![feature(rustc_attrs)] +#![feature(float_bits_const)] #![cfg_attr(f16_enabled, feature(f16))] #![cfg_attr(f128_enabled, feature(f128))] #![no_builtins] diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index bf99fee4fc78..8bb919de729e 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -145,6 +145,11 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] pub const RADIX: u32 = 2; + /// The size of this float type in bits. + // #[unstable(feature = "f128", issue = "116909")] + #[unstable(feature = "float_bits_const", issue = "151073")] + pub const BITS: u32 = 128; + /// Number of significant digits in base 2. /// /// Note that the size of the mantissa in the bitwise representation is one diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index f39ee22871d5..699b2e3c25c4 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -142,6 +142,11 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] pub const RADIX: u32 = 2; + /// The size of this float type in bits. + // #[unstable(feature = "f16", issue = "116909")] + #[unstable(feature = "float_bits_const", issue = "151073")] + pub const BITS: u32 = 16; + /// Number of significant digits in base 2. /// /// Note that the size of the mantissa in the bitwise representation is one diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 6fe4285374b2..118ef4ff3d43 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -390,6 +390,10 @@ impl f32 { #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const RADIX: u32 = 2; + /// The size of this float type in bits. + #[unstable(feature = "float_bits_const", issue = "151073")] + pub const BITS: u32 = 32; + /// Number of significant digits in base 2. /// /// Note that the size of the mantissa in the bitwise representation is one diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index d0aca152415e..eacbd3ff20bf 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -390,6 +390,10 @@ impl f64 { #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const RADIX: u32 = 2; + /// The size of this float type in bits. + #[unstable(feature = "float_bits_const", issue = "151073")] + pub const BITS: u32 = 64; + /// Number of significant digits in base 2. /// /// Note that the size of the mantissa in the bitwise representation is one diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index a74a66d5455a..052c83d1aa31 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -353,7 +353,7 @@ macro_rules! test_ftoi_itof { assert_itof(i, f, msg); } - let fbits = <$fty>::BITS; + let fbits = <$fty as Float>::BITS; let fsig_bits = <$fty>::SIGNIFICAND_BITS; let ibits = <$ity>::BITS; let imax: $ity = <$ity>::MAX; @@ -528,9 +528,9 @@ macro_rules! test_ftof { assert!((<$f1>::NAN as $f2).is_nan(), "{} -> {} nan", stringify!($f1), stringify!($f2)); let min_sub_casted = <$f1>::from_bits(0x1) as $f2; - let min_neg_sub_casted = <$f1>::from_bits(0x1 | 1 << (<$f1>::BITS - 1)) as $f2; + let min_neg_sub_casted = <$f1>::from_bits(0x1 | 1 << (<$f1 as Float>::BITS - 1)) as $f2; - if <$f1>::BITS > <$f2>::BITS { + if <$f1 as Float>::BITS > <$f2 as Float>::BITS { assert_feq(<$f1>::MAX as $f2, <$f2>::INFINITY, "max -> inf"); assert_feq(<$f1>::MIN as $f2, <$f2>::NEG_INFINITY, "max -> inf"); assert_biteq(min_sub_casted, f2zero, "min subnormal -> 0.0"); diff --git a/src/tools/test-float-parse/src/traits.rs b/src/tools/test-float-parse/src/traits.rs index 65a8721bfa5c..0cb44d297bfb 100644 --- a/src/tools/test-float-parse/src/traits.rs +++ b/src/tools/test-float-parse/src/traits.rs @@ -155,7 +155,7 @@ macro_rules! impl_float { const BITS: u32 = <$ity>::BITS; const MAN_BITS: u32 = Self::MANTISSA_DIGITS - 1; const MAN_MASK: Self::Int = (Self::Int::ONE << Self::MAN_BITS) - Self::Int::ONE; - const SIGN_MASK: Self::Int = Self::Int::ONE << (Self::BITS-1); + const SIGN_MASK: Self::Int = Self::Int::ONE << (::BITS-1); fn from_bits(i: Self::Int) -> Self { Self::from_bits(i) } fn to_bits(self) -> Self::Int { self.to_bits() } fn constants() -> &'static Constants { From af302a67fdc508cfd08ee22facb96bcf0e5bf831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sun, 4 Jan 2026 19:34:37 +0100 Subject: [PATCH 057/978] discriminant reads: make semantics independent of module/crate --- .../src/builder/matches/match_pair.rs | 20 +++----- .../fail/match/all_variants_uninhabited.rs | 25 ++++++++++ .../match/all_variants_uninhabited.stderr | 13 +++++ .../{ => match}/closures/deref-in-pattern.rs | 0 .../closures/deref-in-pattern.stderr | 2 +- .../{ => match}/closures/partial-pattern.rs | 0 .../closures/partial-pattern.stderr | 2 +- .../closures/uninhabited-variant1.rs} | 0 .../closures/uninhabited-variant1.stderr} | 6 +-- .../match/closures/uninhabited-variant2.rs | 32 ++++++++++++ .../closures/uninhabited-variant2.stderr | 18 +++++++ .../fail/match/only_inhabited_variant.rs | 21 ++++++++ .../fail/match/only_inhabited_variant.stderr | 13 +++++ .../miri/tests/fail/match/single_variant.rs | 31 ++++++++++++ .../tests/fail/match/single_variant.stderr | 13 +++++ .../tests/fail/match/single_variant_uninit.rs | 36 +++++++++++++ .../fail/match/single_variant_uninit.stderr | 18 +++++++ .../enum/enum-transparent-extract.rs | 4 ++ ...atterns.opt1.SimplifyCfg-initial.after.mir | 10 ++-- ...atterns.opt2.SimplifyCfg-initial.after.mir | 15 ++++++ ...atterns.opt3.SimplifyCfg-initial.after.mir | 17 ++++--- ...ng.identity.JumpThreading.panic-abort.diff | 19 +++++-- ...g.identity.JumpThreading.panic-unwind.diff | 19 +++++-- ...map_via_question_mark.PreCodegen.after.mir | 50 +++++++++++-------- ...e_const_switch.identity.JumpThreading.diff | 15 ++++-- ...ch.UnreachablePropagation.panic-abort.diff | 12 +++-- ...h.UnreachablePropagation.panic-unwind.diff | 12 +++-- tests/mir-opt/unreachable.rs | 2 +- ....UnreachableEnumBranching.panic-abort.diff | 28 +++++------ ...UnreachableEnumBranching.panic-unwind.diff | 28 +++++------ tests/ui/match/borrowck-uninhabited.rs | 2 + tests/ui/match/borrowck-uninhabited.stderr | 13 ++++- tests/ui/match/uninhabited-granular-moves.rs | 4 +- .../match/uninhabited-granular-moves.stderr | 32 +++++++++++- .../borrowck-exhaustive.rs | 12 ----- .../borrowck-non-exhaustive.rs | 12 +++++ .../borrowck-non-exhaustive.stderr | 15 +++++- 37 files changed, 455 insertions(+), 116 deletions(-) create mode 100644 src/tools/miri/tests/fail/match/all_variants_uninhabited.rs create mode 100644 src/tools/miri/tests/fail/match/all_variants_uninhabited.stderr rename src/tools/miri/tests/fail/{ => match}/closures/deref-in-pattern.rs (100%) rename src/tools/miri/tests/fail/{ => match}/closures/deref-in-pattern.stderr (91%) rename src/tools/miri/tests/fail/{ => match}/closures/partial-pattern.rs (100%) rename src/tools/miri/tests/fail/{ => match}/closures/partial-pattern.stderr (92%) rename src/tools/miri/tests/fail/{closures/uninhabited-variant.rs => match/closures/uninhabited-variant1.rs} (100%) rename src/tools/miri/tests/fail/{closures/uninhabited-variant.stderr => match/closures/uninhabited-variant1.stderr} (74%) create mode 100644 src/tools/miri/tests/fail/match/closures/uninhabited-variant2.rs create mode 100644 src/tools/miri/tests/fail/match/closures/uninhabited-variant2.stderr create mode 100644 src/tools/miri/tests/fail/match/only_inhabited_variant.rs create mode 100644 src/tools/miri/tests/fail/match/only_inhabited_variant.stderr create mode 100644 src/tools/miri/tests/fail/match/single_variant.rs create mode 100644 src/tools/miri/tests/fail/match/single_variant.stderr create mode 100644 src/tools/miri/tests/fail/match/single_variant_uninit.rs create mode 100644 src/tools/miri/tests/fail/match/single_variant_uninit.stderr diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index 8cee3ff27e8f..07af66127ef9 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -295,22 +295,18 @@ impl<'tcx> MatchPairTree<'tcx> { } } - PatKind::Variant { adt_def, variant_index, args, ref subpatterns } => { + PatKind::Variant { adt_def, variant_index, args: _, ref subpatterns } => { let downcast_place = place_builder.downcast(adt_def, variant_index); // `(x as Variant)` cx.field_match_pairs(&mut subpairs, extra_data, downcast_place, subpatterns); - let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| { - i == variant_index - || !v.inhabited_predicate(cx.tcx, adt_def).instantiate(cx.tcx, args).apply( - cx.tcx, - cx.infcx.typing_env(cx.param_env), - cx.def_id.into(), - ) - }) && !adt_def.variant_list_has_applicable_non_exhaustive(); - if irrefutable { - None - } else { + // We treat non-exhaustive enums the same independent of the crate they are + // defined in, to avoid differences in the operational semantics between crates. + let refutable = + adt_def.variants().len() > 1 || adt_def.is_variant_list_non_exhaustive(); + if refutable { Some(TestableCase::Variant { adt_def, variant_index }) + } else { + None } } diff --git a/src/tools/miri/tests/fail/match/all_variants_uninhabited.rs b/src/tools/miri/tests/fail/match/all_variants_uninhabited.rs new file mode 100644 index 000000000000..e7ca45579d84 --- /dev/null +++ b/src/tools/miri/tests/fail/match/all_variants_uninhabited.rs @@ -0,0 +1,25 @@ +#![allow(deref_nullptr)] + +enum Never {} + +fn main() { + unsafe { + match *std::ptr::null::>() { + //~^ ERROR: read discriminant of an uninhabited enum variant + Ok(_) => { + lol(); + } + Err(_) => { + wut(); + } + } + } +} + +fn lol() { + println!("lol"); +} + +fn wut() { + println!("wut"); +} diff --git a/src/tools/miri/tests/fail/match/all_variants_uninhabited.stderr b/src/tools/miri/tests/fail/match/all_variants_uninhabited.stderr new file mode 100644 index 000000000000..90809219340b --- /dev/null +++ b/src/tools/miri/tests/fail/match/all_variants_uninhabited.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: read discriminant of an uninhabited enum variant + --> tests/fail/match/all_variants_uninhabited.rs:LL:CC + | +LL | match *std::ptr::null::>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/closures/deref-in-pattern.rs b/src/tools/miri/tests/fail/match/closures/deref-in-pattern.rs similarity index 100% rename from src/tools/miri/tests/fail/closures/deref-in-pattern.rs rename to src/tools/miri/tests/fail/match/closures/deref-in-pattern.rs diff --git a/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr b/src/tools/miri/tests/fail/match/closures/deref-in-pattern.stderr similarity index 91% rename from src/tools/miri/tests/fail/closures/deref-in-pattern.stderr rename to src/tools/miri/tests/fail/match/closures/deref-in-pattern.stderr index fae2d286c487..cbb74df5de77 100644 --- a/src/tools/miri/tests/fail/closures/deref-in-pattern.stderr +++ b/src/tools/miri/tests/fail/match/closures/deref-in-pattern.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: constructing invalid value: encountered a dangling reference (use-after-free) - --> tests/fail/closures/deref-in-pattern.rs:LL:CC + --> tests/fail/match/closures/deref-in-pattern.rs:LL:CC | LL | let _ = || { | _____________^ diff --git a/src/tools/miri/tests/fail/closures/partial-pattern.rs b/src/tools/miri/tests/fail/match/closures/partial-pattern.rs similarity index 100% rename from src/tools/miri/tests/fail/closures/partial-pattern.rs rename to src/tools/miri/tests/fail/match/closures/partial-pattern.rs diff --git a/src/tools/miri/tests/fail/closures/partial-pattern.stderr b/src/tools/miri/tests/fail/match/closures/partial-pattern.stderr similarity index 92% rename from src/tools/miri/tests/fail/closures/partial-pattern.stderr rename to src/tools/miri/tests/fail/match/closures/partial-pattern.stderr index 8dea4d4d8c64..b8ca04559e23 100644 --- a/src/tools/miri/tests/fail/closures/partial-pattern.stderr +++ b/src/tools/miri/tests/fail/match/closures/partial-pattern.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: constructing invalid value: encountered a dangling reference (use-after-free) - --> tests/fail/closures/partial-pattern.rs:LL:CC + --> tests/fail/match/closures/partial-pattern.rs:LL:CC | LL | let _ = || { | _____________^ diff --git a/src/tools/miri/tests/fail/closures/uninhabited-variant.rs b/src/tools/miri/tests/fail/match/closures/uninhabited-variant1.rs similarity index 100% rename from src/tools/miri/tests/fail/closures/uninhabited-variant.rs rename to src/tools/miri/tests/fail/match/closures/uninhabited-variant1.rs diff --git a/src/tools/miri/tests/fail/closures/uninhabited-variant.stderr b/src/tools/miri/tests/fail/match/closures/uninhabited-variant1.stderr similarity index 74% rename from src/tools/miri/tests/fail/closures/uninhabited-variant.stderr rename to src/tools/miri/tests/fail/match/closures/uninhabited-variant1.stderr index aea878660115..1a10a5b24d25 100644 --- a/src/tools/miri/tests/fail/closures/uninhabited-variant.stderr +++ b/src/tools/miri/tests/fail/match/closures/uninhabited-variant1.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: read discriminant of an uninhabited enum variant - --> tests/fail/closures/uninhabited-variant.rs:LL:CC + --> tests/fail/match/closures/uninhabited-variant1.rs:LL:CC | LL | match r { | ^ Undefined Behavior occurred here @@ -8,9 +8,9 @@ LL | match r { = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: stack backtrace: 0: main::{closure#0} - at tests/fail/closures/uninhabited-variant.rs:LL:CC + at tests/fail/match/closures/uninhabited-variant1.rs:LL:CC 1: main - at tests/fail/closures/uninhabited-variant.rs:LL:CC + at tests/fail/match/closures/uninhabited-variant1.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.rs b/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.rs new file mode 100644 index 000000000000..ed68e357fbd5 --- /dev/null +++ b/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.rs @@ -0,0 +1,32 @@ +// Motivated by rust-lang/rust#138961, this shows how invalid discriminants interact with +// closure captures. +// +// Test case with only one inhabited variant, for which rustc used to not emit +// a discriminant read in the first place. See: rust-lang/miri#4778 +#![feature(never_type)] + +#[repr(C)] +#[allow(dead_code)] +enum E { + V0, // discriminant: 0 + V1(!), // 1 +} + +fn main() { + assert_eq!(std::mem::size_of::(), 4); + + let val = 1u32; + let ptr = (&raw const val).cast::(); + let r = unsafe { &*ptr }; + let f = || { + // After rust-lang/rust#138961, constructing the closure performs a reborrow of r. + // Nevertheless, the discriminant is only actually inspected when the closure + // is called. + match r { //~ ERROR: read discriminant of an uninhabited enum variant + E::V0 => {} + E::V1(_) => {} + } + }; + + f(); +} diff --git a/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.stderr b/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.stderr new file mode 100644 index 000000000000..611e0435ef0e --- /dev/null +++ b/src/tools/miri/tests/fail/match/closures/uninhabited-variant2.stderr @@ -0,0 +1,18 @@ +error: Undefined Behavior: read discriminant of an uninhabited enum variant + --> tests/fail/match/closures/uninhabited-variant2.rs:LL:CC + | +LL | match r { + | ^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: stack backtrace: + 0: main::{closure#0} + at tests/fail/match/closures/uninhabited-variant2.rs:LL:CC + 1: main + at tests/fail/match/closures/uninhabited-variant2.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/match/only_inhabited_variant.rs b/src/tools/miri/tests/fail/match/only_inhabited_variant.rs new file mode 100644 index 000000000000..30a7350d2b66 --- /dev/null +++ b/src/tools/miri/tests/fail/match/only_inhabited_variant.rs @@ -0,0 +1,21 @@ +// rust-lang/miri#4778 +#![feature(never_type)] + +#[repr(C)] +#[allow(dead_code)] +enum E { + V0, // discriminant: 0 + V1(!), // 1 +} + +fn main() { + assert_eq!(std::mem::size_of::(), 4); + + let val = 1u32; + let ptr = (&raw const val).cast::(); + let r = unsafe { &*ptr }; + match r { //~ ERROR: read discriminant of an uninhabited enum variant + E::V0 => {} + E::V1(_) => {} + } +} diff --git a/src/tools/miri/tests/fail/match/only_inhabited_variant.stderr b/src/tools/miri/tests/fail/match/only_inhabited_variant.stderr new file mode 100644 index 000000000000..8ca362f902d3 --- /dev/null +++ b/src/tools/miri/tests/fail/match/only_inhabited_variant.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: read discriminant of an uninhabited enum variant + --> tests/fail/match/only_inhabited_variant.rs:LL:CC + | +LL | match r { + | ^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/match/single_variant.rs b/src/tools/miri/tests/fail/match/single_variant.rs new file mode 100644 index 000000000000..dcef6d461a2c --- /dev/null +++ b/src/tools/miri/tests/fail/match/single_variant.rs @@ -0,0 +1,31 @@ +// Ideally, this would be UB regardless of #[non_exhaustive]. For now, +// at least the semantics don't depend on the crate you're in. +// +// See: rust-lang/rust#147722 +#![allow(dead_code)] + +#[repr(u8)] +enum Exhaustive { + A(u8) = 42, +} + +#[repr(u8)] +#[non_exhaustive] +enum NonExhaustive { + A(u8) = 42, +} + +fn main() { + unsafe { + let x: &[u8; 2] = &[21, 37]; + let y: &Exhaustive = std::mem::transmute(x); + match y { + Exhaustive::A(_) => {}, + } + + let y: &NonExhaustive = std::mem::transmute(x); + match y { //~ ERROR: enum value has invalid tag + NonExhaustive::A(_) => {}, + } + } +} diff --git a/src/tools/miri/tests/fail/match/single_variant.stderr b/src/tools/miri/tests/fail/match/single_variant.stderr new file mode 100644 index 000000000000..7467e27ff791 --- /dev/null +++ b/src/tools/miri/tests/fail/match/single_variant.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: enum value has invalid tag: 0x15 + --> tests/fail/match/single_variant.rs:LL:CC + | +LL | match y { + | ^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/match/single_variant_uninit.rs b/src/tools/miri/tests/fail/match/single_variant_uninit.rs new file mode 100644 index 000000000000..51e8bc57c837 --- /dev/null +++ b/src/tools/miri/tests/fail/match/single_variant_uninit.rs @@ -0,0 +1,36 @@ +// Ideally, this would be UB regardless of #[non_exhaustive]. For now, +// at least the semantics don't depend on the crate you're in. +// +// See: rust-lang/rust#147722 +#![allow(dead_code)] +#![allow(unreachable_patterns)] + +#[repr(u8)] +enum Exhaustive { + A(u8) = 0, +} + +#[repr(u8)] +#[non_exhaustive] +enum NonExhaustive { + A(u8) = 0, +} + +use std::mem::MaybeUninit; + +fn main() { + let buffer: [MaybeUninit; 2] = [MaybeUninit::uninit(), MaybeUninit::new(0u8)]; + let exh: *const Exhaustive = (&raw const buffer).cast(); + let nexh: *const NonExhaustive = (&raw const buffer).cast(); + unsafe { + match *exh { + Exhaustive::A(ref _val) => {} + _ => {} + } + + match *nexh { //~ ERROR: memory is uninitialized + NonExhaustive::A(ref _val) => {} + _ => {} + } + } +} diff --git a/src/tools/miri/tests/fail/match/single_variant_uninit.stderr b/src/tools/miri/tests/fail/match/single_variant_uninit.stderr new file mode 100644 index 000000000000..fa8e9babae60 --- /dev/null +++ b/src/tools/miri/tests/fail/match/single_variant_uninit.stderr @@ -0,0 +1,18 @@ +error: Undefined Behavior: reading memory at ALLOC[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory + --> tests/fail/match/single_variant_uninit.rs:LL:CC + | +LL | match *nexh { + | ^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +Uninitialized memory occurred at ALLOC[0x0..0x1], in this allocation: +ALLOC (stack variable, size: 2, align: 1) { + __ 00 │ ░. +} + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/tests/codegen-llvm/enum/enum-transparent-extract.rs b/tests/codegen-llvm/enum/enum-transparent-extract.rs index 1435e6ec8022..1a05b236abfb 100644 --- a/tests/codegen-llvm/enum/enum-transparent-extract.rs +++ b/tests/codegen-llvm/enum/enum-transparent-extract.rs @@ -11,6 +11,8 @@ pub enum Never {} pub fn make_unmake_result_never(x: i32) -> i32 { // CHECK-LABEL: define i32 @make_unmake_result_never(i32{{( signext)?}} %x) // CHECK: start: + // CHECK-NEXT: br label %[[next:bb.*]] + // CHECK: [[next]]: // CHECK-NEXT: ret i32 %x let y: Result = Ok(x); @@ -22,6 +24,8 @@ pub fn make_unmake_result_never(x: i32) -> i32 { pub fn extract_control_flow_never(x: ControlFlow<&str, Never>) -> &str { // CHECK-LABEL: define { ptr, i64 } @extract_control_flow_never(ptr align 1 %x.0, i64 %x.1) // CHECK: start: + // CHECK-NEXT: br label %[[next:bb.*]] + // CHECK: [[next]]: // CHECK-NEXT: %[[P0:.+]] = insertvalue { ptr, i64 } poison, ptr %x.0, 0 // CHECK-NEXT: %[[P1:.+]] = insertvalue { ptr, i64 } %[[P0]], i64 %x.1, 1 // CHECK-NEXT: ret { ptr, i64 } %[[P1]] diff --git a/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir index bba4d9c0149a..78356a90743a 100644 --- a/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir @@ -13,17 +13,17 @@ fn opt1(_1: &Result) -> &u32 { bb0: { PlaceMention(_1); - falseEdge -> [real: bb4, imaginary: bb1]; + _2 = discriminant((*_1)); + switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1]; } bb1: { - _2 = discriminant((*_1)); - switchInt(move _2) -> [1: bb3, otherwise: bb2]; + FakeRead(ForMatchedPlace(None), _1); + unreachable; } bb2: { - FakeRead(ForMatchedPlace(None), _1); - unreachable; + falseEdge -> [real: bb4, imaginary: bb3]; } bb3: { diff --git a/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir index fc0769d6f7dc..979fbb2860dc 100644 --- a/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir @@ -11,10 +11,25 @@ fn opt2(_1: &Result) -> &u32 { bb0: { PlaceMention(_1); + _2 = discriminant((*_1)); + switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1]; + } + + bb1: { + FakeRead(ForMatchedPlace(None), _1); + unreachable; + } + + bb2: { StorageLive(_3); _3 = &(((*_1) as Ok).0: u32); _0 = &(*_3); StorageDead(_3); return; } + + bb3: { + FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void)); + unreachable; + } } diff --git a/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir index 86347db4d92e..93ebe600b3ff 100644 --- a/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir @@ -12,19 +12,24 @@ fn opt3(_1: &Result) -> &u32 { bb0: { PlaceMention(_1); _2 = discriminant((*_1)); - switchInt(move _2) -> [1: bb2, otherwise: bb1]; + switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; } bb1: { - StorageLive(_3); - _3 = &(((*_1) as Ok).0: u32); - _0 = &(*_3); - StorageDead(_3); - return; + FakeRead(ForMatchedPlace(None), _1); + unreachable; } bb2: { FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void)); unreachable; } + + bb3: { + StorageLive(_3); + _3 = &(((*_1) as Ok).0: u32); + _0 = &(*_3); + StorageDead(_3); + return; + } } diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff index 97b8d484194f..9630f4001494 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-abort.diff @@ -16,8 +16,10 @@ debug residual => _6; scope 2 { scope 8 (inlined #[track_caller] as FromResidual>>::from_residual) { - let _14: i32; - let mut _15: i32; + let mut _14: isize; + let _15: i32; + let mut _16: i32; + let mut _17: bool; scope 9 { scope 10 (inlined >::from) { } @@ -74,10 +76,17 @@ StorageLive(_8); _8 = copy _6; StorageLive(_14); - _14 = move ((_8 as Err).0: i32); StorageLive(_15); - _15 = move _14; - _0 = Result::::Err(move _15); + StorageLive(_17); + _14 = discriminant(_8); + _17 = Eq(copy _14, const 1_isize); + assume(move _17); + _15 = move ((_8 as Err).0: i32); + StorageLive(_16); + _16 = move _15; + _0 = Result::::Err(move _16); + StorageDead(_16); + StorageDead(_17); StorageDead(_15); StorageDead(_14); StorageDead(_8); diff --git a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff index 97b8d484194f..9630f4001494 100644 --- a/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.identity.JumpThreading.panic-unwind.diff @@ -16,8 +16,10 @@ debug residual => _6; scope 2 { scope 8 (inlined #[track_caller] as FromResidual>>::from_residual) { - let _14: i32; - let mut _15: i32; + let mut _14: isize; + let _15: i32; + let mut _16: i32; + let mut _17: bool; scope 9 { scope 10 (inlined >::from) { } @@ -74,10 +76,17 @@ StorageLive(_8); _8 = copy _6; StorageLive(_14); - _14 = move ((_8 as Err).0: i32); StorageLive(_15); - _15 = move _14; - _0 = Result::::Err(move _15); + StorageLive(_17); + _14 = discriminant(_8); + _17 = Eq(copy _14, const 1_isize); + assume(move _17); + _15 = move ((_8 as Err).0: i32); + StorageLive(_16); + _16 = move _15; + _0 = Result::::Err(move _16); + StorageDead(_16); + StorageDead(_17); StorageDead(_15); StorageDead(_14); StorageDead(_8); diff --git a/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir index b921b96966b2..ef7ccfa5bddf 100644 --- a/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/simple_option_map.map_via_question_mark.PreCodegen.after.mir @@ -3,56 +3,66 @@ fn map_via_question_mark(_1: Option) -> Option { debug x => _1; let mut _0: std::option::Option; - let mut _4: std::ops::ControlFlow, i32>; - let _5: i32; - let mut _6: i32; + let mut _4: std::option::Option; + let mut _7: std::ops::ControlFlow, i32>; + let _8: i32; + let mut _9: i32; scope 1 { debug residual => const Option::::None; scope 2 { scope 7 (inlined as FromResidual>>::from_residual) { + let mut _3: isize; + let mut _5: bool; } } } scope 3 { - debug val => _5; + debug val => _8; scope 4 { } } scope 5 (inlined as Try>::branch) { let mut _2: isize; - let _3: i32; + let _6: i32; scope 6 { } } bb0: { - StorageLive(_6); - StorageLive(_4); + StorageLive(_9); + StorageLive(_7); StorageLive(_2); - StorageLive(_3); + StorageLive(_6); _2 = discriminant(_1); switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; } bb1: { - StorageDead(_3); - StorageDead(_2); - _0 = const Option::::None; StorageDead(_6); - StorageDead(_4); + StorageDead(_2); + StorageLive(_3); + StorageLive(_5); + _3 = discriminant(_4); + _5 = Eq(copy _3, const 0_isize); + assume(move _5); + _0 = const Option::::None; + StorageDead(_5); + StorageDead(_3); + StorageDead(_9); + StorageDead(_7); goto -> bb3; } bb2: { - _3 = copy ((_1 as Some).0: i32); - _4 = ControlFlow::, i32>::Continue(copy _3); - StorageDead(_3); - StorageDead(_2); - _5 = copy ((_4 as Continue).0: i32); - _6 = Add(copy _5, const 1_i32); - _0 = Option::::Some(move _6); + _6 = copy ((_1 as Some).0: i32); + _7 = ControlFlow::, i32>::Continue(copy _6); StorageDead(_6); - StorageDead(_4); + StorageDead(_2); + _8 = copy ((_7 as Continue).0: i32); + _9 = Add(copy _8, const 1_i32); + _0 = Option::::Some(move _9); + StorageDead(_9); + StorageDead(_7); goto -> bb3; } diff --git a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff index 34f451fc698c..10ad4ec75414 100644 --- a/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff +++ b/tests/mir-opt/separate_const_switch.identity.JumpThreading.diff @@ -12,7 +12,9 @@ debug residual => _4; scope 2 { scope 8 (inlined #[track_caller] as FromResidual>>::from_residual) { - let _10: i32; + let mut _10: isize; + let _11: i32; + let mut _12: bool; scope 9 { scope 10 (inlined >::from) { } @@ -58,8 +60,15 @@ bb3: { _4 = copy ((_2 as Break).0: std::result::Result); - _10 = copy ((_4 as Err).0: i32); - _0 = Result::::Err(copy _10); + StorageLive(_10); + StorageLive(_12); + _10 = discriminant(_4); + _12 = Eq(copy _10, const 1_isize); + assume(move _12); + _11 = copy ((_4 as Err).0: i32); + _0 = Result::::Err(copy _11); + StorageDead(_12); + StorageDead(_10); StorageDead(_2); return; } diff --git a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff index 17ddce0cdf8d..8c3b8ad9b66a 100644 --- a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff +++ b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff @@ -19,19 +19,23 @@ bb1: { _2 = discriminant(_1); -- switchInt(move _2) -> [1: bb3, otherwise: bb2]; -+ _5 = Ne(copy _2, const 1_isize); +- switchInt(move _2) -> [0: bb3, 1: bb4, otherwise: bb2]; ++ _5 = Eq(copy _2, const 0_isize); + assume(move _5); -+ goto -> bb2; ++ goto -> bb3; } bb2: { + unreachable; + } + + bb3: { _0 = const (); StorageDead(_1); return; } - bb3: { + bb4: { - StorageLive(_3); - _3 = move ((_1 as Some).0: Empty); - StorageLive(_4); diff --git a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff index 2f78092f5bd2..98f2a0a692ff 100644 --- a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff +++ b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff @@ -19,19 +19,23 @@ bb1: { _2 = discriminant(_1); -- switchInt(move _2) -> [1: bb3, otherwise: bb2]; -+ _5 = Ne(copy _2, const 1_isize); +- switchInt(move _2) -> [0: bb3, 1: bb4, otherwise: bb2]; ++ _5 = Eq(copy _2, const 0_isize); + assume(move _5); -+ goto -> bb2; ++ goto -> bb3; } bb2: { + unreachable; + } + + bb3: { _0 = const (); StorageDead(_1); return; } - bb3: { + bb4: { - StorageLive(_3); - _3 = move ((_1 as Some).0: Empty); - StorageLive(_4); diff --git a/tests/mir-opt/unreachable.rs b/tests/mir-opt/unreachable.rs index afab1291fc3d..97cd15b107c1 100644 --- a/tests/mir-opt/unreachable.rs +++ b/tests/mir-opt/unreachable.rs @@ -45,7 +45,7 @@ fn as_match() { // CHECK: bb0: { // CHECK: {{_.*}} = empty() // CHECK: bb1: { - // CHECK: [[eq:_.*]] = Ne({{.*}}, const 1_isize); + // CHECK: [[eq:_.*]] = Eq({{.*}}, const 0_isize); // CHECK-NEXT: assume(move [[eq]]); // CHECK-NEXT: goto -> [[return:bb.*]]; // CHECK: [[return]]: { diff --git a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff index c24bd7e7446d..befee026d6cb 100644 --- a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff +++ b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff @@ -14,40 +14,40 @@ StorageLive(_2); _2 = Test1::C; _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5]; +- switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1]; } bb1: { + unreachable; + } + + bb2: { StorageLive(_5); _5 = const "C"; _1 = &(*_5); StorageDead(_5); - goto -> bb4; + goto -> bb5; } - bb2: { + bb3: { StorageLive(_4); _4 = const "B(Empty)"; _1 = &(*_4); StorageDead(_4); - goto -> bb4; - } - - bb3: { - _1 = const "A(Empty)"; - goto -> bb4; + goto -> bb5; } bb4: { + _1 = const "A(Empty)"; + goto -> bb5; + } + + bb5: { StorageDead(_2); StorageDead(_1); _0 = const (); return; -+ } -+ -+ bb5: { -+ unreachable; } } diff --git a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff index c24bd7e7446d..befee026d6cb 100644 --- a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff +++ b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff @@ -14,40 +14,40 @@ StorageLive(_2); _2 = Test1::C; _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5]; +- switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1]; } bb1: { + unreachable; + } + + bb2: { StorageLive(_5); _5 = const "C"; _1 = &(*_5); StorageDead(_5); - goto -> bb4; + goto -> bb5; } - bb2: { + bb3: { StorageLive(_4); _4 = const "B(Empty)"; _1 = &(*_4); StorageDead(_4); - goto -> bb4; - } - - bb3: { - _1 = const "A(Empty)"; - goto -> bb4; + goto -> bb5; } bb4: { + _1 = const "A(Empty)"; + goto -> bb5; + } + + bb5: { StorageDead(_2); StorageDead(_1); _0 = const (); return; -+ } -+ -+ bb5: { -+ unreachable; } } diff --git a/tests/ui/match/borrowck-uninhabited.rs b/tests/ui/match/borrowck-uninhabited.rs index 93838ede2793..34f5e323a91e 100644 --- a/tests/ui/match/borrowck-uninhabited.rs +++ b/tests/ui/match/borrowck-uninhabited.rs @@ -17,9 +17,11 @@ fn both_inhabited(x: &mut Result) { }; } +// this used to be accepted, even though it shouldn't fn ref_uninhabited(x: &mut Result) { match x { &mut Ok(ref mut y) => match x { + //~^ ERROR: cannot use `*x` because it was mutably borrowed &mut Err(ref mut z) => { let _y = y; let _z = z; diff --git a/tests/ui/match/borrowck-uninhabited.stderr b/tests/ui/match/borrowck-uninhabited.stderr index ee3b814da9f4..4bbe6ecea16b 100644 --- a/tests/ui/match/borrowck-uninhabited.stderr +++ b/tests/ui/match/borrowck-uninhabited.stderr @@ -9,6 +9,17 @@ LL | &mut Ok(ref mut y) => match x { LL | let _y = y; | - borrow later used here -error: aborting due to 1 previous error +error[E0503]: cannot use `*x` because it was mutably borrowed + --> $DIR/borrowck-uninhabited.rs:23:37 + | +LL | &mut Ok(ref mut y) => match x { + | --------- ^ use of borrowed `x.0` + | | + | `x.0` is borrowed here +... +LL | let _y = y; + | - borrow later used here + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/match/uninhabited-granular-moves.rs b/tests/ui/match/uninhabited-granular-moves.rs index 9d04fcb3259e..f836aedbebc7 100644 --- a/tests/ui/match/uninhabited-granular-moves.rs +++ b/tests/ui/match/uninhabited-granular-moves.rs @@ -17,7 +17,7 @@ fn test1(thefoo: Foo<(Box, Box)>) { Foo::Bar((a, _)) => { } } - match thefoo { + match thefoo { //~ ERROR: use of partially moved value: `thefoo` Foo::Bar((_, a)) => { } } } @@ -38,7 +38,7 @@ fn test3(thefoo: Foo<(Box, Box)>) { Foo::Bar((a, _)) => { } Foo::Qux(_) => { } } - match thefoo { + match thefoo { //~ ERROR: use of partially moved value: `thefoo` Foo::Bar((_, a)) => { } } } diff --git a/tests/ui/match/uninhabited-granular-moves.stderr b/tests/ui/match/uninhabited-granular-moves.stderr index d32f935d3d55..e3a66db526d4 100644 --- a/tests/ui/match/uninhabited-granular-moves.stderr +++ b/tests/ui/match/uninhabited-granular-moves.stderr @@ -1,3 +1,18 @@ +error[E0382]: use of partially moved value: `thefoo` + --> $DIR/uninhabited-granular-moves.rs:20:11 + | +LL | Foo::Bar((a, _)) => { } + | - value partially moved here +... +LL | match thefoo { + | ^^^^^^ value used here after partial move + | + = note: partial move occurs because value has type `Box`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | Foo::Bar((ref a, _)) => { } + | +++ + error[E0382]: use of partially moved value: `thefoo` --> $DIR/uninhabited-granular-moves.rs:30:11 | @@ -13,6 +28,21 @@ help: borrow this binding in the pattern to avoid moving the value LL | Foo::Bar((ref a, _)) => { } | +++ -error: aborting due to 1 previous error +error[E0382]: use of partially moved value: `thefoo` + --> $DIR/uninhabited-granular-moves.rs:41:11 + | +LL | Foo::Bar((a, _)) => { } + | - value partially moved here +... +LL | match thefoo { + | ^^^^^^ value used here after partial move + | + = note: partial move occurs because value has type `Box`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | Foo::Bar((ref a, _)) => { } + | +++ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-exhaustive.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-exhaustive.rs index b2ebab382bd9..2e40819d69ad 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-exhaustive.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-exhaustive.rs @@ -14,11 +14,6 @@ enum Local { Variant(u32), } -#[non_exhaustive] -enum LocalNonExhaustive { - Variant(u32), -} - fn main() { let mut x = ExhaustiveMonovariant::Variant(1); let y = &mut x; @@ -34,11 +29,4 @@ fn main() { _ => {}, } drop(y); - let mut x = LocalNonExhaustive::Variant(1); - let y = &mut x; - match x { - LocalNonExhaustive::Variant(_) => {}, - _ => {}, - } - drop(y); } diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs index d616f5e5e89a..a6a369e92a6c 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs @@ -6,6 +6,11 @@ extern crate monovariants; use monovariants::NonExhaustiveMonovariant; +#[non_exhaustive] +enum LocalNonExhaustive { + Variant(u32), +} + fn main() { let mut x = NonExhaustiveMonovariant::Variant(1); let y = &mut x; @@ -15,4 +20,11 @@ fn main() { _ => {}, } drop(y); + let mut x = LocalNonExhaustive::Variant(1); + let y = &mut x; + match x { //~ ERROR cannot use `x` because it was mutably borrowed + LocalNonExhaustive::Variant(_) => {}, + _ => {}, + } + drop(y); } diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr index 70f5b2b84d86..d6225adc95cb 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr @@ -1,5 +1,5 @@ error[E0503]: cannot use `x` because it was mutably borrowed - --> $DIR/borrowck-non-exhaustive.rs:12:11 + --> $DIR/borrowck-non-exhaustive.rs:17:11 | LL | let y = &mut x; | ------ `x` is borrowed here @@ -9,6 +9,17 @@ LL | match x { LL | drop(y); | - borrow later used here -error: aborting due to 1 previous error +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/borrowck-non-exhaustive.rs:25:11 + | +LL | let y = &mut x; + | ------ `x` is borrowed here +LL | match x { + | ^ use of borrowed `x` +... +LL | drop(y); + | - borrow later used here + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0503`. From b4781c8fe9f97b582b44d615d2edf2bb114f1f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 15 Jan 2026 20:39:14 +0000 Subject: [PATCH 058/978] Use default field values in a few more cases Makes the use expressions significantly shorter. --- .../src/diagnostics/conflict_errors.rs | 48 ++++++------------- compiler/rustc_borrowck/src/lib.rs | 1 + .../rustc_hir_analysis/src/hir_wf_check.rs | 18 ++----- compiler/rustc_hir_analysis/src/lib.rs | 1 + 4 files changed, 22 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 5cfe9db009bf..1b1c72394e75 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2312,12 +2312,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { tcx: TyCtxt<'hir>, issue_span: Span, expr_span: Span, - body_expr: Option<&'hir hir::Expr<'hir>>, - loop_bind: Option<&'hir Ident>, - loop_span: Option, - head_span: Option, - pat_span: Option, - head: Option<&'hir hir::Expr<'hir>>, + body_expr: Option<&'hir hir::Expr<'hir>> = None, + loop_bind: Option<&'hir Ident> = None, + loop_span: Option = None, + head_span: Option = None, + pat_span: Option = None, + head: Option<&'hir hir::Expr<'hir>> = None, } impl<'hir> Visitor<'hir> for ExprFinder<'hir> { fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) { @@ -2383,17 +2383,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { hir::intravisit::walk_expr(self, ex); } } - let mut finder = ExprFinder { - tcx, - expr_span: span, - issue_span, - loop_bind: None, - body_expr: None, - head_span: None, - loop_span: None, - pat_span: None, - head: None, - }; + let mut finder = ExprFinder { tcx, expr_span: span, issue_span, .. }; finder.visit_expr(tcx.hir_body(body_id).value); if let Some(body_expr) = finder.body_expr @@ -2628,13 +2618,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { struct ExpressionFinder<'tcx> { capture_span: Span, - closure_change_spans: Vec, - closure_arg_span: Option, - in_closure: bool, - suggest_arg: String, + closure_change_spans: Vec = vec![], + closure_arg_span: Option = None, + in_closure: bool = false, + suggest_arg: String = String::new(), tcx: TyCtxt<'tcx>, - closure_local_id: Option, - closure_call_changes: Vec<(Span, String)>, + closure_local_id: Option = None, + closure_call_changes: Vec<(Span, String)> = vec![], } impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> { fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) { @@ -2715,16 +2705,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { }) = self.infcx.tcx.hir_node(self.mir_hir_id()) && let hir::Node::Expr(expr) = self.infcx.tcx.hir_node(body_id.hir_id) { - let mut finder = ExpressionFinder { - capture_span: *capture_kind_span, - closure_change_spans: vec![], - closure_arg_span: None, - in_closure: false, - suggest_arg: String::new(), - closure_local_id: None, - closure_call_changes: vec![], - tcx: self.infcx.tcx, - }; + let mut finder = + ExpressionFinder { capture_span: *capture_kind_span, tcx: self.infcx.tcx, .. }; finder.visit_expr(expr); if finder.closure_change_spans.is_empty() || finder.closure_call_changes.is_empty() { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 91defbad0a0e..f2ea8cef192e 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -4,6 +4,7 @@ #![allow(internal_features)] #![feature(assert_matches)] #![feature(box_patterns)] +#![feature(default_field_values)] #![feature(file_buffered)] #![feature(if_let_guard)] #![feature(negative_impls)] diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index f879153c5765..d414f4dbcc24 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -51,12 +51,12 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>( struct HirWfCheck<'tcx> { tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>, - cause: Option>, - cause_depth: usize, + cause: Option> = None, + cause_depth: usize = 0, icx: ItemCtxt<'tcx>, def_id: LocalDefId, param_env: ty::ParamEnv<'tcx>, - depth: usize, + depth: usize = 0, } impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> { @@ -124,16 +124,8 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>( } } - let mut visitor = HirWfCheck { - tcx, - predicate, - cause: None, - cause_depth: 0, - icx, - def_id, - param_env: tcx.param_env(def_id.to_def_id()), - depth: 0, - }; + let param_env = tcx.param_env(def_id.to_def_id()); + let mut visitor = HirWfCheck { tcx, predicate, icx, def_id, param_env, .. }; // Get the starting `hir::Ty` using our `WellFormedLoc`. // We will walk 'into' this type to try to find diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index a51355adf72f..95f0e641c611 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -59,6 +59,7 @@ This API is completely unstable and subject to change. #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] +#![feature(default_field_values)] #![feature(gen_blocks)] #![feature(if_let_guard)] #![feature(iter_intersperse)] From 3e789ed57663cac867309eb4d9e1f14094b02900 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Jan 2026 16:38:10 +0100 Subject: [PATCH 059/978] Stop cloning old `llvmint` repositories to generate intrinsics --- src/intrinsic/archs.rs | 1424 +--------------------------------- src/intrinsic/llvm.rs | 2 + src/intrinsic/old_archs.rs | 1384 +++++++++++++++++++++++++++++++++ tools/generate_intrinsics.py | 50 +- 4 files changed, 1420 insertions(+), 1440 deletions(-) create mode 100644 src/intrinsic/old_archs.rs diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index 43e7c352c34a..89a6cf7f3d6e 100644 --- a/src/intrinsic/archs.rs +++ b/src/intrinsic/archs.rs @@ -6,47 +6,13 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { unimplemented!("***** unsupported LLVM intrinsic {}", full_name) }; let Some((arch, name)) = name.split_once('.') else { - unimplemented!("***** unsupported LLVM intrinsic {}", name) + unimplemented!("***** unsupported LLVM intrinsic llvm.{}", name) }; + let old_arch_res = old_archs(arch, name); + if let ArchCheckResult::Ok(res) = old_arch_res { + return res; + } match arch { - "AMDGPU" => { - #[expect(non_snake_case)] - fn AMDGPU(name: &str, full_name: &str) -> &'static str { - match name { - // AMDGPU - "div.fixup.f32" => "__builtin_amdgpu_div_fixup", - "div.fixup.f64" => "__builtin_amdgpu_div_fixup", - "div.fixup.v2f64" => "__builtin_amdgpu_div_fixup", - "div.fixup.v4f32" => "__builtin_amdgpu_div_fixup", - "div.fmas.f32" => "__builtin_amdgpu_div_fmas", - "div.fmas.f64" => "__builtin_amdgpu_div_fmas", - "div.fmas.v2f64" => "__builtin_amdgpu_div_fmas", - "div.fmas.v4f32" => "__builtin_amdgpu_div_fmas", - "ldexp.f32" => "__builtin_amdgpu_ldexp", - "ldexp.f64" => "__builtin_amdgpu_ldexp", - "ldexp.v2f64" => "__builtin_amdgpu_ldexp", - "ldexp.v4f32" => "__builtin_amdgpu_ldexp", - "rcp.f32" => "__builtin_amdgpu_rcp", - "rcp.f64" => "__builtin_amdgpu_rcp", - "rcp.v2f64" => "__builtin_amdgpu_rcp", - "rcp.v4f32" => "__builtin_amdgpu_rcp", - "rsq.clamped.f32" => "__builtin_amdgpu_rsq_clamped", - "rsq.clamped.f64" => "__builtin_amdgpu_rsq_clamped", - "rsq.clamped.v2f64" => "__builtin_amdgpu_rsq_clamped", - "rsq.clamped.v4f32" => "__builtin_amdgpu_rsq_clamped", - "rsq.f32" => "__builtin_amdgpu_rsq", - "rsq.f64" => "__builtin_amdgpu_rsq", - "rsq.v2f64" => "__builtin_amdgpu_rsq", - "rsq.v4f32" => "__builtin_amdgpu_rsq", - "trig.preop.f32" => "__builtin_amdgpu_trig_preop", - "trig.preop.f64" => "__builtin_amdgpu_trig_preop", - "trig.preop.v2f64" => "__builtin_amdgpu_trig_preop", - "trig.preop.v4f32" => "__builtin_amdgpu_trig_preop", - _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), - } - } - AMDGPU(name, full_name) - } "aarch64" => { fn aarch64(name: &str, full_name: &str) -> &'static str { match name { @@ -537,8 +503,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "ldcl" => "__builtin_arm_ldcl", "mcr" => "__builtin_arm_mcr", "mcr2" => "__builtin_arm_mcr2", - "mcrr" => "__builtin_arm_mcrr", - "mcrr2" => "__builtin_arm_mcrr2", "mrc" => "__builtin_arm_mrc", "mrc2" => "__builtin_arm_mrc2", "qadd" => "__builtin_arm_qadd", @@ -595,7 +559,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "stcl" => "__builtin_arm_stcl", "sxtab16" => "__builtin_arm_sxtab16", "sxtb16" => "__builtin_arm_sxtb16", - "thread.pointer" => "__builtin_thread_pointer", "uadd16" => "__builtin_arm_uadd16", "uadd8" => "__builtin_arm_uadd8", "uasx" => "__builtin_arm_uasx", @@ -646,16 +609,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { } bpf(name, full_name) } - "cuda" => { - fn cuda(name: &str, full_name: &str) -> &'static str { - match name { - // cuda - "syncthreads" => "__syncthreads", - _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), - } - } - cuda(name, full_name) - } "hexagon" => { fn hexagon(name: &str, full_name: &str) -> &'static str { match name { @@ -959,19 +912,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "F2.dfcmpge" => "__builtin_HEXAGON_F2_dfcmpge", "F2.dfcmpgt" => "__builtin_HEXAGON_F2_dfcmpgt", "F2.dfcmpuo" => "__builtin_HEXAGON_F2_dfcmpuo", - "F2.dffixupd" => "__builtin_HEXAGON_F2_dffixupd", - "F2.dffixupn" => "__builtin_HEXAGON_F2_dffixupn", - "F2.dffixupr" => "__builtin_HEXAGON_F2_dffixupr", - "F2.dffma" => "__builtin_HEXAGON_F2_dffma", - "F2.dffma.lib" => "__builtin_HEXAGON_F2_dffma_lib", - "F2.dffma.sc" => "__builtin_HEXAGON_F2_dffma_sc", - "F2.dffms" => "__builtin_HEXAGON_F2_dffms", - "F2.dffms.lib" => "__builtin_HEXAGON_F2_dffms_lib", "F2.dfimm.n" => "__builtin_HEXAGON_F2_dfimm_n", "F2.dfimm.p" => "__builtin_HEXAGON_F2_dfimm_p", "F2.dfmax" => "__builtin_HEXAGON_F2_dfmax", "F2.dfmin" => "__builtin_HEXAGON_F2_dfmin", - "F2.dfmpy" => "__builtin_HEXAGON_F2_dfmpy", "F2.dfmpyfix" => "__builtin_HEXAGON_F2_dfmpyfix", "F2.dfmpyhh" => "__builtin_HEXAGON_F2_dfmpyhh", "F2.dfmpylh" => "__builtin_HEXAGON_F2_dfmpylh", @@ -1398,7 +1342,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "S2.asr.r.vw" => "__builtin_HEXAGON_S2_asr_r_vw", "S2.brev" => "__builtin_HEXAGON_S2_brev", "S2.brevp" => "__builtin_HEXAGON_S2_brevp", - "S2.cabacencbin" => "__builtin_HEXAGON_S2_cabacencbin", "S2.cl0" => "__builtin_HEXAGON_S2_cl0", "S2.cl0p" => "__builtin_HEXAGON_S2_cl0p", "S2.cl1" => "__builtin_HEXAGON_S2_cl1", @@ -1569,7 +1512,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "S6.vsplatrbp" => "__builtin_HEXAGON_S6_vsplatrbp", "S6.vtrunehb.ppp" => "__builtin_HEXAGON_S6_vtrunehb_ppp", "S6.vtrunohb.ppp" => "__builtin_HEXAGON_S6_vtrunohb_ppp", - "SI.to.SXTHI.asrh" => "__builtin_SI_to_SXTHI_asrh", "V6.extractw" => "__builtin_HEXAGON_V6_extractw", "V6.extractw.128B" => "__builtin_HEXAGON_V6_extractw_128B", "V6.get.qfext" => "__builtin_HEXAGON_V6_get_qfext", @@ -2160,14 +2102,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "V6.vlsrwv.128B" => "__builtin_HEXAGON_V6_vlsrwv_128B", "V6.vlut4" => "__builtin_HEXAGON_V6_vlut4", "V6.vlut4.128B" => "__builtin_HEXAGON_V6_vlut4_128B", - "V6.vlutb" => "__builtin_HEXAGON_V6_vlutb", - "V6.vlutb.128B" => "__builtin_HEXAGON_V6_vlutb_128B", - "V6.vlutb.acc" => "__builtin_HEXAGON_V6_vlutb_acc", - "V6.vlutb.acc.128B" => "__builtin_HEXAGON_V6_vlutb_acc_128B", - "V6.vlutb.dv" => "__builtin_HEXAGON_V6_vlutb_dv", - "V6.vlutb.dv.128B" => "__builtin_HEXAGON_V6_vlutb_dv_128B", - "V6.vlutb.dv.acc" => "__builtin_HEXAGON_V6_vlutb_dv_acc", - "V6.vlutb.dv.acc.128B" => "__builtin_HEXAGON_V6_vlutb_dv_acc_128B", "V6.vlutvvb" => "__builtin_HEXAGON_V6_vlutvvb", "V6.vlutvvb.128B" => "__builtin_HEXAGON_V6_vlutvvb_128B", "V6.vlutvvb.nm" => "__builtin_HEXAGON_V6_vlutvvb_nm", @@ -2669,17 +2603,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "Y6.dmresume" => "__builtin_HEXAGON_Y6_dmresume", "Y6.dmstart" => "__builtin_HEXAGON_Y6_dmstart", "Y6.dmwait" => "__builtin_HEXAGON_Y6_dmwait", - "brev.ldb" => "__builtin_brev_ldb", - "brev.ldd" => "__builtin_brev_ldd", - "brev.ldh" => "__builtin_brev_ldh", - "brev.ldub" => "__builtin_brev_ldub", - "brev.lduh" => "__builtin_brev_lduh", - "brev.ldw" => "__builtin_brev_ldw", - "brev.stb" => "__builtin_brev_stb", - "brev.std" => "__builtin_brev_std", - "brev.sth" => "__builtin_brev_sth", - "brev.sthhi" => "__builtin_brev_sthhi", - "brev.stw" => "__builtin_brev_stw", "circ.ldb" => "__builtin_circ_ldb", "circ.ldd" => "__builtin_circ_ldd", "circ.ldh" => "__builtin_circ_ldh", @@ -2691,7 +2614,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "circ.sth" => "__builtin_circ_sth", "circ.sthhi" => "__builtin_circ_sthhi", "circ.stw" => "__builtin_circ_stw", - "mm256i.vaddw" => "__builtin__mm256i_vaddw", "prefetch" => "__builtin_HEXAGON_prefetch", "vmemcpy" => "__builtin_hexagon_vmemcpy", "vmemset" => "__builtin_hexagon_vmemset", @@ -4910,8 +4832,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { fn nvvm(name: &str, full_name: &str) -> &'static str { match name { // nvvm - "abs.i" => "__nvvm_abs_i", - "abs.ll" => "__nvvm_abs_ll", "activemask" => "__nvvm_activemask", "add.rm.d" => "__nvvm_add_rm_d", "add.rm.f" => "__nvvm_add_rm_f", @@ -4925,10 +4845,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "add.rz.d" => "__nvvm_add_rz_d", "add.rz.f" => "__nvvm_add_rz_f", "add.rz.ftz.f" => "__nvvm_add_rz_ftz_f", - "bar.sync" => "__nvvm_bar_sync", "bar.warp.sync" => "__nvvm_bar_warp_sync", - "barrier0" => "__nvvm_bar0", - // [DUPLICATE]: "barrier0" => "__syncthreads", "barrier0.and" => "__nvvm_bar0_and", "barrier0.or" => "__nvvm_bar0_or", "barrier0.popc" => "__nvvm_bar0_popc", @@ -4938,17 +4855,9 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "bf16x2.to.ue8m0x2.rz.satfinite" => "__nvvm_bf16x2_to_ue8m0x2_rz_satfinite", "bf2h.rn" => "__nvvm_bf2h_rn", "bf2h.rn.ftz" => "__nvvm_bf2h_rn_ftz", - "bitcast.d2ll" => "__nvvm_bitcast_d2ll", - "bitcast.f2i" => "__nvvm_bitcast_f2i", - "bitcast.i2f" => "__nvvm_bitcast_i2f", - "bitcast.ll2d" => "__nvvm_bitcast_ll2d", - "brev32" => "__nvvm_brev32", - "brev64" => "__nvvm_brev64", "ceil.d" => "__nvvm_ceil_d", "ceil.f" => "__nvvm_ceil_f", "ceil.ftz.f" => "__nvvm_ceil_ftz_f", - "clz.i" => "__nvvm_clz_i", - "clz.ll" => "__nvvm_clz_ll", "cos.approx.f" => "__nvvm_cos_approx_f", "cos.approx.ftz.f" => "__nvvm_cos_approx_ftz_f", "cp.async.commit.group" => "__nvvm_cp_async_commit_group", @@ -5012,9 +4921,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "e4m3x2.to.f16x2.rn.relu" => "__nvvm_e4m3x2_to_f16x2_rn_relu", "e5m2x2.to.f16x2.rn" => "__nvvm_e5m2x2_to_f16x2_rn", "e5m2x2.to.f16x2.rn.relu" => "__nvvm_e5m2x2_to_f16x2_rn_relu", - "ex2.approx.d" => "__nvvm_ex2_approx_d", - "ex2.approx.f" => "__nvvm_ex2_approx_f", - "ex2.approx.ftz.f" => "__nvvm_ex2_approx_ftz_f", "exit" => "__nvvm_exit", "f16x2.to.e4m3x2.rn" => "__nvvm_f16x2_to_e4m3x2_rn", "f16x2.to.e4m3x2.rn.relu" => "__nvvm_f16x2_to_e4m3x2_rn_relu", @@ -5100,9 +5006,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "__nvvm_f32x4_to_e5m2x4_rs_relu_satfinite" } "f32x4.to.e5m2x4.rs.satfinite" => "__nvvm_f32x4_to_e5m2x4_rs_satfinite", - "fabs.d" => "__nvvm_fabs_d", - "fabs.f" => "__nvvm_fabs_f", - "fabs.ftz.f" => "__nvvm_fabs_ftz_f", "ff.to.e2m1x2.rn.relu.satfinite" => "__nvvm_ff_to_e2m1x2_rn_relu_satfinite", "ff.to.e2m1x2.rn.satfinite" => "__nvvm_ff_to_e2m1x2_rn_satfinite", "ff.to.e2m3x2.rn.relu.satfinite" => "__nvvm_ff_to_e2m3x2_rn_relu_satfinite", @@ -5219,7 +5122,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fmin.xorsign.abs.bf16x2" => "__nvvm_fmin_xorsign_abs_bf16x2", "fmin.xorsign.abs.f" => "__nvvm_fmin_xorsign_abs_f", "fns" => "__nvvm_fns", - "h2f" => "__nvvm_h2f", "i2d.rm" => "__nvvm_i2d_rm", "i2d.rn" => "__nvvm_i2d_rn", "i2d.rp" => "__nvvm_i2d_rp", @@ -5250,10 +5152,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "lohi.i2d" => "__nvvm_lohi_i2d", "match.any.sync.i32" => "__nvvm_match_any_sync_i32", "match.any.sync.i64" => "__nvvm_match_any_sync_i64", - "max.i" => "__nvvm_max_i", - "max.ll" => "__nvvm_max_ll", - "max.ui" => "__nvvm_max_ui", - "max.ull" => "__nvvm_max_ull", "mbarrier.arrive" => "__nvvm_mbarrier_arrive", "mbarrier.arrive.drop" => "__nvvm_mbarrier_arrive_drop", "mbarrier.arrive.drop.noComplete" => "__nvvm_mbarrier_arrive_drop_noComplete", @@ -5276,10 +5174,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "membar.cta" => "__nvvm_membar_cta", "membar.gl" => "__nvvm_membar_gl", "membar.sys" => "__nvvm_membar_sys", - "min.i" => "__nvvm_min_i", - "min.ll" => "__nvvm_min_ll", - "min.ui" => "__nvvm_min_ui", - "min.ull" => "__nvvm_min_ull", "mul.rm.d" => "__nvvm_mul_rm_d", "mul.rm.f" => "__nvvm_mul_rm_f", "mul.rm.ftz.f" => "__nvvm_mul_rm_ftz_f", @@ -5304,8 +5198,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "neg.bf16" => "__nvvm_neg_bf16", "neg.bf16x2" => "__nvvm_neg_bf16x2", "pm.event.mask" => "__nvvm_pm_event_mask", - "popc.i" => "__nvvm_popc_i", - "popc.ll" => "__nvvm_popc_ll", "prmt" => "__nvvm_prmt", "rcp.approx.ftz.d" => "__nvvm_rcp_approx_ftz_d", "rcp.approx.ftz.f" => "__nvvm_rcp_approx_ftz_f", @@ -5322,9 +5214,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "rcp.rz.f" => "__nvvm_rcp_rz_f", "rcp.rz.ftz.f" => "__nvvm_rcp_rz_ftz_f", "read.ptx.sreg.clock" => "__nvvm_read_ptx_sreg_clock", - // [DUPLICATE]: "read.ptx.sreg.clock" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.clock64" => "__nvvm_read_ptx_sreg_clock64", - // [DUPLICATE]: "read.ptx.sreg.clock64" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.ctaid.w" => "__nvvm_read_ptx_sreg_ctaid_w", "read.ptx.sreg.ctaid.x" => "__nvvm_read_ptx_sreg_ctaid_x", "read.ptx.sreg.ctaid.y" => "__nvvm_read_ptx_sreg_ctaid_y", @@ -5364,49 +5254,33 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "read.ptx.sreg.globaltimer" => "__nvvm_read_ptx_sreg_globaltimer", "read.ptx.sreg.globaltimer.lo" => "__nvvm_read_ptx_sreg_globaltimer_lo", "read.ptx.sreg.gridid" => "__nvvm_read_ptx_sreg_gridid", - // [DUPLICATE]: "read.ptx.sreg.gridid" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.laneid" => "__nvvm_read_ptx_sreg_laneid", - // [DUPLICATE]: "read.ptx.sreg.laneid" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.lanemask.eq" => "__nvvm_read_ptx_sreg_lanemask_eq", - // [DUPLICATE]: "read.ptx.sreg.lanemask.eq" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.lanemask.ge" => "__nvvm_read_ptx_sreg_lanemask_ge", - // [DUPLICATE]: "read.ptx.sreg.lanemask.ge" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.lanemask.gt" => "__nvvm_read_ptx_sreg_lanemask_gt", - // [DUPLICATE]: "read.ptx.sreg.lanemask.gt" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.lanemask.le" => "__nvvm_read_ptx_sreg_lanemask_le", - // [DUPLICATE]: "read.ptx.sreg.lanemask.le" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.lanemask.lt" => "__nvvm_read_ptx_sreg_lanemask_lt", - // [DUPLICATE]: "read.ptx.sreg.lanemask.lt" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.nctaid.w" => "__nvvm_read_ptx_sreg_nctaid_w", "read.ptx.sreg.nctaid.x" => "__nvvm_read_ptx_sreg_nctaid_x", "read.ptx.sreg.nctaid.y" => "__nvvm_read_ptx_sreg_nctaid_y", "read.ptx.sreg.nctaid.z" => "__nvvm_read_ptx_sreg_nctaid_z", "read.ptx.sreg.nsmid" => "__nvvm_read_ptx_sreg_nsmid", - // [DUPLICATE]: "read.ptx.sreg.nsmid" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.ntid.w" => "__nvvm_read_ptx_sreg_ntid_w", "read.ptx.sreg.ntid.x" => "__nvvm_read_ptx_sreg_ntid_x", "read.ptx.sreg.ntid.y" => "__nvvm_read_ptx_sreg_ntid_y", "read.ptx.sreg.ntid.z" => "__nvvm_read_ptx_sreg_ntid_z", "read.ptx.sreg.nwarpid" => "__nvvm_read_ptx_sreg_nwarpid", - // [DUPLICATE]: "read.ptx.sreg.nwarpid" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.pm0" => "__nvvm_read_ptx_sreg_pm0", - // [DUPLICATE]: "read.ptx.sreg.pm0" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.pm1" => "__nvvm_read_ptx_sreg_pm1", - // [DUPLICATE]: "read.ptx.sreg.pm1" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.pm2" => "__nvvm_read_ptx_sreg_pm2", - // [DUPLICATE]: "read.ptx.sreg.pm2" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.pm3" => "__nvvm_read_ptx_sreg_pm3", - // [DUPLICATE]: "read.ptx.sreg.pm3" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.smid" => "__nvvm_read_ptx_sreg_smid", - // [DUPLICATE]: "read.ptx.sreg.smid" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.tid.w" => "__nvvm_read_ptx_sreg_tid_w", "read.ptx.sreg.tid.x" => "__nvvm_read_ptx_sreg_tid_x", "read.ptx.sreg.tid.y" => "__nvvm_read_ptx_sreg_tid_y", "read.ptx.sreg.tid.z" => "__nvvm_read_ptx_sreg_tid_z", "read.ptx.sreg.warpid" => "__nvvm_read_ptx_sreg_warpid", - // [DUPLICATE]: "read.ptx.sreg.warpid" => "__nvvm_read_ptx_sreg_", "read.ptx.sreg.warpsize" => "__nvvm_read_ptx_sreg_warpsize", - // [DUPLICATE]: "read.ptx.sreg.warpsize" => "__nvvm_read_ptx_sreg_", "redux.sync.add" => "__nvvm_redux_sync_add", "redux.sync.and" => "__nvvm_redux_sync_and", "redux.sync.fmax" => "__nvvm_redux_sync_fmax", @@ -5424,9 +5298,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "redux.sync.umin" => "__nvvm_redux_sync_umin", "redux.sync.xor" => "__nvvm_redux_sync_xor", "reflect" => "__nvvm_reflect", - "rotate.b32" => "__nvvm_rotate_b32", - "rotate.b64" => "__nvvm_rotate_b64", - "rotate.right.b64" => "__nvvm_rotate_right_b64", "round.d" => "__nvvm_round_d", "round.f" => "__nvvm_round_f", "round.ftz.f" => "__nvvm_round_ftz_f", @@ -5692,7 +5563,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sust.p.3d.v4i16.trap" => "__nvvm_sust_p_3d_v4i16_trap", "sust.p.3d.v4i32.trap" => "__nvvm_sust_p_3d_v4i32_trap", "sust.p.3d.v4i8.trap" => "__nvvm_sust_p_3d_v4i8_trap", - "swap.lo.hi.b64" => "__nvvm_swap_lo_hi_b64", "trunc.d" => "__nvvm_trunc_d", "trunc.f" => "__nvvm_trunc_f", "trunc.ftz.f" => "__nvvm_trunc_ftz_f", @@ -6132,89 +6002,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "packed2zoned" => "__builtin_ppc_packed2zoned", "pdepd" => "__builtin_pdepd", "pextd" => "__builtin_pextd", - "qpx.qvfabs" => "__builtin_qpx_qvfabs", - "qpx.qvfadd" => "__builtin_qpx_qvfadd", - "qpx.qvfadds" => "__builtin_qpx_qvfadds", - "qpx.qvfcfid" => "__builtin_qpx_qvfcfid", - "qpx.qvfcfids" => "__builtin_qpx_qvfcfids", - "qpx.qvfcfidu" => "__builtin_qpx_qvfcfidu", - "qpx.qvfcfidus" => "__builtin_qpx_qvfcfidus", - "qpx.qvfcmpeq" => "__builtin_qpx_qvfcmpeq", - "qpx.qvfcmpgt" => "__builtin_qpx_qvfcmpgt", - "qpx.qvfcmplt" => "__builtin_qpx_qvfcmplt", - "qpx.qvfcpsgn" => "__builtin_qpx_qvfcpsgn", - "qpx.qvfctid" => "__builtin_qpx_qvfctid", - "qpx.qvfctidu" => "__builtin_qpx_qvfctidu", - "qpx.qvfctiduz" => "__builtin_qpx_qvfctiduz", - "qpx.qvfctidz" => "__builtin_qpx_qvfctidz", - "qpx.qvfctiw" => "__builtin_qpx_qvfctiw", - "qpx.qvfctiwu" => "__builtin_qpx_qvfctiwu", - "qpx.qvfctiwuz" => "__builtin_qpx_qvfctiwuz", - "qpx.qvfctiwz" => "__builtin_qpx_qvfctiwz", - "qpx.qvflogical" => "__builtin_qpx_qvflogical", - "qpx.qvfmadd" => "__builtin_qpx_qvfmadd", - "qpx.qvfmadds" => "__builtin_qpx_qvfmadds", - "qpx.qvfmsub" => "__builtin_qpx_qvfmsub", - "qpx.qvfmsubs" => "__builtin_qpx_qvfmsubs", - "qpx.qvfmul" => "__builtin_qpx_qvfmul", - "qpx.qvfmuls" => "__builtin_qpx_qvfmuls", - "qpx.qvfnabs" => "__builtin_qpx_qvfnabs", - "qpx.qvfneg" => "__builtin_qpx_qvfneg", - "qpx.qvfnmadd" => "__builtin_qpx_qvfnmadd", - "qpx.qvfnmadds" => "__builtin_qpx_qvfnmadds", - "qpx.qvfnmsub" => "__builtin_qpx_qvfnmsub", - "qpx.qvfnmsubs" => "__builtin_qpx_qvfnmsubs", - "qpx.qvfperm" => "__builtin_qpx_qvfperm", - "qpx.qvfre" => "__builtin_qpx_qvfre", - "qpx.qvfres" => "__builtin_qpx_qvfres", - "qpx.qvfrim" => "__builtin_qpx_qvfrim", - "qpx.qvfrin" => "__builtin_qpx_qvfrin", - "qpx.qvfrip" => "__builtin_qpx_qvfrip", - "qpx.qvfriz" => "__builtin_qpx_qvfriz", - "qpx.qvfrsp" => "__builtin_qpx_qvfrsp", - "qpx.qvfrsqrte" => "__builtin_qpx_qvfrsqrte", - "qpx.qvfrsqrtes" => "__builtin_qpx_qvfrsqrtes", - "qpx.qvfsel" => "__builtin_qpx_qvfsel", - "qpx.qvfsub" => "__builtin_qpx_qvfsub", - "qpx.qvfsubs" => "__builtin_qpx_qvfsubs", - "qpx.qvftstnan" => "__builtin_qpx_qvftstnan", - "qpx.qvfxmadd" => "__builtin_qpx_qvfxmadd", - "qpx.qvfxmadds" => "__builtin_qpx_qvfxmadds", - "qpx.qvfxmul" => "__builtin_qpx_qvfxmul", - "qpx.qvfxmuls" => "__builtin_qpx_qvfxmuls", - "qpx.qvfxxcpnmadd" => "__builtin_qpx_qvfxxcpnmadd", - "qpx.qvfxxcpnmadds" => "__builtin_qpx_qvfxxcpnmadds", - "qpx.qvfxxmadd" => "__builtin_qpx_qvfxxmadd", - "qpx.qvfxxmadds" => "__builtin_qpx_qvfxxmadds", - "qpx.qvfxxnpmadd" => "__builtin_qpx_qvfxxnpmadd", - "qpx.qvfxxnpmadds" => "__builtin_qpx_qvfxxnpmadds", - "qpx.qvgpci" => "__builtin_qpx_qvgpci", - "qpx.qvlfcd" => "__builtin_qpx_qvlfcd", - "qpx.qvlfcda" => "__builtin_qpx_qvlfcda", - "qpx.qvlfcs" => "__builtin_qpx_qvlfcs", - "qpx.qvlfcsa" => "__builtin_qpx_qvlfcsa", - "qpx.qvlfd" => "__builtin_qpx_qvlfd", - "qpx.qvlfda" => "__builtin_qpx_qvlfda", - "qpx.qvlfiwa" => "__builtin_qpx_qvlfiwa", - "qpx.qvlfiwaa" => "__builtin_qpx_qvlfiwaa", - "qpx.qvlfiwz" => "__builtin_qpx_qvlfiwz", - "qpx.qvlfiwza" => "__builtin_qpx_qvlfiwza", - "qpx.qvlfs" => "__builtin_qpx_qvlfs", - "qpx.qvlfsa" => "__builtin_qpx_qvlfsa", - "qpx.qvlpcld" => "__builtin_qpx_qvlpcld", - "qpx.qvlpcls" => "__builtin_qpx_qvlpcls", - "qpx.qvlpcrd" => "__builtin_qpx_qvlpcrd", - "qpx.qvlpcrs" => "__builtin_qpx_qvlpcrs", - "qpx.qvstfcd" => "__builtin_qpx_qvstfcd", - "qpx.qvstfcda" => "__builtin_qpx_qvstfcda", - "qpx.qvstfcs" => "__builtin_qpx_qvstfcs", - "qpx.qvstfcsa" => "__builtin_qpx_qvstfcsa", - "qpx.qvstfd" => "__builtin_qpx_qvstfd", - "qpx.qvstfda" => "__builtin_qpx_qvstfda", - "qpx.qvstfiw" => "__builtin_qpx_qvstfiw", - "qpx.qvstfiwa" => "__builtin_qpx_qvstfiwa", - "qpx.qvstfs" => "__builtin_qpx_qvstfs", - "qpx.qvstfsa" => "__builtin_qpx_qvstfsa", "readflm" => "__builtin_readflm", "rlwimi" => "__builtin_ppc_rlwimi", "rlwnm" => "__builtin_ppc_rlwnm", @@ -6329,33 +6116,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { } ppc(name, full_name) } - "ptx" => { - fn ptx(name: &str, full_name: &str) -> &'static str { - match name { - // ptx - "bar.sync" => "__builtin_ptx_bar_sync", - "read.clock" => "__builtin_ptx_read_clock", - "read.clock64" => "__builtin_ptx_read_clock64", - "read.gridid" => "__builtin_ptx_read_gridid", - "read.laneid" => "__builtin_ptx_read_laneid", - "read.lanemask.eq" => "__builtin_ptx_read_lanemask_eq", - "read.lanemask.ge" => "__builtin_ptx_read_lanemask_ge", - "read.lanemask.gt" => "__builtin_ptx_read_lanemask_gt", - "read.lanemask.le" => "__builtin_ptx_read_lanemask_le", - "read.lanemask.lt" => "__builtin_ptx_read_lanemask_lt", - "read.nsmid" => "__builtin_ptx_read_nsmid", - "read.nwarpid" => "__builtin_ptx_read_nwarpid", - "read.pm0" => "__builtin_ptx_read_pm0", - "read.pm1" => "__builtin_ptx_read_pm1", - "read.pm2" => "__builtin_ptx_read_pm2", - "read.pm3" => "__builtin_ptx_read_pm3", - "read.smid" => "__builtin_ptx_read_smid", - "read.warpid" => "__builtin_ptx_read_warpid", - _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), - } - } - ptx(name, full_name) - } "r600" => { fn r600(name: &str, full_name: &str) -> &'static str { match name { @@ -7902,10 +7662,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "aadd64" => "__builtin_ia32_aadd64", "aand32" => "__builtin_ia32_aand32", "aand64" => "__builtin_ia32_aand64", - "addcarry.u32" => "__builtin_ia32_addcarry_u32", - "addcarry.u64" => "__builtin_ia32_addcarry_u64", - "addcarryx.u32" => "__builtin_ia32_addcarryx_u32", - "addcarryx.u64" => "__builtin_ia32_addcarryx_u64", "aesni.aesdec" => "__builtin_ia32_aesdec128", "aesni.aesdec.256" => "__builtin_ia32_aesdec256", "aesni.aesdec.512" => "__builtin_ia32_aesdec512", @@ -7924,18 +7680,11 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "aor64" => "__builtin_ia32_aor64", "avx.addsub.pd.256" => "__builtin_ia32_addsubpd256", "avx.addsub.ps.256" => "__builtin_ia32_addsubps256", - "avx.blend.pd.256" => "__builtin_ia32_blendpd256", - "avx.blend.ps.256" => "__builtin_ia32_blendps256", "avx.blendv.pd.256" => "__builtin_ia32_blendvpd256", "avx.blendv.ps.256" => "__builtin_ia32_blendvps256", - "avx.cmp.pd.256" => "__builtin_ia32_cmppd256", - "avx.cmp.ps.256" => "__builtin_ia32_cmpps256", "avx.cvt.pd2.ps.256" => "__builtin_ia32_cvtpd2ps256", "avx.cvt.pd2dq.256" => "__builtin_ia32_cvtpd2dq256", - "avx.cvt.ps2.pd.256" => "__builtin_ia32_cvtps2pd256", "avx.cvt.ps2dq.256" => "__builtin_ia32_cvtps2dq256", - "avx.cvtdq2.pd.256" => "__builtin_ia32_cvtdq2pd256", - "avx.cvtdq2.ps.256" => "__builtin_ia32_cvtdq2ps256", "avx.cvtt.pd2dq.256" => "__builtin_ia32_cvttpd2dq256", "avx.cvtt.ps2dq.256" => "__builtin_ia32_cvttps2dq256", "avx.dp.ps.256" => "__builtin_ia32_dpps256", @@ -7965,22 +7714,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx.round.pd.256" => "__builtin_ia32_roundpd256", "avx.round.ps.256" => "__builtin_ia32_roundps256", "avx.rsqrt.ps.256" => "__builtin_ia32_rsqrtps256", - "avx.sqrt.pd.256" => "__builtin_ia32_sqrtpd256", - "avx.sqrt.ps.256" => "__builtin_ia32_sqrtps256", - "avx.storeu.dq.256" => "__builtin_ia32_storedqu256", - "avx.storeu.pd.256" => "__builtin_ia32_storeupd256", - "avx.storeu.ps.256" => "__builtin_ia32_storeups256", - "avx.vbroadcastf128.pd.256" => "__builtin_ia32_vbroadcastf128_pd256", - "avx.vbroadcastf128.ps.256" => "__builtin_ia32_vbroadcastf128_ps256", - "avx.vextractf128.pd.256" => "__builtin_ia32_vextractf128_pd256", - "avx.vextractf128.ps.256" => "__builtin_ia32_vextractf128_ps256", - "avx.vextractf128.si.256" => "__builtin_ia32_vextractf128_si256", - "avx.vinsertf128.pd.256" => "__builtin_ia32_vinsertf128_pd256", - "avx.vinsertf128.ps.256" => "__builtin_ia32_vinsertf128_ps256", - "avx.vinsertf128.si.256" => "__builtin_ia32_vinsertf128_si256", - "avx.vperm2f128.pd.256" => "__builtin_ia32_vperm2f128_pd256", - "avx.vperm2f128.ps.256" => "__builtin_ia32_vperm2f128_ps256", - "avx.vperm2f128.si.256" => "__builtin_ia32_vperm2f128_si256", "avx.vpermilvar.pd" => "__builtin_ia32_vpermilvarpd", "avx.vpermilvar.pd.256" => "__builtin_ia32_vpermilvarpd256", "avx.vpermilvar.ps" => "__builtin_ia32_vpermilvarps", @@ -8265,33 +7998,14 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx2.maskstore.d.256" => "__builtin_ia32_maskstored256", "avx2.maskstore.q" => "__builtin_ia32_maskstoreq", "avx2.maskstore.q.256" => "__builtin_ia32_maskstoreq256", - "avx2.movntdqa" => "__builtin_ia32_movntdqa256", "avx2.mpsadbw" => "__builtin_ia32_mpsadbw256", - "avx2.pabs.b" => "__builtin_ia32_pabsb256", - "avx2.pabs.d" => "__builtin_ia32_pabsd256", - "avx2.pabs.w" => "__builtin_ia32_pabsw256", "avx2.packssdw" => "__builtin_ia32_packssdw256", "avx2.packsswb" => "__builtin_ia32_packsswb256", "avx2.packusdw" => "__builtin_ia32_packusdw256", "avx2.packuswb" => "__builtin_ia32_packuswb256", - "avx2.padds.b" => "__builtin_ia32_paddsb256", - "avx2.padds.w" => "__builtin_ia32_paddsw256", - "avx2.paddus.b" => "__builtin_ia32_paddusb256", - "avx2.paddus.w" => "__builtin_ia32_paddusw256", "avx2.pavg.b" => "__builtin_ia32_pavgb256", "avx2.pavg.w" => "__builtin_ia32_pavgw256", - "avx2.pblendd.128" => "__builtin_ia32_pblendd128", - "avx2.pblendd.256" => "__builtin_ia32_pblendd256", "avx2.pblendvb" => "__builtin_ia32_pblendvb256", - "avx2.pblendw" => "__builtin_ia32_pblendw256", - "avx2.pbroadcastb.128" => "__builtin_ia32_pbroadcastb128", - "avx2.pbroadcastb.256" => "__builtin_ia32_pbroadcastb256", - "avx2.pbroadcastd.128" => "__builtin_ia32_pbroadcastd128", - "avx2.pbroadcastd.256" => "__builtin_ia32_pbroadcastd256", - "avx2.pbroadcastq.128" => "__builtin_ia32_pbroadcastq128", - "avx2.pbroadcastq.256" => "__builtin_ia32_pbroadcastq256", - "avx2.pbroadcastw.128" => "__builtin_ia32_pbroadcastw128", - "avx2.pbroadcastw.256" => "__builtin_ia32_pbroadcastw256", "avx2.permd" => "__builtin_ia32_permvarsi256", "avx2.permps" => "__builtin_ia32_permvarsf256", "avx2.phadd.d" => "__builtin_ia32_phaddd256", @@ -8302,44 +8016,16 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx2.phsub.w" => "__builtin_ia32_phsubw256", "avx2.pmadd.ub.sw" => "__builtin_ia32_pmaddubsw256", "avx2.pmadd.wd" => "__builtin_ia32_pmaddwd256", - "avx2.pmaxs.b" => "__builtin_ia32_pmaxsb256", - "avx2.pmaxs.d" => "__builtin_ia32_pmaxsd256", - "avx2.pmaxs.w" => "__builtin_ia32_pmaxsw256", - "avx2.pmaxu.b" => "__builtin_ia32_pmaxub256", - "avx2.pmaxu.d" => "__builtin_ia32_pmaxud256", - "avx2.pmaxu.w" => "__builtin_ia32_pmaxuw256", - "avx2.pmins.b" => "__builtin_ia32_pminsb256", - "avx2.pmins.d" => "__builtin_ia32_pminsd256", - "avx2.pmins.w" => "__builtin_ia32_pminsw256", - "avx2.pminu.b" => "__builtin_ia32_pminub256", - "avx2.pminu.d" => "__builtin_ia32_pminud256", - "avx2.pminu.w" => "__builtin_ia32_pminuw256", "avx2.pmovmskb" => "__builtin_ia32_pmovmskb256", - "avx2.pmovsxbd" => "__builtin_ia32_pmovsxbd256", - "avx2.pmovsxbq" => "__builtin_ia32_pmovsxbq256", - "avx2.pmovsxbw" => "__builtin_ia32_pmovsxbw256", - "avx2.pmovsxdq" => "__builtin_ia32_pmovsxdq256", - "avx2.pmovsxwd" => "__builtin_ia32_pmovsxwd256", - "avx2.pmovsxwq" => "__builtin_ia32_pmovsxwq256", - "avx2.pmovzxbd" => "__builtin_ia32_pmovzxbd256", - "avx2.pmovzxbq" => "__builtin_ia32_pmovzxbq256", - "avx2.pmovzxbw" => "__builtin_ia32_pmovzxbw256", - "avx2.pmovzxdq" => "__builtin_ia32_pmovzxdq256", - "avx2.pmovzxwd" => "__builtin_ia32_pmovzxwd256", - "avx2.pmovzxwq" => "__builtin_ia32_pmovzxwq256", - "avx2.pmul.dq" => "__builtin_ia32_pmuldq256", "avx2.pmul.hr.sw" => "__builtin_ia32_pmulhrsw256", "avx2.pmulh.w" => "__builtin_ia32_pmulhw256", "avx2.pmulhu.w" => "__builtin_ia32_pmulhuw256", - "avx2.pmulu.dq" => "__builtin_ia32_pmuludq256", "avx2.psad.bw" => "__builtin_ia32_psadbw256", "avx2.pshuf.b" => "__builtin_ia32_pshufb256", "avx2.psign.b" => "__builtin_ia32_psignb256", "avx2.psign.d" => "__builtin_ia32_psignd256", "avx2.psign.w" => "__builtin_ia32_psignw256", "avx2.psll.d" => "__builtin_ia32_pslld256", - "avx2.psll.dq" => "__builtin_ia32_pslldqi256", - "avx2.psll.dq.bs" => "__builtin_ia32_pslldqi256_byteshift", "avx2.psll.q" => "__builtin_ia32_psllq256", "avx2.psll.w" => "__builtin_ia32_psllw256", "avx2.pslli.d" => "__builtin_ia32_pslldi256", @@ -8356,8 +8042,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx2.psrav.d" => "__builtin_ia32_psrav4si", "avx2.psrav.d.256" => "__builtin_ia32_psrav8si", "avx2.psrl.d" => "__builtin_ia32_psrld256", - "avx2.psrl.dq" => "__builtin_ia32_psrldqi256", - "avx2.psrl.dq.bs" => "__builtin_ia32_psrldqi256_byteshift", "avx2.psrl.q" => "__builtin_ia32_psrlq256", "avx2.psrl.w" => "__builtin_ia32_psrlw256", "avx2.psrli.d" => "__builtin_ia32_psrldi256", @@ -8367,15 +8051,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx2.psrlv.d.256" => "__builtin_ia32_psrlv8si", "avx2.psrlv.q" => "__builtin_ia32_psrlv2di", "avx2.psrlv.q.256" => "__builtin_ia32_psrlv4di", - "avx2.psubs.b" => "__builtin_ia32_psubsb256", - "avx2.psubs.w" => "__builtin_ia32_psubsw256", - "avx2.psubus.b" => "__builtin_ia32_psubusb256", - "avx2.psubus.w" => "__builtin_ia32_psubusw256", - "avx2.vbroadcast.sd.pd.256" => "__builtin_ia32_vbroadcastsd_pd256", - "avx2.vbroadcast.ss.ps" => "__builtin_ia32_vbroadcastss_ps", - "avx2.vbroadcast.ss.ps.256" => "__builtin_ia32_vbroadcastss_ps256", - "avx2.vextracti128" => "__builtin_ia32_extract128i256", - "avx2.vinserti128" => "__builtin_ia32_insert128i256", "avx2.vpdpbssd.128" => "__builtin_ia32_vpdpbssd128", "avx2.vpdpbssd.256" => "__builtin_ia32_vpdpbssd256", "avx2.vpdpbssds.128" => "__builtin_ia32_vpdpbssds128", @@ -8400,7 +8075,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx2.vpdpwuud.256" => "__builtin_ia32_vpdpwuud256", "avx2.vpdpwuuds.128" => "__builtin_ia32_vpdpwuuds128", "avx2.vpdpwuuds.256" => "__builtin_ia32_vpdpwuuds256", - "avx2.vperm2i128" => "__builtin_ia32_permti256", "avx512.add.pd.512" => "__builtin_ia32_addpd512", "avx512.add.ps.512" => "__builtin_ia32_addps512", "avx512.broadcastmb.128" => "__builtin_ia32_broadcastmb128", @@ -8415,194 +8089,32 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.conflict.q.128" => "__builtin_ia32_vpconflictdi_128", "avx512.conflict.q.256" => "__builtin_ia32_vpconflictdi_256", "avx512.conflict.q.512" => "__builtin_ia32_vpconflictdi_512", - "avx512.cvtb2mask.128" => "__builtin_ia32_cvtb2mask128", - "avx512.cvtb2mask.256" => "__builtin_ia32_cvtb2mask256", - "avx512.cvtb2mask.512" => "__builtin_ia32_cvtb2mask512", - "avx512.cvtd2mask.128" => "__builtin_ia32_cvtd2mask128", - "avx512.cvtd2mask.256" => "__builtin_ia32_cvtd2mask256", - "avx512.cvtd2mask.512" => "__builtin_ia32_cvtd2mask512", - "avx512.cvtmask2b.128" => "__builtin_ia32_cvtmask2b128", - "avx512.cvtmask2b.256" => "__builtin_ia32_cvtmask2b256", - "avx512.cvtmask2b.512" => "__builtin_ia32_cvtmask2b512", - "avx512.cvtmask2d.128" => "__builtin_ia32_cvtmask2d128", - "avx512.cvtmask2d.256" => "__builtin_ia32_cvtmask2d256", - "avx512.cvtmask2d.512" => "__builtin_ia32_cvtmask2d512", - "avx512.cvtmask2q.128" => "__builtin_ia32_cvtmask2q128", - "avx512.cvtmask2q.256" => "__builtin_ia32_cvtmask2q256", - "avx512.cvtmask2q.512" => "__builtin_ia32_cvtmask2q512", - "avx512.cvtmask2w.128" => "__builtin_ia32_cvtmask2w128", - "avx512.cvtmask2w.256" => "__builtin_ia32_cvtmask2w256", - "avx512.cvtmask2w.512" => "__builtin_ia32_cvtmask2w512", - "avx512.cvtq2mask.128" => "__builtin_ia32_cvtq2mask128", - "avx512.cvtq2mask.256" => "__builtin_ia32_cvtq2mask256", - "avx512.cvtq2mask.512" => "__builtin_ia32_cvtq2mask512", - "avx512.cvtsd2usi" => "__builtin_ia32_cvtsd2usi", - "avx512.cvtsd2usi64" => "__builtin_ia32_cvtsd2usi64", - "avx512.cvtsi2sd32" => "__builtin_ia32_cvtsi2sd32", "avx512.cvtsi2sd64" => "__builtin_ia32_cvtsi2sd64", "avx512.cvtsi2ss32" => "__builtin_ia32_cvtsi2ss32", "avx512.cvtsi2ss64" => "__builtin_ia32_cvtsi2ss64", - "avx512.cvtss2usi" => "__builtin_ia32_cvtss2usi", - "avx512.cvtss2usi64" => "__builtin_ia32_cvtss2usi64", "avx512.cvttsd2si" => "__builtin_ia32_vcvttsd2si32", "avx512.cvttsd2si64" => "__builtin_ia32_vcvttsd2si64", "avx512.cvttsd2usi" => "__builtin_ia32_vcvttsd2usi32", - // [DUPLICATE]: "avx512.cvttsd2usi" => "__builtin_ia32_cvttsd2usi", "avx512.cvttsd2usi64" => "__builtin_ia32_vcvttsd2usi64", - // [DUPLICATE]: "avx512.cvttsd2usi64" => "__builtin_ia32_cvttsd2usi64", "avx512.cvttss2si" => "__builtin_ia32_vcvttss2si32", "avx512.cvttss2si64" => "__builtin_ia32_vcvttss2si64", "avx512.cvttss2usi" => "__builtin_ia32_vcvttss2usi32", - // [DUPLICATE]: "avx512.cvttss2usi" => "__builtin_ia32_cvttss2usi", "avx512.cvttss2usi64" => "__builtin_ia32_vcvttss2usi64", - // [DUPLICATE]: "avx512.cvttss2usi64" => "__builtin_ia32_cvttss2usi64", - "avx512.cvtusi2sd" => "__builtin_ia32_cvtusi2sd", - // [DUPLICATE]: "avx512.cvtusi2sd" => "__builtin_ia32_cvtusi2sd32", "avx512.cvtusi2ss" => "__builtin_ia32_cvtusi2ss32", - // [DUPLICATE]: "avx512.cvtusi2ss" => "__builtin_ia32_cvtusi2ss", "avx512.cvtusi642sd" => "__builtin_ia32_cvtusi2sd64", - // [DUPLICATE]: "avx512.cvtusi642sd" => "__builtin_ia32_cvtusi642sd", "avx512.cvtusi642ss" => "__builtin_ia32_cvtusi2ss64", - // [DUPLICATE]: "avx512.cvtusi642ss" => "__builtin_ia32_cvtusi642ss", - "avx512.cvtw2mask.128" => "__builtin_ia32_cvtw2mask128", - "avx512.cvtw2mask.256" => "__builtin_ia32_cvtw2mask256", - "avx512.cvtw2mask.512" => "__builtin_ia32_cvtw2mask512", "avx512.dbpsadbw.128" => "__builtin_ia32_dbpsadbw128", "avx512.dbpsadbw.256" => "__builtin_ia32_dbpsadbw256", "avx512.dbpsadbw.512" => "__builtin_ia32_dbpsadbw512", "avx512.div.pd.512" => "__builtin_ia32_divpd512", "avx512.div.ps.512" => "__builtin_ia32_divps512", - "avx512.exp2.pd" => "__builtin_ia32_exp2pd_mask", - "avx512.exp2.ps" => "__builtin_ia32_exp2ps_mask", - "avx512.gather.dpd.512" => "__builtin_ia32_gathersiv8df", - "avx512.gather.dpi.512" => "__builtin_ia32_gathersiv16si", - "avx512.gather.dpq.512" => "__builtin_ia32_gathersiv8di", - "avx512.gather.dps.512" => "__builtin_ia32_gathersiv16sf", - "avx512.gather.qpd.512" => "__builtin_ia32_gatherdiv8df", - "avx512.gather.qpi.512" => "__builtin_ia32_gatherdiv16si", - "avx512.gather.qpq.512" => "__builtin_ia32_gatherdiv8di", - "avx512.gather.qps.512" => "__builtin_ia32_gatherdiv16sf", - "avx512.gather3div2.df" => "__builtin_ia32_gather3div2df", - "avx512.gather3div2.di" => "__builtin_ia32_gather3div2di", - "avx512.gather3div4.df" => "__builtin_ia32_gather3div4df", - "avx512.gather3div4.di" => "__builtin_ia32_gather3div4di", - "avx512.gather3div4.sf" => "__builtin_ia32_gather3div4sf", - "avx512.gather3div4.si" => "__builtin_ia32_gather3div4si", - "avx512.gather3div8.sf" => "__builtin_ia32_gather3div8sf", - "avx512.gather3div8.si" => "__builtin_ia32_gather3div8si", - "avx512.gather3siv2.df" => "__builtin_ia32_gather3siv2df", - "avx512.gather3siv2.di" => "__builtin_ia32_gather3siv2di", - "avx512.gather3siv4.df" => "__builtin_ia32_gather3siv4df", - "avx512.gather3siv4.di" => "__builtin_ia32_gather3siv4di", - "avx512.gather3siv4.sf" => "__builtin_ia32_gather3siv4sf", - "avx512.gather3siv4.si" => "__builtin_ia32_gather3siv4si", - "avx512.gather3siv8.sf" => "__builtin_ia32_gather3siv8sf", - "avx512.gather3siv8.si" => "__builtin_ia32_gather3siv8si", - "avx512.gatherpf.dpd.512" => "__builtin_ia32_gatherpfdpd", - "avx512.gatherpf.dps.512" => "__builtin_ia32_gatherpfdps", - "avx512.gatherpf.qpd.512" => "__builtin_ia32_gatherpfqpd", - "avx512.gatherpf.qps.512" => "__builtin_ia32_gatherpfqps", - "avx512.kand.w" => "__builtin_ia32_kandhi", - "avx512.kandn.w" => "__builtin_ia32_kandnhi", - "avx512.knot.w" => "__builtin_ia32_knothi", - "avx512.kor.w" => "__builtin_ia32_korhi", - "avx512.kortestc.w" => "__builtin_ia32_kortestchi", - "avx512.kortestz.w" => "__builtin_ia32_kortestzhi", - "avx512.kunpck.bw" => "__builtin_ia32_kunpckhi", - "avx512.kunpck.dq" => "__builtin_ia32_kunpckdi", - "avx512.kunpck.wd" => "__builtin_ia32_kunpcksi", - "avx512.kxnor.w" => "__builtin_ia32_kxnorhi", - "avx512.kxor.w" => "__builtin_ia32_kxorhi", - "avx512.mask.add.pd.128" => "__builtin_ia32_addpd128_mask", - "avx512.mask.add.pd.256" => "__builtin_ia32_addpd256_mask", - "avx512.mask.add.pd.512" => "__builtin_ia32_addpd512_mask", - "avx512.mask.add.ps.128" => "__builtin_ia32_addps128_mask", - "avx512.mask.add.ps.256" => "__builtin_ia32_addps256_mask", - "avx512.mask.add.ps.512" => "__builtin_ia32_addps512_mask", // [INVALID CONVERSION]: "avx512.mask.add.sd.round" => "__builtin_ia32_addsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.add.ss.round" => "__builtin_ia32_addss_round_mask", - "avx512.mask.and.pd.128" => "__builtin_ia32_andpd128_mask", - "avx512.mask.and.pd.256" => "__builtin_ia32_andpd256_mask", - "avx512.mask.and.pd.512" => "__builtin_ia32_andpd512_mask", - "avx512.mask.and.ps.128" => "__builtin_ia32_andps128_mask", - "avx512.mask.and.ps.256" => "__builtin_ia32_andps256_mask", - "avx512.mask.and.ps.512" => "__builtin_ia32_andps512_mask", - "avx512.mask.andn.pd.128" => "__builtin_ia32_andnpd128_mask", - "avx512.mask.andn.pd.256" => "__builtin_ia32_andnpd256_mask", - "avx512.mask.andn.pd.512" => "__builtin_ia32_andnpd512_mask", - "avx512.mask.andn.ps.128" => "__builtin_ia32_andnps128_mask", - "avx512.mask.andn.ps.256" => "__builtin_ia32_andnps256_mask", - "avx512.mask.andn.ps.512" => "__builtin_ia32_andnps512_mask", - "avx512.mask.blend.d.512" => "__builtin_ia32_blendmd_512_mask", - "avx512.mask.blend.pd.512" => "__builtin_ia32_blendmpd_512_mask", - "avx512.mask.blend.ps.512" => "__builtin_ia32_blendmps_512_mask", - "avx512.mask.blend.q.512" => "__builtin_ia32_blendmq_512_mask", - "avx512.mask.broadcastf32x2.256" => "__builtin_ia32_broadcastf32x2_256_mask", - "avx512.mask.broadcastf32x2.512" => "__builtin_ia32_broadcastf32x2_512_mask", - "avx512.mask.broadcastf32x4.256" => "__builtin_ia32_broadcastf32x4_256_mask", - "avx512.mask.broadcastf32x4.512" => "__builtin_ia32_broadcastf32x4_512", - "avx512.mask.broadcastf32x8.512" => "__builtin_ia32_broadcastf32x8_512_mask", - "avx512.mask.broadcastf64x2.256" => "__builtin_ia32_broadcastf64x2_256_mask", - "avx512.mask.broadcastf64x2.512" => "__builtin_ia32_broadcastf64x2_512_mask", - "avx512.mask.broadcastf64x4.512" => "__builtin_ia32_broadcastf64x4_512", - "avx512.mask.broadcasti32x2.128" => "__builtin_ia32_broadcasti32x2_128_mask", - "avx512.mask.broadcasti32x2.256" => "__builtin_ia32_broadcasti32x2_256_mask", - "avx512.mask.broadcasti32x2.512" => "__builtin_ia32_broadcasti32x2_512_mask", - "avx512.mask.broadcasti32x4.256" => "__builtin_ia32_broadcasti32x4_256_mask", - "avx512.mask.broadcasti32x4.512" => "__builtin_ia32_broadcasti32x4_512", - "avx512.mask.broadcasti32x8.512" => "__builtin_ia32_broadcasti32x8_512_mask", - "avx512.mask.broadcasti64x2.256" => "__builtin_ia32_broadcasti64x2_256_mask", - "avx512.mask.broadcasti64x2.512" => "__builtin_ia32_broadcasti64x2_512_mask", - "avx512.mask.broadcasti64x4.512" => "__builtin_ia32_broadcasti64x4_512", - "avx512.mask.cmp.pd.128" => "__builtin_ia32_cmppd128_mask", - "avx512.mask.cmp.pd.256" => "__builtin_ia32_cmppd256_mask", - "avx512.mask.cmp.pd.512" => "__builtin_ia32_cmppd512_mask", - "avx512.mask.cmp.ps.128" => "__builtin_ia32_cmpps128_mask", - "avx512.mask.cmp.ps.256" => "__builtin_ia32_cmpps256_mask", - "avx512.mask.cmp.ps.512" => "__builtin_ia32_cmpps512_mask", "avx512.mask.cmp.sd" => "__builtin_ia32_cmpsd_mask", "avx512.mask.cmp.ss" => "__builtin_ia32_cmpss_mask", - "avx512.mask.compress.d.128" => "__builtin_ia32_compresssi128_mask", - "avx512.mask.compress.d.256" => "__builtin_ia32_compresssi256_mask", - "avx512.mask.compress.d.512" => "__builtin_ia32_compresssi512_mask", - "avx512.mask.compress.pd.128" => "__builtin_ia32_compressdf128_mask", - "avx512.mask.compress.pd.256" => "__builtin_ia32_compressdf256_mask", - "avx512.mask.compress.pd.512" => "__builtin_ia32_compressdf512_mask", - "avx512.mask.compress.ps.128" => "__builtin_ia32_compresssf128_mask", - "avx512.mask.compress.ps.256" => "__builtin_ia32_compresssf256_mask", - "avx512.mask.compress.ps.512" => "__builtin_ia32_compresssf512_mask", - "avx512.mask.compress.q.128" => "__builtin_ia32_compressdi128_mask", - "avx512.mask.compress.q.256" => "__builtin_ia32_compressdi256_mask", - "avx512.mask.compress.q.512" => "__builtin_ia32_compressdi512_mask", - "avx512.mask.compress.store.d.128" => "__builtin_ia32_compressstoresi128_mask", - "avx512.mask.compress.store.d.256" => "__builtin_ia32_compressstoresi256_mask", - "avx512.mask.compress.store.d.512" => "__builtin_ia32_compressstoresi512_mask", - "avx512.mask.compress.store.pd.128" => "__builtin_ia32_compressstoredf128_mask", - "avx512.mask.compress.store.pd.256" => "__builtin_ia32_compressstoredf256_mask", - "avx512.mask.compress.store.pd.512" => "__builtin_ia32_compressstoredf512_mask", - "avx512.mask.compress.store.ps.128" => "__builtin_ia32_compressstoresf128_mask", - "avx512.mask.compress.store.ps.256" => "__builtin_ia32_compressstoresf256_mask", - "avx512.mask.compress.store.ps.512" => "__builtin_ia32_compressstoresf512_mask", - "avx512.mask.compress.store.q.128" => "__builtin_ia32_compressstoredi128_mask", - "avx512.mask.compress.store.q.256" => "__builtin_ia32_compressstoredi256_mask", - "avx512.mask.compress.store.q.512" => "__builtin_ia32_compressstoredi512_mask", - "avx512.mask.conflict.d.128" => "__builtin_ia32_vpconflictsi_128_mask", - "avx512.mask.conflict.d.256" => "__builtin_ia32_vpconflictsi_256_mask", - "avx512.mask.conflict.d.512" => "__builtin_ia32_vpconflictsi_512_mask", - "avx512.mask.conflict.q.128" => "__builtin_ia32_vpconflictdi_128_mask", - "avx512.mask.conflict.q.256" => "__builtin_ia32_vpconflictdi_256_mask", - "avx512.mask.conflict.q.512" => "__builtin_ia32_vpconflictdi_512_mask", - "avx512.mask.cvtdq2pd.128" => "__builtin_ia32_cvtdq2pd128_mask", - "avx512.mask.cvtdq2pd.256" => "__builtin_ia32_cvtdq2pd256_mask", - "avx512.mask.cvtdq2pd.512" => "__builtin_ia32_cvtdq2pd512_mask", - "avx512.mask.cvtdq2ps.128" => "__builtin_ia32_cvtdq2ps128_mask", - "avx512.mask.cvtdq2ps.256" => "__builtin_ia32_cvtdq2ps256_mask", - "avx512.mask.cvtdq2ps.512" => "__builtin_ia32_cvtdq2ps512_mask", "avx512.mask.cvtpd2dq.128" => "__builtin_ia32_cvtpd2dq128_mask", - "avx512.mask.cvtpd2dq.256" => "__builtin_ia32_cvtpd2dq256_mask", "avx512.mask.cvtpd2dq.512" => "__builtin_ia32_cvtpd2dq512_mask", "avx512.mask.cvtpd2ps" => "__builtin_ia32_cvtpd2ps_mask", - "avx512.mask.cvtpd2ps.256" => "__builtin_ia32_cvtpd2ps256_mask", "avx512.mask.cvtpd2ps.512" => "__builtin_ia32_cvtpd2ps512_mask", "avx512.mask.cvtpd2qq.128" => "__builtin_ia32_cvtpd2qq128_mask", "avx512.mask.cvtpd2qq.256" => "__builtin_ia32_cvtpd2qq256_mask", @@ -8616,8 +8128,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.cvtps2dq.128" => "__builtin_ia32_cvtps2dq128_mask", "avx512.mask.cvtps2dq.256" => "__builtin_ia32_cvtps2dq256_mask", "avx512.mask.cvtps2dq.512" => "__builtin_ia32_cvtps2dq512_mask", - "avx512.mask.cvtps2pd.128" => "__builtin_ia32_cvtps2pd128_mask", - "avx512.mask.cvtps2pd.256" => "__builtin_ia32_cvtps2pd256_mask", "avx512.mask.cvtps2pd.512" => "__builtin_ia32_cvtps2pd512_mask", "avx512.mask.cvtps2qq.128" => "__builtin_ia32_cvtps2qq128_mask", "avx512.mask.cvtps2qq.256" => "__builtin_ia32_cvtps2qq256_mask", @@ -8628,16 +8138,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.cvtps2uqq.128" => "__builtin_ia32_cvtps2uqq128_mask", "avx512.mask.cvtps2uqq.256" => "__builtin_ia32_cvtps2uqq256_mask", "avx512.mask.cvtps2uqq.512" => "__builtin_ia32_cvtps2uqq512_mask", - "avx512.mask.cvtqq2pd.128" => "__builtin_ia32_cvtqq2pd128_mask", - "avx512.mask.cvtqq2pd.256" => "__builtin_ia32_cvtqq2pd256_mask", - "avx512.mask.cvtqq2pd.512" => "__builtin_ia32_cvtqq2pd512_mask", "avx512.mask.cvtqq2ps.128" => "__builtin_ia32_cvtqq2ps128_mask", - "avx512.mask.cvtqq2ps.256" => "__builtin_ia32_cvtqq2ps256_mask", - "avx512.mask.cvtqq2ps.512" => "__builtin_ia32_cvtqq2ps512_mask", // [INVALID CONVERSION]: "avx512.mask.cvtsd2ss.round" => "__builtin_ia32_cvtsd2ss_round_mask", // [INVALID CONVERSION]: "avx512.mask.cvtss2sd.round" => "__builtin_ia32_cvtss2sd_round_mask", "avx512.mask.cvttpd2dq.128" => "__builtin_ia32_cvttpd2dq128_mask", - "avx512.mask.cvttpd2dq.256" => "__builtin_ia32_cvttpd2dq256_mask", "avx512.mask.cvttpd2dq.512" => "__builtin_ia32_cvttpd2dq512_mask", "avx512.mask.cvttpd2qq.128" => "__builtin_ia32_cvttpd2qq128_mask", "avx512.mask.cvttpd2qq.256" => "__builtin_ia32_cvttpd2qq256_mask", @@ -8648,8 +8152,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.cvttpd2uqq.128" => "__builtin_ia32_cvttpd2uqq128_mask", "avx512.mask.cvttpd2uqq.256" => "__builtin_ia32_cvttpd2uqq256_mask", "avx512.mask.cvttpd2uqq.512" => "__builtin_ia32_cvttpd2uqq512_mask", - "avx512.mask.cvttps2dq.128" => "__builtin_ia32_cvttps2dq128_mask", - "avx512.mask.cvttps2dq.256" => "__builtin_ia32_cvttps2dq256_mask", "avx512.mask.cvttps2dq.512" => "__builtin_ia32_cvttps2dq512_mask", "avx512.mask.cvttps2qq.128" => "__builtin_ia32_cvttps2qq128_mask", "avx512.mask.cvttps2qq.256" => "__builtin_ia32_cvttps2qq256_mask", @@ -8660,53 +8162,9 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.cvttps2uqq.128" => "__builtin_ia32_cvttps2uqq128_mask", "avx512.mask.cvttps2uqq.256" => "__builtin_ia32_cvttps2uqq256_mask", "avx512.mask.cvttps2uqq.512" => "__builtin_ia32_cvttps2uqq512_mask", - "avx512.mask.cvtudq2pd.128" => "__builtin_ia32_cvtudq2pd128_mask", - "avx512.mask.cvtudq2pd.256" => "__builtin_ia32_cvtudq2pd256_mask", - "avx512.mask.cvtudq2pd.512" => "__builtin_ia32_cvtudq2pd512_mask", - "avx512.mask.cvtudq2ps.128" => "__builtin_ia32_cvtudq2ps128_mask", - "avx512.mask.cvtudq2ps.256" => "__builtin_ia32_cvtudq2ps256_mask", - "avx512.mask.cvtudq2ps.512" => "__builtin_ia32_cvtudq2ps512_mask", - "avx512.mask.cvtuqq2pd.128" => "__builtin_ia32_cvtuqq2pd128_mask", - "avx512.mask.cvtuqq2pd.256" => "__builtin_ia32_cvtuqq2pd256_mask", - "avx512.mask.cvtuqq2pd.512" => "__builtin_ia32_cvtuqq2pd512_mask", "avx512.mask.cvtuqq2ps.128" => "__builtin_ia32_cvtuqq2ps128_mask", - "avx512.mask.cvtuqq2ps.256" => "__builtin_ia32_cvtuqq2ps256_mask", - "avx512.mask.cvtuqq2ps.512" => "__builtin_ia32_cvtuqq2ps512_mask", - "avx512.mask.dbpsadbw.128" => "__builtin_ia32_dbpsadbw128_mask", - "avx512.mask.dbpsadbw.256" => "__builtin_ia32_dbpsadbw256_mask", - "avx512.mask.dbpsadbw.512" => "__builtin_ia32_dbpsadbw512_mask", - "avx512.mask.div.pd.128" => "__builtin_ia32_divpd_mask", - "avx512.mask.div.pd.256" => "__builtin_ia32_divpd256_mask", - "avx512.mask.div.pd.512" => "__builtin_ia32_divpd512_mask", - "avx512.mask.div.ps.128" => "__builtin_ia32_divps_mask", - "avx512.mask.div.ps.256" => "__builtin_ia32_divps256_mask", - "avx512.mask.div.ps.512" => "__builtin_ia32_divps512_mask", // [INVALID CONVERSION]: "avx512.mask.div.sd.round" => "__builtin_ia32_divsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.div.ss.round" => "__builtin_ia32_divss_round_mask", - "avx512.mask.expand.d.128" => "__builtin_ia32_expandsi128_mask", - "avx512.mask.expand.d.256" => "__builtin_ia32_expandsi256_mask", - "avx512.mask.expand.d.512" => "__builtin_ia32_expandsi512_mask", - "avx512.mask.expand.load.d.128" => "__builtin_ia32_expandloadsi128_mask", - "avx512.mask.expand.load.d.256" => "__builtin_ia32_expandloadsi256_mask", - "avx512.mask.expand.load.d.512" => "__builtin_ia32_expandloadsi512_mask", - "avx512.mask.expand.load.pd.128" => "__builtin_ia32_expandloaddf128_mask", - "avx512.mask.expand.load.pd.256" => "__builtin_ia32_expandloaddf256_mask", - "avx512.mask.expand.load.pd.512" => "__builtin_ia32_expandloaddf512_mask", - "avx512.mask.expand.load.ps.128" => "__builtin_ia32_expandloadsf128_mask", - "avx512.mask.expand.load.ps.256" => "__builtin_ia32_expandloadsf256_mask", - "avx512.mask.expand.load.ps.512" => "__builtin_ia32_expandloadsf512_mask", - "avx512.mask.expand.load.q.128" => "__builtin_ia32_expandloaddi128_mask", - "avx512.mask.expand.load.q.256" => "__builtin_ia32_expandloaddi256_mask", - "avx512.mask.expand.load.q.512" => "__builtin_ia32_expandloaddi512_mask", - "avx512.mask.expand.pd.128" => "__builtin_ia32_expanddf128_mask", - "avx512.mask.expand.pd.256" => "__builtin_ia32_expanddf256_mask", - "avx512.mask.expand.pd.512" => "__builtin_ia32_expanddf512_mask", - "avx512.mask.expand.ps.128" => "__builtin_ia32_expandsf128_mask", - "avx512.mask.expand.ps.256" => "__builtin_ia32_expandsf256_mask", - "avx512.mask.expand.ps.512" => "__builtin_ia32_expandsf512_mask", - "avx512.mask.expand.q.128" => "__builtin_ia32_expanddi128_mask", - "avx512.mask.expand.q.256" => "__builtin_ia32_expanddi256_mask", - "avx512.mask.expand.q.512" => "__builtin_ia32_expanddi512_mask", "avx512.mask.fixupimm.pd.128" => "__builtin_ia32_fixupimmpd128_mask", "avx512.mask.fixupimm.pd.256" => "__builtin_ia32_fixupimmpd256_mask", "avx512.mask.fixupimm.pd.512" => "__builtin_ia32_fixupimmpd512_mask", @@ -8715,12 +8173,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.fixupimm.ps.512" => "__builtin_ia32_fixupimmps512_mask", "avx512.mask.fixupimm.sd" => "__builtin_ia32_fixupimmsd_mask", "avx512.mask.fixupimm.ss" => "__builtin_ia32_fixupimmss_mask", - "avx512.mask.fpclass.pd.128" => "__builtin_ia32_fpclasspd128_mask", - "avx512.mask.fpclass.pd.256" => "__builtin_ia32_fpclasspd256_mask", - "avx512.mask.fpclass.pd.512" => "__builtin_ia32_fpclasspd512_mask", - "avx512.mask.fpclass.ps.128" => "__builtin_ia32_fpclassps128_mask", - "avx512.mask.fpclass.ps.256" => "__builtin_ia32_fpclassps256_mask", - "avx512.mask.fpclass.ps.512" => "__builtin_ia32_fpclassps512_mask", "avx512.mask.fpclass.sd" => "__builtin_ia32_fpclasssd_mask", "avx512.mask.fpclass.ss" => "__builtin_ia32_fpclassss_mask", "avx512.mask.getexp.pd.128" => "__builtin_ia32_getexppd128_mask", @@ -8739,226 +8191,19 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.getmant.ps.512" => "__builtin_ia32_getmantps512_mask", // [INVALID CONVERSION]: "avx512.mask.getmant.sd" => "__builtin_ia32_getmantsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.getmant.ss" => "__builtin_ia32_getmantss_round_mask", - "avx512.mask.insertf32x4.256" => "__builtin_ia32_insertf32x4_256_mask", - "avx512.mask.insertf32x4.512" => "__builtin_ia32_insertf32x4_mask", - "avx512.mask.insertf32x8.512" => "__builtin_ia32_insertf32x8_mask", - "avx512.mask.insertf64x2.256" => "__builtin_ia32_insertf64x2_256_mask", - "avx512.mask.insertf64x2.512" => "__builtin_ia32_insertf64x2_512_mask", - "avx512.mask.insertf64x4.512" => "__builtin_ia32_insertf64x4_mask", - "avx512.mask.inserti32x4.256" => "__builtin_ia32_inserti32x4_256_mask", - "avx512.mask.inserti32x4.512" => "__builtin_ia32_inserti32x4_mask", - "avx512.mask.inserti32x8.512" => "__builtin_ia32_inserti32x8_mask", - "avx512.mask.inserti64x2.256" => "__builtin_ia32_inserti64x2_256_mask", - "avx512.mask.inserti64x2.512" => "__builtin_ia32_inserti64x2_512_mask", - "avx512.mask.inserti64x4.512" => "__builtin_ia32_inserti64x4_mask", - "avx512.mask.loadu.d.512" => "__builtin_ia32_loaddqusi512_mask", - "avx512.mask.loadu.pd.512" => "__builtin_ia32_loadupd512_mask", - "avx512.mask.loadu.ps.512" => "__builtin_ia32_loadups512_mask", - "avx512.mask.loadu.q.512" => "__builtin_ia32_loaddqudi512_mask", - "avx512.mask.lzcnt.d.512" => "__builtin_ia32_vplzcntd_512_mask", - "avx512.mask.lzcnt.q.512" => "__builtin_ia32_vplzcntq_512_mask", - "avx512.mask.max.pd.128" => "__builtin_ia32_maxpd_mask", - "avx512.mask.max.pd.256" => "__builtin_ia32_maxpd256_mask", - "avx512.mask.max.pd.512" => "__builtin_ia32_maxpd512_mask", - "avx512.mask.max.ps.128" => "__builtin_ia32_maxps_mask", - "avx512.mask.max.ps.256" => "__builtin_ia32_maxps256_mask", - "avx512.mask.max.ps.512" => "__builtin_ia32_maxps512_mask", // [INVALID CONVERSION]: "avx512.mask.max.sd.round" => "__builtin_ia32_maxsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.max.ss.round" => "__builtin_ia32_maxss_round_mask", - "avx512.mask.min.pd.128" => "__builtin_ia32_minpd_mask", - "avx512.mask.min.pd.256" => "__builtin_ia32_minpd256_mask", - "avx512.mask.min.pd.512" => "__builtin_ia32_minpd512_mask", - "avx512.mask.min.ps.128" => "__builtin_ia32_minps_mask", - "avx512.mask.min.ps.256" => "__builtin_ia32_minps256_mask", - "avx512.mask.min.ps.512" => "__builtin_ia32_minps512_mask", // [INVALID CONVERSION]: "avx512.mask.min.sd.round" => "__builtin_ia32_minsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.min.ss.round" => "__builtin_ia32_minss_round_mask", - "avx512.mask.move.sd" => "__builtin_ia32_movsd_mask", - "avx512.mask.move.ss" => "__builtin_ia32_movss_mask", - "avx512.mask.mul.pd.128" => "__builtin_ia32_mulpd_mask", - "avx512.mask.mul.pd.256" => "__builtin_ia32_mulpd256_mask", - "avx512.mask.mul.pd.512" => "__builtin_ia32_mulpd512_mask", - "avx512.mask.mul.ps.128" => "__builtin_ia32_mulps_mask", - "avx512.mask.mul.ps.256" => "__builtin_ia32_mulps256_mask", - "avx512.mask.mul.ps.512" => "__builtin_ia32_mulps512_mask", // [INVALID CONVERSION]: "avx512.mask.mul.sd.round" => "__builtin_ia32_mulsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.mul.ss.round" => "__builtin_ia32_mulss_round_mask", - "avx512.mask.or.pd.128" => "__builtin_ia32_orpd128_mask", - "avx512.mask.or.pd.256" => "__builtin_ia32_orpd256_mask", - "avx512.mask.or.pd.512" => "__builtin_ia32_orpd512_mask", - "avx512.mask.or.ps.128" => "__builtin_ia32_orps128_mask", - "avx512.mask.or.ps.256" => "__builtin_ia32_orps256_mask", - "avx512.mask.or.ps.512" => "__builtin_ia32_orps512_mask", - "avx512.mask.pabs.b.128" => "__builtin_ia32_pabsb128_mask", - "avx512.mask.pabs.b.256" => "__builtin_ia32_pabsb256_mask", - "avx512.mask.pabs.b.512" => "__builtin_ia32_pabsb512_mask", - "avx512.mask.pabs.d.128" => "__builtin_ia32_pabsd128_mask", - "avx512.mask.pabs.d.256" => "__builtin_ia32_pabsd256_mask", - "avx512.mask.pabs.d.512" => "__builtin_ia32_pabsd512_mask", - "avx512.mask.pabs.q.128" => "__builtin_ia32_pabsq128_mask", - "avx512.mask.pabs.q.256" => "__builtin_ia32_pabsq256_mask", - "avx512.mask.pabs.q.512" => "__builtin_ia32_pabsq512_mask", - "avx512.mask.pabs.w.128" => "__builtin_ia32_pabsw128_mask", - "avx512.mask.pabs.w.256" => "__builtin_ia32_pabsw256_mask", - "avx512.mask.pabs.w.512" => "__builtin_ia32_pabsw512_mask", - "avx512.mask.packssdw.128" => "__builtin_ia32_packssdw128_mask", - "avx512.mask.packssdw.256" => "__builtin_ia32_packssdw256_mask", - "avx512.mask.packssdw.512" => "__builtin_ia32_packssdw512_mask", - "avx512.mask.packsswb.128" => "__builtin_ia32_packsswb128_mask", - "avx512.mask.packsswb.256" => "__builtin_ia32_packsswb256_mask", - "avx512.mask.packsswb.512" => "__builtin_ia32_packsswb512_mask", - "avx512.mask.packusdw.128" => "__builtin_ia32_packusdw128_mask", - "avx512.mask.packusdw.256" => "__builtin_ia32_packusdw256_mask", - "avx512.mask.packusdw.512" => "__builtin_ia32_packusdw512_mask", - "avx512.mask.packuswb.128" => "__builtin_ia32_packuswb128_mask", - "avx512.mask.packuswb.256" => "__builtin_ia32_packuswb256_mask", - "avx512.mask.packuswb.512" => "__builtin_ia32_packuswb512_mask", - "avx512.mask.padd.b.128" => "__builtin_ia32_paddb128_mask", - "avx512.mask.padd.b.256" => "__builtin_ia32_paddb256_mask", - "avx512.mask.padd.b.512" => "__builtin_ia32_paddb512_mask", - "avx512.mask.padd.d.128" => "__builtin_ia32_paddd128_mask", - "avx512.mask.padd.d.256" => "__builtin_ia32_paddd256_mask", - "avx512.mask.padd.d.512" => "__builtin_ia32_paddd512_mask", - "avx512.mask.padd.q.128" => "__builtin_ia32_paddq128_mask", - "avx512.mask.padd.q.256" => "__builtin_ia32_paddq256_mask", - "avx512.mask.padd.q.512" => "__builtin_ia32_paddq512_mask", - "avx512.mask.padd.w.128" => "__builtin_ia32_paddw128_mask", - "avx512.mask.padd.w.256" => "__builtin_ia32_paddw256_mask", - "avx512.mask.padd.w.512" => "__builtin_ia32_paddw512_mask", - "avx512.mask.padds.b.128" => "__builtin_ia32_paddsb128_mask", - "avx512.mask.padds.b.256" => "__builtin_ia32_paddsb256_mask", - "avx512.mask.padds.b.512" => "__builtin_ia32_paddsb512_mask", - "avx512.mask.padds.w.128" => "__builtin_ia32_paddsw128_mask", - "avx512.mask.padds.w.256" => "__builtin_ia32_paddsw256_mask", - "avx512.mask.padds.w.512" => "__builtin_ia32_paddsw512_mask", - "avx512.mask.paddus.b.128" => "__builtin_ia32_paddusb128_mask", - "avx512.mask.paddus.b.256" => "__builtin_ia32_paddusb256_mask", - "avx512.mask.paddus.b.512" => "__builtin_ia32_paddusb512_mask", - "avx512.mask.paddus.w.128" => "__builtin_ia32_paddusw128_mask", - "avx512.mask.paddus.w.256" => "__builtin_ia32_paddusw256_mask", - "avx512.mask.paddus.w.512" => "__builtin_ia32_paddusw512_mask", - "avx512.mask.pand.d.512" => "__builtin_ia32_pandd512_mask", - "avx512.mask.pand.q.512" => "__builtin_ia32_pandq512_mask", - "avx512.mask.pavg.b.128" => "__builtin_ia32_pavgb128_mask", - "avx512.mask.pavg.b.256" => "__builtin_ia32_pavgb256_mask", - "avx512.mask.pavg.b.512" => "__builtin_ia32_pavgb512_mask", - "avx512.mask.pavg.w.128" => "__builtin_ia32_pavgw128_mask", - "avx512.mask.pavg.w.256" => "__builtin_ia32_pavgw256_mask", - "avx512.mask.pavg.w.512" => "__builtin_ia32_pavgw512_mask", - "avx512.mask.pbroadcast.b.gpr.128" => "__builtin_ia32_pbroadcastb128_gpr_mask", - "avx512.mask.pbroadcast.b.gpr.256" => "__builtin_ia32_pbroadcastb256_gpr_mask", - "avx512.mask.pbroadcast.b.gpr.512" => "__builtin_ia32_pbroadcastb512_gpr_mask", - "avx512.mask.pbroadcast.d.gpr.128" => "__builtin_ia32_pbroadcastd128_gpr_mask", - "avx512.mask.pbroadcast.d.gpr.256" => "__builtin_ia32_pbroadcastd256_gpr_mask", - "avx512.mask.pbroadcast.d.gpr.512" => "__builtin_ia32_pbroadcastd512_gpr_mask", - "avx512.mask.pbroadcast.q.gpr.128" => "__builtin_ia32_pbroadcastq128_gpr_mask", - "avx512.mask.pbroadcast.q.gpr.256" => "__builtin_ia32_pbroadcastq256_gpr_mask", - "avx512.mask.pbroadcast.q.gpr.512" => "__builtin_ia32_pbroadcastq512_gpr_mask", - "avx512.mask.pbroadcast.q.mem.512" => "__builtin_ia32_pbroadcastq512_mem_mask", - "avx512.mask.pbroadcast.w.gpr.128" => "__builtin_ia32_pbroadcastw128_gpr_mask", - "avx512.mask.pbroadcast.w.gpr.256" => "__builtin_ia32_pbroadcastw256_gpr_mask", - "avx512.mask.pbroadcast.w.gpr.512" => "__builtin_ia32_pbroadcastw512_gpr_mask", - "avx512.mask.pcmpeq.b.128" => "__builtin_ia32_pcmpeqb128_mask", - "avx512.mask.pcmpeq.b.256" => "__builtin_ia32_pcmpeqb256_mask", - "avx512.mask.pcmpeq.b.512" => "__builtin_ia32_pcmpeqb512_mask", - "avx512.mask.pcmpeq.d.128" => "__builtin_ia32_pcmpeqd128_mask", - "avx512.mask.pcmpeq.d.256" => "__builtin_ia32_pcmpeqd256_mask", - "avx512.mask.pcmpeq.d.512" => "__builtin_ia32_pcmpeqd512_mask", - "avx512.mask.pcmpeq.q.128" => "__builtin_ia32_pcmpeqq128_mask", - "avx512.mask.pcmpeq.q.256" => "__builtin_ia32_pcmpeqq256_mask", - "avx512.mask.pcmpeq.q.512" => "__builtin_ia32_pcmpeqq512_mask", - "avx512.mask.pcmpeq.w.128" => "__builtin_ia32_pcmpeqw128_mask", - "avx512.mask.pcmpeq.w.256" => "__builtin_ia32_pcmpeqw256_mask", - "avx512.mask.pcmpeq.w.512" => "__builtin_ia32_pcmpeqw512_mask", - "avx512.mask.pcmpgt.b.128" => "__builtin_ia32_pcmpgtb128_mask", - "avx512.mask.pcmpgt.b.256" => "__builtin_ia32_pcmpgtb256_mask", - "avx512.mask.pcmpgt.b.512" => "__builtin_ia32_pcmpgtb512_mask", - "avx512.mask.pcmpgt.d.128" => "__builtin_ia32_pcmpgtd128_mask", - "avx512.mask.pcmpgt.d.256" => "__builtin_ia32_pcmpgtd256_mask", - "avx512.mask.pcmpgt.d.512" => "__builtin_ia32_pcmpgtd512_mask", - "avx512.mask.pcmpgt.q.128" => "__builtin_ia32_pcmpgtq128_mask", - "avx512.mask.pcmpgt.q.256" => "__builtin_ia32_pcmpgtq256_mask", - "avx512.mask.pcmpgt.q.512" => "__builtin_ia32_pcmpgtq512_mask", - "avx512.mask.pcmpgt.w.128" => "__builtin_ia32_pcmpgtw128_mask", - "avx512.mask.pcmpgt.w.256" => "__builtin_ia32_pcmpgtw256_mask", - "avx512.mask.pcmpgt.w.512" => "__builtin_ia32_pcmpgtw512_mask", - "avx512.mask.permvar.df.256" => "__builtin_ia32_permvardf256_mask", - "avx512.mask.permvar.df.512" => "__builtin_ia32_permvardf512_mask", - "avx512.mask.permvar.di.256" => "__builtin_ia32_permvardi256_mask", - "avx512.mask.permvar.di.512" => "__builtin_ia32_permvardi512_mask", - "avx512.mask.permvar.hi.128" => "__builtin_ia32_permvarhi128_mask", - "avx512.mask.permvar.hi.256" => "__builtin_ia32_permvarhi256_mask", - "avx512.mask.permvar.hi.512" => "__builtin_ia32_permvarhi512_mask", - "avx512.mask.permvar.qi.128" => "__builtin_ia32_permvarqi128_mask", - "avx512.mask.permvar.qi.256" => "__builtin_ia32_permvarqi256_mask", - "avx512.mask.permvar.qi.512" => "__builtin_ia32_permvarqi512_mask", - "avx512.mask.permvar.sf.256" => "__builtin_ia32_permvarsf256_mask", - "avx512.mask.permvar.sf.512" => "__builtin_ia32_permvarsf512_mask", - "avx512.mask.permvar.si.256" => "__builtin_ia32_permvarsi256_mask", - "avx512.mask.permvar.si.512" => "__builtin_ia32_permvarsi512_mask", - "avx512.mask.pmaddubs.w.128" => "__builtin_ia32_pmaddubsw128_mask", - "avx512.mask.pmaddubs.w.256" => "__builtin_ia32_pmaddubsw256_mask", - "avx512.mask.pmaddubs.w.512" => "__builtin_ia32_pmaddubsw512_mask", - "avx512.mask.pmaddw.d.128" => "__builtin_ia32_pmaddwd128_mask", - "avx512.mask.pmaddw.d.256" => "__builtin_ia32_pmaddwd256_mask", - "avx512.mask.pmaddw.d.512" => "__builtin_ia32_pmaddwd512_mask", - "avx512.mask.pmaxs.b.128" => "__builtin_ia32_pmaxsb128_mask", - "avx512.mask.pmaxs.b.256" => "__builtin_ia32_pmaxsb256_mask", - "avx512.mask.pmaxs.b.512" => "__builtin_ia32_pmaxsb512_mask", - "avx512.mask.pmaxs.d.128" => "__builtin_ia32_pmaxsd128_mask", - "avx512.mask.pmaxs.d.256" => "__builtin_ia32_pmaxsd256_mask", - "avx512.mask.pmaxs.d.512" => "__builtin_ia32_pmaxsd512_mask", - "avx512.mask.pmaxs.q.128" => "__builtin_ia32_pmaxsq128_mask", - "avx512.mask.pmaxs.q.256" => "__builtin_ia32_pmaxsq256_mask", - "avx512.mask.pmaxs.q.512" => "__builtin_ia32_pmaxsq512_mask", - "avx512.mask.pmaxs.w.128" => "__builtin_ia32_pmaxsw128_mask", - "avx512.mask.pmaxs.w.256" => "__builtin_ia32_pmaxsw256_mask", - "avx512.mask.pmaxs.w.512" => "__builtin_ia32_pmaxsw512_mask", - "avx512.mask.pmaxu.b.128" => "__builtin_ia32_pmaxub128_mask", - "avx512.mask.pmaxu.b.256" => "__builtin_ia32_pmaxub256_mask", - "avx512.mask.pmaxu.b.512" => "__builtin_ia32_pmaxub512_mask", - "avx512.mask.pmaxu.d.128" => "__builtin_ia32_pmaxud128_mask", - "avx512.mask.pmaxu.d.256" => "__builtin_ia32_pmaxud256_mask", - "avx512.mask.pmaxu.d.512" => "__builtin_ia32_pmaxud512_mask", - "avx512.mask.pmaxu.q.128" => "__builtin_ia32_pmaxuq128_mask", - "avx512.mask.pmaxu.q.256" => "__builtin_ia32_pmaxuq256_mask", - "avx512.mask.pmaxu.q.512" => "__builtin_ia32_pmaxuq512_mask", - "avx512.mask.pmaxu.w.128" => "__builtin_ia32_pmaxuw128_mask", - "avx512.mask.pmaxu.w.256" => "__builtin_ia32_pmaxuw256_mask", - "avx512.mask.pmaxu.w.512" => "__builtin_ia32_pmaxuw512_mask", - "avx512.mask.pmins.b.128" => "__builtin_ia32_pminsb128_mask", - "avx512.mask.pmins.b.256" => "__builtin_ia32_pminsb256_mask", - "avx512.mask.pmins.b.512" => "__builtin_ia32_pminsb512_mask", - "avx512.mask.pmins.d.128" => "__builtin_ia32_pminsd128_mask", - "avx512.mask.pmins.d.256" => "__builtin_ia32_pminsd256_mask", - "avx512.mask.pmins.d.512" => "__builtin_ia32_pminsd512_mask", - "avx512.mask.pmins.q.128" => "__builtin_ia32_pminsq128_mask", - "avx512.mask.pmins.q.256" => "__builtin_ia32_pminsq256_mask", - "avx512.mask.pmins.q.512" => "__builtin_ia32_pminsq512_mask", - "avx512.mask.pmins.w.128" => "__builtin_ia32_pminsw128_mask", - "avx512.mask.pmins.w.256" => "__builtin_ia32_pminsw256_mask", - "avx512.mask.pmins.w.512" => "__builtin_ia32_pminsw512_mask", - "avx512.mask.pminu.b.128" => "__builtin_ia32_pminub128_mask", - "avx512.mask.pminu.b.256" => "__builtin_ia32_pminub256_mask", - "avx512.mask.pminu.b.512" => "__builtin_ia32_pminub512_mask", - "avx512.mask.pminu.d.128" => "__builtin_ia32_pminud128_mask", - "avx512.mask.pminu.d.256" => "__builtin_ia32_pminud256_mask", - "avx512.mask.pminu.d.512" => "__builtin_ia32_pminud512_mask", - "avx512.mask.pminu.q.128" => "__builtin_ia32_pminuq128_mask", - "avx512.mask.pminu.q.256" => "__builtin_ia32_pminuq256_mask", - "avx512.mask.pminu.q.512" => "__builtin_ia32_pminuq512_mask", - "avx512.mask.pminu.w.128" => "__builtin_ia32_pminuw128_mask", - "avx512.mask.pminu.w.256" => "__builtin_ia32_pminuw256_mask", - "avx512.mask.pminu.w.512" => "__builtin_ia32_pminuw512_mask", "avx512.mask.pmov.db.128" => "__builtin_ia32_pmovdb128_mask", "avx512.mask.pmov.db.256" => "__builtin_ia32_pmovdb256_mask", - "avx512.mask.pmov.db.512" => "__builtin_ia32_pmovdb512_mask", "avx512.mask.pmov.db.mem.128" => "__builtin_ia32_pmovdb128mem_mask", "avx512.mask.pmov.db.mem.256" => "__builtin_ia32_pmovdb256mem_mask", "avx512.mask.pmov.db.mem.512" => "__builtin_ia32_pmovdb512mem_mask", "avx512.mask.pmov.dw.128" => "__builtin_ia32_pmovdw128_mask", "avx512.mask.pmov.dw.256" => "__builtin_ia32_pmovdw256_mask", - "avx512.mask.pmov.dw.512" => "__builtin_ia32_pmovdw512_mask", "avx512.mask.pmov.dw.mem.128" => "__builtin_ia32_pmovdw128mem_mask", "avx512.mask.pmov.dw.mem.256" => "__builtin_ia32_pmovdw256mem_mask", "avx512.mask.pmov.dw.mem.512" => "__builtin_ia32_pmovdw512mem_mask", @@ -8969,20 +8214,15 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.pmov.qb.mem.256" => "__builtin_ia32_pmovqb256mem_mask", "avx512.mask.pmov.qb.mem.512" => "__builtin_ia32_pmovqb512mem_mask", "avx512.mask.pmov.qd.128" => "__builtin_ia32_pmovqd128_mask", - "avx512.mask.pmov.qd.256" => "__builtin_ia32_pmovqd256_mask", - "avx512.mask.pmov.qd.512" => "__builtin_ia32_pmovqd512_mask", "avx512.mask.pmov.qd.mem.128" => "__builtin_ia32_pmovqd128mem_mask", "avx512.mask.pmov.qd.mem.256" => "__builtin_ia32_pmovqd256mem_mask", "avx512.mask.pmov.qd.mem.512" => "__builtin_ia32_pmovqd512mem_mask", "avx512.mask.pmov.qw.128" => "__builtin_ia32_pmovqw128_mask", "avx512.mask.pmov.qw.256" => "__builtin_ia32_pmovqw256_mask", - "avx512.mask.pmov.qw.512" => "__builtin_ia32_pmovqw512_mask", "avx512.mask.pmov.qw.mem.128" => "__builtin_ia32_pmovqw128mem_mask", "avx512.mask.pmov.qw.mem.256" => "__builtin_ia32_pmovqw256mem_mask", "avx512.mask.pmov.qw.mem.512" => "__builtin_ia32_pmovqw512mem_mask", "avx512.mask.pmov.wb.128" => "__builtin_ia32_pmovwb128_mask", - "avx512.mask.pmov.wb.256" => "__builtin_ia32_pmovwb256_mask", - "avx512.mask.pmov.wb.512" => "__builtin_ia32_pmovwb512_mask", "avx512.mask.pmov.wb.mem.128" => "__builtin_ia32_pmovwb128mem_mask", "avx512.mask.pmov.wb.mem.256" => "__builtin_ia32_pmovwb256mem_mask", "avx512.mask.pmov.wb.mem.512" => "__builtin_ia32_pmovwb512mem_mask", @@ -9022,24 +8262,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.pmovs.wb.mem.128" => "__builtin_ia32_pmovswb128mem_mask", "avx512.mask.pmovs.wb.mem.256" => "__builtin_ia32_pmovswb256mem_mask", "avx512.mask.pmovs.wb.mem.512" => "__builtin_ia32_pmovswb512mem_mask", - "avx512.mask.pmovsxb.d.128" => "__builtin_ia32_pmovsxbd128_mask", - "avx512.mask.pmovsxb.d.256" => "__builtin_ia32_pmovsxbd256_mask", - "avx512.mask.pmovsxb.d.512" => "__builtin_ia32_pmovsxbd512_mask", - "avx512.mask.pmovsxb.q.128" => "__builtin_ia32_pmovsxbq128_mask", - "avx512.mask.pmovsxb.q.256" => "__builtin_ia32_pmovsxbq256_mask", - "avx512.mask.pmovsxb.q.512" => "__builtin_ia32_pmovsxbq512_mask", - "avx512.mask.pmovsxb.w.128" => "__builtin_ia32_pmovsxbw128_mask", - "avx512.mask.pmovsxb.w.256" => "__builtin_ia32_pmovsxbw256_mask", - "avx512.mask.pmovsxb.w.512" => "__builtin_ia32_pmovsxbw512_mask", - "avx512.mask.pmovsxd.q.128" => "__builtin_ia32_pmovsxdq128_mask", - "avx512.mask.pmovsxd.q.256" => "__builtin_ia32_pmovsxdq256_mask", - "avx512.mask.pmovsxd.q.512" => "__builtin_ia32_pmovsxdq512_mask", - "avx512.mask.pmovsxw.d.128" => "__builtin_ia32_pmovsxwd128_mask", - "avx512.mask.pmovsxw.d.256" => "__builtin_ia32_pmovsxwd256_mask", - "avx512.mask.pmovsxw.d.512" => "__builtin_ia32_pmovsxwd512_mask", - "avx512.mask.pmovsxw.q.128" => "__builtin_ia32_pmovsxwq128_mask", - "avx512.mask.pmovsxw.q.256" => "__builtin_ia32_pmovsxwq256_mask", - "avx512.mask.pmovsxw.q.512" => "__builtin_ia32_pmovsxwq512_mask", "avx512.mask.pmovus.db.128" => "__builtin_ia32_pmovusdb128_mask", "avx512.mask.pmovus.db.256" => "__builtin_ia32_pmovusdb256_mask", "avx512.mask.pmovus.db.512" => "__builtin_ia32_pmovusdb512_mask", @@ -9076,191 +8298,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.pmovus.wb.mem.128" => "__builtin_ia32_pmovuswb128mem_mask", "avx512.mask.pmovus.wb.mem.256" => "__builtin_ia32_pmovuswb256mem_mask", "avx512.mask.pmovus.wb.mem.512" => "__builtin_ia32_pmovuswb512mem_mask", - "avx512.mask.pmovzxb.d.128" => "__builtin_ia32_pmovzxbd128_mask", - "avx512.mask.pmovzxb.d.256" => "__builtin_ia32_pmovzxbd256_mask", - "avx512.mask.pmovzxb.d.512" => "__builtin_ia32_pmovzxbd512_mask", - "avx512.mask.pmovzxb.q.128" => "__builtin_ia32_pmovzxbq128_mask", - "avx512.mask.pmovzxb.q.256" => "__builtin_ia32_pmovzxbq256_mask", - "avx512.mask.pmovzxb.q.512" => "__builtin_ia32_pmovzxbq512_mask", - "avx512.mask.pmovzxb.w.128" => "__builtin_ia32_pmovzxbw128_mask", - "avx512.mask.pmovzxb.w.256" => "__builtin_ia32_pmovzxbw256_mask", - "avx512.mask.pmovzxb.w.512" => "__builtin_ia32_pmovzxbw512_mask", - "avx512.mask.pmovzxd.q.128" => "__builtin_ia32_pmovzxdq128_mask", - "avx512.mask.pmovzxd.q.256" => "__builtin_ia32_pmovzxdq256_mask", - "avx512.mask.pmovzxd.q.512" => "__builtin_ia32_pmovzxdq512_mask", - "avx512.mask.pmovzxw.d.128" => "__builtin_ia32_pmovzxwd128_mask", - "avx512.mask.pmovzxw.d.256" => "__builtin_ia32_pmovzxwd256_mask", - "avx512.mask.pmovzxw.d.512" => "__builtin_ia32_pmovzxwd512_mask", - "avx512.mask.pmovzxw.q.128" => "__builtin_ia32_pmovzxwq128_mask", - "avx512.mask.pmovzxw.q.256" => "__builtin_ia32_pmovzxwq256_mask", - "avx512.mask.pmovzxw.q.512" => "__builtin_ia32_pmovzxwq512_mask", - "avx512.mask.pmul.dq.128" => "__builtin_ia32_pmuldq128_mask", - "avx512.mask.pmul.dq.256" => "__builtin_ia32_pmuldq256_mask", - "avx512.mask.pmul.dq.512" => "__builtin_ia32_pmuldq512_mask", - "avx512.mask.pmul.hr.sw.128" => "__builtin_ia32_pmulhrsw128_mask", - "avx512.mask.pmul.hr.sw.256" => "__builtin_ia32_pmulhrsw256_mask", - "avx512.mask.pmul.hr.sw.512" => "__builtin_ia32_pmulhrsw512_mask", - "avx512.mask.pmulh.w.128" => "__builtin_ia32_pmulhw128_mask", - "avx512.mask.pmulh.w.256" => "__builtin_ia32_pmulhw256_mask", - "avx512.mask.pmulh.w.512" => "__builtin_ia32_pmulhw512_mask", - "avx512.mask.pmulhu.w.128" => "__builtin_ia32_pmulhuw128_mask", - "avx512.mask.pmulhu.w.256" => "__builtin_ia32_pmulhuw256_mask", - "avx512.mask.pmulhu.w.512" => "__builtin_ia32_pmulhuw512_mask", - "avx512.mask.pmull.d.128" => "__builtin_ia32_pmulld128_mask", - "avx512.mask.pmull.d.256" => "__builtin_ia32_pmulld256_mask", - "avx512.mask.pmull.d.512" => "__builtin_ia32_pmulld512_mask", - "avx512.mask.pmull.q.128" => "__builtin_ia32_pmullq128_mask", - "avx512.mask.pmull.q.256" => "__builtin_ia32_pmullq256_mask", - "avx512.mask.pmull.q.512" => "__builtin_ia32_pmullq512_mask", - "avx512.mask.pmull.w.128" => "__builtin_ia32_pmullw128_mask", - "avx512.mask.pmull.w.256" => "__builtin_ia32_pmullw256_mask", - "avx512.mask.pmull.w.512" => "__builtin_ia32_pmullw512_mask", - "avx512.mask.pmultishift.qb.128" => "__builtin_ia32_vpmultishiftqb128_mask", - "avx512.mask.pmultishift.qb.256" => "__builtin_ia32_vpmultishiftqb256_mask", - "avx512.mask.pmultishift.qb.512" => "__builtin_ia32_vpmultishiftqb512_mask", - "avx512.mask.pmulu.dq.128" => "__builtin_ia32_pmuludq128_mask", - "avx512.mask.pmulu.dq.256" => "__builtin_ia32_pmuludq256_mask", - "avx512.mask.pmulu.dq.512" => "__builtin_ia32_pmuludq512_mask", - "avx512.mask.prol.d.128" => "__builtin_ia32_prold128_mask", - "avx512.mask.prol.d.256" => "__builtin_ia32_prold256_mask", - "avx512.mask.prol.d.512" => "__builtin_ia32_prold512_mask", - "avx512.mask.prol.q.128" => "__builtin_ia32_prolq128_mask", - "avx512.mask.prol.q.256" => "__builtin_ia32_prolq256_mask", - "avx512.mask.prol.q.512" => "__builtin_ia32_prolq512_mask", - "avx512.mask.prolv.d.128" => "__builtin_ia32_prolvd128_mask", - "avx512.mask.prolv.d.256" => "__builtin_ia32_prolvd256_mask", - "avx512.mask.prolv.d.512" => "__builtin_ia32_prolvd512_mask", - "avx512.mask.prolv.q.128" => "__builtin_ia32_prolvq128_mask", - "avx512.mask.prolv.q.256" => "__builtin_ia32_prolvq256_mask", - "avx512.mask.prolv.q.512" => "__builtin_ia32_prolvq512_mask", - "avx512.mask.pror.d.128" => "__builtin_ia32_prord128_mask", - "avx512.mask.pror.d.256" => "__builtin_ia32_prord256_mask", - "avx512.mask.pror.d.512" => "__builtin_ia32_prord512_mask", - "avx512.mask.pror.q.128" => "__builtin_ia32_prorq128_mask", - "avx512.mask.pror.q.256" => "__builtin_ia32_prorq256_mask", - "avx512.mask.pror.q.512" => "__builtin_ia32_prorq512_mask", - "avx512.mask.prorv.d.128" => "__builtin_ia32_prorvd128_mask", - "avx512.mask.prorv.d.256" => "__builtin_ia32_prorvd256_mask", - "avx512.mask.prorv.d.512" => "__builtin_ia32_prorvd512_mask", - "avx512.mask.prorv.q.128" => "__builtin_ia32_prorvq128_mask", - "avx512.mask.prorv.q.256" => "__builtin_ia32_prorvq256_mask", - "avx512.mask.prorv.q.512" => "__builtin_ia32_prorvq512_mask", - "avx512.mask.pshuf.b.128" => "__builtin_ia32_pshufb128_mask", - "avx512.mask.pshuf.b.256" => "__builtin_ia32_pshufb256_mask", - "avx512.mask.pshuf.b.512" => "__builtin_ia32_pshufb512_mask", - "avx512.mask.psll.d" => "__builtin_ia32_pslld512_mask", - "avx512.mask.psll.d.128" => "__builtin_ia32_pslld128_mask", - "avx512.mask.psll.d.256" => "__builtin_ia32_pslld256_mask", - "avx512.mask.psll.di.128" => "__builtin_ia32_pslldi128_mask", - "avx512.mask.psll.di.256" => "__builtin_ia32_pslldi256_mask", - "avx512.mask.psll.di.512" => "__builtin_ia32_pslldi512_mask", - "avx512.mask.psll.q" => "__builtin_ia32_psllq512_mask", - "avx512.mask.psll.q.128" => "__builtin_ia32_psllq128_mask", - "avx512.mask.psll.q.256" => "__builtin_ia32_psllq256_mask", - "avx512.mask.psll.qi.128" => "__builtin_ia32_psllqi128_mask", - "avx512.mask.psll.qi.256" => "__builtin_ia32_psllqi256_mask", - "avx512.mask.psll.qi.512" => "__builtin_ia32_psllqi512_mask", - "avx512.mask.psll.w.128" => "__builtin_ia32_psllw128_mask", - "avx512.mask.psll.w.256" => "__builtin_ia32_psllw256_mask", - "avx512.mask.psll.w.512" => "__builtin_ia32_psllw512_mask", - "avx512.mask.psll.wi.128" => "__builtin_ia32_psllwi128_mask", - "avx512.mask.psll.wi.256" => "__builtin_ia32_psllwi256_mask", - "avx512.mask.psll.wi.512" => "__builtin_ia32_psllwi512_mask", - "avx512.mask.psllv.d" => "__builtin_ia32_psllv16si_mask", - "avx512.mask.psllv.q" => "__builtin_ia32_psllv8di_mask", - "avx512.mask.psllv16.hi" => "__builtin_ia32_psllv16hi_mask", - "avx512.mask.psllv2.di" => "__builtin_ia32_psllv2di_mask", - "avx512.mask.psllv32hi" => "__builtin_ia32_psllv32hi_mask", - "avx512.mask.psllv4.di" => "__builtin_ia32_psllv4di_mask", - "avx512.mask.psllv4.si" => "__builtin_ia32_psllv4si_mask", - "avx512.mask.psllv8.hi" => "__builtin_ia32_psllv8hi_mask", - "avx512.mask.psllv8.si" => "__builtin_ia32_psllv8si_mask", - "avx512.mask.psra.d" => "__builtin_ia32_psrad512_mask", - "avx512.mask.psra.d.128" => "__builtin_ia32_psrad128_mask", - "avx512.mask.psra.d.256" => "__builtin_ia32_psrad256_mask", - "avx512.mask.psra.di.128" => "__builtin_ia32_psradi128_mask", - "avx512.mask.psra.di.256" => "__builtin_ia32_psradi256_mask", - "avx512.mask.psra.di.512" => "__builtin_ia32_psradi512_mask", - "avx512.mask.psra.q" => "__builtin_ia32_psraq512_mask", - "avx512.mask.psra.q.128" => "__builtin_ia32_psraq128_mask", - "avx512.mask.psra.q.256" => "__builtin_ia32_psraq256_mask", - "avx512.mask.psra.qi.128" => "__builtin_ia32_psraqi128_mask", - "avx512.mask.psra.qi.256" => "__builtin_ia32_psraqi256_mask", - "avx512.mask.psra.qi.512" => "__builtin_ia32_psraqi512_mask", - "avx512.mask.psra.w.128" => "__builtin_ia32_psraw128_mask", - "avx512.mask.psra.w.256" => "__builtin_ia32_psraw256_mask", - "avx512.mask.psra.w.512" => "__builtin_ia32_psraw512_mask", - "avx512.mask.psra.wi.128" => "__builtin_ia32_psrawi128_mask", - "avx512.mask.psra.wi.256" => "__builtin_ia32_psrawi256_mask", - "avx512.mask.psra.wi.512" => "__builtin_ia32_psrawi512_mask", - "avx512.mask.psrav.d" => "__builtin_ia32_psrav16si_mask", - "avx512.mask.psrav.q" => "__builtin_ia32_psrav8di_mask", - "avx512.mask.psrav.q.128" => "__builtin_ia32_psravq128_mask", - "avx512.mask.psrav.q.256" => "__builtin_ia32_psravq256_mask", - "avx512.mask.psrav16.hi" => "__builtin_ia32_psrav16hi_mask", - "avx512.mask.psrav32.hi" => "__builtin_ia32_psrav32hi_mask", - "avx512.mask.psrav4.si" => "__builtin_ia32_psrav4si_mask", - "avx512.mask.psrav8.hi" => "__builtin_ia32_psrav8hi_mask", - "avx512.mask.psrav8.si" => "__builtin_ia32_psrav8si_mask", - "avx512.mask.psrl.d" => "__builtin_ia32_psrld512_mask", - "avx512.mask.psrl.d.128" => "__builtin_ia32_psrld128_mask", - "avx512.mask.psrl.d.256" => "__builtin_ia32_psrld256_mask", - "avx512.mask.psrl.di.128" => "__builtin_ia32_psrldi128_mask", - "avx512.mask.psrl.di.256" => "__builtin_ia32_psrldi256_mask", - "avx512.mask.psrl.di.512" => "__builtin_ia32_psrldi512_mask", - "avx512.mask.psrl.q" => "__builtin_ia32_psrlq512_mask", - "avx512.mask.psrl.q.128" => "__builtin_ia32_psrlq128_mask", - "avx512.mask.psrl.q.256" => "__builtin_ia32_psrlq256_mask", - "avx512.mask.psrl.qi.128" => "__builtin_ia32_psrlqi128_mask", - "avx512.mask.psrl.qi.256" => "__builtin_ia32_psrlqi256_mask", - "avx512.mask.psrl.qi.512" => "__builtin_ia32_psrlqi512_mask", - "avx512.mask.psrl.w.128" => "__builtin_ia32_psrlw128_mask", - "avx512.mask.psrl.w.256" => "__builtin_ia32_psrlw256_mask", - "avx512.mask.psrl.w.512" => "__builtin_ia32_psrlw512_mask", - "avx512.mask.psrl.wi.128" => "__builtin_ia32_psrlwi128_mask", - "avx512.mask.psrl.wi.256" => "__builtin_ia32_psrlwi256_mask", - "avx512.mask.psrl.wi.512" => "__builtin_ia32_psrlwi512_mask", - "avx512.mask.psrlv.d" => "__builtin_ia32_psrlv16si_mask", - "avx512.mask.psrlv.q" => "__builtin_ia32_psrlv8di_mask", - "avx512.mask.psrlv16.hi" => "__builtin_ia32_psrlv16hi_mask", - "avx512.mask.psrlv2.di" => "__builtin_ia32_psrlv2di_mask", - "avx512.mask.psrlv32hi" => "__builtin_ia32_psrlv32hi_mask", - "avx512.mask.psrlv4.di" => "__builtin_ia32_psrlv4di_mask", - "avx512.mask.psrlv4.si" => "__builtin_ia32_psrlv4si_mask", - "avx512.mask.psrlv8.hi" => "__builtin_ia32_psrlv8hi_mask", - "avx512.mask.psrlv8.si" => "__builtin_ia32_psrlv8si_mask", - "avx512.mask.psub.b.128" => "__builtin_ia32_psubb128_mask", - "avx512.mask.psub.b.256" => "__builtin_ia32_psubb256_mask", - "avx512.mask.psub.b.512" => "__builtin_ia32_psubb512_mask", - "avx512.mask.psub.d.128" => "__builtin_ia32_psubd128_mask", - "avx512.mask.psub.d.256" => "__builtin_ia32_psubd256_mask", - "avx512.mask.psub.d.512" => "__builtin_ia32_psubd512_mask", - "avx512.mask.psub.q.128" => "__builtin_ia32_psubq128_mask", - "avx512.mask.psub.q.256" => "__builtin_ia32_psubq256_mask", - "avx512.mask.psub.q.512" => "__builtin_ia32_psubq512_mask", - "avx512.mask.psub.w.128" => "__builtin_ia32_psubw128_mask", - "avx512.mask.psub.w.256" => "__builtin_ia32_psubw256_mask", - "avx512.mask.psub.w.512" => "__builtin_ia32_psubw512_mask", - "avx512.mask.psubs.b.128" => "__builtin_ia32_psubsb128_mask", - "avx512.mask.psubs.b.256" => "__builtin_ia32_psubsb256_mask", - "avx512.mask.psubs.b.512" => "__builtin_ia32_psubsb512_mask", - "avx512.mask.psubs.w.128" => "__builtin_ia32_psubsw128_mask", - "avx512.mask.psubs.w.256" => "__builtin_ia32_psubsw256_mask", - "avx512.mask.psubs.w.512" => "__builtin_ia32_psubsw512_mask", - "avx512.mask.psubus.b.128" => "__builtin_ia32_psubusb128_mask", - "avx512.mask.psubus.b.256" => "__builtin_ia32_psubusb256_mask", - "avx512.mask.psubus.b.512" => "__builtin_ia32_psubusb512_mask", - "avx512.mask.psubus.w.128" => "__builtin_ia32_psubusw128_mask", - "avx512.mask.psubus.w.256" => "__builtin_ia32_psubusw256_mask", - "avx512.mask.psubus.w.512" => "__builtin_ia32_psubusw512_mask", - "avx512.mask.pternlog.d.128" => "__builtin_ia32_pternlogd128_mask", - "avx512.mask.pternlog.d.256" => "__builtin_ia32_pternlogd256_mask", - "avx512.mask.pternlog.d.512" => "__builtin_ia32_pternlogd512_mask", - "avx512.mask.pternlog.q.128" => "__builtin_ia32_pternlogq128_mask", - "avx512.mask.pternlog.q.256" => "__builtin_ia32_pternlogq256_mask", - "avx512.mask.pternlog.q.512" => "__builtin_ia32_pternlogq512_mask", - "avx512.mask.ptestm.d.512" => "__builtin_ia32_ptestmd512", - "avx512.mask.ptestm.q.512" => "__builtin_ia32_ptestmq512", "avx512.mask.range.pd.128" => "__builtin_ia32_rangepd128_mask", "avx512.mask.range.pd.256" => "__builtin_ia32_rangepd256_mask", "avx512.mask.range.pd.512" => "__builtin_ia32_rangepd512_mask", @@ -9293,181 +8330,11 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.mask.scalef.ps.512" => "__builtin_ia32_scalefps512_mask", // [INVALID CONVERSION]: "avx512.mask.scalef.sd" => "__builtin_ia32_scalefsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.scalef.ss" => "__builtin_ia32_scalefss_round_mask", - "avx512.mask.shuf.f32x4" => "__builtin_ia32_shuf_f32x4_mask", - "avx512.mask.shuf.f32x4.256" => "__builtin_ia32_shuf_f32x4_256_mask", - "avx512.mask.shuf.f64x2" => "__builtin_ia32_shuf_f64x2_mask", - "avx512.mask.shuf.f64x2.256" => "__builtin_ia32_shuf_f64x2_256_mask", - "avx512.mask.shuf.i32x4" => "__builtin_ia32_shuf_i32x4_mask", - "avx512.mask.shuf.i32x4.256" => "__builtin_ia32_shuf_i32x4_256_mask", - "avx512.mask.shuf.i64x2" => "__builtin_ia32_shuf_i64x2_mask", - "avx512.mask.shuf.i64x2.256" => "__builtin_ia32_shuf_i64x2_256_mask", - "avx512.mask.shuf.pd.128" => "__builtin_ia32_shufpd128_mask", - "avx512.mask.shuf.pd.256" => "__builtin_ia32_shufpd256_mask", - "avx512.mask.shuf.pd.512" => "__builtin_ia32_shufpd512_mask", - "avx512.mask.shuf.ps.128" => "__builtin_ia32_shufps128_mask", - "avx512.mask.shuf.ps.256" => "__builtin_ia32_shufps256_mask", - "avx512.mask.shuf.ps.512" => "__builtin_ia32_shufps512_mask", - "avx512.mask.sqrt.pd.128" => "__builtin_ia32_sqrtpd128_mask", - "avx512.mask.sqrt.pd.256" => "__builtin_ia32_sqrtpd256_mask", - "avx512.mask.sqrt.pd.512" => "__builtin_ia32_sqrtpd512_mask", - "avx512.mask.sqrt.ps.128" => "__builtin_ia32_sqrtps128_mask", - "avx512.mask.sqrt.ps.256" => "__builtin_ia32_sqrtps256_mask", - "avx512.mask.sqrt.ps.512" => "__builtin_ia32_sqrtps512_mask", - // [INVALID CONVERSION]: "avx512.mask.sqrt.sd" => "__builtin_ia32_sqrtsd_round_mask", - // [INVALID CONVERSION]: "avx512.mask.sqrt.ss" => "__builtin_ia32_sqrtss_round_mask", - "avx512.mask.store.ss" => "__builtin_ia32_storess_mask", - "avx512.mask.storeu.d.512" => "__builtin_ia32_storedqusi512_mask", - "avx512.mask.storeu.pd.512" => "__builtin_ia32_storeupd512_mask", - "avx512.mask.storeu.ps.512" => "__builtin_ia32_storeups512_mask", - "avx512.mask.storeu.q.512" => "__builtin_ia32_storedqudi512_mask", - "avx512.mask.sub.pd.128" => "__builtin_ia32_subpd128_mask", - "avx512.mask.sub.pd.256" => "__builtin_ia32_subpd256_mask", - "avx512.mask.sub.pd.512" => "__builtin_ia32_subpd512_mask", - "avx512.mask.sub.ps.128" => "__builtin_ia32_subps128_mask", - "avx512.mask.sub.ps.256" => "__builtin_ia32_subps256_mask", - "avx512.mask.sub.ps.512" => "__builtin_ia32_subps512_mask", // [INVALID CONVERSION]: "avx512.mask.sub.sd.round" => "__builtin_ia32_subsd_round_mask", // [INVALID CONVERSION]: "avx512.mask.sub.ss.round" => "__builtin_ia32_subss_round_mask", - "avx512.mask.valign.d.128" => "__builtin_ia32_alignd128_mask", - "avx512.mask.valign.d.256" => "__builtin_ia32_alignd256_mask", - "avx512.mask.valign.d.512" => "__builtin_ia32_alignd512_mask", - "avx512.mask.valign.q.128" => "__builtin_ia32_alignq128_mask", - "avx512.mask.valign.q.256" => "__builtin_ia32_alignq256_mask", - "avx512.mask.valign.q.512" => "__builtin_ia32_alignq512_mask", - "avx512.mask.vcvtph2ps.128" => "__builtin_ia32_vcvtph2ps_mask", - "avx512.mask.vcvtph2ps.256" => "__builtin_ia32_vcvtph2ps256_mask", - "avx512.mask.vcvtph2ps.512" => "__builtin_ia32_vcvtph2ps512_mask", "avx512.mask.vcvtps2ph.128" => "__builtin_ia32_vcvtps2ph_mask", "avx512.mask.vcvtps2ph.256" => "__builtin_ia32_vcvtps2ph256_mask", "avx512.mask.vcvtps2ph.512" => "__builtin_ia32_vcvtps2ph512_mask", - "avx512.mask.vextractf32x4.256" => "__builtin_ia32_extractf32x4_256_mask", - "avx512.mask.vextractf32x4.512" => "__builtin_ia32_extractf32x4_mask", - "avx512.mask.vextractf32x8.512" => "__builtin_ia32_extractf32x8_mask", - "avx512.mask.vextractf64x2.256" => "__builtin_ia32_extractf64x2_256_mask", - "avx512.mask.vextractf64x2.512" => "__builtin_ia32_extractf64x2_512_mask", - "avx512.mask.vextractf64x4.512" => "__builtin_ia32_extractf64x4_mask", - "avx512.mask.vextracti32x4.256" => "__builtin_ia32_extracti32x4_256_mask", - "avx512.mask.vextracti32x4.512" => "__builtin_ia32_extracti32x4_mask", - "avx512.mask.vextracti32x8.512" => "__builtin_ia32_extracti32x8_mask", - "avx512.mask.vextracti64x2.256" => "__builtin_ia32_extracti64x2_256_mask", - "avx512.mask.vextracti64x2.512" => "__builtin_ia32_extracti64x2_512_mask", - "avx512.mask.vextracti64x4.512" => "__builtin_ia32_extracti64x4_mask", - "avx512.mask.vfmadd.pd.128" => "__builtin_ia32_vfmaddpd128_mask", - "avx512.mask.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256_mask", - "avx512.mask.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask", - "avx512.mask.vfmadd.ps.128" => "__builtin_ia32_vfmaddps128_mask", - "avx512.mask.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256_mask", - "avx512.mask.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask", - "avx512.mask.vfmadd.sd" => "__builtin_ia32_vfmaddsd3_mask", - "avx512.mask.vfmadd.ss" => "__builtin_ia32_vfmaddss3_mask", - "avx512.mask.vfmaddsub.pd.128" => "__builtin_ia32_vfmaddsubpd128_mask", - "avx512.mask.vfmaddsub.pd.256" => "__builtin_ia32_vfmaddsubpd256_mask", - "avx512.mask.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask", - "avx512.mask.vfmaddsub.ps.128" => "__builtin_ia32_vfmaddsubps128_mask", - "avx512.mask.vfmaddsub.ps.256" => "__builtin_ia32_vfmaddsubps256_mask", - "avx512.mask.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_mask", - "avx512.mask.vfnmadd.pd.128" => "__builtin_ia32_vfnmaddpd128_mask", - "avx512.mask.vfnmadd.pd.256" => "__builtin_ia32_vfnmaddpd256_mask", - "avx512.mask.vfnmadd.pd.512" => "__builtin_ia32_vfnmaddpd512_mask", - "avx512.mask.vfnmadd.ps.128" => "__builtin_ia32_vfnmaddps128_mask", - "avx512.mask.vfnmadd.ps.256" => "__builtin_ia32_vfnmaddps256_mask", - "avx512.mask.vfnmadd.ps.512" => "__builtin_ia32_vfnmaddps512_mask", - "avx512.mask.vfnmsub.pd.128" => "__builtin_ia32_vfnmsubpd128_mask", - "avx512.mask.vfnmsub.pd.256" => "__builtin_ia32_vfnmsubpd256_mask", - "avx512.mask.vfnmsub.pd.512" => "__builtin_ia32_vfnmsubpd512_mask", - "avx512.mask.vfnmsub.ps.128" => "__builtin_ia32_vfnmsubps128_mask", - "avx512.mask.vfnmsub.ps.256" => "__builtin_ia32_vfnmsubps256_mask", - "avx512.mask.vfnmsub.ps.512" => "__builtin_ia32_vfnmsubps512_mask", - "avx512.mask.vpermi2var.d.128" => "__builtin_ia32_vpermi2vard128_mask", - "avx512.mask.vpermi2var.d.256" => "__builtin_ia32_vpermi2vard256_mask", - "avx512.mask.vpermi2var.d.512" => "__builtin_ia32_vpermi2vard512_mask", - "avx512.mask.vpermi2var.hi.128" => "__builtin_ia32_vpermi2varhi128_mask", - "avx512.mask.vpermi2var.hi.256" => "__builtin_ia32_vpermi2varhi256_mask", - "avx512.mask.vpermi2var.hi.512" => "__builtin_ia32_vpermi2varhi512_mask", - "avx512.mask.vpermi2var.pd.128" => "__builtin_ia32_vpermi2varpd128_mask", - "avx512.mask.vpermi2var.pd.256" => "__builtin_ia32_vpermi2varpd256_mask", - "avx512.mask.vpermi2var.pd.512" => "__builtin_ia32_vpermi2varpd512_mask", - "avx512.mask.vpermi2var.ps.128" => "__builtin_ia32_vpermi2varps128_mask", - "avx512.mask.vpermi2var.ps.256" => "__builtin_ia32_vpermi2varps256_mask", - "avx512.mask.vpermi2var.ps.512" => "__builtin_ia32_vpermi2varps512_mask", - "avx512.mask.vpermi2var.q.128" => "__builtin_ia32_vpermi2varq128_mask", - "avx512.mask.vpermi2var.q.256" => "__builtin_ia32_vpermi2varq256_mask", - "avx512.mask.vpermi2var.q.512" => "__builtin_ia32_vpermi2varq512_mask", - "avx512.mask.vpermi2var.qi.128" => "__builtin_ia32_vpermi2varqi128_mask", - "avx512.mask.vpermi2var.qi.256" => "__builtin_ia32_vpermi2varqi256_mask", - "avx512.mask.vpermi2var.qi.512" => "__builtin_ia32_vpermi2varqi512_mask", - "avx512.mask.vpermilvar.pd.128" => "__builtin_ia32_vpermilvarpd_mask", - "avx512.mask.vpermilvar.pd.256" => "__builtin_ia32_vpermilvarpd256_mask", - "avx512.mask.vpermilvar.pd.512" => "__builtin_ia32_vpermilvarpd512_mask", - "avx512.mask.vpermilvar.ps.128" => "__builtin_ia32_vpermilvarps_mask", - "avx512.mask.vpermilvar.ps.256" => "__builtin_ia32_vpermilvarps256_mask", - "avx512.mask.vpermilvar.ps.512" => "__builtin_ia32_vpermilvarps512_mask", - "avx512.mask.vpermt.d.512" => "__builtin_ia32_vpermt2vard512_mask", - "avx512.mask.vpermt.pd.512" => "__builtin_ia32_vpermt2varpd512_mask", - "avx512.mask.vpermt.ps.512" => "__builtin_ia32_vpermt2varps512_mask", - "avx512.mask.vpermt.q.512" => "__builtin_ia32_vpermt2varq512_mask", - "avx512.mask.vpermt2var.d.128" => "__builtin_ia32_vpermt2vard128_mask", - "avx512.mask.vpermt2var.d.256" => "__builtin_ia32_vpermt2vard256_mask", - "avx512.mask.vpermt2var.d.512" => "__builtin_ia32_vpermt2vard512_mask", - "avx512.mask.vpermt2var.hi.128" => "__builtin_ia32_vpermt2varhi128_mask", - "avx512.mask.vpermt2var.hi.256" => "__builtin_ia32_vpermt2varhi256_mask", - "avx512.mask.vpermt2var.hi.512" => "__builtin_ia32_vpermt2varhi512_mask", - "avx512.mask.vpermt2var.pd.128" => "__builtin_ia32_vpermt2varpd128_mask", - "avx512.mask.vpermt2var.pd.256" => "__builtin_ia32_vpermt2varpd256_mask", - "avx512.mask.vpermt2var.pd.512" => "__builtin_ia32_vpermt2varpd512_mask", - "avx512.mask.vpermt2var.ps.128" => "__builtin_ia32_vpermt2varps128_mask", - "avx512.mask.vpermt2var.ps.256" => "__builtin_ia32_vpermt2varps256_mask", - "avx512.mask.vpermt2var.ps.512" => "__builtin_ia32_vpermt2varps512_mask", - "avx512.mask.vpermt2var.q.128" => "__builtin_ia32_vpermt2varq128_mask", - "avx512.mask.vpermt2var.q.256" => "__builtin_ia32_vpermt2varq256_mask", - "avx512.mask.vpermt2var.q.512" => "__builtin_ia32_vpermt2varq512_mask", - "avx512.mask.vpermt2var.qi.128" => "__builtin_ia32_vpermt2varqi128_mask", - "avx512.mask.vpermt2var.qi.256" => "__builtin_ia32_vpermt2varqi256_mask", - "avx512.mask.vpermt2var.qi.512" => "__builtin_ia32_vpermt2varqi512_mask", - "avx512.mask.vpmadd52h.uq.128" => "__builtin_ia32_vpmadd52huq128_mask", - "avx512.mask.vpmadd52h.uq.256" => "__builtin_ia32_vpmadd52huq256_mask", - "avx512.mask.vpmadd52h.uq.512" => "__builtin_ia32_vpmadd52huq512_mask", - "avx512.mask.vpmadd52l.uq.128" => "__builtin_ia32_vpmadd52luq128_mask", - "avx512.mask.vpmadd52l.uq.256" => "__builtin_ia32_vpmadd52luq256_mask", - "avx512.mask.vpmadd52l.uq.512" => "__builtin_ia32_vpmadd52luq512_mask", - "avx512.mask.xor.pd.128" => "__builtin_ia32_xorpd128_mask", - "avx512.mask.xor.pd.256" => "__builtin_ia32_xorpd256_mask", - "avx512.mask.xor.pd.512" => "__builtin_ia32_xorpd512_mask", - "avx512.mask.xor.ps.128" => "__builtin_ia32_xorps128_mask", - "avx512.mask.xor.ps.256" => "__builtin_ia32_xorps256_mask", - "avx512.mask.xor.ps.512" => "__builtin_ia32_xorps512_mask", - "avx512.mask3.vfmadd.pd.128" => "__builtin_ia32_vfmaddpd128_mask3", - "avx512.mask3.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256_mask3", - "avx512.mask3.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask3", - "avx512.mask3.vfmadd.ps.128" => "__builtin_ia32_vfmaddps128_mask3", - "avx512.mask3.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256_mask3", - "avx512.mask3.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask3", - "avx512.mask3.vfmadd.sd" => "__builtin_ia32_vfmaddsd3_mask3", - "avx512.mask3.vfmadd.ss" => "__builtin_ia32_vfmaddss3_mask3", - "avx512.mask3.vfmaddsub.pd.128" => "__builtin_ia32_vfmaddsubpd128_mask3", - "avx512.mask3.vfmaddsub.pd.256" => "__builtin_ia32_vfmaddsubpd256_mask3", - "avx512.mask3.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask3", - "avx512.mask3.vfmaddsub.ps.128" => "__builtin_ia32_vfmaddsubps128_mask3", - "avx512.mask3.vfmaddsub.ps.256" => "__builtin_ia32_vfmaddsubps256_mask3", - "avx512.mask3.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_mask3", - "avx512.mask3.vfmsub.pd.128" => "__builtin_ia32_vfmsubpd128_mask3", - "avx512.mask3.vfmsub.pd.256" => "__builtin_ia32_vfmsubpd256_mask3", - "avx512.mask3.vfmsub.pd.512" => "__builtin_ia32_vfmsubpd512_mask3", - "avx512.mask3.vfmsub.ps.128" => "__builtin_ia32_vfmsubps128_mask3", - "avx512.mask3.vfmsub.ps.256" => "__builtin_ia32_vfmsubps256_mask3", - "avx512.mask3.vfmsub.ps.512" => "__builtin_ia32_vfmsubps512_mask3", - "avx512.mask3.vfmsubadd.pd.128" => "__builtin_ia32_vfmsubaddpd128_mask3", - "avx512.mask3.vfmsubadd.pd.256" => "__builtin_ia32_vfmsubaddpd256_mask3", - "avx512.mask3.vfmsubadd.pd.512" => "__builtin_ia32_vfmsubaddpd512_mask3", - "avx512.mask3.vfmsubadd.ps.128" => "__builtin_ia32_vfmsubaddps128_mask3", - "avx512.mask3.vfmsubadd.ps.256" => "__builtin_ia32_vfmsubaddps256_mask3", - "avx512.mask3.vfmsubadd.ps.512" => "__builtin_ia32_vfmsubaddps512_mask3", - "avx512.mask3.vfnmsub.pd.128" => "__builtin_ia32_vfnmsubpd128_mask3", - "avx512.mask3.vfnmsub.pd.256" => "__builtin_ia32_vfnmsubpd256_mask3", - "avx512.mask3.vfnmsub.pd.512" => "__builtin_ia32_vfnmsubpd512_mask3", - "avx512.mask3.vfnmsub.ps.128" => "__builtin_ia32_vfnmsubps128_mask3", - "avx512.mask3.vfnmsub.ps.256" => "__builtin_ia32_vfnmsubps256_mask3", - "avx512.mask3.vfnmsub.ps.512" => "__builtin_ia32_vfnmsubps512_mask3", "avx512.maskz.fixupimm.pd.128" => "__builtin_ia32_fixupimmpd128_maskz", "avx512.maskz.fixupimm.pd.256" => "__builtin_ia32_fixupimmpd256_maskz", "avx512.maskz.fixupimm.pd.512" => "__builtin_ia32_fixupimmpd512_maskz", @@ -9476,55 +8343,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.maskz.fixupimm.ps.512" => "__builtin_ia32_fixupimmps512_maskz", "avx512.maskz.fixupimm.sd" => "__builtin_ia32_fixupimmsd_maskz", "avx512.maskz.fixupimm.ss" => "__builtin_ia32_fixupimmss_maskz", - "avx512.maskz.pternlog.d.128" => "__builtin_ia32_pternlogd128_maskz", - "avx512.maskz.pternlog.d.256" => "__builtin_ia32_pternlogd256_maskz", - "avx512.maskz.pternlog.d.512" => "__builtin_ia32_pternlogd512_maskz", - "avx512.maskz.pternlog.q.128" => "__builtin_ia32_pternlogq128_maskz", - "avx512.maskz.pternlog.q.256" => "__builtin_ia32_pternlogq256_maskz", - "avx512.maskz.pternlog.q.512" => "__builtin_ia32_pternlogq512_maskz", - "avx512.maskz.vfmadd.pd.128" => "__builtin_ia32_vfmaddpd128_maskz", - "avx512.maskz.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256_maskz", - "avx512.maskz.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_maskz", - "avx512.maskz.vfmadd.ps.128" => "__builtin_ia32_vfmaddps128_maskz", - "avx512.maskz.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256_maskz", - "avx512.maskz.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_maskz", - "avx512.maskz.vfmadd.sd" => "__builtin_ia32_vfmaddsd3_maskz", - "avx512.maskz.vfmadd.ss" => "__builtin_ia32_vfmaddss3_maskz", - "avx512.maskz.vfmaddsub.pd.128" => "__builtin_ia32_vfmaddsubpd128_maskz", - "avx512.maskz.vfmaddsub.pd.256" => "__builtin_ia32_vfmaddsubpd256_maskz", - "avx512.maskz.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_maskz", - "avx512.maskz.vfmaddsub.ps.128" => "__builtin_ia32_vfmaddsubps128_maskz", - "avx512.maskz.vfmaddsub.ps.256" => "__builtin_ia32_vfmaddsubps256_maskz", - "avx512.maskz.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_maskz", - "avx512.maskz.vpermt2var.d.128" => "__builtin_ia32_vpermt2vard128_maskz", - "avx512.maskz.vpermt2var.d.256" => "__builtin_ia32_vpermt2vard256_maskz", - "avx512.maskz.vpermt2var.d.512" => "__builtin_ia32_vpermt2vard512_maskz", - "avx512.maskz.vpermt2var.hi.128" => "__builtin_ia32_vpermt2varhi128_maskz", - "avx512.maskz.vpermt2var.hi.256" => "__builtin_ia32_vpermt2varhi256_maskz", - "avx512.maskz.vpermt2var.hi.512" => "__builtin_ia32_vpermt2varhi512_maskz", - "avx512.maskz.vpermt2var.pd.128" => "__builtin_ia32_vpermt2varpd128_maskz", - "avx512.maskz.vpermt2var.pd.256" => "__builtin_ia32_vpermt2varpd256_maskz", - "avx512.maskz.vpermt2var.pd.512" => "__builtin_ia32_vpermt2varpd512_maskz", - "avx512.maskz.vpermt2var.ps.128" => "__builtin_ia32_vpermt2varps128_maskz", - "avx512.maskz.vpermt2var.ps.256" => "__builtin_ia32_vpermt2varps256_maskz", - "avx512.maskz.vpermt2var.ps.512" => "__builtin_ia32_vpermt2varps512_maskz", - "avx512.maskz.vpermt2var.q.128" => "__builtin_ia32_vpermt2varq128_maskz", - "avx512.maskz.vpermt2var.q.256" => "__builtin_ia32_vpermt2varq256_maskz", - "avx512.maskz.vpermt2var.q.512" => "__builtin_ia32_vpermt2varq512_maskz", - "avx512.maskz.vpermt2var.qi.128" => "__builtin_ia32_vpermt2varqi128_maskz", - "avx512.maskz.vpermt2var.qi.256" => "__builtin_ia32_vpermt2varqi256_maskz", - "avx512.maskz.vpermt2var.qi.512" => "__builtin_ia32_vpermt2varqi512_maskz", - "avx512.maskz.vpmadd52h.uq.128" => "__builtin_ia32_vpmadd52huq128_maskz", - "avx512.maskz.vpmadd52h.uq.256" => "__builtin_ia32_vpmadd52huq256_maskz", - "avx512.maskz.vpmadd52h.uq.512" => "__builtin_ia32_vpmadd52huq512_maskz", - "avx512.maskz.vpmadd52l.uq.128" => "__builtin_ia32_vpmadd52luq128_maskz", - "avx512.maskz.vpmadd52l.uq.256" => "__builtin_ia32_vpmadd52luq256_maskz", - "avx512.maskz.vpmadd52l.uq.512" => "__builtin_ia32_vpmadd52luq512_maskz", "avx512.max.pd.512" => "__builtin_ia32_maxpd512", "avx512.max.ps.512" => "__builtin_ia32_maxps512", "avx512.min.pd.512" => "__builtin_ia32_minpd512", "avx512.min.ps.512" => "__builtin_ia32_minps512", - "avx512.movntdqa" => "__builtin_ia32_movntdqa512", "avx512.mul.pd.512" => "__builtin_ia32_mulpd512", "avx512.mul.ps.512" => "__builtin_ia32_mulps512", "avx512.packssdw.512" => "__builtin_ia32_packssdw512", @@ -9533,8 +8355,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.packuswb.512" => "__builtin_ia32_packuswb512", "avx512.pavg.b.512" => "__builtin_ia32_pavgb512", "avx512.pavg.w.512" => "__builtin_ia32_pavgw512", - "avx512.pbroadcastd.512" => "__builtin_ia32_pbroadcastd512", - "avx512.pbroadcastq.512" => "__builtin_ia32_pbroadcastq512", "avx512.permvar.df.256" => "__builtin_ia32_permvardf256", "avx512.permvar.df.512" => "__builtin_ia32_permvardf512", "avx512.permvar.di.256" => "__builtin_ia32_permvardi256", @@ -9549,11 +8369,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.permvar.si.512" => "__builtin_ia32_permvarsi512", "avx512.pmaddubs.w.512" => "__builtin_ia32_pmaddubsw512", "avx512.pmaddw.d.512" => "__builtin_ia32_pmaddwd512", - "avx512.pmovzxbd" => "__builtin_ia32_pmovzxbd512", - "avx512.pmovzxbq" => "__builtin_ia32_pmovzxbq512", - "avx512.pmovzxdq" => "__builtin_ia32_pmovzxdq512", - "avx512.pmovzxwd" => "__builtin_ia32_pmovzxwd512", - "avx512.pmovzxwq" => "__builtin_ia32_pmovzxwq512", "avx512.pmul.hr.sw.512" => "__builtin_ia32_pmulhrsw512", "avx512.pmulh.w.512" => "__builtin_ia32_pmulhw512", "avx512.pmulhu.w.512" => "__builtin_ia32_pmulhuw512", @@ -9563,8 +8378,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.psad.bw.512" => "__builtin_ia32_psadbw512", "avx512.pshuf.b.512" => "__builtin_ia32_pshufb512", "avx512.psll.d.512" => "__builtin_ia32_pslld512", - "avx512.psll.dq" => "__builtin_ia32_pslldqi512", - "avx512.psll.dq.bs" => "__builtin_ia32_pslldqi512_byteshift", "avx512.psll.q.512" => "__builtin_ia32_psllq512", "avx512.psll.w.512" => "__builtin_ia32_psllw512", "avx512.pslli.d.512" => "__builtin_ia32_pslldi512", @@ -9593,8 +8406,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.psrav.w.256" => "__builtin_ia32_psrav16hi", "avx512.psrav.w.512" => "__builtin_ia32_psrav32hi", "avx512.psrl.d.512" => "__builtin_ia32_psrld512", - "avx512.psrl.dq" => "__builtin_ia32_psrldqi512", - "avx512.psrl.dq.bs" => "__builtin_ia32_psrldqi512_byteshift", "avx512.psrl.q.512" => "__builtin_ia32_psrlq512", "avx512.psrl.w.512" => "__builtin_ia32_psrlw512", "avx512.psrli.d.512" => "__builtin_ia32_psrldi512", @@ -9611,30 +8422,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.pternlog.q.128" => "__builtin_ia32_pternlogq128", "avx512.pternlog.q.256" => "__builtin_ia32_pternlogq256", "avx512.pternlog.q.512" => "__builtin_ia32_pternlogq512", - "avx512.ptestm.b.128" => "__builtin_ia32_ptestmb128", - "avx512.ptestm.b.256" => "__builtin_ia32_ptestmb256", - "avx512.ptestm.b.512" => "__builtin_ia32_ptestmb512", - "avx512.ptestm.d.128" => "__builtin_ia32_ptestmd128", - "avx512.ptestm.d.256" => "__builtin_ia32_ptestmd256", - "avx512.ptestm.d.512" => "__builtin_ia32_ptestmd512", - "avx512.ptestm.q.128" => "__builtin_ia32_ptestmq128", - "avx512.ptestm.q.256" => "__builtin_ia32_ptestmq256", - "avx512.ptestm.q.512" => "__builtin_ia32_ptestmq512", - "avx512.ptestm.w.128" => "__builtin_ia32_ptestmw128", - "avx512.ptestm.w.256" => "__builtin_ia32_ptestmw256", - "avx512.ptestm.w.512" => "__builtin_ia32_ptestmw512", - "avx512.ptestnm.b.128" => "__builtin_ia32_ptestnmb128", - "avx512.ptestnm.b.256" => "__builtin_ia32_ptestnmb256", - "avx512.ptestnm.b.512" => "__builtin_ia32_ptestnmb512", - "avx512.ptestnm.d.128" => "__builtin_ia32_ptestnmd128", - "avx512.ptestnm.d.256" => "__builtin_ia32_ptestnmd256", - "avx512.ptestnm.d.512" => "__builtin_ia32_ptestnmd512", - "avx512.ptestnm.q.128" => "__builtin_ia32_ptestnmq128", - "avx512.ptestnm.q.256" => "__builtin_ia32_ptestnmq256", - "avx512.ptestnm.q.512" => "__builtin_ia32_ptestnmq512", - "avx512.ptestnm.w.128" => "__builtin_ia32_ptestnmw128", - "avx512.ptestnm.w.256" => "__builtin_ia32_ptestnmw256", - "avx512.ptestnm.w.512" => "__builtin_ia32_ptestnmw512", "avx512.rcp14.pd.128" => "__builtin_ia32_rcp14pd128_mask", "avx512.rcp14.pd.256" => "__builtin_ia32_rcp14pd256_mask", "avx512.rcp14.pd.512" => "__builtin_ia32_rcp14pd512_mask", @@ -9643,14 +8430,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.rcp14.ps.512" => "__builtin_ia32_rcp14ps512_mask", "avx512.rcp14.sd" => "__builtin_ia32_rcp14sd_mask", "avx512.rcp14.ss" => "__builtin_ia32_rcp14ss_mask", - "avx512.rcp28.pd" => "__builtin_ia32_rcp28pd_mask", - "avx512.rcp28.ps" => "__builtin_ia32_rcp28ps_mask", - "avx512.rcp28.sd" => "__builtin_ia32_rcp28sd_mask", - // [DUPLICATE]: "avx512.rcp28.sd" => "__builtin_ia32_rcp28sd_round_mask", - "avx512.rcp28.ss" => "__builtin_ia32_rcp28ss_mask", - // [DUPLICATE]: "avx512.rcp28.ss" => "__builtin_ia32_rcp28ss_round_mask", - "avx512.rndscale.sd" => "__builtin_ia32_rndscalesd", - "avx512.rndscale.ss" => "__builtin_ia32_rndscaless", "avx512.rsqrt14.pd.128" => "__builtin_ia32_rsqrt14pd128_mask", "avx512.rsqrt14.pd.256" => "__builtin_ia32_rsqrt14pd256_mask", "avx512.rsqrt14.pd.512" => "__builtin_ia32_rsqrt14pd512_mask", @@ -9659,50 +8438,8 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx512.rsqrt14.ps.512" => "__builtin_ia32_rsqrt14ps512_mask", "avx512.rsqrt14.sd" => "__builtin_ia32_rsqrt14sd_mask", "avx512.rsqrt14.ss" => "__builtin_ia32_rsqrt14ss_mask", - "avx512.rsqrt28.pd" => "__builtin_ia32_rsqrt28pd_mask", - "avx512.rsqrt28.ps" => "__builtin_ia32_rsqrt28ps_mask", - "avx512.rsqrt28.sd" => "__builtin_ia32_rsqrt28sd_mask", - // [DUPLICATE]: "avx512.rsqrt28.sd" => "__builtin_ia32_rsqrt28sd_round_mask", - "avx512.rsqrt28.ss" => "__builtin_ia32_rsqrt28ss_mask", - // [DUPLICATE]: "avx512.rsqrt28.ss" => "__builtin_ia32_rsqrt28ss_round_mask", - "avx512.scatter.dpd.512" => "__builtin_ia32_scattersiv8df", - "avx512.scatter.dpi.512" => "__builtin_ia32_scattersiv16si", - "avx512.scatter.dpq.512" => "__builtin_ia32_scattersiv8di", - "avx512.scatter.dps.512" => "__builtin_ia32_scattersiv16sf", - "avx512.scatter.qpd.512" => "__builtin_ia32_scatterdiv8df", - "avx512.scatter.qpi.512" => "__builtin_ia32_scatterdiv16si", - "avx512.scatter.qpq.512" => "__builtin_ia32_scatterdiv8di", - "avx512.scatter.qps.512" => "__builtin_ia32_scatterdiv16sf", - "avx512.scatterdiv2.df" => "__builtin_ia32_scatterdiv2df", - "avx512.scatterdiv2.di" => "__builtin_ia32_scatterdiv2di", - "avx512.scatterdiv4.df" => "__builtin_ia32_scatterdiv4df", - "avx512.scatterdiv4.di" => "__builtin_ia32_scatterdiv4di", - "avx512.scatterdiv4.sf" => "__builtin_ia32_scatterdiv4sf", - "avx512.scatterdiv4.si" => "__builtin_ia32_scatterdiv4si", - "avx512.scatterdiv8.sf" => "__builtin_ia32_scatterdiv8sf", - "avx512.scatterdiv8.si" => "__builtin_ia32_scatterdiv8si", - "avx512.scatterpf.dpd.512" => "__builtin_ia32_scatterpfdpd", - "avx512.scatterpf.dps.512" => "__builtin_ia32_scatterpfdps", - "avx512.scatterpf.qpd.512" => "__builtin_ia32_scatterpfqpd", - "avx512.scatterpf.qps.512" => "__builtin_ia32_scatterpfqps", - "avx512.scattersiv2.df" => "__builtin_ia32_scattersiv2df", - "avx512.scattersiv2.di" => "__builtin_ia32_scattersiv2di", - "avx512.scattersiv4.df" => "__builtin_ia32_scattersiv4df", - "avx512.scattersiv4.di" => "__builtin_ia32_scattersiv4di", - "avx512.scattersiv4.sf" => "__builtin_ia32_scattersiv4sf", - "avx512.scattersiv4.si" => "__builtin_ia32_scattersiv4si", - "avx512.scattersiv8.sf" => "__builtin_ia32_scattersiv8sf", - "avx512.scattersiv8.si" => "__builtin_ia32_scattersiv8si", - "avx512.sqrt.pd.512" => "__builtin_ia32_sqrtpd512_mask", - "avx512.sqrt.ps.512" => "__builtin_ia32_sqrtps512_mask", - "avx512.sqrt.sd" => "__builtin_ia32_sqrtrndsd", - "avx512.sqrt.ss" => "__builtin_ia32_sqrtrndss", "avx512.sub.pd.512" => "__builtin_ia32_subpd512", "avx512.sub.ps.512" => "__builtin_ia32_subps512", - "avx512.vbroadcast.sd.512" => "__builtin_ia32_vbroadcastsd512", - "avx512.vbroadcast.sd.pd.512" => "__builtin_ia32_vbroadcastsd_pd512", - "avx512.vbroadcast.ss.512" => "__builtin_ia32_vbroadcastss512", - "avx512.vbroadcast.ss.ps.512" => "__builtin_ia32_vbroadcastss_ps512", "avx512.vcomi.sd" => "__builtin_ia32_vcomisd", "avx512.vcomi.ss" => "__builtin_ia32_vcomiss", "avx512.vcvtsd2si32" => "__builtin_ia32_vcvtsd2si32", @@ -9928,50 +8665,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "flags.read.u64" => "__builtin_ia32_readeflags_u64", "flags.write.u32" => "__builtin_ia32_writeeflags_u32", "flags.write.u64" => "__builtin_ia32_writeeflags_u64", - "fma.mask.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask", - "fma.mask.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask", - "fma.mask.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask", - "fma.mask.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_mask", - "fma.mask.vfmsub.pd.512" => "__builtin_ia32_vfmsubpd512_mask", - "fma.mask.vfmsub.ps.512" => "__builtin_ia32_vfmsubps512_mask", - "fma.mask.vfmsubadd.pd.512" => "__builtin_ia32_vfmsubaddpd512_mask", - "fma.mask.vfmsubadd.ps.512" => "__builtin_ia32_vfmsubaddps512_mask", - "fma.mask.vfnmadd.pd.512" => "__builtin_ia32_vfnmaddpd512_mask", - "fma.mask.vfnmadd.ps.512" => "__builtin_ia32_vfnmaddps512_mask", - "fma.mask.vfnmsub.pd.512" => "__builtin_ia32_vfnmsubpd512_mask", - "fma.mask.vfnmsub.ps.512" => "__builtin_ia32_vfnmsubps512_mask", - "fma.vfmadd.pd" => "__builtin_ia32_vfmaddpd", - "fma.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256", - "fma.vfmadd.ps" => "__builtin_ia32_vfmaddps", - "fma.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256", - "fma.vfmadd.sd" => "__builtin_ia32_vfmaddsd", - "fma.vfmadd.ss" => "__builtin_ia32_vfmaddss", "fma.vfmaddsub.pd" => "__builtin_ia32_vfmaddsubpd", "fma.vfmaddsub.pd.256" => "__builtin_ia32_vfmaddsubpd256", "fma.vfmaddsub.ps" => "__builtin_ia32_vfmaddsubps", "fma.vfmaddsub.ps.256" => "__builtin_ia32_vfmaddsubps256", - "fma.vfmsub.pd" => "__builtin_ia32_vfmsubpd", - "fma.vfmsub.pd.256" => "__builtin_ia32_vfmsubpd256", - "fma.vfmsub.ps" => "__builtin_ia32_vfmsubps", - "fma.vfmsub.ps.256" => "__builtin_ia32_vfmsubps256", - "fma.vfmsub.sd" => "__builtin_ia32_vfmsubsd", - "fma.vfmsub.ss" => "__builtin_ia32_vfmsubss", - "fma.vfmsubadd.pd" => "__builtin_ia32_vfmsubaddpd", - "fma.vfmsubadd.pd.256" => "__builtin_ia32_vfmsubaddpd256", - "fma.vfmsubadd.ps" => "__builtin_ia32_vfmsubaddps", - "fma.vfmsubadd.ps.256" => "__builtin_ia32_vfmsubaddps256", - "fma.vfnmadd.pd" => "__builtin_ia32_vfnmaddpd", - "fma.vfnmadd.pd.256" => "__builtin_ia32_vfnmaddpd256", - "fma.vfnmadd.ps" => "__builtin_ia32_vfnmaddps", - "fma.vfnmadd.ps.256" => "__builtin_ia32_vfnmaddps256", - "fma.vfnmadd.sd" => "__builtin_ia32_vfnmaddsd", - "fma.vfnmadd.ss" => "__builtin_ia32_vfnmaddss", - "fma.vfnmsub.pd" => "__builtin_ia32_vfnmsubpd", - "fma.vfnmsub.pd.256" => "__builtin_ia32_vfnmsubpd256", - "fma.vfnmsub.ps" => "__builtin_ia32_vfnmsubps", - "fma.vfnmsub.ps.256" => "__builtin_ia32_vfnmsubps256", - "fma.vfnmsub.sd" => "__builtin_ia32_vfnmsubsd", - "fma.vfnmsub.ss" => "__builtin_ia32_vfnmsubss", "fxrstor" => "__builtin_ia32_fxrstor", "fxrstor64" => "__builtin_ia32_fxrstor64", "fxsave" => "__builtin_ia32_fxsave", @@ -9988,7 +8685,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "lwpval32" => "__builtin_ia32_lwpval32", "lwpval64" => "__builtin_ia32_lwpval64", "mmx.emms" => "__builtin_ia32_emms", - "mmx.femms" => "__builtin_ia32_femms", "monitorx" => "__builtin_ia32_monitorx", "movdir64b" => "__builtin_ia32_movdir64b", "movrsdi" => "__builtin_ia32_movrsdi", @@ -10013,7 +8709,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "rdsspd" => "__builtin_ia32_rdsspd", "rdsspq" => "__builtin_ia32_rdsspq", "rdtsc" => "__builtin_ia32_rdtsc", - "rdtscp" => "__builtin_ia32_rdtscp", "rstorssp" => "__builtin_ia32_rstorssp", "saveprevssp" => "__builtin_ia32_saveprevssp", "senduipi" => "__builtin_ia32_senduipi", @@ -10027,8 +8722,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sha256msg2" => "__builtin_ia32_sha256msg2", "sha256rnds2" => "__builtin_ia32_sha256rnds2", "slwpcb" => "__builtin_ia32_slwpcb", - "sse.add.ss" => "__builtin_ia32_addss", - "sse.cmp.ps" => "__builtin_ia32_cmpps", "sse.cmp.ss" => "__builtin_ia32_cmpss", "sse.comieq.ss" => "__builtin_ia32_comieq", "sse.comige.ss" => "__builtin_ia32_comige", @@ -10036,37 +8729,27 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sse.comile.ss" => "__builtin_ia32_comile", "sse.comilt.ss" => "__builtin_ia32_comilt", "sse.comineq.ss" => "__builtin_ia32_comineq", - "sse.cvtsi2ss" => "__builtin_ia32_cvtsi2ss", - "sse.cvtsi642ss" => "__builtin_ia32_cvtsi642ss", "sse.cvtss2si" => "__builtin_ia32_cvtss2si", "sse.cvtss2si64" => "__builtin_ia32_cvtss2si64", "sse.cvttss2si" => "__builtin_ia32_cvttss2si", "sse.cvttss2si64" => "__builtin_ia32_cvttss2si64", - "sse.div.ss" => "__builtin_ia32_divss", "sse.max.ps" => "__builtin_ia32_maxps", "sse.max.ss" => "__builtin_ia32_maxss", "sse.min.ps" => "__builtin_ia32_minps", "sse.min.ss" => "__builtin_ia32_minss", "sse.movmsk.ps" => "__builtin_ia32_movmskps", - "sse.mul.ss" => "__builtin_ia32_mulss", "sse.rcp.ps" => "__builtin_ia32_rcpps", "sse.rcp.ss" => "__builtin_ia32_rcpss", "sse.rsqrt.ps" => "__builtin_ia32_rsqrtps", "sse.rsqrt.ss" => "__builtin_ia32_rsqrtss", "sse.sfence" => "__builtin_ia32_sfence", - "sse.sqrt.ps" => "__builtin_ia32_sqrtps", - "sse.sqrt.ss" => "__builtin_ia32_sqrtss", - "sse.storeu.ps" => "__builtin_ia32_storeups", - "sse.sub.ss" => "__builtin_ia32_subss", "sse.ucomieq.ss" => "__builtin_ia32_ucomieq", "sse.ucomige.ss" => "__builtin_ia32_ucomige", "sse.ucomigt.ss" => "__builtin_ia32_ucomigt", "sse.ucomile.ss" => "__builtin_ia32_ucomile", "sse.ucomilt.ss" => "__builtin_ia32_ucomilt", "sse.ucomineq.ss" => "__builtin_ia32_ucomineq", - "sse2.add.sd" => "__builtin_ia32_addsd", "sse2.clflush" => "__builtin_ia32_clflush", - "sse2.cmp.pd" => "__builtin_ia32_cmppd", "sse2.cmp.sd" => "__builtin_ia32_cmpsd", "sse2.comieq.sd" => "__builtin_ia32_comisdeq", "sse2.comige.sd" => "__builtin_ia32_comisdge", @@ -10074,23 +8757,16 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sse2.comile.sd" => "__builtin_ia32_comisdle", "sse2.comilt.sd" => "__builtin_ia32_comisdlt", "sse2.comineq.sd" => "__builtin_ia32_comisdneq", - "sse2.cvtdq2pd" => "__builtin_ia32_cvtdq2pd", - "sse2.cvtdq2ps" => "__builtin_ia32_cvtdq2ps", "sse2.cvtpd2dq" => "__builtin_ia32_cvtpd2dq", "sse2.cvtpd2ps" => "__builtin_ia32_cvtpd2ps", "sse2.cvtps2dq" => "__builtin_ia32_cvtps2dq", - "sse2.cvtps2pd" => "__builtin_ia32_cvtps2pd", "sse2.cvtsd2si" => "__builtin_ia32_cvtsd2si", "sse2.cvtsd2si64" => "__builtin_ia32_cvtsd2si64", "sse2.cvtsd2ss" => "__builtin_ia32_cvtsd2ss", - "sse2.cvtsi2sd" => "__builtin_ia32_cvtsi2sd", - "sse2.cvtsi642sd" => "__builtin_ia32_cvtsi642sd", - "sse2.cvtss2sd" => "__builtin_ia32_cvtss2sd", "sse2.cvttpd2dq" => "__builtin_ia32_cvttpd2dq", "sse2.cvttps2dq" => "__builtin_ia32_cvttps2dq", "sse2.cvttsd2si" => "__builtin_ia32_cvttsd2si", "sse2.cvttsd2si64" => "__builtin_ia32_cvttsd2si64", - "sse2.div.sd" => "__builtin_ia32_divsd", "sse2.lfence" => "__builtin_ia32_lfence", "sse2.maskmov.dqu" => "__builtin_ia32_maskmovdqu", "sse2.max.pd" => "__builtin_ia32_maxpd", @@ -10099,33 +8775,18 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sse2.min.pd" => "__builtin_ia32_minpd", "sse2.min.sd" => "__builtin_ia32_minsd", "sse2.movmsk.pd" => "__builtin_ia32_movmskpd", - "sse2.mul.sd" => "__builtin_ia32_mulsd", "sse2.packssdw.128" => "__builtin_ia32_packssdw128", "sse2.packsswb.128" => "__builtin_ia32_packsswb128", "sse2.packuswb.128" => "__builtin_ia32_packuswb128", - "sse2.padds.b" => "__builtin_ia32_paddsb128", - "sse2.padds.w" => "__builtin_ia32_paddsw128", - "sse2.paddus.b" => "__builtin_ia32_paddusb128", - "sse2.paddus.w" => "__builtin_ia32_paddusw128", "sse2.pause" => "__builtin_ia32_pause", "sse2.pavg.b" => "__builtin_ia32_pavgb128", "sse2.pavg.w" => "__builtin_ia32_pavgw128", "sse2.pmadd.wd" => "__builtin_ia32_pmaddwd128", - "sse2.pmaxs.w" => "__builtin_ia32_pmaxsw128", - "sse2.pmaxu.b" => "__builtin_ia32_pmaxub128", - "sse2.pmins.w" => "__builtin_ia32_pminsw128", - "sse2.pminu.b" => "__builtin_ia32_pminub128", "sse2.pmovmskb.128" => "__builtin_ia32_pmovmskb128", "sse2.pmulh.w" => "__builtin_ia32_pmulhw128", "sse2.pmulhu.w" => "__builtin_ia32_pmulhuw128", - "sse2.pmulu.dq" => "__builtin_ia32_pmuludq128", "sse2.psad.bw" => "__builtin_ia32_psadbw128", - "sse2.pshuf.d" => "__builtin_ia32_pshufd", - "sse2.pshufh.w" => "__builtin_ia32_pshufhw", - "sse2.pshufl.w" => "__builtin_ia32_pshuflw", "sse2.psll.d" => "__builtin_ia32_pslld128", - "sse2.psll.dq" => "__builtin_ia32_pslldqi128", - "sse2.psll.dq.bs" => "__builtin_ia32_pslldqi128_byteshift", "sse2.psll.q" => "__builtin_ia32_psllq128", "sse2.psll.w" => "__builtin_ia32_psllw128", "sse2.pslli.d" => "__builtin_ia32_pslldi128", @@ -10136,23 +8797,11 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sse2.psrai.d" => "__builtin_ia32_psradi128", "sse2.psrai.w" => "__builtin_ia32_psrawi128", "sse2.psrl.d" => "__builtin_ia32_psrld128", - "sse2.psrl.dq" => "__builtin_ia32_psrldqi128", - "sse2.psrl.dq.bs" => "__builtin_ia32_psrldqi128_byteshift", "sse2.psrl.q" => "__builtin_ia32_psrlq128", "sse2.psrl.w" => "__builtin_ia32_psrlw128", "sse2.psrli.d" => "__builtin_ia32_psrldi128", "sse2.psrli.q" => "__builtin_ia32_psrlqi128", "sse2.psrli.w" => "__builtin_ia32_psrlwi128", - "sse2.psubs.b" => "__builtin_ia32_psubsb128", - "sse2.psubs.w" => "__builtin_ia32_psubsw128", - "sse2.psubus.b" => "__builtin_ia32_psubusb128", - "sse2.psubus.w" => "__builtin_ia32_psubusw128", - "sse2.sqrt.pd" => "__builtin_ia32_sqrtpd", - "sse2.sqrt.sd" => "__builtin_ia32_sqrtsd", - "sse2.storel.dq" => "__builtin_ia32_storelv4si", - "sse2.storeu.dq" => "__builtin_ia32_storedqu", - "sse2.storeu.pd" => "__builtin_ia32_storeupd", - "sse2.sub.sd" => "__builtin_ia32_subsd", "sse2.ucomieq.sd" => "__builtin_ia32_ucomisdeq", "sse2.ucomige.sd" => "__builtin_ia32_ucomisdge", "sse2.ucomigt.sd" => "__builtin_ia32_ucomisdgt", @@ -10168,41 +8817,15 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sse3.ldu.dq" => "__builtin_ia32_lddqu", "sse3.monitor" => "__builtin_ia32_monitor", "sse3.mwait" => "__builtin_ia32_mwait", - "sse41.blendpd" => "__builtin_ia32_blendpd", - "sse41.blendps" => "__builtin_ia32_blendps", "sse41.blendvpd" => "__builtin_ia32_blendvpd", "sse41.blendvps" => "__builtin_ia32_blendvps", "sse41.dppd" => "__builtin_ia32_dppd", "sse41.dpps" => "__builtin_ia32_dpps", - "sse41.extractps" => "__builtin_ia32_extractps128", "sse41.insertps" => "__builtin_ia32_insertps128", - "sse41.movntdqa" => "__builtin_ia32_movntdqa", "sse41.mpsadbw" => "__builtin_ia32_mpsadbw128", "sse41.packusdw" => "__builtin_ia32_packusdw128", "sse41.pblendvb" => "__builtin_ia32_pblendvb128", - "sse41.pblendw" => "__builtin_ia32_pblendw128", "sse41.phminposuw" => "__builtin_ia32_phminposuw128", - "sse41.pmaxsb" => "__builtin_ia32_pmaxsb128", - "sse41.pmaxsd" => "__builtin_ia32_pmaxsd128", - "sse41.pmaxud" => "__builtin_ia32_pmaxud128", - "sse41.pmaxuw" => "__builtin_ia32_pmaxuw128", - "sse41.pminsb" => "__builtin_ia32_pminsb128", - "sse41.pminsd" => "__builtin_ia32_pminsd128", - "sse41.pminud" => "__builtin_ia32_pminud128", - "sse41.pminuw" => "__builtin_ia32_pminuw128", - "sse41.pmovsxbd" => "__builtin_ia32_pmovsxbd128", - "sse41.pmovsxbq" => "__builtin_ia32_pmovsxbq128", - "sse41.pmovsxbw" => "__builtin_ia32_pmovsxbw128", - "sse41.pmovsxdq" => "__builtin_ia32_pmovsxdq128", - "sse41.pmovsxwd" => "__builtin_ia32_pmovsxwd128", - "sse41.pmovsxwq" => "__builtin_ia32_pmovsxwq128", - "sse41.pmovzxbd" => "__builtin_ia32_pmovzxbd128", - "sse41.pmovzxbq" => "__builtin_ia32_pmovzxbq128", - "sse41.pmovzxbw" => "__builtin_ia32_pmovzxbw128", - "sse41.pmovzxdq" => "__builtin_ia32_pmovzxdq128", - "sse41.pmovzxwd" => "__builtin_ia32_pmovzxwd128", - "sse41.pmovzxwq" => "__builtin_ia32_pmovzxwq128", - "sse41.pmuldq" => "__builtin_ia32_pmuldq128", "sse41.ptestc" => "__builtin_ia32_ptestc128", "sse41.ptestnzc" => "__builtin_ia32_ptestnzc128", "sse41.ptestz" => "__builtin_ia32_ptestz128", @@ -10232,11 +8855,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sse4a.extrqi" => "__builtin_ia32_extrqi", "sse4a.insertq" => "__builtin_ia32_insertq", "sse4a.insertqi" => "__builtin_ia32_insertqi", - "sse4a.movnt.sd" => "__builtin_ia32_movntsd", - "sse4a.movnt.ss" => "__builtin_ia32_movntss", - "ssse3.pabs.b.128" => "__builtin_ia32_pabsb128", - "ssse3.pabs.d.128" => "__builtin_ia32_pabsd128", - "ssse3.pabs.w.128" => "__builtin_ia32_pabsw128", "ssse3.phadd.d.128" => "__builtin_ia32_phaddd128", "ssse3.phadd.sw.128" => "__builtin_ia32_phaddsw128", "ssse3.phadd.w.128" => "__builtin_ia32_phaddw128", @@ -10251,8 +8869,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "ssse3.psign.w.128" => "__builtin_ia32_psignw128", "sttilecfg" => "__builtin_ia32_tile_storeconfig", "stui" => "__builtin_ia32_stui", - "subborrow.u32" => "__builtin_ia32_subborrow_u32", - "subborrow.u64" => "__builtin_ia32_subborrow_u64", "t2rpntlvwz0rs" => "__builtin_ia32_t2rpntlvwz0rs", "t2rpntlvwz0rst1" => "__builtin_ia32_t2rpntlvwz0rst1", "t2rpntlvwz1rs" => "__builtin_ia32_t2rpntlvwz1rs", @@ -10330,8 +8946,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "vcvtneoph2ps256" => "__builtin_ia32_vcvtneoph2ps256", "vcvtneps2bf16128" => "__builtin_ia32_vcvtneps2bf16128", "vcvtneps2bf16256" => "__builtin_ia32_vcvtneps2bf16256", - "vcvtph2ps.128" => "__builtin_ia32_vcvtph2ps", - "vcvtph2ps.256" => "__builtin_ia32_vcvtph2ps256", "vcvtps2ph.128" => "__builtin_ia32_vcvtps2ph", "vcvtps2ph.256" => "__builtin_ia32_vcvtps2ph256", "vgf2p8affineinvqb.128" => "__builtin_ia32_vgf2p8affineinvqb_v16qi", @@ -10375,16 +8989,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "xop.vfrcz.ps.256" => "__builtin_ia32_vfrczps256", "xop.vfrcz.sd" => "__builtin_ia32_vfrczsd", "xop.vfrcz.ss" => "__builtin_ia32_vfrczss", - "xop.vpcmov" => "__builtin_ia32_vpcmov", - "xop.vpcmov.256" => "__builtin_ia32_vpcmov_256", - "xop.vpcomb" => "__builtin_ia32_vpcomb", - "xop.vpcomd" => "__builtin_ia32_vpcomd", - "xop.vpcomq" => "__builtin_ia32_vpcomq", - "xop.vpcomub" => "__builtin_ia32_vpcomub", - "xop.vpcomud" => "__builtin_ia32_vpcomud", - "xop.vpcomuq" => "__builtin_ia32_vpcomuq", - "xop.vpcomuw" => "__builtin_ia32_vpcomuw", - "xop.vpcomw" => "__builtin_ia32_vpcomw", "xop.vpermil2pd" => "__builtin_ia32_vpermil2pd", "xop.vpermil2pd.256" => "__builtin_ia32_vpermil2pd256", "xop.vpermil2ps" => "__builtin_ia32_vpermil2ps", @@ -10417,14 +9021,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "xop.vpmadcsswd" => "__builtin_ia32_vpmadcsswd", "xop.vpmadcswd" => "__builtin_ia32_vpmadcswd", "xop.vpperm" => "__builtin_ia32_vpperm", - "xop.vprotb" => "__builtin_ia32_vprotb", - "xop.vprotbi" => "__builtin_ia32_vprotbi", - "xop.vprotd" => "__builtin_ia32_vprotd", - "xop.vprotdi" => "__builtin_ia32_vprotdi", - "xop.vprotq" => "__builtin_ia32_vprotq", - "xop.vprotqi" => "__builtin_ia32_vprotqi", - "xop.vprotw" => "__builtin_ia32_vprotw", - "xop.vprotwi" => "__builtin_ia32_vprotwi", "xop.vpshab" => "__builtin_ia32_vpshab", "xop.vpshad" => "__builtin_ia32_vpshad", "xop.vpshaq" => "__builtin_ia32_vpshaq", @@ -10454,6 +9050,14 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { } xcore(name, full_name) } - _ => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic:{full_name}"), + _ => match old_arch_res { + ArchCheckResult::UnknownIntrinsic => { + unimplemented!("***** unsupported LLVM intrinsic {full_name}") + } + ArchCheckResult::UnknownArch => { + unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic: {full_name}") + } + ArchCheckResult::Ok(_) => unreachable!(), + }, } } diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index e3d189c95ced..72fc72d118b7 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1604,5 +1604,7 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function func } +#[cfg(feature = "master")] +include!("old_archs.rs"); #[cfg(feature = "master")] include!("archs.rs"); diff --git a/src/intrinsic/old_archs.rs b/src/intrinsic/old_archs.rs new file mode 100644 index 000000000000..3a59707b2ebe --- /dev/null +++ b/src/intrinsic/old_archs.rs @@ -0,0 +1,1384 @@ +// All these translations used to be automatically generated in the past. However, since they never +// changed, we decided to simplify the translation generation script to move them directly into this +// file. +// +// So in short: avoid editing this file. + +pub(crate) enum ArchCheckResult { + Ok(&'static str), + UnknownIntrinsic, + UnknownArch, +} + +pub(crate) fn old_archs(arch: &str, name: &str) -> ArchCheckResult { + ArchCheckResult::Ok(match arch { + "AMDGPU" => match name { + "div.fixup.f32" => "__builtin_amdgpu_div_fixup", + "div.fixup.f64" => "__builtin_amdgpu_div_fixup", + "div.fixup.v2f64" => "__builtin_amdgpu_div_fixup", + "div.fixup.v4f32" => "__builtin_amdgpu_div_fixup", + "div.fmas.f32" => "__builtin_amdgpu_div_fmas", + "div.fmas.f64" => "__builtin_amdgpu_div_fmas", + "div.fmas.v2f64" => "__builtin_amdgpu_div_fmas", + "div.fmas.v4f32" => "__builtin_amdgpu_div_fmas", + "ldexp.f32" => "__builtin_amdgpu_ldexp", + "ldexp.f64" => "__builtin_amdgpu_ldexp", + "ldexp.v2f64" => "__builtin_amdgpu_ldexp", + "ldexp.v4f32" => "__builtin_amdgpu_ldexp", + "rcp.f32" => "__builtin_amdgpu_rcp", + "rcp.f64" => "__builtin_amdgpu_rcp", + "rcp.v2f64" => "__builtin_amdgpu_rcp", + "rcp.v4f32" => "__builtin_amdgpu_rcp", + "rsq.clamped.f32" => "__builtin_amdgpu_rsq_clamped", + "rsq.clamped.f64" => "__builtin_amdgpu_rsq_clamped", + "rsq.clamped.v2f64" => "__builtin_amdgpu_rsq_clamped", + "rsq.clamped.v4f32" => "__builtin_amdgpu_rsq_clamped", + "rsq.f32" => "__builtin_amdgpu_rsq", + "rsq.f64" => "__builtin_amdgpu_rsq", + "rsq.v2f64" => "__builtin_amdgpu_rsq", + "rsq.v4f32" => "__builtin_amdgpu_rsq", + "trig.preop.f32" => "__builtin_amdgpu_trig_preop", + "trig.preop.f64" => "__builtin_amdgpu_trig_preop", + "trig.preop.v2f64" => "__builtin_amdgpu_trig_preop", + "trig.preop.v4f32" => "__builtin_amdgpu_trig_preop", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + "arm" => match name { + "mcrr" => "__builtin_arm_mcrr", + "mcrr2" => "__builtin_arm_mcrr2", + "thread.pointer" => "__builtin_thread_pointer", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + "cuda" => match name { + "syncthreads" => "__syncthreads", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + "hexagon" => match name { + "F2.dffixupd" => "__builtin_HEXAGON_F2_dffixupd", + "F2.dffixupn" => "__builtin_HEXAGON_F2_dffixupn", + "F2.dffixupr" => "__builtin_HEXAGON_F2_dffixupr", + "F2.dffma" => "__builtin_HEXAGON_F2_dffma", + "F2.dffma.lib" => "__builtin_HEXAGON_F2_dffma_lib", + "F2.dffma.sc" => "__builtin_HEXAGON_F2_dffma_sc", + "F2.dffms" => "__builtin_HEXAGON_F2_dffms", + "F2.dffms.lib" => "__builtin_HEXAGON_F2_dffms_lib", + "F2.dfmpy" => "__builtin_HEXAGON_F2_dfmpy", + "S2.cabacencbin" => "__builtin_HEXAGON_S2_cabacencbin", + "SI.to.SXTHI.asrh" => "__builtin_SI_to_SXTHI_asrh", + "V6.vlutb" => "__builtin_HEXAGON_V6_vlutb", + "V6.vlutb.128B" => "__builtin_HEXAGON_V6_vlutb_128B", + "V6.vlutb.acc" => "__builtin_HEXAGON_V6_vlutb_acc", + "V6.vlutb.acc.128B" => "__builtin_HEXAGON_V6_vlutb_acc_128B", + "V6.vlutb.dv" => "__builtin_HEXAGON_V6_vlutb_dv", + "V6.vlutb.dv.128B" => "__builtin_HEXAGON_V6_vlutb_dv_128B", + "V6.vlutb.dv.acc" => "__builtin_HEXAGON_V6_vlutb_dv_acc", + "V6.vlutb.dv.acc.128B" => "__builtin_HEXAGON_V6_vlutb_dv_acc_128B", + "brev.ldb" => "__builtin_brev_ldb", + "brev.ldd" => "__builtin_brev_ldd", + "brev.ldh" => "__builtin_brev_ldh", + "brev.ldub" => "__builtin_brev_ldub", + "brev.lduh" => "__builtin_brev_lduh", + "brev.ldw" => "__builtin_brev_ldw", + "brev.stb" => "__builtin_brev_stb", + "brev.std" => "__builtin_brev_std", + "brev.sth" => "__builtin_brev_sth", + "brev.sthhi" => "__builtin_brev_sthhi", + "brev.stw" => "__builtin_brev_stw", + "mm256i.vaddw" => "__builtin__mm256i_vaddw", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + "nvvm" => match name { + "abs.i" => "__nvvm_abs_i", + "abs.ll" => "__nvvm_abs_ll", + "bar.sync" => "__nvvm_bar_sync", + "barrier0" => "__nvvm_bar0", + "bitcast.d2ll" => "__nvvm_bitcast_d2ll", + "bitcast.f2i" => "__nvvm_bitcast_f2i", + "bitcast.i2f" => "__nvvm_bitcast_i2f", + "bitcast.ll2d" => "__nvvm_bitcast_ll2d", + "brev32" => "__nvvm_brev32", + "brev64" => "__nvvm_brev64", + "clz.i" => "__nvvm_clz_i", + "clz.ll" => "__nvvm_clz_ll", + "ex2.approx.d" => "__nvvm_ex2_approx_d", + "ex2.approx.f" => "__nvvm_ex2_approx_f", + "ex2.approx.ftz.f" => "__nvvm_ex2_approx_ftz_f", + "fabs.d" => "__nvvm_fabs_d", + "fabs.f" => "__nvvm_fabs_f", + "fabs.ftz.f" => "__nvvm_fabs_ftz_f", + "h2f" => "__nvvm_h2f", + "max.i" => "__nvvm_max_i", + "max.ll" => "__nvvm_max_ll", + "max.ui" => "__nvvm_max_ui", + "max.ull" => "__nvvm_max_ull", + "min.i" => "__nvvm_min_i", + "min.ll" => "__nvvm_min_ll", + "min.ui" => "__nvvm_min_ui", + "min.ull" => "__nvvm_min_ull", + "popc.i" => "__nvvm_popc_i", + "popc.ll" => "__nvvm_popc_ll", + "rotate.b32" => "__nvvm_rotate_b32", + "rotate.b64" => "__nvvm_rotate_b64", + "rotate.right.b64" => "__nvvm_rotate_right_b64", + "swap.lo.hi.b64" => "__nvvm_swap_lo_hi_b64", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + "ppc" => match name { + "qpx.qvfabs" => "__builtin_qpx_qvfabs", + "qpx.qvfadd" => "__builtin_qpx_qvfadd", + "qpx.qvfadds" => "__builtin_qpx_qvfadds", + "qpx.qvfcfid" => "__builtin_qpx_qvfcfid", + "qpx.qvfcfids" => "__builtin_qpx_qvfcfids", + "qpx.qvfcfidu" => "__builtin_qpx_qvfcfidu", + "qpx.qvfcfidus" => "__builtin_qpx_qvfcfidus", + "qpx.qvfcmpeq" => "__builtin_qpx_qvfcmpeq", + "qpx.qvfcmpgt" => "__builtin_qpx_qvfcmpgt", + "qpx.qvfcmplt" => "__builtin_qpx_qvfcmplt", + "qpx.qvfcpsgn" => "__builtin_qpx_qvfcpsgn", + "qpx.qvfctid" => "__builtin_qpx_qvfctid", + "qpx.qvfctidu" => "__builtin_qpx_qvfctidu", + "qpx.qvfctiduz" => "__builtin_qpx_qvfctiduz", + "qpx.qvfctidz" => "__builtin_qpx_qvfctidz", + "qpx.qvfctiw" => "__builtin_qpx_qvfctiw", + "qpx.qvfctiwu" => "__builtin_qpx_qvfctiwu", + "qpx.qvfctiwuz" => "__builtin_qpx_qvfctiwuz", + "qpx.qvfctiwz" => "__builtin_qpx_qvfctiwz", + "qpx.qvflogical" => "__builtin_qpx_qvflogical", + "qpx.qvfmadd" => "__builtin_qpx_qvfmadd", + "qpx.qvfmadds" => "__builtin_qpx_qvfmadds", + "qpx.qvfmsub" => "__builtin_qpx_qvfmsub", + "qpx.qvfmsubs" => "__builtin_qpx_qvfmsubs", + "qpx.qvfmul" => "__builtin_qpx_qvfmul", + "qpx.qvfmuls" => "__builtin_qpx_qvfmuls", + "qpx.qvfnabs" => "__builtin_qpx_qvfnabs", + "qpx.qvfneg" => "__builtin_qpx_qvfneg", + "qpx.qvfnmadd" => "__builtin_qpx_qvfnmadd", + "qpx.qvfnmadds" => "__builtin_qpx_qvfnmadds", + "qpx.qvfnmsub" => "__builtin_qpx_qvfnmsub", + "qpx.qvfnmsubs" => "__builtin_qpx_qvfnmsubs", + "qpx.qvfperm" => "__builtin_qpx_qvfperm", + "qpx.qvfre" => "__builtin_qpx_qvfre", + "qpx.qvfres" => "__builtin_qpx_qvfres", + "qpx.qvfrim" => "__builtin_qpx_qvfrim", + "qpx.qvfrin" => "__builtin_qpx_qvfrin", + "qpx.qvfrip" => "__builtin_qpx_qvfrip", + "qpx.qvfriz" => "__builtin_qpx_qvfriz", + "qpx.qvfrsp" => "__builtin_qpx_qvfrsp", + "qpx.qvfrsqrte" => "__builtin_qpx_qvfrsqrte", + "qpx.qvfrsqrtes" => "__builtin_qpx_qvfrsqrtes", + "qpx.qvfsel" => "__builtin_qpx_qvfsel", + "qpx.qvfsub" => "__builtin_qpx_qvfsub", + "qpx.qvfsubs" => "__builtin_qpx_qvfsubs", + "qpx.qvftstnan" => "__builtin_qpx_qvftstnan", + "qpx.qvfxmadd" => "__builtin_qpx_qvfxmadd", + "qpx.qvfxmadds" => "__builtin_qpx_qvfxmadds", + "qpx.qvfxmul" => "__builtin_qpx_qvfxmul", + "qpx.qvfxmuls" => "__builtin_qpx_qvfxmuls", + "qpx.qvfxxcpnmadd" => "__builtin_qpx_qvfxxcpnmadd", + "qpx.qvfxxcpnmadds" => "__builtin_qpx_qvfxxcpnmadds", + "qpx.qvfxxmadd" => "__builtin_qpx_qvfxxmadd", + "qpx.qvfxxmadds" => "__builtin_qpx_qvfxxmadds", + "qpx.qvfxxnpmadd" => "__builtin_qpx_qvfxxnpmadd", + "qpx.qvfxxnpmadds" => "__builtin_qpx_qvfxxnpmadds", + "qpx.qvgpci" => "__builtin_qpx_qvgpci", + "qpx.qvlfcd" => "__builtin_qpx_qvlfcd", + "qpx.qvlfcda" => "__builtin_qpx_qvlfcda", + "qpx.qvlfcs" => "__builtin_qpx_qvlfcs", + "qpx.qvlfcsa" => "__builtin_qpx_qvlfcsa", + "qpx.qvlfd" => "__builtin_qpx_qvlfd", + "qpx.qvlfda" => "__builtin_qpx_qvlfda", + "qpx.qvlfiwa" => "__builtin_qpx_qvlfiwa", + "qpx.qvlfiwaa" => "__builtin_qpx_qvlfiwaa", + "qpx.qvlfiwz" => "__builtin_qpx_qvlfiwz", + "qpx.qvlfiwza" => "__builtin_qpx_qvlfiwza", + "qpx.qvlfs" => "__builtin_qpx_qvlfs", + "qpx.qvlfsa" => "__builtin_qpx_qvlfsa", + "qpx.qvlpcld" => "__builtin_qpx_qvlpcld", + "qpx.qvlpcls" => "__builtin_qpx_qvlpcls", + "qpx.qvlpcrd" => "__builtin_qpx_qvlpcrd", + "qpx.qvlpcrs" => "__builtin_qpx_qvlpcrs", + "qpx.qvstfcd" => "__builtin_qpx_qvstfcd", + "qpx.qvstfcda" => "__builtin_qpx_qvstfcda", + "qpx.qvstfcs" => "__builtin_qpx_qvstfcs", + "qpx.qvstfcsa" => "__builtin_qpx_qvstfcsa", + "qpx.qvstfd" => "__builtin_qpx_qvstfd", + "qpx.qvstfda" => "__builtin_qpx_qvstfda", + "qpx.qvstfiw" => "__builtin_qpx_qvstfiw", + "qpx.qvstfiwa" => "__builtin_qpx_qvstfiwa", + "qpx.qvstfs" => "__builtin_qpx_qvstfs", + "qpx.qvstfsa" => "__builtin_qpx_qvstfsa", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + "ptx" => match name { + "bar.sync" => "__builtin_ptx_bar_sync", + "read.clock" => "__builtin_ptx_read_clock", + "read.clock64" => "__builtin_ptx_read_clock64", + "read.gridid" => "__builtin_ptx_read_gridid", + "read.laneid" => "__builtin_ptx_read_laneid", + "read.lanemask.eq" => "__builtin_ptx_read_lanemask_eq", + "read.lanemask.ge" => "__builtin_ptx_read_lanemask_ge", + "read.lanemask.gt" => "__builtin_ptx_read_lanemask_gt", + "read.lanemask.le" => "__builtin_ptx_read_lanemask_le", + "read.lanemask.lt" => "__builtin_ptx_read_lanemask_lt", + "read.nsmid" => "__builtin_ptx_read_nsmid", + "read.nwarpid" => "__builtin_ptx_read_nwarpid", + "read.pm0" => "__builtin_ptx_read_pm0", + "read.pm1" => "__builtin_ptx_read_pm1", + "read.pm2" => "__builtin_ptx_read_pm2", + "read.pm3" => "__builtin_ptx_read_pm3", + "read.smid" => "__builtin_ptx_read_smid", + "read.warpid" => "__builtin_ptx_read_warpid", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + "x86" => match name { + "addcarry.u32" => "__builtin_ia32_addcarry_u32", + "addcarry.u64" => "__builtin_ia32_addcarry_u64", + "addcarryx.u32" => "__builtin_ia32_addcarryx_u32", + "addcarryx.u64" => "__builtin_ia32_addcarryx_u64", + "avx.blend.pd.256" => "__builtin_ia32_blendpd256", + "avx.blend.ps.256" => "__builtin_ia32_blendps256", + "avx.cmp.pd.256" => "__builtin_ia32_cmppd256", + "avx.cmp.ps.256" => "__builtin_ia32_cmpps256", + "avx.cvt.ps2.pd.256" => "__builtin_ia32_cvtps2pd256", + "avx.cvtdq2.pd.256" => "__builtin_ia32_cvtdq2pd256", + "avx.cvtdq2.ps.256" => "__builtin_ia32_cvtdq2ps256", + "avx.sqrt.pd.256" => "__builtin_ia32_sqrtpd256", + "avx.sqrt.ps.256" => "__builtin_ia32_sqrtps256", + "avx.storeu.dq.256" => "__builtin_ia32_storedqu256", + "avx.storeu.pd.256" => "__builtin_ia32_storeupd256", + "avx.storeu.ps.256" => "__builtin_ia32_storeups256", + "avx.vbroadcastf128.pd.256" => "__builtin_ia32_vbroadcastf128_pd256", + "avx.vbroadcastf128.ps.256" => "__builtin_ia32_vbroadcastf128_ps256", + "avx.vextractf128.pd.256" => "__builtin_ia32_vextractf128_pd256", + "avx.vextractf128.ps.256" => "__builtin_ia32_vextractf128_ps256", + "avx.vextractf128.si.256" => "__builtin_ia32_vextractf128_si256", + "avx.vinsertf128.pd.256" => "__builtin_ia32_vinsertf128_pd256", + "avx.vinsertf128.ps.256" => "__builtin_ia32_vinsertf128_ps256", + "avx.vinsertf128.si.256" => "__builtin_ia32_vinsertf128_si256", + "avx.vperm2f128.pd.256" => "__builtin_ia32_vperm2f128_pd256", + "avx.vperm2f128.ps.256" => "__builtin_ia32_vperm2f128_ps256", + "avx.vperm2f128.si.256" => "__builtin_ia32_vperm2f128_si256", + "avx2.movntdqa" => "__builtin_ia32_movntdqa256", + "avx2.pabs.b" => "__builtin_ia32_pabsb256", + "avx2.pabs.d" => "__builtin_ia32_pabsd256", + "avx2.pabs.w" => "__builtin_ia32_pabsw256", + "avx2.padds.b" => "__builtin_ia32_paddsb256", + "avx2.padds.w" => "__builtin_ia32_paddsw256", + "avx2.paddus.b" => "__builtin_ia32_paddusb256", + "avx2.paddus.w" => "__builtin_ia32_paddusw256", + "avx2.pblendd.128" => "__builtin_ia32_pblendd128", + "avx2.pblendd.256" => "__builtin_ia32_pblendd256", + "avx2.pblendw" => "__builtin_ia32_pblendw256", + "avx2.pbroadcastb.128" => "__builtin_ia32_pbroadcastb128", + "avx2.pbroadcastb.256" => "__builtin_ia32_pbroadcastb256", + "avx2.pbroadcastd.128" => "__builtin_ia32_pbroadcastd128", + "avx2.pbroadcastd.256" => "__builtin_ia32_pbroadcastd256", + "avx2.pbroadcastq.128" => "__builtin_ia32_pbroadcastq128", + "avx2.pbroadcastq.256" => "__builtin_ia32_pbroadcastq256", + "avx2.pbroadcastw.128" => "__builtin_ia32_pbroadcastw128", + "avx2.pbroadcastw.256" => "__builtin_ia32_pbroadcastw256", + "avx2.pmaxs.b" => "__builtin_ia32_pmaxsb256", + "avx2.pmaxs.d" => "__builtin_ia32_pmaxsd256", + "avx2.pmaxs.w" => "__builtin_ia32_pmaxsw256", + "avx2.pmaxu.b" => "__builtin_ia32_pmaxub256", + "avx2.pmaxu.d" => "__builtin_ia32_pmaxud256", + "avx2.pmaxu.w" => "__builtin_ia32_pmaxuw256", + "avx2.pmins.b" => "__builtin_ia32_pminsb256", + "avx2.pmins.d" => "__builtin_ia32_pminsd256", + "avx2.pmins.w" => "__builtin_ia32_pminsw256", + "avx2.pminu.b" => "__builtin_ia32_pminub256", + "avx2.pminu.d" => "__builtin_ia32_pminud256", + "avx2.pminu.w" => "__builtin_ia32_pminuw256", + "avx2.pmovsxbd" => "__builtin_ia32_pmovsxbd256", + "avx2.pmovsxbq" => "__builtin_ia32_pmovsxbq256", + "avx2.pmovsxbw" => "__builtin_ia32_pmovsxbw256", + "avx2.pmovsxdq" => "__builtin_ia32_pmovsxdq256", + "avx2.pmovsxwd" => "__builtin_ia32_pmovsxwd256", + "avx2.pmovsxwq" => "__builtin_ia32_pmovsxwq256", + "avx2.pmovzxbd" => "__builtin_ia32_pmovzxbd256", + "avx2.pmovzxbq" => "__builtin_ia32_pmovzxbq256", + "avx2.pmovzxbw" => "__builtin_ia32_pmovzxbw256", + "avx2.pmovzxdq" => "__builtin_ia32_pmovzxdq256", + "avx2.pmovzxwd" => "__builtin_ia32_pmovzxwd256", + "avx2.pmovzxwq" => "__builtin_ia32_pmovzxwq256", + "avx2.pmul.dq" => "__builtin_ia32_pmuldq256", + "avx2.pmulu.dq" => "__builtin_ia32_pmuludq256", + "avx2.psll.dq" => "__builtin_ia32_pslldqi256", + "avx2.psll.dq.bs" => "__builtin_ia32_pslldqi256_byteshift", + "avx2.psrl.dq" => "__builtin_ia32_psrldqi256", + "avx2.psrl.dq.bs" => "__builtin_ia32_psrldqi256_byteshift", + "avx2.psubs.b" => "__builtin_ia32_psubsb256", + "avx2.psubs.w" => "__builtin_ia32_psubsw256", + "avx2.psubus.b" => "__builtin_ia32_psubusb256", + "avx2.psubus.w" => "__builtin_ia32_psubusw256", + "avx2.vbroadcast.sd.pd.256" => "__builtin_ia32_vbroadcastsd_pd256", + "avx2.vbroadcast.ss.ps" => "__builtin_ia32_vbroadcastss_ps", + "avx2.vbroadcast.ss.ps.256" => "__builtin_ia32_vbroadcastss_ps256", + "avx2.vextracti128" => "__builtin_ia32_extract128i256", + "avx2.vinserti128" => "__builtin_ia32_insert128i256", + "avx2.vperm2i128" => "__builtin_ia32_permti256", + "avx512.cvtb2mask.128" => "__builtin_ia32_cvtb2mask128", + "avx512.cvtb2mask.256" => "__builtin_ia32_cvtb2mask256", + "avx512.cvtb2mask.512" => "__builtin_ia32_cvtb2mask512", + "avx512.cvtd2mask.128" => "__builtin_ia32_cvtd2mask128", + "avx512.cvtd2mask.256" => "__builtin_ia32_cvtd2mask256", + "avx512.cvtd2mask.512" => "__builtin_ia32_cvtd2mask512", + "avx512.cvtmask2b.128" => "__builtin_ia32_cvtmask2b128", + "avx512.cvtmask2b.256" => "__builtin_ia32_cvtmask2b256", + "avx512.cvtmask2b.512" => "__builtin_ia32_cvtmask2b512", + "avx512.cvtmask2d.128" => "__builtin_ia32_cvtmask2d128", + "avx512.cvtmask2d.256" => "__builtin_ia32_cvtmask2d256", + "avx512.cvtmask2d.512" => "__builtin_ia32_cvtmask2d512", + "avx512.cvtmask2q.128" => "__builtin_ia32_cvtmask2q128", + "avx512.cvtmask2q.256" => "__builtin_ia32_cvtmask2q256", + "avx512.cvtmask2q.512" => "__builtin_ia32_cvtmask2q512", + "avx512.cvtmask2w.128" => "__builtin_ia32_cvtmask2w128", + "avx512.cvtmask2w.256" => "__builtin_ia32_cvtmask2w256", + "avx512.cvtmask2w.512" => "__builtin_ia32_cvtmask2w512", + "avx512.cvtq2mask.128" => "__builtin_ia32_cvtq2mask128", + "avx512.cvtq2mask.256" => "__builtin_ia32_cvtq2mask256", + "avx512.cvtq2mask.512" => "__builtin_ia32_cvtq2mask512", + "avx512.cvtsd2usi" => "__builtin_ia32_cvtsd2usi", + "avx512.cvtsd2usi64" => "__builtin_ia32_cvtsd2usi64", + "avx512.cvtsi2sd32" => "__builtin_ia32_cvtsi2sd32", + "avx512.cvtss2usi" => "__builtin_ia32_cvtss2usi", + "avx512.cvtss2usi64" => "__builtin_ia32_cvtss2usi64", + "avx512.cvtw2mask.128" => "__builtin_ia32_cvtw2mask128", + "avx512.cvtw2mask.256" => "__builtin_ia32_cvtw2mask256", + "avx512.cvtw2mask.512" => "__builtin_ia32_cvtw2mask512", + "avx512.exp2.pd" => "__builtin_ia32_exp2pd_mask", + "avx512.exp2.ps" => "__builtin_ia32_exp2ps_mask", + "avx512.gather.dpd.512" => "__builtin_ia32_gathersiv8df", + "avx512.gather.dpi.512" => "__builtin_ia32_gathersiv16si", + "avx512.gather.dpq.512" => "__builtin_ia32_gathersiv8di", + "avx512.gather.dps.512" => "__builtin_ia32_gathersiv16sf", + "avx512.gather.qpd.512" => "__builtin_ia32_gatherdiv8df", + "avx512.gather.qpi.512" => "__builtin_ia32_gatherdiv16si", + "avx512.gather.qpq.512" => "__builtin_ia32_gatherdiv8di", + "avx512.gather.qps.512" => "__builtin_ia32_gatherdiv16sf", + "avx512.gather3div2.df" => "__builtin_ia32_gather3div2df", + "avx512.gather3div2.di" => "__builtin_ia32_gather3div2di", + "avx512.gather3div4.df" => "__builtin_ia32_gather3div4df", + "avx512.gather3div4.di" => "__builtin_ia32_gather3div4di", + "avx512.gather3div4.sf" => "__builtin_ia32_gather3div4sf", + "avx512.gather3div4.si" => "__builtin_ia32_gather3div4si", + "avx512.gather3div8.sf" => "__builtin_ia32_gather3div8sf", + "avx512.gather3div8.si" => "__builtin_ia32_gather3div8si", + "avx512.gather3siv2.df" => "__builtin_ia32_gather3siv2df", + "avx512.gather3siv2.di" => "__builtin_ia32_gather3siv2di", + "avx512.gather3siv4.df" => "__builtin_ia32_gather3siv4df", + "avx512.gather3siv4.di" => "__builtin_ia32_gather3siv4di", + "avx512.gather3siv4.sf" => "__builtin_ia32_gather3siv4sf", + "avx512.gather3siv4.si" => "__builtin_ia32_gather3siv4si", + "avx512.gather3siv8.sf" => "__builtin_ia32_gather3siv8sf", + "avx512.gather3siv8.si" => "__builtin_ia32_gather3siv8si", + "avx512.gatherpf.dpd.512" => "__builtin_ia32_gatherpfdpd", + "avx512.gatherpf.dps.512" => "__builtin_ia32_gatherpfdps", + "avx512.gatherpf.qpd.512" => "__builtin_ia32_gatherpfqpd", + "avx512.gatherpf.qps.512" => "__builtin_ia32_gatherpfqps", + "avx512.kand.w" => "__builtin_ia32_kandhi", + "avx512.kandn.w" => "__builtin_ia32_kandnhi", + "avx512.knot.w" => "__builtin_ia32_knothi", + "avx512.kor.w" => "__builtin_ia32_korhi", + "avx512.kortestc.w" => "__builtin_ia32_kortestchi", + "avx512.kortestz.w" => "__builtin_ia32_kortestzhi", + "avx512.kunpck.bw" => "__builtin_ia32_kunpckhi", + "avx512.kunpck.dq" => "__builtin_ia32_kunpckdi", + "avx512.kunpck.wd" => "__builtin_ia32_kunpcksi", + "avx512.kxnor.w" => "__builtin_ia32_kxnorhi", + "avx512.kxor.w" => "__builtin_ia32_kxorhi", + "avx512.mask.add.pd.128" => "__builtin_ia32_addpd128_mask", + "avx512.mask.add.pd.256" => "__builtin_ia32_addpd256_mask", + "avx512.mask.add.pd.512" => "__builtin_ia32_addpd512_mask", + "avx512.mask.add.ps.128" => "__builtin_ia32_addps128_mask", + "avx512.mask.add.ps.256" => "__builtin_ia32_addps256_mask", + "avx512.mask.add.ps.512" => "__builtin_ia32_addps512_mask", + "avx512.mask.and.pd.128" => "__builtin_ia32_andpd128_mask", + "avx512.mask.and.pd.256" => "__builtin_ia32_andpd256_mask", + "avx512.mask.and.pd.512" => "__builtin_ia32_andpd512_mask", + "avx512.mask.and.ps.128" => "__builtin_ia32_andps128_mask", + "avx512.mask.and.ps.256" => "__builtin_ia32_andps256_mask", + "avx512.mask.and.ps.512" => "__builtin_ia32_andps512_mask", + "avx512.mask.andn.pd.128" => "__builtin_ia32_andnpd128_mask", + "avx512.mask.andn.pd.256" => "__builtin_ia32_andnpd256_mask", + "avx512.mask.andn.pd.512" => "__builtin_ia32_andnpd512_mask", + "avx512.mask.andn.ps.128" => "__builtin_ia32_andnps128_mask", + "avx512.mask.andn.ps.256" => "__builtin_ia32_andnps256_mask", + "avx512.mask.andn.ps.512" => "__builtin_ia32_andnps512_mask", + "avx512.mask.blend.d.512" => "__builtin_ia32_blendmd_512_mask", + "avx512.mask.blend.pd.512" => "__builtin_ia32_blendmpd_512_mask", + "avx512.mask.blend.ps.512" => "__builtin_ia32_blendmps_512_mask", + "avx512.mask.blend.q.512" => "__builtin_ia32_blendmq_512_mask", + "avx512.mask.broadcastf32x2.256" => "__builtin_ia32_broadcastf32x2_256_mask", + "avx512.mask.broadcastf32x2.512" => "__builtin_ia32_broadcastf32x2_512_mask", + "avx512.mask.broadcastf32x4.256" => "__builtin_ia32_broadcastf32x4_256_mask", + "avx512.mask.broadcastf32x4.512" => "__builtin_ia32_broadcastf32x4_512", + "avx512.mask.broadcastf32x8.512" => "__builtin_ia32_broadcastf32x8_512_mask", + "avx512.mask.broadcastf64x2.256" => "__builtin_ia32_broadcastf64x2_256_mask", + "avx512.mask.broadcastf64x2.512" => "__builtin_ia32_broadcastf64x2_512_mask", + "avx512.mask.broadcastf64x4.512" => "__builtin_ia32_broadcastf64x4_512", + "avx512.mask.broadcasti32x2.128" => "__builtin_ia32_broadcasti32x2_128_mask", + "avx512.mask.broadcasti32x2.256" => "__builtin_ia32_broadcasti32x2_256_mask", + "avx512.mask.broadcasti32x2.512" => "__builtin_ia32_broadcasti32x2_512_mask", + "avx512.mask.broadcasti32x4.256" => "__builtin_ia32_broadcasti32x4_256_mask", + "avx512.mask.broadcasti32x4.512" => "__builtin_ia32_broadcasti32x4_512", + "avx512.mask.broadcasti32x8.512" => "__builtin_ia32_broadcasti32x8_512_mask", + "avx512.mask.broadcasti64x2.256" => "__builtin_ia32_broadcasti64x2_256_mask", + "avx512.mask.broadcasti64x2.512" => "__builtin_ia32_broadcasti64x2_512_mask", + "avx512.mask.broadcasti64x4.512" => "__builtin_ia32_broadcasti64x4_512", + "avx512.mask.cmp.pd.128" => "__builtin_ia32_cmppd128_mask", + "avx512.mask.cmp.pd.256" => "__builtin_ia32_cmppd256_mask", + "avx512.mask.cmp.pd.512" => "__builtin_ia32_cmppd512_mask", + "avx512.mask.cmp.ps.128" => "__builtin_ia32_cmpps128_mask", + "avx512.mask.cmp.ps.256" => "__builtin_ia32_cmpps256_mask", + "avx512.mask.cmp.ps.512" => "__builtin_ia32_cmpps512_mask", + "avx512.mask.compress.d.128" => "__builtin_ia32_compresssi128_mask", + "avx512.mask.compress.d.256" => "__builtin_ia32_compresssi256_mask", + "avx512.mask.compress.d.512" => "__builtin_ia32_compresssi512_mask", + "avx512.mask.compress.pd.128" => "__builtin_ia32_compressdf128_mask", + "avx512.mask.compress.pd.256" => "__builtin_ia32_compressdf256_mask", + "avx512.mask.compress.pd.512" => "__builtin_ia32_compressdf512_mask", + "avx512.mask.compress.ps.128" => "__builtin_ia32_compresssf128_mask", + "avx512.mask.compress.ps.256" => "__builtin_ia32_compresssf256_mask", + "avx512.mask.compress.ps.512" => "__builtin_ia32_compresssf512_mask", + "avx512.mask.compress.q.128" => "__builtin_ia32_compressdi128_mask", + "avx512.mask.compress.q.256" => "__builtin_ia32_compressdi256_mask", + "avx512.mask.compress.q.512" => "__builtin_ia32_compressdi512_mask", + "avx512.mask.compress.store.d.128" => "__builtin_ia32_compressstoresi128_mask", + "avx512.mask.compress.store.d.256" => "__builtin_ia32_compressstoresi256_mask", + "avx512.mask.compress.store.d.512" => "__builtin_ia32_compressstoresi512_mask", + "avx512.mask.compress.store.pd.128" => "__builtin_ia32_compressstoredf128_mask", + "avx512.mask.compress.store.pd.256" => "__builtin_ia32_compressstoredf256_mask", + "avx512.mask.compress.store.pd.512" => "__builtin_ia32_compressstoredf512_mask", + "avx512.mask.compress.store.ps.128" => "__builtin_ia32_compressstoresf128_mask", + "avx512.mask.compress.store.ps.256" => "__builtin_ia32_compressstoresf256_mask", + "avx512.mask.compress.store.ps.512" => "__builtin_ia32_compressstoresf512_mask", + "avx512.mask.compress.store.q.128" => "__builtin_ia32_compressstoredi128_mask", + "avx512.mask.compress.store.q.256" => "__builtin_ia32_compressstoredi256_mask", + "avx512.mask.compress.store.q.512" => "__builtin_ia32_compressstoredi512_mask", + "avx512.mask.conflict.d.128" => "__builtin_ia32_vpconflictsi_128_mask", + "avx512.mask.conflict.d.256" => "__builtin_ia32_vpconflictsi_256_mask", + "avx512.mask.conflict.d.512" => "__builtin_ia32_vpconflictsi_512_mask", + "avx512.mask.conflict.q.128" => "__builtin_ia32_vpconflictdi_128_mask", + "avx512.mask.conflict.q.256" => "__builtin_ia32_vpconflictdi_256_mask", + "avx512.mask.conflict.q.512" => "__builtin_ia32_vpconflictdi_512_mask", + "avx512.mask.cvtdq2pd.128" => "__builtin_ia32_cvtdq2pd128_mask", + "avx512.mask.cvtdq2pd.256" => "__builtin_ia32_cvtdq2pd256_mask", + "avx512.mask.cvtdq2pd.512" => "__builtin_ia32_cvtdq2pd512_mask", + "avx512.mask.cvtdq2ps.128" => "__builtin_ia32_cvtdq2ps128_mask", + "avx512.mask.cvtdq2ps.256" => "__builtin_ia32_cvtdq2ps256_mask", + "avx512.mask.cvtdq2ps.512" => "__builtin_ia32_cvtdq2ps512_mask", + "avx512.mask.cvtpd2dq.256" => "__builtin_ia32_cvtpd2dq256_mask", + "avx512.mask.cvtps2pd.128" => "__builtin_ia32_cvtps2pd128_mask", + "avx512.mask.cvtps2pd.256" => "__builtin_ia32_cvtps2pd256_mask", + "avx512.mask.cvtqq2pd.128" => "__builtin_ia32_cvtqq2pd128_mask", + "avx512.mask.cvtqq2pd.256" => "__builtin_ia32_cvtqq2pd256_mask", + "avx512.mask.cvtqq2pd.512" => "__builtin_ia32_cvtqq2pd512_mask", + "avx512.mask.cvtqq2ps.256" => "__builtin_ia32_cvtqq2ps256_mask", + "avx512.mask.cvtqq2ps.512" => "__builtin_ia32_cvtqq2ps512_mask", + "avx512.mask.cvttpd2dq.256" => "__builtin_ia32_cvttpd2dq256_mask", + "avx512.mask.cvttps2dq.128" => "__builtin_ia32_cvttps2dq128_mask", + "avx512.mask.cvttps2dq.256" => "__builtin_ia32_cvttps2dq256_mask", + "avx512.mask.cvtudq2pd.128" => "__builtin_ia32_cvtudq2pd128_mask", + "avx512.mask.cvtudq2pd.256" => "__builtin_ia32_cvtudq2pd256_mask", + "avx512.mask.cvtudq2pd.512" => "__builtin_ia32_cvtudq2pd512_mask", + "avx512.mask.cvtudq2ps.128" => "__builtin_ia32_cvtudq2ps128_mask", + "avx512.mask.cvtudq2ps.256" => "__builtin_ia32_cvtudq2ps256_mask", + "avx512.mask.cvtudq2ps.512" => "__builtin_ia32_cvtudq2ps512_mask", + "avx512.mask.cvtuqq2pd.128" => "__builtin_ia32_cvtuqq2pd128_mask", + "avx512.mask.cvtuqq2pd.256" => "__builtin_ia32_cvtuqq2pd256_mask", + "avx512.mask.cvtuqq2pd.512" => "__builtin_ia32_cvtuqq2pd512_mask", + "avx512.mask.cvtuqq2ps.256" => "__builtin_ia32_cvtuqq2ps256_mask", + "avx512.mask.cvtuqq2ps.512" => "__builtin_ia32_cvtuqq2ps512_mask", + "avx512.mask.dbpsadbw.128" => "__builtin_ia32_dbpsadbw128_mask", + "avx512.mask.dbpsadbw.256" => "__builtin_ia32_dbpsadbw256_mask", + "avx512.mask.dbpsadbw.512" => "__builtin_ia32_dbpsadbw512_mask", + "avx512.mask.div.pd.128" => "__builtin_ia32_divpd_mask", + "avx512.mask.div.pd.256" => "__builtin_ia32_divpd256_mask", + "avx512.mask.div.pd.512" => "__builtin_ia32_divpd512_mask", + "avx512.mask.div.ps.128" => "__builtin_ia32_divps_mask", + "avx512.mask.div.ps.256" => "__builtin_ia32_divps256_mask", + "avx512.mask.div.ps.512" => "__builtin_ia32_divps512_mask", + "avx512.mask.expand.d.128" => "__builtin_ia32_expandsi128_mask", + "avx512.mask.expand.d.256" => "__builtin_ia32_expandsi256_mask", + "avx512.mask.expand.d.512" => "__builtin_ia32_expandsi512_mask", + "avx512.mask.expand.load.d.128" => "__builtin_ia32_expandloadsi128_mask", + "avx512.mask.expand.load.d.256" => "__builtin_ia32_expandloadsi256_mask", + "avx512.mask.expand.load.d.512" => "__builtin_ia32_expandloadsi512_mask", + "avx512.mask.expand.load.pd.128" => "__builtin_ia32_expandloaddf128_mask", + "avx512.mask.expand.load.pd.256" => "__builtin_ia32_expandloaddf256_mask", + "avx512.mask.expand.load.pd.512" => "__builtin_ia32_expandloaddf512_mask", + "avx512.mask.expand.load.ps.128" => "__builtin_ia32_expandloadsf128_mask", + "avx512.mask.expand.load.ps.256" => "__builtin_ia32_expandloadsf256_mask", + "avx512.mask.expand.load.ps.512" => "__builtin_ia32_expandloadsf512_mask", + "avx512.mask.expand.load.q.128" => "__builtin_ia32_expandloaddi128_mask", + "avx512.mask.expand.load.q.256" => "__builtin_ia32_expandloaddi256_mask", + "avx512.mask.expand.load.q.512" => "__builtin_ia32_expandloaddi512_mask", + "avx512.mask.expand.pd.128" => "__builtin_ia32_expanddf128_mask", + "avx512.mask.expand.pd.256" => "__builtin_ia32_expanddf256_mask", + "avx512.mask.expand.pd.512" => "__builtin_ia32_expanddf512_mask", + "avx512.mask.expand.ps.128" => "__builtin_ia32_expandsf128_mask", + "avx512.mask.expand.ps.256" => "__builtin_ia32_expandsf256_mask", + "avx512.mask.expand.ps.512" => "__builtin_ia32_expandsf512_mask", + "avx512.mask.expand.q.128" => "__builtin_ia32_expanddi128_mask", + "avx512.mask.expand.q.256" => "__builtin_ia32_expanddi256_mask", + "avx512.mask.expand.q.512" => "__builtin_ia32_expanddi512_mask", + "avx512.mask.fpclass.pd.128" => "__builtin_ia32_fpclasspd128_mask", + "avx512.mask.fpclass.pd.256" => "__builtin_ia32_fpclasspd256_mask", + "avx512.mask.fpclass.pd.512" => "__builtin_ia32_fpclasspd512_mask", + "avx512.mask.fpclass.ps.128" => "__builtin_ia32_fpclassps128_mask", + "avx512.mask.fpclass.ps.256" => "__builtin_ia32_fpclassps256_mask", + "avx512.mask.fpclass.ps.512" => "__builtin_ia32_fpclassps512_mask", + "avx512.mask.insertf32x4.256" => "__builtin_ia32_insertf32x4_256_mask", + "avx512.mask.insertf32x4.512" => "__builtin_ia32_insertf32x4_mask", + "avx512.mask.insertf32x8.512" => "__builtin_ia32_insertf32x8_mask", + "avx512.mask.insertf64x2.256" => "__builtin_ia32_insertf64x2_256_mask", + "avx512.mask.insertf64x2.512" => "__builtin_ia32_insertf64x2_512_mask", + "avx512.mask.insertf64x4.512" => "__builtin_ia32_insertf64x4_mask", + "avx512.mask.inserti32x4.256" => "__builtin_ia32_inserti32x4_256_mask", + "avx512.mask.inserti32x4.512" => "__builtin_ia32_inserti32x4_mask", + "avx512.mask.inserti32x8.512" => "__builtin_ia32_inserti32x8_mask", + "avx512.mask.inserti64x2.256" => "__builtin_ia32_inserti64x2_256_mask", + "avx512.mask.inserti64x2.512" => "__builtin_ia32_inserti64x2_512_mask", + "avx512.mask.inserti64x4.512" => "__builtin_ia32_inserti64x4_mask", + "avx512.mask.loadu.d.512" => "__builtin_ia32_loaddqusi512_mask", + "avx512.mask.loadu.pd.512" => "__builtin_ia32_loadupd512_mask", + "avx512.mask.loadu.ps.512" => "__builtin_ia32_loadups512_mask", + "avx512.mask.loadu.q.512" => "__builtin_ia32_loaddqudi512_mask", + "avx512.mask.lzcnt.d.512" => "__builtin_ia32_vplzcntd_512_mask", + "avx512.mask.lzcnt.q.512" => "__builtin_ia32_vplzcntq_512_mask", + "avx512.mask.max.pd.128" => "__builtin_ia32_maxpd_mask", + "avx512.mask.max.pd.256" => "__builtin_ia32_maxpd256_mask", + "avx512.mask.max.pd.512" => "__builtin_ia32_maxpd512_mask", + "avx512.mask.max.ps.128" => "__builtin_ia32_maxps_mask", + "avx512.mask.max.ps.256" => "__builtin_ia32_maxps256_mask", + "avx512.mask.max.ps.512" => "__builtin_ia32_maxps512_mask", + "avx512.mask.min.pd.128" => "__builtin_ia32_minpd_mask", + "avx512.mask.min.pd.256" => "__builtin_ia32_minpd256_mask", + "avx512.mask.min.pd.512" => "__builtin_ia32_minpd512_mask", + "avx512.mask.min.ps.128" => "__builtin_ia32_minps_mask", + "avx512.mask.min.ps.256" => "__builtin_ia32_minps256_mask", + "avx512.mask.min.ps.512" => "__builtin_ia32_minps512_mask", + "avx512.mask.move.sd" => "__builtin_ia32_movsd_mask", + "avx512.mask.move.ss" => "__builtin_ia32_movss_mask", + "avx512.mask.mul.pd.128" => "__builtin_ia32_mulpd_mask", + "avx512.mask.mul.pd.256" => "__builtin_ia32_mulpd256_mask", + "avx512.mask.mul.pd.512" => "__builtin_ia32_mulpd512_mask", + "avx512.mask.mul.ps.128" => "__builtin_ia32_mulps_mask", + "avx512.mask.mul.ps.256" => "__builtin_ia32_mulps256_mask", + "avx512.mask.mul.ps.512" => "__builtin_ia32_mulps512_mask", + "avx512.mask.or.pd.128" => "__builtin_ia32_orpd128_mask", + "avx512.mask.or.pd.256" => "__builtin_ia32_orpd256_mask", + "avx512.mask.or.pd.512" => "__builtin_ia32_orpd512_mask", + "avx512.mask.or.ps.128" => "__builtin_ia32_orps128_mask", + "avx512.mask.or.ps.256" => "__builtin_ia32_orps256_mask", + "avx512.mask.or.ps.512" => "__builtin_ia32_orps512_mask", + "avx512.mask.pabs.b.128" => "__builtin_ia32_pabsb128_mask", + "avx512.mask.pabs.b.256" => "__builtin_ia32_pabsb256_mask", + "avx512.mask.pabs.b.512" => "__builtin_ia32_pabsb512_mask", + "avx512.mask.pabs.d.128" => "__builtin_ia32_pabsd128_mask", + "avx512.mask.pabs.d.256" => "__builtin_ia32_pabsd256_mask", + "avx512.mask.pabs.d.512" => "__builtin_ia32_pabsd512_mask", + "avx512.mask.pabs.q.128" => "__builtin_ia32_pabsq128_mask", + "avx512.mask.pabs.q.256" => "__builtin_ia32_pabsq256_mask", + "avx512.mask.pabs.q.512" => "__builtin_ia32_pabsq512_mask", + "avx512.mask.pabs.w.128" => "__builtin_ia32_pabsw128_mask", + "avx512.mask.pabs.w.256" => "__builtin_ia32_pabsw256_mask", + "avx512.mask.pabs.w.512" => "__builtin_ia32_pabsw512_mask", + "avx512.mask.packssdw.128" => "__builtin_ia32_packssdw128_mask", + "avx512.mask.packssdw.256" => "__builtin_ia32_packssdw256_mask", + "avx512.mask.packssdw.512" => "__builtin_ia32_packssdw512_mask", + "avx512.mask.packsswb.128" => "__builtin_ia32_packsswb128_mask", + "avx512.mask.packsswb.256" => "__builtin_ia32_packsswb256_mask", + "avx512.mask.packsswb.512" => "__builtin_ia32_packsswb512_mask", + "avx512.mask.packusdw.128" => "__builtin_ia32_packusdw128_mask", + "avx512.mask.packusdw.256" => "__builtin_ia32_packusdw256_mask", + "avx512.mask.packusdw.512" => "__builtin_ia32_packusdw512_mask", + "avx512.mask.packuswb.128" => "__builtin_ia32_packuswb128_mask", + "avx512.mask.packuswb.256" => "__builtin_ia32_packuswb256_mask", + "avx512.mask.packuswb.512" => "__builtin_ia32_packuswb512_mask", + "avx512.mask.padd.b.128" => "__builtin_ia32_paddb128_mask", + "avx512.mask.padd.b.256" => "__builtin_ia32_paddb256_mask", + "avx512.mask.padd.b.512" => "__builtin_ia32_paddb512_mask", + "avx512.mask.padd.d.128" => "__builtin_ia32_paddd128_mask", + "avx512.mask.padd.d.256" => "__builtin_ia32_paddd256_mask", + "avx512.mask.padd.d.512" => "__builtin_ia32_paddd512_mask", + "avx512.mask.padd.q.128" => "__builtin_ia32_paddq128_mask", + "avx512.mask.padd.q.256" => "__builtin_ia32_paddq256_mask", + "avx512.mask.padd.q.512" => "__builtin_ia32_paddq512_mask", + "avx512.mask.padd.w.128" => "__builtin_ia32_paddw128_mask", + "avx512.mask.padd.w.256" => "__builtin_ia32_paddw256_mask", + "avx512.mask.padd.w.512" => "__builtin_ia32_paddw512_mask", + "avx512.mask.padds.b.128" => "__builtin_ia32_paddsb128_mask", + "avx512.mask.padds.b.256" => "__builtin_ia32_paddsb256_mask", + "avx512.mask.padds.b.512" => "__builtin_ia32_paddsb512_mask", + "avx512.mask.padds.w.128" => "__builtin_ia32_paddsw128_mask", + "avx512.mask.padds.w.256" => "__builtin_ia32_paddsw256_mask", + "avx512.mask.padds.w.512" => "__builtin_ia32_paddsw512_mask", + "avx512.mask.paddus.b.128" => "__builtin_ia32_paddusb128_mask", + "avx512.mask.paddus.b.256" => "__builtin_ia32_paddusb256_mask", + "avx512.mask.paddus.b.512" => "__builtin_ia32_paddusb512_mask", + "avx512.mask.paddus.w.128" => "__builtin_ia32_paddusw128_mask", + "avx512.mask.paddus.w.256" => "__builtin_ia32_paddusw256_mask", + "avx512.mask.paddus.w.512" => "__builtin_ia32_paddusw512_mask", + "avx512.mask.pand.d.512" => "__builtin_ia32_pandd512_mask", + "avx512.mask.pand.q.512" => "__builtin_ia32_pandq512_mask", + "avx512.mask.pavg.b.128" => "__builtin_ia32_pavgb128_mask", + "avx512.mask.pavg.b.256" => "__builtin_ia32_pavgb256_mask", + "avx512.mask.pavg.b.512" => "__builtin_ia32_pavgb512_mask", + "avx512.mask.pavg.w.128" => "__builtin_ia32_pavgw128_mask", + "avx512.mask.pavg.w.256" => "__builtin_ia32_pavgw256_mask", + "avx512.mask.pavg.w.512" => "__builtin_ia32_pavgw512_mask", + "avx512.mask.pbroadcast.b.gpr.128" => "__builtin_ia32_pbroadcastb128_gpr_mask", + "avx512.mask.pbroadcast.b.gpr.256" => "__builtin_ia32_pbroadcastb256_gpr_mask", + "avx512.mask.pbroadcast.b.gpr.512" => "__builtin_ia32_pbroadcastb512_gpr_mask", + "avx512.mask.pbroadcast.d.gpr.128" => "__builtin_ia32_pbroadcastd128_gpr_mask", + "avx512.mask.pbroadcast.d.gpr.256" => "__builtin_ia32_pbroadcastd256_gpr_mask", + "avx512.mask.pbroadcast.d.gpr.512" => "__builtin_ia32_pbroadcastd512_gpr_mask", + "avx512.mask.pbroadcast.q.gpr.128" => "__builtin_ia32_pbroadcastq128_gpr_mask", + "avx512.mask.pbroadcast.q.gpr.256" => "__builtin_ia32_pbroadcastq256_gpr_mask", + "avx512.mask.pbroadcast.q.gpr.512" => "__builtin_ia32_pbroadcastq512_gpr_mask", + "avx512.mask.pbroadcast.q.mem.512" => "__builtin_ia32_pbroadcastq512_mem_mask", + "avx512.mask.pbroadcast.w.gpr.128" => "__builtin_ia32_pbroadcastw128_gpr_mask", + "avx512.mask.pbroadcast.w.gpr.256" => "__builtin_ia32_pbroadcastw256_gpr_mask", + "avx512.mask.pbroadcast.w.gpr.512" => "__builtin_ia32_pbroadcastw512_gpr_mask", + "avx512.mask.pcmpeq.b.128" => "__builtin_ia32_pcmpeqb128_mask", + "avx512.mask.pcmpeq.b.256" => "__builtin_ia32_pcmpeqb256_mask", + "avx512.mask.pcmpeq.b.512" => "__builtin_ia32_pcmpeqb512_mask", + "avx512.mask.pcmpeq.d.128" => "__builtin_ia32_pcmpeqd128_mask", + "avx512.mask.pcmpeq.d.256" => "__builtin_ia32_pcmpeqd256_mask", + "avx512.mask.pcmpeq.d.512" => "__builtin_ia32_pcmpeqd512_mask", + "avx512.mask.pcmpeq.q.128" => "__builtin_ia32_pcmpeqq128_mask", + "avx512.mask.pcmpeq.q.256" => "__builtin_ia32_pcmpeqq256_mask", + "avx512.mask.pcmpeq.q.512" => "__builtin_ia32_pcmpeqq512_mask", + "avx512.mask.pcmpeq.w.128" => "__builtin_ia32_pcmpeqw128_mask", + "avx512.mask.pcmpeq.w.256" => "__builtin_ia32_pcmpeqw256_mask", + "avx512.mask.pcmpeq.w.512" => "__builtin_ia32_pcmpeqw512_mask", + "avx512.mask.pcmpgt.b.128" => "__builtin_ia32_pcmpgtb128_mask", + "avx512.mask.pcmpgt.b.256" => "__builtin_ia32_pcmpgtb256_mask", + "avx512.mask.pcmpgt.b.512" => "__builtin_ia32_pcmpgtb512_mask", + "avx512.mask.pcmpgt.d.128" => "__builtin_ia32_pcmpgtd128_mask", + "avx512.mask.pcmpgt.d.256" => "__builtin_ia32_pcmpgtd256_mask", + "avx512.mask.pcmpgt.d.512" => "__builtin_ia32_pcmpgtd512_mask", + "avx512.mask.pcmpgt.q.128" => "__builtin_ia32_pcmpgtq128_mask", + "avx512.mask.pcmpgt.q.256" => "__builtin_ia32_pcmpgtq256_mask", + "avx512.mask.pcmpgt.q.512" => "__builtin_ia32_pcmpgtq512_mask", + "avx512.mask.pcmpgt.w.128" => "__builtin_ia32_pcmpgtw128_mask", + "avx512.mask.pcmpgt.w.256" => "__builtin_ia32_pcmpgtw256_mask", + "avx512.mask.pcmpgt.w.512" => "__builtin_ia32_pcmpgtw512_mask", + "avx512.mask.permvar.df.256" => "__builtin_ia32_permvardf256_mask", + "avx512.mask.permvar.df.512" => "__builtin_ia32_permvardf512_mask", + "avx512.mask.permvar.di.256" => "__builtin_ia32_permvardi256_mask", + "avx512.mask.permvar.di.512" => "__builtin_ia32_permvardi512_mask", + "avx512.mask.permvar.hi.128" => "__builtin_ia32_permvarhi128_mask", + "avx512.mask.permvar.hi.256" => "__builtin_ia32_permvarhi256_mask", + "avx512.mask.permvar.hi.512" => "__builtin_ia32_permvarhi512_mask", + "avx512.mask.permvar.qi.128" => "__builtin_ia32_permvarqi128_mask", + "avx512.mask.permvar.qi.256" => "__builtin_ia32_permvarqi256_mask", + "avx512.mask.permvar.qi.512" => "__builtin_ia32_permvarqi512_mask", + "avx512.mask.permvar.sf.256" => "__builtin_ia32_permvarsf256_mask", + "avx512.mask.permvar.sf.512" => "__builtin_ia32_permvarsf512_mask", + "avx512.mask.permvar.si.256" => "__builtin_ia32_permvarsi256_mask", + "avx512.mask.permvar.si.512" => "__builtin_ia32_permvarsi512_mask", + "avx512.mask.pmaddubs.w.128" => "__builtin_ia32_pmaddubsw128_mask", + "avx512.mask.pmaddubs.w.256" => "__builtin_ia32_pmaddubsw256_mask", + "avx512.mask.pmaddubs.w.512" => "__builtin_ia32_pmaddubsw512_mask", + "avx512.mask.pmaddw.d.128" => "__builtin_ia32_pmaddwd128_mask", + "avx512.mask.pmaddw.d.256" => "__builtin_ia32_pmaddwd256_mask", + "avx512.mask.pmaddw.d.512" => "__builtin_ia32_pmaddwd512_mask", + "avx512.mask.pmaxs.b.128" => "__builtin_ia32_pmaxsb128_mask", + "avx512.mask.pmaxs.b.256" => "__builtin_ia32_pmaxsb256_mask", + "avx512.mask.pmaxs.b.512" => "__builtin_ia32_pmaxsb512_mask", + "avx512.mask.pmaxs.d.128" => "__builtin_ia32_pmaxsd128_mask", + "avx512.mask.pmaxs.d.256" => "__builtin_ia32_pmaxsd256_mask", + "avx512.mask.pmaxs.d.512" => "__builtin_ia32_pmaxsd512_mask", + "avx512.mask.pmaxs.q.128" => "__builtin_ia32_pmaxsq128_mask", + "avx512.mask.pmaxs.q.256" => "__builtin_ia32_pmaxsq256_mask", + "avx512.mask.pmaxs.q.512" => "__builtin_ia32_pmaxsq512_mask", + "avx512.mask.pmaxs.w.128" => "__builtin_ia32_pmaxsw128_mask", + "avx512.mask.pmaxs.w.256" => "__builtin_ia32_pmaxsw256_mask", + "avx512.mask.pmaxs.w.512" => "__builtin_ia32_pmaxsw512_mask", + "avx512.mask.pmaxu.b.128" => "__builtin_ia32_pmaxub128_mask", + "avx512.mask.pmaxu.b.256" => "__builtin_ia32_pmaxub256_mask", + "avx512.mask.pmaxu.b.512" => "__builtin_ia32_pmaxub512_mask", + "avx512.mask.pmaxu.d.128" => "__builtin_ia32_pmaxud128_mask", + "avx512.mask.pmaxu.d.256" => "__builtin_ia32_pmaxud256_mask", + "avx512.mask.pmaxu.d.512" => "__builtin_ia32_pmaxud512_mask", + "avx512.mask.pmaxu.q.128" => "__builtin_ia32_pmaxuq128_mask", + "avx512.mask.pmaxu.q.256" => "__builtin_ia32_pmaxuq256_mask", + "avx512.mask.pmaxu.q.512" => "__builtin_ia32_pmaxuq512_mask", + "avx512.mask.pmaxu.w.128" => "__builtin_ia32_pmaxuw128_mask", + "avx512.mask.pmaxu.w.256" => "__builtin_ia32_pmaxuw256_mask", + "avx512.mask.pmaxu.w.512" => "__builtin_ia32_pmaxuw512_mask", + "avx512.mask.pmins.b.128" => "__builtin_ia32_pminsb128_mask", + "avx512.mask.pmins.b.256" => "__builtin_ia32_pminsb256_mask", + "avx512.mask.pmins.b.512" => "__builtin_ia32_pminsb512_mask", + "avx512.mask.pmins.d.128" => "__builtin_ia32_pminsd128_mask", + "avx512.mask.pmins.d.256" => "__builtin_ia32_pminsd256_mask", + "avx512.mask.pmins.d.512" => "__builtin_ia32_pminsd512_mask", + "avx512.mask.pmins.q.128" => "__builtin_ia32_pminsq128_mask", + "avx512.mask.pmins.q.256" => "__builtin_ia32_pminsq256_mask", + "avx512.mask.pmins.q.512" => "__builtin_ia32_pminsq512_mask", + "avx512.mask.pmins.w.128" => "__builtin_ia32_pminsw128_mask", + "avx512.mask.pmins.w.256" => "__builtin_ia32_pminsw256_mask", + "avx512.mask.pmins.w.512" => "__builtin_ia32_pminsw512_mask", + "avx512.mask.pminu.b.128" => "__builtin_ia32_pminub128_mask", + "avx512.mask.pminu.b.256" => "__builtin_ia32_pminub256_mask", + "avx512.mask.pminu.b.512" => "__builtin_ia32_pminub512_mask", + "avx512.mask.pminu.d.128" => "__builtin_ia32_pminud128_mask", + "avx512.mask.pminu.d.256" => "__builtin_ia32_pminud256_mask", + "avx512.mask.pminu.d.512" => "__builtin_ia32_pminud512_mask", + "avx512.mask.pminu.q.128" => "__builtin_ia32_pminuq128_mask", + "avx512.mask.pminu.q.256" => "__builtin_ia32_pminuq256_mask", + "avx512.mask.pminu.q.512" => "__builtin_ia32_pminuq512_mask", + "avx512.mask.pminu.w.128" => "__builtin_ia32_pminuw128_mask", + "avx512.mask.pminu.w.256" => "__builtin_ia32_pminuw256_mask", + "avx512.mask.pminu.w.512" => "__builtin_ia32_pminuw512_mask", + "avx512.mask.pmov.db.512" => "__builtin_ia32_pmovdb512_mask", + "avx512.mask.pmov.dw.512" => "__builtin_ia32_pmovdw512_mask", + "avx512.mask.pmov.qd.256" => "__builtin_ia32_pmovqd256_mask", + "avx512.mask.pmov.qd.512" => "__builtin_ia32_pmovqd512_mask", + "avx512.mask.pmov.qw.512" => "__builtin_ia32_pmovqw512_mask", + "avx512.mask.pmov.wb.256" => "__builtin_ia32_pmovwb256_mask", + "avx512.mask.pmov.wb.512" => "__builtin_ia32_pmovwb512_mask", + "avx512.mask.pmovsxb.d.128" => "__builtin_ia32_pmovsxbd128_mask", + "avx512.mask.pmovsxb.d.256" => "__builtin_ia32_pmovsxbd256_mask", + "avx512.mask.pmovsxb.d.512" => "__builtin_ia32_pmovsxbd512_mask", + "avx512.mask.pmovsxb.q.128" => "__builtin_ia32_pmovsxbq128_mask", + "avx512.mask.pmovsxb.q.256" => "__builtin_ia32_pmovsxbq256_mask", + "avx512.mask.pmovsxb.q.512" => "__builtin_ia32_pmovsxbq512_mask", + "avx512.mask.pmovsxb.w.128" => "__builtin_ia32_pmovsxbw128_mask", + "avx512.mask.pmovsxb.w.256" => "__builtin_ia32_pmovsxbw256_mask", + "avx512.mask.pmovsxb.w.512" => "__builtin_ia32_pmovsxbw512_mask", + "avx512.mask.pmovsxd.q.128" => "__builtin_ia32_pmovsxdq128_mask", + "avx512.mask.pmovsxd.q.256" => "__builtin_ia32_pmovsxdq256_mask", + "avx512.mask.pmovsxd.q.512" => "__builtin_ia32_pmovsxdq512_mask", + "avx512.mask.pmovsxw.d.128" => "__builtin_ia32_pmovsxwd128_mask", + "avx512.mask.pmovsxw.d.256" => "__builtin_ia32_pmovsxwd256_mask", + "avx512.mask.pmovsxw.d.512" => "__builtin_ia32_pmovsxwd512_mask", + "avx512.mask.pmovsxw.q.128" => "__builtin_ia32_pmovsxwq128_mask", + "avx512.mask.pmovsxw.q.256" => "__builtin_ia32_pmovsxwq256_mask", + "avx512.mask.pmovsxw.q.512" => "__builtin_ia32_pmovsxwq512_mask", + "avx512.mask.pmovzxb.d.128" => "__builtin_ia32_pmovzxbd128_mask", + "avx512.mask.pmovzxb.d.256" => "__builtin_ia32_pmovzxbd256_mask", + "avx512.mask.pmovzxb.d.512" => "__builtin_ia32_pmovzxbd512_mask", + "avx512.mask.pmovzxb.q.128" => "__builtin_ia32_pmovzxbq128_mask", + "avx512.mask.pmovzxb.q.256" => "__builtin_ia32_pmovzxbq256_mask", + "avx512.mask.pmovzxb.q.512" => "__builtin_ia32_pmovzxbq512_mask", + "avx512.mask.pmovzxb.w.128" => "__builtin_ia32_pmovzxbw128_mask", + "avx512.mask.pmovzxb.w.256" => "__builtin_ia32_pmovzxbw256_mask", + "avx512.mask.pmovzxb.w.512" => "__builtin_ia32_pmovzxbw512_mask", + "avx512.mask.pmovzxd.q.128" => "__builtin_ia32_pmovzxdq128_mask", + "avx512.mask.pmovzxd.q.256" => "__builtin_ia32_pmovzxdq256_mask", + "avx512.mask.pmovzxd.q.512" => "__builtin_ia32_pmovzxdq512_mask", + "avx512.mask.pmovzxw.d.128" => "__builtin_ia32_pmovzxwd128_mask", + "avx512.mask.pmovzxw.d.256" => "__builtin_ia32_pmovzxwd256_mask", + "avx512.mask.pmovzxw.d.512" => "__builtin_ia32_pmovzxwd512_mask", + "avx512.mask.pmovzxw.q.128" => "__builtin_ia32_pmovzxwq128_mask", + "avx512.mask.pmovzxw.q.256" => "__builtin_ia32_pmovzxwq256_mask", + "avx512.mask.pmovzxw.q.512" => "__builtin_ia32_pmovzxwq512_mask", + "avx512.mask.pmul.dq.128" => "__builtin_ia32_pmuldq128_mask", + "avx512.mask.pmul.dq.256" => "__builtin_ia32_pmuldq256_mask", + "avx512.mask.pmul.dq.512" => "__builtin_ia32_pmuldq512_mask", + "avx512.mask.pmul.hr.sw.128" => "__builtin_ia32_pmulhrsw128_mask", + "avx512.mask.pmul.hr.sw.256" => "__builtin_ia32_pmulhrsw256_mask", + "avx512.mask.pmul.hr.sw.512" => "__builtin_ia32_pmulhrsw512_mask", + "avx512.mask.pmulh.w.128" => "__builtin_ia32_pmulhw128_mask", + "avx512.mask.pmulh.w.256" => "__builtin_ia32_pmulhw256_mask", + "avx512.mask.pmulh.w.512" => "__builtin_ia32_pmulhw512_mask", + "avx512.mask.pmulhu.w.128" => "__builtin_ia32_pmulhuw128_mask", + "avx512.mask.pmulhu.w.256" => "__builtin_ia32_pmulhuw256_mask", + "avx512.mask.pmulhu.w.512" => "__builtin_ia32_pmulhuw512_mask", + "avx512.mask.pmull.d.128" => "__builtin_ia32_pmulld128_mask", + "avx512.mask.pmull.d.256" => "__builtin_ia32_pmulld256_mask", + "avx512.mask.pmull.d.512" => "__builtin_ia32_pmulld512_mask", + "avx512.mask.pmull.q.128" => "__builtin_ia32_pmullq128_mask", + "avx512.mask.pmull.q.256" => "__builtin_ia32_pmullq256_mask", + "avx512.mask.pmull.q.512" => "__builtin_ia32_pmullq512_mask", + "avx512.mask.pmull.w.128" => "__builtin_ia32_pmullw128_mask", + "avx512.mask.pmull.w.256" => "__builtin_ia32_pmullw256_mask", + "avx512.mask.pmull.w.512" => "__builtin_ia32_pmullw512_mask", + "avx512.mask.pmultishift.qb.128" => "__builtin_ia32_vpmultishiftqb128_mask", + "avx512.mask.pmultishift.qb.256" => "__builtin_ia32_vpmultishiftqb256_mask", + "avx512.mask.pmultishift.qb.512" => "__builtin_ia32_vpmultishiftqb512_mask", + "avx512.mask.pmulu.dq.128" => "__builtin_ia32_pmuludq128_mask", + "avx512.mask.pmulu.dq.256" => "__builtin_ia32_pmuludq256_mask", + "avx512.mask.pmulu.dq.512" => "__builtin_ia32_pmuludq512_mask", + "avx512.mask.prol.d.128" => "__builtin_ia32_prold128_mask", + "avx512.mask.prol.d.256" => "__builtin_ia32_prold256_mask", + "avx512.mask.prol.d.512" => "__builtin_ia32_prold512_mask", + "avx512.mask.prol.q.128" => "__builtin_ia32_prolq128_mask", + "avx512.mask.prol.q.256" => "__builtin_ia32_prolq256_mask", + "avx512.mask.prol.q.512" => "__builtin_ia32_prolq512_mask", + "avx512.mask.prolv.d.128" => "__builtin_ia32_prolvd128_mask", + "avx512.mask.prolv.d.256" => "__builtin_ia32_prolvd256_mask", + "avx512.mask.prolv.d.512" => "__builtin_ia32_prolvd512_mask", + "avx512.mask.prolv.q.128" => "__builtin_ia32_prolvq128_mask", + "avx512.mask.prolv.q.256" => "__builtin_ia32_prolvq256_mask", + "avx512.mask.prolv.q.512" => "__builtin_ia32_prolvq512_mask", + "avx512.mask.pror.d.128" => "__builtin_ia32_prord128_mask", + "avx512.mask.pror.d.256" => "__builtin_ia32_prord256_mask", + "avx512.mask.pror.d.512" => "__builtin_ia32_prord512_mask", + "avx512.mask.pror.q.128" => "__builtin_ia32_prorq128_mask", + "avx512.mask.pror.q.256" => "__builtin_ia32_prorq256_mask", + "avx512.mask.pror.q.512" => "__builtin_ia32_prorq512_mask", + "avx512.mask.prorv.d.128" => "__builtin_ia32_prorvd128_mask", + "avx512.mask.prorv.d.256" => "__builtin_ia32_prorvd256_mask", + "avx512.mask.prorv.d.512" => "__builtin_ia32_prorvd512_mask", + "avx512.mask.prorv.q.128" => "__builtin_ia32_prorvq128_mask", + "avx512.mask.prorv.q.256" => "__builtin_ia32_prorvq256_mask", + "avx512.mask.prorv.q.512" => "__builtin_ia32_prorvq512_mask", + "avx512.mask.pshuf.b.128" => "__builtin_ia32_pshufb128_mask", + "avx512.mask.pshuf.b.256" => "__builtin_ia32_pshufb256_mask", + "avx512.mask.pshuf.b.512" => "__builtin_ia32_pshufb512_mask", + "avx512.mask.psll.d" => "__builtin_ia32_pslld512_mask", + "avx512.mask.psll.d.128" => "__builtin_ia32_pslld128_mask", + "avx512.mask.psll.d.256" => "__builtin_ia32_pslld256_mask", + "avx512.mask.psll.di.128" => "__builtin_ia32_pslldi128_mask", + "avx512.mask.psll.di.256" => "__builtin_ia32_pslldi256_mask", + "avx512.mask.psll.di.512" => "__builtin_ia32_pslldi512_mask", + "avx512.mask.psll.q" => "__builtin_ia32_psllq512_mask", + "avx512.mask.psll.q.128" => "__builtin_ia32_psllq128_mask", + "avx512.mask.psll.q.256" => "__builtin_ia32_psllq256_mask", + "avx512.mask.psll.qi.128" => "__builtin_ia32_psllqi128_mask", + "avx512.mask.psll.qi.256" => "__builtin_ia32_psllqi256_mask", + "avx512.mask.psll.qi.512" => "__builtin_ia32_psllqi512_mask", + "avx512.mask.psll.w.128" => "__builtin_ia32_psllw128_mask", + "avx512.mask.psll.w.256" => "__builtin_ia32_psllw256_mask", + "avx512.mask.psll.w.512" => "__builtin_ia32_psllw512_mask", + "avx512.mask.psll.wi.128" => "__builtin_ia32_psllwi128_mask", + "avx512.mask.psll.wi.256" => "__builtin_ia32_psllwi256_mask", + "avx512.mask.psll.wi.512" => "__builtin_ia32_psllwi512_mask", + "avx512.mask.psllv.d" => "__builtin_ia32_psllv16si_mask", + "avx512.mask.psllv.q" => "__builtin_ia32_psllv8di_mask", + "avx512.mask.psllv16.hi" => "__builtin_ia32_psllv16hi_mask", + "avx512.mask.psllv2.di" => "__builtin_ia32_psllv2di_mask", + "avx512.mask.psllv32hi" => "__builtin_ia32_psllv32hi_mask", + "avx512.mask.psllv4.di" => "__builtin_ia32_psllv4di_mask", + "avx512.mask.psllv4.si" => "__builtin_ia32_psllv4si_mask", + "avx512.mask.psllv8.hi" => "__builtin_ia32_psllv8hi_mask", + "avx512.mask.psllv8.si" => "__builtin_ia32_psllv8si_mask", + "avx512.mask.psra.d" => "__builtin_ia32_psrad512_mask", + "avx512.mask.psra.d.128" => "__builtin_ia32_psrad128_mask", + "avx512.mask.psra.d.256" => "__builtin_ia32_psrad256_mask", + "avx512.mask.psra.di.128" => "__builtin_ia32_psradi128_mask", + "avx512.mask.psra.di.256" => "__builtin_ia32_psradi256_mask", + "avx512.mask.psra.di.512" => "__builtin_ia32_psradi512_mask", + "avx512.mask.psra.q" => "__builtin_ia32_psraq512_mask", + "avx512.mask.psra.q.128" => "__builtin_ia32_psraq128_mask", + "avx512.mask.psra.q.256" => "__builtin_ia32_psraq256_mask", + "avx512.mask.psra.qi.128" => "__builtin_ia32_psraqi128_mask", + "avx512.mask.psra.qi.256" => "__builtin_ia32_psraqi256_mask", + "avx512.mask.psra.qi.512" => "__builtin_ia32_psraqi512_mask", + "avx512.mask.psra.w.128" => "__builtin_ia32_psraw128_mask", + "avx512.mask.psra.w.256" => "__builtin_ia32_psraw256_mask", + "avx512.mask.psra.w.512" => "__builtin_ia32_psraw512_mask", + "avx512.mask.psra.wi.128" => "__builtin_ia32_psrawi128_mask", + "avx512.mask.psra.wi.256" => "__builtin_ia32_psrawi256_mask", + "avx512.mask.psra.wi.512" => "__builtin_ia32_psrawi512_mask", + "avx512.mask.psrav.d" => "__builtin_ia32_psrav16si_mask", + "avx512.mask.psrav.q" => "__builtin_ia32_psrav8di_mask", + "avx512.mask.psrav.q.128" => "__builtin_ia32_psravq128_mask", + "avx512.mask.psrav.q.256" => "__builtin_ia32_psravq256_mask", + "avx512.mask.psrav16.hi" => "__builtin_ia32_psrav16hi_mask", + "avx512.mask.psrav32.hi" => "__builtin_ia32_psrav32hi_mask", + "avx512.mask.psrav4.si" => "__builtin_ia32_psrav4si_mask", + "avx512.mask.psrav8.hi" => "__builtin_ia32_psrav8hi_mask", + "avx512.mask.psrav8.si" => "__builtin_ia32_psrav8si_mask", + "avx512.mask.psrl.d" => "__builtin_ia32_psrld512_mask", + "avx512.mask.psrl.d.128" => "__builtin_ia32_psrld128_mask", + "avx512.mask.psrl.d.256" => "__builtin_ia32_psrld256_mask", + "avx512.mask.psrl.di.128" => "__builtin_ia32_psrldi128_mask", + "avx512.mask.psrl.di.256" => "__builtin_ia32_psrldi256_mask", + "avx512.mask.psrl.di.512" => "__builtin_ia32_psrldi512_mask", + "avx512.mask.psrl.q" => "__builtin_ia32_psrlq512_mask", + "avx512.mask.psrl.q.128" => "__builtin_ia32_psrlq128_mask", + "avx512.mask.psrl.q.256" => "__builtin_ia32_psrlq256_mask", + "avx512.mask.psrl.qi.128" => "__builtin_ia32_psrlqi128_mask", + "avx512.mask.psrl.qi.256" => "__builtin_ia32_psrlqi256_mask", + "avx512.mask.psrl.qi.512" => "__builtin_ia32_psrlqi512_mask", + "avx512.mask.psrl.w.128" => "__builtin_ia32_psrlw128_mask", + "avx512.mask.psrl.w.256" => "__builtin_ia32_psrlw256_mask", + "avx512.mask.psrl.w.512" => "__builtin_ia32_psrlw512_mask", + "avx512.mask.psrl.wi.128" => "__builtin_ia32_psrlwi128_mask", + "avx512.mask.psrl.wi.256" => "__builtin_ia32_psrlwi256_mask", + "avx512.mask.psrl.wi.512" => "__builtin_ia32_psrlwi512_mask", + "avx512.mask.psrlv.d" => "__builtin_ia32_psrlv16si_mask", + "avx512.mask.psrlv.q" => "__builtin_ia32_psrlv8di_mask", + "avx512.mask.psrlv16.hi" => "__builtin_ia32_psrlv16hi_mask", + "avx512.mask.psrlv2.di" => "__builtin_ia32_psrlv2di_mask", + "avx512.mask.psrlv32hi" => "__builtin_ia32_psrlv32hi_mask", + "avx512.mask.psrlv4.di" => "__builtin_ia32_psrlv4di_mask", + "avx512.mask.psrlv4.si" => "__builtin_ia32_psrlv4si_mask", + "avx512.mask.psrlv8.hi" => "__builtin_ia32_psrlv8hi_mask", + "avx512.mask.psrlv8.si" => "__builtin_ia32_psrlv8si_mask", + "avx512.mask.psub.b.128" => "__builtin_ia32_psubb128_mask", + "avx512.mask.psub.b.256" => "__builtin_ia32_psubb256_mask", + "avx512.mask.psub.b.512" => "__builtin_ia32_psubb512_mask", + "avx512.mask.psub.d.128" => "__builtin_ia32_psubd128_mask", + "avx512.mask.psub.d.256" => "__builtin_ia32_psubd256_mask", + "avx512.mask.psub.d.512" => "__builtin_ia32_psubd512_mask", + "avx512.mask.psub.q.128" => "__builtin_ia32_psubq128_mask", + "avx512.mask.psub.q.256" => "__builtin_ia32_psubq256_mask", + "avx512.mask.psub.q.512" => "__builtin_ia32_psubq512_mask", + "avx512.mask.psub.w.128" => "__builtin_ia32_psubw128_mask", + "avx512.mask.psub.w.256" => "__builtin_ia32_psubw256_mask", + "avx512.mask.psub.w.512" => "__builtin_ia32_psubw512_mask", + "avx512.mask.psubs.b.128" => "__builtin_ia32_psubsb128_mask", + "avx512.mask.psubs.b.256" => "__builtin_ia32_psubsb256_mask", + "avx512.mask.psubs.b.512" => "__builtin_ia32_psubsb512_mask", + "avx512.mask.psubs.w.128" => "__builtin_ia32_psubsw128_mask", + "avx512.mask.psubs.w.256" => "__builtin_ia32_psubsw256_mask", + "avx512.mask.psubs.w.512" => "__builtin_ia32_psubsw512_mask", + "avx512.mask.psubus.b.128" => "__builtin_ia32_psubusb128_mask", + "avx512.mask.psubus.b.256" => "__builtin_ia32_psubusb256_mask", + "avx512.mask.psubus.b.512" => "__builtin_ia32_psubusb512_mask", + "avx512.mask.psubus.w.128" => "__builtin_ia32_psubusw128_mask", + "avx512.mask.psubus.w.256" => "__builtin_ia32_psubusw256_mask", + "avx512.mask.psubus.w.512" => "__builtin_ia32_psubusw512_mask", + "avx512.mask.pternlog.d.128" => "__builtin_ia32_pternlogd128_mask", + "avx512.mask.pternlog.d.256" => "__builtin_ia32_pternlogd256_mask", + "avx512.mask.pternlog.d.512" => "__builtin_ia32_pternlogd512_mask", + "avx512.mask.pternlog.q.128" => "__builtin_ia32_pternlogq128_mask", + "avx512.mask.pternlog.q.256" => "__builtin_ia32_pternlogq256_mask", + "avx512.mask.pternlog.q.512" => "__builtin_ia32_pternlogq512_mask", + "avx512.mask.ptestm.d.512" => "__builtin_ia32_ptestmd512", + "avx512.mask.ptestm.q.512" => "__builtin_ia32_ptestmq512", + "avx512.mask.shuf.f32x4" => "__builtin_ia32_shuf_f32x4_mask", + "avx512.mask.shuf.f32x4.256" => "__builtin_ia32_shuf_f32x4_256_mask", + "avx512.mask.shuf.f64x2" => "__builtin_ia32_shuf_f64x2_mask", + "avx512.mask.shuf.f64x2.256" => "__builtin_ia32_shuf_f64x2_256_mask", + "avx512.mask.shuf.i32x4" => "__builtin_ia32_shuf_i32x4_mask", + "avx512.mask.shuf.i32x4.256" => "__builtin_ia32_shuf_i32x4_256_mask", + "avx512.mask.shuf.i64x2" => "__builtin_ia32_shuf_i64x2_mask", + "avx512.mask.shuf.i64x2.256" => "__builtin_ia32_shuf_i64x2_256_mask", + "avx512.mask.shuf.pd.128" => "__builtin_ia32_shufpd128_mask", + "avx512.mask.shuf.pd.256" => "__builtin_ia32_shufpd256_mask", + "avx512.mask.shuf.pd.512" => "__builtin_ia32_shufpd512_mask", + "avx512.mask.shuf.ps.128" => "__builtin_ia32_shufps128_mask", + "avx512.mask.shuf.ps.256" => "__builtin_ia32_shufps256_mask", + "avx512.mask.shuf.ps.512" => "__builtin_ia32_shufps512_mask", + "avx512.mask.sqrt.pd.128" => "__builtin_ia32_sqrtpd128_mask", + "avx512.mask.sqrt.pd.256" => "__builtin_ia32_sqrtpd256_mask", + "avx512.mask.sqrt.pd.512" => "__builtin_ia32_sqrtpd512_mask", + "avx512.mask.sqrt.ps.128" => "__builtin_ia32_sqrtps128_mask", + "avx512.mask.sqrt.ps.256" => "__builtin_ia32_sqrtps256_mask", + "avx512.mask.sqrt.ps.512" => "__builtin_ia32_sqrtps512_mask", + "avx512.mask.store.ss" => "__builtin_ia32_storess_mask", + "avx512.mask.storeu.d.512" => "__builtin_ia32_storedqusi512_mask", + "avx512.mask.storeu.pd.512" => "__builtin_ia32_storeupd512_mask", + "avx512.mask.storeu.ps.512" => "__builtin_ia32_storeups512_mask", + "avx512.mask.storeu.q.512" => "__builtin_ia32_storedqudi512_mask", + "avx512.mask.sub.pd.128" => "__builtin_ia32_subpd128_mask", + "avx512.mask.sub.pd.256" => "__builtin_ia32_subpd256_mask", + "avx512.mask.sub.pd.512" => "__builtin_ia32_subpd512_mask", + "avx512.mask.sub.ps.128" => "__builtin_ia32_subps128_mask", + "avx512.mask.sub.ps.256" => "__builtin_ia32_subps256_mask", + "avx512.mask.sub.ps.512" => "__builtin_ia32_subps512_mask", + "avx512.mask.valign.d.128" => "__builtin_ia32_alignd128_mask", + "avx512.mask.valign.d.256" => "__builtin_ia32_alignd256_mask", + "avx512.mask.valign.d.512" => "__builtin_ia32_alignd512_mask", + "avx512.mask.valign.q.128" => "__builtin_ia32_alignq128_mask", + "avx512.mask.valign.q.256" => "__builtin_ia32_alignq256_mask", + "avx512.mask.valign.q.512" => "__builtin_ia32_alignq512_mask", + "avx512.mask.vcvtph2ps.128" => "__builtin_ia32_vcvtph2ps_mask", + "avx512.mask.vcvtph2ps.256" => "__builtin_ia32_vcvtph2ps256_mask", + "avx512.mask.vcvtph2ps.512" => "__builtin_ia32_vcvtph2ps512_mask", + "avx512.mask.vextractf32x4.256" => "__builtin_ia32_extractf32x4_256_mask", + "avx512.mask.vextractf32x4.512" => "__builtin_ia32_extractf32x4_mask", + "avx512.mask.vextractf32x8.512" => "__builtin_ia32_extractf32x8_mask", + "avx512.mask.vextractf64x2.256" => "__builtin_ia32_extractf64x2_256_mask", + "avx512.mask.vextractf64x2.512" => "__builtin_ia32_extractf64x2_512_mask", + "avx512.mask.vextractf64x4.512" => "__builtin_ia32_extractf64x4_mask", + "avx512.mask.vextracti32x4.256" => "__builtin_ia32_extracti32x4_256_mask", + "avx512.mask.vextracti32x4.512" => "__builtin_ia32_extracti32x4_mask", + "avx512.mask.vextracti32x8.512" => "__builtin_ia32_extracti32x8_mask", + "avx512.mask.vextracti64x2.256" => "__builtin_ia32_extracti64x2_256_mask", + "avx512.mask.vextracti64x2.512" => "__builtin_ia32_extracti64x2_512_mask", + "avx512.mask.vextracti64x4.512" => "__builtin_ia32_extracti64x4_mask", + "avx512.mask.vfmadd.pd.128" => "__builtin_ia32_vfmaddpd128_mask", + "avx512.mask.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256_mask", + "avx512.mask.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask", + "avx512.mask.vfmadd.ps.128" => "__builtin_ia32_vfmaddps128_mask", + "avx512.mask.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256_mask", + "avx512.mask.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask", + "avx512.mask.vfmadd.sd" => "__builtin_ia32_vfmaddsd3_mask", + "avx512.mask.vfmadd.ss" => "__builtin_ia32_vfmaddss3_mask", + "avx512.mask.vfmaddsub.pd.128" => "__builtin_ia32_vfmaddsubpd128_mask", + "avx512.mask.vfmaddsub.pd.256" => "__builtin_ia32_vfmaddsubpd256_mask", + "avx512.mask.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask", + "avx512.mask.vfmaddsub.ps.128" => "__builtin_ia32_vfmaddsubps128_mask", + "avx512.mask.vfmaddsub.ps.256" => "__builtin_ia32_vfmaddsubps256_mask", + "avx512.mask.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_mask", + "avx512.mask.vfnmadd.pd.128" => "__builtin_ia32_vfnmaddpd128_mask", + "avx512.mask.vfnmadd.pd.256" => "__builtin_ia32_vfnmaddpd256_mask", + "avx512.mask.vfnmadd.pd.512" => "__builtin_ia32_vfnmaddpd512_mask", + "avx512.mask.vfnmadd.ps.128" => "__builtin_ia32_vfnmaddps128_mask", + "avx512.mask.vfnmadd.ps.256" => "__builtin_ia32_vfnmaddps256_mask", + "avx512.mask.vfnmadd.ps.512" => "__builtin_ia32_vfnmaddps512_mask", + "avx512.mask.vfnmsub.pd.128" => "__builtin_ia32_vfnmsubpd128_mask", + "avx512.mask.vfnmsub.pd.256" => "__builtin_ia32_vfnmsubpd256_mask", + "avx512.mask.vfnmsub.pd.512" => "__builtin_ia32_vfnmsubpd512_mask", + "avx512.mask.vfnmsub.ps.128" => "__builtin_ia32_vfnmsubps128_mask", + "avx512.mask.vfnmsub.ps.256" => "__builtin_ia32_vfnmsubps256_mask", + "avx512.mask.vfnmsub.ps.512" => "__builtin_ia32_vfnmsubps512_mask", + "avx512.mask.vpermi2var.d.128" => "__builtin_ia32_vpermi2vard128_mask", + "avx512.mask.vpermi2var.d.256" => "__builtin_ia32_vpermi2vard256_mask", + "avx512.mask.vpermi2var.d.512" => "__builtin_ia32_vpermi2vard512_mask", + "avx512.mask.vpermi2var.hi.128" => "__builtin_ia32_vpermi2varhi128_mask", + "avx512.mask.vpermi2var.hi.256" => "__builtin_ia32_vpermi2varhi256_mask", + "avx512.mask.vpermi2var.hi.512" => "__builtin_ia32_vpermi2varhi512_mask", + "avx512.mask.vpermi2var.pd.128" => "__builtin_ia32_vpermi2varpd128_mask", + "avx512.mask.vpermi2var.pd.256" => "__builtin_ia32_vpermi2varpd256_mask", + "avx512.mask.vpermi2var.pd.512" => "__builtin_ia32_vpermi2varpd512_mask", + "avx512.mask.vpermi2var.ps.128" => "__builtin_ia32_vpermi2varps128_mask", + "avx512.mask.vpermi2var.ps.256" => "__builtin_ia32_vpermi2varps256_mask", + "avx512.mask.vpermi2var.ps.512" => "__builtin_ia32_vpermi2varps512_mask", + "avx512.mask.vpermi2var.q.128" => "__builtin_ia32_vpermi2varq128_mask", + "avx512.mask.vpermi2var.q.256" => "__builtin_ia32_vpermi2varq256_mask", + "avx512.mask.vpermi2var.q.512" => "__builtin_ia32_vpermi2varq512_mask", + "avx512.mask.vpermi2var.qi.128" => "__builtin_ia32_vpermi2varqi128_mask", + "avx512.mask.vpermi2var.qi.256" => "__builtin_ia32_vpermi2varqi256_mask", + "avx512.mask.vpermi2var.qi.512" => "__builtin_ia32_vpermi2varqi512_mask", + "avx512.mask.vpermilvar.pd.128" => "__builtin_ia32_vpermilvarpd_mask", + "avx512.mask.vpermilvar.pd.256" => "__builtin_ia32_vpermilvarpd256_mask", + "avx512.mask.vpermilvar.pd.512" => "__builtin_ia32_vpermilvarpd512_mask", + "avx512.mask.vpermilvar.ps.128" => "__builtin_ia32_vpermilvarps_mask", + "avx512.mask.vpermilvar.ps.256" => "__builtin_ia32_vpermilvarps256_mask", + "avx512.mask.vpermilvar.ps.512" => "__builtin_ia32_vpermilvarps512_mask", + "avx512.mask.vpermt.d.512" => "__builtin_ia32_vpermt2vard512_mask", + "avx512.mask.vpermt.pd.512" => "__builtin_ia32_vpermt2varpd512_mask", + "avx512.mask.vpermt.ps.512" => "__builtin_ia32_vpermt2varps512_mask", + "avx512.mask.vpermt.q.512" => "__builtin_ia32_vpermt2varq512_mask", + "avx512.mask.vpermt2var.d.128" => "__builtin_ia32_vpermt2vard128_mask", + "avx512.mask.vpermt2var.d.256" => "__builtin_ia32_vpermt2vard256_mask", + "avx512.mask.vpermt2var.d.512" => "__builtin_ia32_vpermt2vard512_mask", + "avx512.mask.vpermt2var.hi.128" => "__builtin_ia32_vpermt2varhi128_mask", + "avx512.mask.vpermt2var.hi.256" => "__builtin_ia32_vpermt2varhi256_mask", + "avx512.mask.vpermt2var.hi.512" => "__builtin_ia32_vpermt2varhi512_mask", + "avx512.mask.vpermt2var.pd.128" => "__builtin_ia32_vpermt2varpd128_mask", + "avx512.mask.vpermt2var.pd.256" => "__builtin_ia32_vpermt2varpd256_mask", + "avx512.mask.vpermt2var.pd.512" => "__builtin_ia32_vpermt2varpd512_mask", + "avx512.mask.vpermt2var.ps.128" => "__builtin_ia32_vpermt2varps128_mask", + "avx512.mask.vpermt2var.ps.256" => "__builtin_ia32_vpermt2varps256_mask", + "avx512.mask.vpermt2var.ps.512" => "__builtin_ia32_vpermt2varps512_mask", + "avx512.mask.vpermt2var.q.128" => "__builtin_ia32_vpermt2varq128_mask", + "avx512.mask.vpermt2var.q.256" => "__builtin_ia32_vpermt2varq256_mask", + "avx512.mask.vpermt2var.q.512" => "__builtin_ia32_vpermt2varq512_mask", + "avx512.mask.vpermt2var.qi.128" => "__builtin_ia32_vpermt2varqi128_mask", + "avx512.mask.vpermt2var.qi.256" => "__builtin_ia32_vpermt2varqi256_mask", + "avx512.mask.vpermt2var.qi.512" => "__builtin_ia32_vpermt2varqi512_mask", + "avx512.mask.vpmadd52h.uq.128" => "__builtin_ia32_vpmadd52huq128_mask", + "avx512.mask.vpmadd52h.uq.256" => "__builtin_ia32_vpmadd52huq256_mask", + "avx512.mask.vpmadd52h.uq.512" => "__builtin_ia32_vpmadd52huq512_mask", + "avx512.mask.vpmadd52l.uq.128" => "__builtin_ia32_vpmadd52luq128_mask", + "avx512.mask.vpmadd52l.uq.256" => "__builtin_ia32_vpmadd52luq256_mask", + "avx512.mask.vpmadd52l.uq.512" => "__builtin_ia32_vpmadd52luq512_mask", + "avx512.mask.xor.pd.128" => "__builtin_ia32_xorpd128_mask", + "avx512.mask.xor.pd.256" => "__builtin_ia32_xorpd256_mask", + "avx512.mask.xor.pd.512" => "__builtin_ia32_xorpd512_mask", + "avx512.mask.xor.ps.128" => "__builtin_ia32_xorps128_mask", + "avx512.mask.xor.ps.256" => "__builtin_ia32_xorps256_mask", + "avx512.mask.xor.ps.512" => "__builtin_ia32_xorps512_mask", + "avx512.mask3.vfmadd.pd.128" => "__builtin_ia32_vfmaddpd128_mask3", + "avx512.mask3.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256_mask3", + "avx512.mask3.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask3", + "avx512.mask3.vfmadd.ps.128" => "__builtin_ia32_vfmaddps128_mask3", + "avx512.mask3.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256_mask3", + "avx512.mask3.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask3", + "avx512.mask3.vfmadd.sd" => "__builtin_ia32_vfmaddsd3_mask3", + "avx512.mask3.vfmadd.ss" => "__builtin_ia32_vfmaddss3_mask3", + "avx512.mask3.vfmaddsub.pd.128" => "__builtin_ia32_vfmaddsubpd128_mask3", + "avx512.mask3.vfmaddsub.pd.256" => "__builtin_ia32_vfmaddsubpd256_mask3", + "avx512.mask3.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask3", + "avx512.mask3.vfmaddsub.ps.128" => "__builtin_ia32_vfmaddsubps128_mask3", + "avx512.mask3.vfmaddsub.ps.256" => "__builtin_ia32_vfmaddsubps256_mask3", + "avx512.mask3.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_mask3", + "avx512.mask3.vfmsub.pd.128" => "__builtin_ia32_vfmsubpd128_mask3", + "avx512.mask3.vfmsub.pd.256" => "__builtin_ia32_vfmsubpd256_mask3", + "avx512.mask3.vfmsub.pd.512" => "__builtin_ia32_vfmsubpd512_mask3", + "avx512.mask3.vfmsub.ps.128" => "__builtin_ia32_vfmsubps128_mask3", + "avx512.mask3.vfmsub.ps.256" => "__builtin_ia32_vfmsubps256_mask3", + "avx512.mask3.vfmsub.ps.512" => "__builtin_ia32_vfmsubps512_mask3", + "avx512.mask3.vfmsubadd.pd.128" => "__builtin_ia32_vfmsubaddpd128_mask3", + "avx512.mask3.vfmsubadd.pd.256" => "__builtin_ia32_vfmsubaddpd256_mask3", + "avx512.mask3.vfmsubadd.pd.512" => "__builtin_ia32_vfmsubaddpd512_mask3", + "avx512.mask3.vfmsubadd.ps.128" => "__builtin_ia32_vfmsubaddps128_mask3", + "avx512.mask3.vfmsubadd.ps.256" => "__builtin_ia32_vfmsubaddps256_mask3", + "avx512.mask3.vfmsubadd.ps.512" => "__builtin_ia32_vfmsubaddps512_mask3", + "avx512.mask3.vfnmsub.pd.128" => "__builtin_ia32_vfnmsubpd128_mask3", + "avx512.mask3.vfnmsub.pd.256" => "__builtin_ia32_vfnmsubpd256_mask3", + "avx512.mask3.vfnmsub.pd.512" => "__builtin_ia32_vfnmsubpd512_mask3", + "avx512.mask3.vfnmsub.ps.128" => "__builtin_ia32_vfnmsubps128_mask3", + "avx512.mask3.vfnmsub.ps.256" => "__builtin_ia32_vfnmsubps256_mask3", + "avx512.mask3.vfnmsub.ps.512" => "__builtin_ia32_vfnmsubps512_mask3", + "avx512.maskz.pternlog.d.128" => "__builtin_ia32_pternlogd128_maskz", + "avx512.maskz.pternlog.d.256" => "__builtin_ia32_pternlogd256_maskz", + "avx512.maskz.pternlog.d.512" => "__builtin_ia32_pternlogd512_maskz", + "avx512.maskz.pternlog.q.128" => "__builtin_ia32_pternlogq128_maskz", + "avx512.maskz.pternlog.q.256" => "__builtin_ia32_pternlogq256_maskz", + "avx512.maskz.pternlog.q.512" => "__builtin_ia32_pternlogq512_maskz", + "avx512.maskz.vfmadd.pd.128" => "__builtin_ia32_vfmaddpd128_maskz", + "avx512.maskz.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256_maskz", + "avx512.maskz.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_maskz", + "avx512.maskz.vfmadd.ps.128" => "__builtin_ia32_vfmaddps128_maskz", + "avx512.maskz.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256_maskz", + "avx512.maskz.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_maskz", + "avx512.maskz.vfmadd.sd" => "__builtin_ia32_vfmaddsd3_maskz", + "avx512.maskz.vfmadd.ss" => "__builtin_ia32_vfmaddss3_maskz", + "avx512.maskz.vfmaddsub.pd.128" => "__builtin_ia32_vfmaddsubpd128_maskz", + "avx512.maskz.vfmaddsub.pd.256" => "__builtin_ia32_vfmaddsubpd256_maskz", + "avx512.maskz.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_maskz", + "avx512.maskz.vfmaddsub.ps.128" => "__builtin_ia32_vfmaddsubps128_maskz", + "avx512.maskz.vfmaddsub.ps.256" => "__builtin_ia32_vfmaddsubps256_maskz", + "avx512.maskz.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_maskz", + "avx512.maskz.vpermt2var.d.128" => "__builtin_ia32_vpermt2vard128_maskz", + "avx512.maskz.vpermt2var.d.256" => "__builtin_ia32_vpermt2vard256_maskz", + "avx512.maskz.vpermt2var.d.512" => "__builtin_ia32_vpermt2vard512_maskz", + "avx512.maskz.vpermt2var.hi.128" => "__builtin_ia32_vpermt2varhi128_maskz", + "avx512.maskz.vpermt2var.hi.256" => "__builtin_ia32_vpermt2varhi256_maskz", + "avx512.maskz.vpermt2var.hi.512" => "__builtin_ia32_vpermt2varhi512_maskz", + "avx512.maskz.vpermt2var.pd.128" => "__builtin_ia32_vpermt2varpd128_maskz", + "avx512.maskz.vpermt2var.pd.256" => "__builtin_ia32_vpermt2varpd256_maskz", + "avx512.maskz.vpermt2var.pd.512" => "__builtin_ia32_vpermt2varpd512_maskz", + "avx512.maskz.vpermt2var.ps.128" => "__builtin_ia32_vpermt2varps128_maskz", + "avx512.maskz.vpermt2var.ps.256" => "__builtin_ia32_vpermt2varps256_maskz", + "avx512.maskz.vpermt2var.ps.512" => "__builtin_ia32_vpermt2varps512_maskz", + "avx512.maskz.vpermt2var.q.128" => "__builtin_ia32_vpermt2varq128_maskz", + "avx512.maskz.vpermt2var.q.256" => "__builtin_ia32_vpermt2varq256_maskz", + "avx512.maskz.vpermt2var.q.512" => "__builtin_ia32_vpermt2varq512_maskz", + "avx512.maskz.vpermt2var.qi.128" => "__builtin_ia32_vpermt2varqi128_maskz", + "avx512.maskz.vpermt2var.qi.256" => "__builtin_ia32_vpermt2varqi256_maskz", + "avx512.maskz.vpermt2var.qi.512" => "__builtin_ia32_vpermt2varqi512_maskz", + "avx512.maskz.vpmadd52h.uq.128" => "__builtin_ia32_vpmadd52huq128_maskz", + "avx512.maskz.vpmadd52h.uq.256" => "__builtin_ia32_vpmadd52huq256_maskz", + "avx512.maskz.vpmadd52h.uq.512" => "__builtin_ia32_vpmadd52huq512_maskz", + "avx512.maskz.vpmadd52l.uq.128" => "__builtin_ia32_vpmadd52luq128_maskz", + "avx512.maskz.vpmadd52l.uq.256" => "__builtin_ia32_vpmadd52luq256_maskz", + "avx512.maskz.vpmadd52l.uq.512" => "__builtin_ia32_vpmadd52luq512_maskz", + "avx512.movntdqa" => "__builtin_ia32_movntdqa512", + "avx512.pbroadcastd.512" => "__builtin_ia32_pbroadcastd512", + "avx512.pbroadcastq.512" => "__builtin_ia32_pbroadcastq512", + "avx512.pmovzxbd" => "__builtin_ia32_pmovzxbd512", + "avx512.pmovzxbq" => "__builtin_ia32_pmovzxbq512", + "avx512.pmovzxdq" => "__builtin_ia32_pmovzxdq512", + "avx512.pmovzxwd" => "__builtin_ia32_pmovzxwd512", + "avx512.pmovzxwq" => "__builtin_ia32_pmovzxwq512", + "avx512.psll.dq" => "__builtin_ia32_pslldqi512", + "avx512.psll.dq.bs" => "__builtin_ia32_pslldqi512_byteshift", + "avx512.psrl.dq" => "__builtin_ia32_psrldqi512", + "avx512.psrl.dq.bs" => "__builtin_ia32_psrldqi512_byteshift", + "avx512.ptestm.b.128" => "__builtin_ia32_ptestmb128", + "avx512.ptestm.b.256" => "__builtin_ia32_ptestmb256", + "avx512.ptestm.b.512" => "__builtin_ia32_ptestmb512", + "avx512.ptestm.d.128" => "__builtin_ia32_ptestmd128", + "avx512.ptestm.d.256" => "__builtin_ia32_ptestmd256", + "avx512.ptestm.d.512" => "__builtin_ia32_ptestmd512", + "avx512.ptestm.q.128" => "__builtin_ia32_ptestmq128", + "avx512.ptestm.q.256" => "__builtin_ia32_ptestmq256", + "avx512.ptestm.q.512" => "__builtin_ia32_ptestmq512", + "avx512.ptestm.w.128" => "__builtin_ia32_ptestmw128", + "avx512.ptestm.w.256" => "__builtin_ia32_ptestmw256", + "avx512.ptestm.w.512" => "__builtin_ia32_ptestmw512", + "avx512.ptestnm.b.128" => "__builtin_ia32_ptestnmb128", + "avx512.ptestnm.b.256" => "__builtin_ia32_ptestnmb256", + "avx512.ptestnm.b.512" => "__builtin_ia32_ptestnmb512", + "avx512.ptestnm.d.128" => "__builtin_ia32_ptestnmd128", + "avx512.ptestnm.d.256" => "__builtin_ia32_ptestnmd256", + "avx512.ptestnm.d.512" => "__builtin_ia32_ptestnmd512", + "avx512.ptestnm.q.128" => "__builtin_ia32_ptestnmq128", + "avx512.ptestnm.q.256" => "__builtin_ia32_ptestnmq256", + "avx512.ptestnm.q.512" => "__builtin_ia32_ptestnmq512", + "avx512.ptestnm.w.128" => "__builtin_ia32_ptestnmw128", + "avx512.ptestnm.w.256" => "__builtin_ia32_ptestnmw256", + "avx512.ptestnm.w.512" => "__builtin_ia32_ptestnmw512", + "avx512.rcp28.pd" => "__builtin_ia32_rcp28pd_mask", + "avx512.rcp28.ps" => "__builtin_ia32_rcp28ps_mask", + "avx512.rcp28.sd" => "__builtin_ia32_rcp28sd_mask", + "avx512.rcp28.ss" => "__builtin_ia32_rcp28ss_mask", + "avx512.rndscale.sd" => "__builtin_ia32_rndscalesd", + "avx512.rndscale.ss" => "__builtin_ia32_rndscaless", + "avx512.rsqrt28.pd" => "__builtin_ia32_rsqrt28pd_mask", + "avx512.rsqrt28.ps" => "__builtin_ia32_rsqrt28ps_mask", + "avx512.rsqrt28.sd" => "__builtin_ia32_rsqrt28sd_mask", + "avx512.rsqrt28.ss" => "__builtin_ia32_rsqrt28ss_mask", + "avx512.scatter.dpd.512" => "__builtin_ia32_scattersiv8df", + "avx512.scatter.dpi.512" => "__builtin_ia32_scattersiv16si", + "avx512.scatter.dpq.512" => "__builtin_ia32_scattersiv8di", + "avx512.scatter.dps.512" => "__builtin_ia32_scattersiv16sf", + "avx512.scatter.qpd.512" => "__builtin_ia32_scatterdiv8df", + "avx512.scatter.qpi.512" => "__builtin_ia32_scatterdiv16si", + "avx512.scatter.qpq.512" => "__builtin_ia32_scatterdiv8di", + "avx512.scatter.qps.512" => "__builtin_ia32_scatterdiv16sf", + "avx512.scatterdiv2.df" => "__builtin_ia32_scatterdiv2df", + "avx512.scatterdiv2.di" => "__builtin_ia32_scatterdiv2di", + "avx512.scatterdiv4.df" => "__builtin_ia32_scatterdiv4df", + "avx512.scatterdiv4.di" => "__builtin_ia32_scatterdiv4di", + "avx512.scatterdiv4.sf" => "__builtin_ia32_scatterdiv4sf", + "avx512.scatterdiv4.si" => "__builtin_ia32_scatterdiv4si", + "avx512.scatterdiv8.sf" => "__builtin_ia32_scatterdiv8sf", + "avx512.scatterdiv8.si" => "__builtin_ia32_scatterdiv8si", + "avx512.scatterpf.dpd.512" => "__builtin_ia32_scatterpfdpd", + "avx512.scatterpf.dps.512" => "__builtin_ia32_scatterpfdps", + "avx512.scatterpf.qpd.512" => "__builtin_ia32_scatterpfqpd", + "avx512.scatterpf.qps.512" => "__builtin_ia32_scatterpfqps", + "avx512.scattersiv2.df" => "__builtin_ia32_scattersiv2df", + "avx512.scattersiv2.di" => "__builtin_ia32_scattersiv2di", + "avx512.scattersiv4.df" => "__builtin_ia32_scattersiv4df", + "avx512.scattersiv4.di" => "__builtin_ia32_scattersiv4di", + "avx512.scattersiv4.sf" => "__builtin_ia32_scattersiv4sf", + "avx512.scattersiv4.si" => "__builtin_ia32_scattersiv4si", + "avx512.scattersiv8.sf" => "__builtin_ia32_scattersiv8sf", + "avx512.scattersiv8.si" => "__builtin_ia32_scattersiv8si", + "avx512.sqrt.pd.512" => "__builtin_ia32_sqrtpd512_mask", + "avx512.sqrt.ps.512" => "__builtin_ia32_sqrtps512_mask", + "avx512.sqrt.sd" => "__builtin_ia32_sqrtrndsd", + "avx512.sqrt.ss" => "__builtin_ia32_sqrtrndss", + "avx512.vbroadcast.sd.512" => "__builtin_ia32_vbroadcastsd512", + "avx512.vbroadcast.sd.pd.512" => "__builtin_ia32_vbroadcastsd_pd512", + "avx512.vbroadcast.ss.512" => "__builtin_ia32_vbroadcastss512", + "avx512.vbroadcast.ss.ps.512" => "__builtin_ia32_vbroadcastss_ps512", + "fma.mask.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask", + "fma.mask.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask", + "fma.mask.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask", + "fma.mask.vfmaddsub.ps.512" => "__builtin_ia32_vfmaddsubps512_mask", + "fma.mask.vfmsub.pd.512" => "__builtin_ia32_vfmsubpd512_mask", + "fma.mask.vfmsub.ps.512" => "__builtin_ia32_vfmsubps512_mask", + "fma.mask.vfmsubadd.pd.512" => "__builtin_ia32_vfmsubaddpd512_mask", + "fma.mask.vfmsubadd.ps.512" => "__builtin_ia32_vfmsubaddps512_mask", + "fma.mask.vfnmadd.pd.512" => "__builtin_ia32_vfnmaddpd512_mask", + "fma.mask.vfnmadd.ps.512" => "__builtin_ia32_vfnmaddps512_mask", + "fma.mask.vfnmsub.pd.512" => "__builtin_ia32_vfnmsubpd512_mask", + "fma.mask.vfnmsub.ps.512" => "__builtin_ia32_vfnmsubps512_mask", + "fma.vfmadd.pd" => "__builtin_ia32_vfmaddpd", + "fma.vfmadd.pd.256" => "__builtin_ia32_vfmaddpd256", + "fma.vfmadd.ps" => "__builtin_ia32_vfmaddps", + "fma.vfmadd.ps.256" => "__builtin_ia32_vfmaddps256", + "fma.vfmadd.sd" => "__builtin_ia32_vfmaddsd", + "fma.vfmadd.ss" => "__builtin_ia32_vfmaddss", + "fma.vfmsub.pd" => "__builtin_ia32_vfmsubpd", + "fma.vfmsub.pd.256" => "__builtin_ia32_vfmsubpd256", + "fma.vfmsub.ps" => "__builtin_ia32_vfmsubps", + "fma.vfmsub.ps.256" => "__builtin_ia32_vfmsubps256", + "fma.vfmsub.sd" => "__builtin_ia32_vfmsubsd", + "fma.vfmsub.ss" => "__builtin_ia32_vfmsubss", + "fma.vfmsubadd.pd" => "__builtin_ia32_vfmsubaddpd", + "fma.vfmsubadd.pd.256" => "__builtin_ia32_vfmsubaddpd256", + "fma.vfmsubadd.ps" => "__builtin_ia32_vfmsubaddps", + "fma.vfmsubadd.ps.256" => "__builtin_ia32_vfmsubaddps256", + "fma.vfnmadd.pd" => "__builtin_ia32_vfnmaddpd", + "fma.vfnmadd.pd.256" => "__builtin_ia32_vfnmaddpd256", + "fma.vfnmadd.ps" => "__builtin_ia32_vfnmaddps", + "fma.vfnmadd.ps.256" => "__builtin_ia32_vfnmaddps256", + "fma.vfnmadd.sd" => "__builtin_ia32_vfnmaddsd", + "fma.vfnmadd.ss" => "__builtin_ia32_vfnmaddss", + "fma.vfnmsub.pd" => "__builtin_ia32_vfnmsubpd", + "fma.vfnmsub.pd.256" => "__builtin_ia32_vfnmsubpd256", + "fma.vfnmsub.ps" => "__builtin_ia32_vfnmsubps", + "fma.vfnmsub.ps.256" => "__builtin_ia32_vfnmsubps256", + "fma.vfnmsub.sd" => "__builtin_ia32_vfnmsubsd", + "fma.vfnmsub.ss" => "__builtin_ia32_vfnmsubss", + "mmx.femms" => "__builtin_ia32_femms", + "rdtscp" => "__builtin_ia32_rdtscp", + "sse.add.ss" => "__builtin_ia32_addss", + "sse.cmp.ps" => "__builtin_ia32_cmpps", + "sse.cvtsi2ss" => "__builtin_ia32_cvtsi2ss", + "sse.cvtsi642ss" => "__builtin_ia32_cvtsi642ss", + "sse.div.ss" => "__builtin_ia32_divss", + "sse.mul.ss" => "__builtin_ia32_mulss", + "sse.sqrt.ps" => "__builtin_ia32_sqrtps", + "sse.sqrt.ss" => "__builtin_ia32_sqrtss", + "sse.storeu.ps" => "__builtin_ia32_storeups", + "sse.sub.ss" => "__builtin_ia32_subss", + "sse2.add.sd" => "__builtin_ia32_addsd", + "sse2.cmp.pd" => "__builtin_ia32_cmppd", + "sse2.cvtdq2pd" => "__builtin_ia32_cvtdq2pd", + "sse2.cvtdq2ps" => "__builtin_ia32_cvtdq2ps", + "sse2.cvtps2pd" => "__builtin_ia32_cvtps2pd", + "sse2.cvtsi2sd" => "__builtin_ia32_cvtsi2sd", + "sse2.cvtsi642sd" => "__builtin_ia32_cvtsi642sd", + "sse2.cvtss2sd" => "__builtin_ia32_cvtss2sd", + "sse2.div.sd" => "__builtin_ia32_divsd", + "sse2.mul.sd" => "__builtin_ia32_mulsd", + "sse2.padds.b" => "__builtin_ia32_paddsb128", + "sse2.padds.w" => "__builtin_ia32_paddsw128", + "sse2.paddus.b" => "__builtin_ia32_paddusb128", + "sse2.paddus.w" => "__builtin_ia32_paddusw128", + "sse2.pmaxs.w" => "__builtin_ia32_pmaxsw128", + "sse2.pmaxu.b" => "__builtin_ia32_pmaxub128", + "sse2.pmins.w" => "__builtin_ia32_pminsw128", + "sse2.pminu.b" => "__builtin_ia32_pminub128", + "sse2.pmulu.dq" => "__builtin_ia32_pmuludq128", + "sse2.pshuf.d" => "__builtin_ia32_pshufd", + "sse2.pshufh.w" => "__builtin_ia32_pshufhw", + "sse2.pshufl.w" => "__builtin_ia32_pshuflw", + "sse2.psll.dq" => "__builtin_ia32_pslldqi128", + "sse2.psll.dq.bs" => "__builtin_ia32_pslldqi128_byteshift", + "sse2.psrl.dq" => "__builtin_ia32_psrldqi128", + "sse2.psrl.dq.bs" => "__builtin_ia32_psrldqi128_byteshift", + "sse2.psubs.b" => "__builtin_ia32_psubsb128", + "sse2.psubs.w" => "__builtin_ia32_psubsw128", + "sse2.psubus.b" => "__builtin_ia32_psubusb128", + "sse2.psubus.w" => "__builtin_ia32_psubusw128", + "sse2.sqrt.pd" => "__builtin_ia32_sqrtpd", + "sse2.sqrt.sd" => "__builtin_ia32_sqrtsd", + "sse2.storel.dq" => "__builtin_ia32_storelv4si", + "sse2.storeu.dq" => "__builtin_ia32_storedqu", + "sse2.storeu.pd" => "__builtin_ia32_storeupd", + "sse2.sub.sd" => "__builtin_ia32_subsd", + "sse41.blendpd" => "__builtin_ia32_blendpd", + "sse41.blendps" => "__builtin_ia32_blendps", + "sse41.extractps" => "__builtin_ia32_extractps128", + "sse41.movntdqa" => "__builtin_ia32_movntdqa", + "sse41.pblendw" => "__builtin_ia32_pblendw128", + "sse41.pmaxsb" => "__builtin_ia32_pmaxsb128", + "sse41.pmaxsd" => "__builtin_ia32_pmaxsd128", + "sse41.pmaxud" => "__builtin_ia32_pmaxud128", + "sse41.pmaxuw" => "__builtin_ia32_pmaxuw128", + "sse41.pminsb" => "__builtin_ia32_pminsb128", + "sse41.pminsd" => "__builtin_ia32_pminsd128", + "sse41.pminud" => "__builtin_ia32_pminud128", + "sse41.pminuw" => "__builtin_ia32_pminuw128", + "sse41.pmovsxbd" => "__builtin_ia32_pmovsxbd128", + "sse41.pmovsxbq" => "__builtin_ia32_pmovsxbq128", + "sse41.pmovsxbw" => "__builtin_ia32_pmovsxbw128", + "sse41.pmovsxdq" => "__builtin_ia32_pmovsxdq128", + "sse41.pmovsxwd" => "__builtin_ia32_pmovsxwd128", + "sse41.pmovsxwq" => "__builtin_ia32_pmovsxwq128", + "sse41.pmovzxbd" => "__builtin_ia32_pmovzxbd128", + "sse41.pmovzxbq" => "__builtin_ia32_pmovzxbq128", + "sse41.pmovzxbw" => "__builtin_ia32_pmovzxbw128", + "sse41.pmovzxdq" => "__builtin_ia32_pmovzxdq128", + "sse41.pmovzxwd" => "__builtin_ia32_pmovzxwd128", + "sse41.pmovzxwq" => "__builtin_ia32_pmovzxwq128", + "sse41.pmuldq" => "__builtin_ia32_pmuldq128", + "sse4a.movnt.sd" => "__builtin_ia32_movntsd", + "sse4a.movnt.ss" => "__builtin_ia32_movntss", + "ssse3.pabs.b.128" => "__builtin_ia32_pabsb128", + "ssse3.pabs.d.128" => "__builtin_ia32_pabsd128", + "ssse3.pabs.w.128" => "__builtin_ia32_pabsw128", + "subborrow.u32" => "__builtin_ia32_subborrow_u32", + "subborrow.u64" => "__builtin_ia32_subborrow_u64", + "xop.vpcmov" => "__builtin_ia32_vpcmov", + "xop.vpcmov.256" => "__builtin_ia32_vpcmov_256", + "xop.vpcomb" => "__builtin_ia32_vpcomb", + "xop.vpcomd" => "__builtin_ia32_vpcomd", + "xop.vpcomq" => "__builtin_ia32_vpcomq", + "xop.vpcomub" => "__builtin_ia32_vpcomub", + "xop.vpcomud" => "__builtin_ia32_vpcomud", + "xop.vpcomuq" => "__builtin_ia32_vpcomuq", + "xop.vpcomuw" => "__builtin_ia32_vpcomuw", + "xop.vpcomw" => "__builtin_ia32_vpcomw", + "xop.vprotb" => "__builtin_ia32_vprotb", + "xop.vprotbi" => "__builtin_ia32_vprotbi", + "xop.vprotd" => "__builtin_ia32_vprotd", + "xop.vprotdi" => "__builtin_ia32_vprotdi", + "xop.vprotq" => "__builtin_ia32_vprotq", + "xop.vprotqi" => "__builtin_ia32_vprotqi", + "xop.vprotw" => "__builtin_ia32_vprotw", + "xop.vprotwi" => "__builtin_ia32_vprotwi", + _ => return ArchCheckResult::UnknownIntrinsic, + }, + _ => return ArchCheckResult::UnknownArch, + }) +} diff --git a/tools/generate_intrinsics.py b/tools/generate_intrinsics.py index 767082c23cce..56b425cdb0cd 100644 --- a/tools/generate_intrinsics.py +++ b/tools/generate_intrinsics.py @@ -147,14 +147,12 @@ def fill_intrinsics(intrinsics, from_intrinsics, all_intrinsics): all_intrinsics[entry[0]] = entry[1] -def update_intrinsics(llvm_path, llvmint, llvmint2): +def update_intrinsics(llvm_path): intrinsics_llvm = {} intrinsics_llvmint = {} all_intrinsics = {} extract_intrinsics_from_llvm(llvm_path, intrinsics_llvm) - extract_intrinsics_from_llvmint(llvmint, intrinsics_llvmint) - extract_intrinsics_from_llvmint(llvmint2, intrinsics_llvmint) intrinsics = {} # We give priority to translations from LLVM over the ones from llvmint. @@ -173,13 +171,17 @@ def update_intrinsics(llvm_path, llvmint, llvmint2): # Since all intrinsic names start with "llvm.", we skip that prefix. print("Updating content of `{}`...".format(output_file)) with open(output_file, "w", encoding="utf8") as out: - out.write("// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py`\n") - out.write("// DO NOT EDIT IT!\n") - out.write("/// Translate a given LLVM intrinsic name to an equivalent GCC one.\n") - out.write("fn map_arch_intrinsic(full_name:&str)->&'static str{\n") - out.write('let Some(name) = full_name.strip_prefix("llvm.") else { unimplemented!("***** unsupported LLVM intrinsic {}", full_name) };\n') - out.write('let Some((arch, name)) = name.split_once(\'.\') else { unimplemented!("***** unsupported LLVM intrinsic {}", name) };\n') - out.write("match arch {\n") + out.write("""// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py` +// DO NOT EDIT IT! +/// Translate a given LLVM intrinsic name to an equivalent GCC one. +fn map_arch_intrinsic(full_name:&str)-> &'static str { + let Some(name) = full_name.strip_prefix("llvm.") else { unimplemented!("***** unsupported LLVM intrinsic {}", full_name) }; + let Some((arch, name)) = name.split_once('.') else { unimplemented!("***** unsupported LLVM intrinsic llvm.{}", name) }; + let old_arch_res = old_archs(arch, name); + if let ArchCheckResult::Ok(res) = old_arch_res { + return res; + } +match arch {""") for arch in archs: if len(intrinsics[arch]) == 0: continue @@ -199,7 +201,13 @@ def update_intrinsics(llvm_path, llvmint, llvmint2): out.write(' "{}" => "{}",\n'.format(llvm_name, entry[1])) out.write(' _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),\n') out.write("}} }} {}(name,full_name) }}\n,".format(arch)) - out.write(' _ => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic:{full_name}"),\n') + out.write(""" _ => { + match old_arch_res { + ArchCheckResult::UnknownIntrinsic => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), + ArchCheckResult::UnknownArch => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic: {full_name}"), + ArchCheckResult::Ok(_) => unreachable!(), + } + }""") out.write("}\n}") subprocess.call(["rustfmt", output_file]) print("Done!") @@ -210,14 +218,6 @@ def main(): os.path.dirname(os.path.abspath(__file__)), "llvm-project", ) - llvmint_path = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - "llvmint", - ) - llvmint2_path = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - "llvmint-2", - ) # First, we clone the LLVM repository if it's not already here. clone_repository( @@ -227,17 +227,7 @@ def main(): branch="main", sub_paths=["llvm/include/llvm/IR", "llvm/include/llvm/CodeGen/"], ) - clone_repository( - "llvmint", - llvmint_path, - "https://github.com/GuillaumeGomez/llvmint", - ) - clone_repository( - "llvmint2", - llvmint2_path, - "https://github.com/antoyo/llvmint", - ) - update_intrinsics(llvm_path, llvmint_path, llvmint2_path) + update_intrinsics(llvm_path) if __name__ == "__main__": From 3dc60d0bf14638cbc2dcaf70e720c6f417608365 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Jan 2026 16:48:14 +0100 Subject: [PATCH 060/978] Simplify intrinsics translation generation script --- tools/generate_intrinsics.py | 150 ++++++++--------------------------- 1 file changed, 33 insertions(+), 117 deletions(-) diff --git a/tools/generate_intrinsics.py b/tools/generate_intrinsics.py index 56b425cdb0cd..539032340777 100644 --- a/tools/generate_intrinsics.py +++ b/tools/generate_intrinsics.py @@ -12,7 +12,7 @@ def run_command(command, cwd=None): sys.exit(1) -def clone_repository(repo_name, path, repo_url, branch="master", sub_paths=None): +def clone_repository(repo_name, path, repo_url, sub_paths): if os.path.exists(path): while True: choice = input("There is already a `{}` folder, do you want to update it? [y/N]".format(path)) @@ -21,18 +21,15 @@ def clone_repository(repo_name, path, repo_url, branch="master", sub_paths=None) return elif choice.lower() == "y": print("Updating repository...") - run_command(["git", "pull", "origin", branch], cwd=path) + run_command(["git", "pull", "origin", "main"], cwd=path) return else: print("Didn't understand answer...") print("Cloning {} repository...".format(repo_name)) - if sub_paths is None: - run_command(["git", "clone", repo_url, "--depth", "1", path]) - else: - run_command(["git", "clone", repo_url, "--filter=tree:0", "--no-checkout", path]) - run_command(["git", "sparse-checkout", "init"], cwd=path) - run_command(["git", "sparse-checkout", "set", *sub_paths], cwd=path) - run_command(["git", "checkout"], cwd=path) + run_command(["git", "clone", repo_url, "--filter=tree:0", "--no-checkout", path]) + run_command(["git", "sparse-checkout", "init"], cwd=path) + run_command(["git", "sparse-checkout", "set", *sub_paths], cwd=path) + run_command(["git", "checkout"], cwd=path) def append_intrinsic(array, intrinsic_name, translation): @@ -45,119 +42,36 @@ def convert_to_string(content): return content -def extract_intrinsics_from_llvm(llvm_path, intrinsics): - command = ["llvm-tblgen", "llvm/IR/Intrinsics.td"] +def extract_intrinsics_from_llvm(llvm_path): + intrinsics = {} + command = ["llvm-tblgen", "llvm/IR/Intrinsics.td", "--dump-json"] cwd = os.path.join(llvm_path, "llvm/include") print("=> Running command `{}` from `{}`".format(command, cwd)) p = subprocess.Popen(command, cwd=cwd, stdout=subprocess.PIPE) output, err = p.communicate() - lines = convert_to_string(output).splitlines() - pos = 0 - while pos < len(lines): - line = lines[pos] - if not line.startswith("def "): - pos += 1 + content = json.loads(convert_to_string(output)) + for intrinsic in content: + data = content[intrinsic] + if not isinstance(data, dict): continue - intrinsic = line.split(" ")[1].strip() - content = line - while pos < len(lines): - line = lines[pos].split(" // ")[0].strip() - content += line - pos += 1 - if line == "}": - break - entries = re.findall('string ClangBuiltinName = "(\\w+)";', content) - current_arch = re.findall('string TargetPrefix = "(\\w+)";', content) - if len(entries) == 1 and len(current_arch) == 1: - current_arch = current_arch[0] - intrinsic = intrinsic.split("_") - if len(intrinsic) < 2 or intrinsic[0] != "int": - continue - intrinsic[0] = "llvm" - intrinsic = ".".join(intrinsic) - if current_arch not in intrinsics: - intrinsics[current_arch] = [] - append_intrinsic(intrinsics[current_arch], intrinsic, entries[0]) - - -def append_translation(json_data, p, array): - it = json_data["index"][p] - content = it["docs"].split('`') - if len(content) != 5: - return - append_intrinsic(array, content[1], content[3]) - - -def extract_intrinsics_from_llvmint(llvmint, intrinsics): - archs = [ - "AMDGPU", - "aarch64", - "arm", - "cuda", - "hexagon", - "mips", - "nvvm", - "ppc", - "ptx", - "x86", - "xcore", - ] - - json_file = os.path.join(llvmint, "target/doc/llvmint.json") - # We need to regenerate the documentation! - run_command( - ["cargo", "rustdoc", "--", "-Zunstable-options", "--output-format", "json"], - cwd=llvmint, - ) - with open(json_file, "r", encoding="utf8") as f: - json_data = json.loads(f.read()) - for p in json_data["paths"]: - it = json_data["paths"][p] - if it["crate_id"] != 0: - # This is from an external crate. + current_arch = data.get("TargetPrefix") + builtin_name = data.get("ClangBuiltinName") + if current_arch is None or current_arch == "" or builtin_name is None: continue - if it["kind"] != "function": - # We're only looking for functions. + intrinsic = intrinsic.split("_") + if len(intrinsic) < 2 or intrinsic[0] != "int": continue - # if len(it["path"]) == 2: - # # This is a "general" intrinsic, not bound to a specific arch. - # append_translation(json_data, p, general) - # continue - if len(it["path"]) != 3 or it["path"][1] not in archs: - continue - arch = it["path"][1] - if arch not in intrinsics: - intrinsics[arch] = [] - append_translation(json_data, p, intrinsics[arch]) + intrinsic[0] = "llvm" + intrinsic = ".".join(intrinsic) + if current_arch not in intrinsics: + intrinsics[current_arch] = [] + append_intrinsic(intrinsics[current_arch], intrinsic, builtin_name) - -def fill_intrinsics(intrinsics, from_intrinsics, all_intrinsics): - for arch in from_intrinsics: - if arch not in intrinsics: - intrinsics[arch] = [] - for entry in from_intrinsics[arch]: - if entry[0] in all_intrinsics: - if all_intrinsics[entry[0]] == entry[1]: - # This is a "full" duplicate, both the LLVM instruction and the GCC - # translation are the same. - continue - intrinsics[arch].append((entry[0], entry[1], True)) - else: - intrinsics[arch].append((entry[0], entry[1], False)) - all_intrinsics[entry[0]] = entry[1] + return intrinsics def update_intrinsics(llvm_path): - intrinsics_llvm = {} - intrinsics_llvmint = {} - all_intrinsics = {} - - extract_intrinsics_from_llvm(llvm_path, intrinsics_llvm) - - intrinsics = {} - # We give priority to translations from LLVM over the ones from llvmint. - fill_intrinsics(intrinsics, intrinsics_llvm, all_intrinsics) - fill_intrinsics(intrinsics, intrinsics_llvmint, all_intrinsics) + intrinsics = extract_intrinsics_from_llvm(llvm_path) archs = [arch for arch in intrinsics] archs.sort() @@ -187,15 +101,13 @@ match arch {""") continue attribute = "#[expect(non_snake_case)]" if arch[0].isupper() else "" out.write("\"{}\" => {{ {} fn {}(name: &str,full_name:&str) -> &'static str {{ match name {{".format(arch, attribute, arch)) - intrinsics[arch].sort(key=lambda x: (x[0], x[2])) + intrinsics[arch].sort(key=lambda x: (x[0], x[1])) out.write(' // {}\n'.format(arch)) for entry in intrinsics[arch]: llvm_name = entry[0].removeprefix("llvm."); llvm_name = llvm_name.removeprefix(arch); llvm_name = llvm_name.removeprefix("."); - if entry[2] is True: # if it is a duplicate - out.write(' // [DUPLICATE]: "{}" => "{}",\n'.format(llvm_name, entry[1])) - elif "_round_mask" in entry[1]: + if "_round_mask" in entry[1]: out.write(' // [INVALID CONVERSION]: "{}" => "{}",\n'.format(llvm_name, entry[1])) else: out.write(' "{}" => "{}",\n'.format(llvm_name, entry[1])) @@ -224,11 +136,15 @@ def main(): "llvm-project", llvm_path, "https://github.com/llvm/llvm-project", - branch="main", - sub_paths=["llvm/include/llvm/IR", "llvm/include/llvm/CodeGen/"], + ["llvm/include/llvm/IR", "llvm/include/llvm/CodeGen/"], ) update_intrinsics(llvm_path) +# llvm-tblgen can be built with: +# +# mkdir llvm-tblgen-build && cd llvm-tblgen-build +# cmake -G Ninja -DLLVM_ENABLE_PROJECTS="llvm" -DCMAKE_BUILD_TYPE=Release ../llvm +# ninja llvm-tblgen if __name__ == "__main__": sys.exit(main()) From c848b28a5d20b512e7edcd03da5ba616fabf0a8d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Jan 2026 17:05:01 +0100 Subject: [PATCH 061/978] Ignore `src/intrinsic/old_archs.rs` for typo checks --- .cspell.json | 1 + _typos.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.cspell.json b/.cspell.json index 388ccce2b091..556432d69a41 100644 --- a/.cspell.json +++ b/.cspell.json @@ -18,6 +18,7 @@ ], "ignorePaths": [ "src/intrinsic/archs.rs", + "src/intrinsic/old_archs.rs", "src/intrinsic/llvm.rs" ], "ignoreRegExpList": [ diff --git a/_typos.toml b/_typos.toml index 4a6a506a981a..c4918b114621 100644 --- a/_typos.toml +++ b/_typos.toml @@ -6,4 +6,4 @@ seh = "seh" typ = "typ" [files] -extend-exclude = ["src/intrinsic/archs.rs"] +extend-exclude = ["src/intrinsic/archs.rs", "src/intrinsic/old_archs.rs"] From 4f59819c26c72f86baa98a2805d411cd5b665759 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 16 Jan 2026 17:46:34 +0100 Subject: [PATCH 062/978] Regenerate intrinsics --- src/intrinsic/archs.rs | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index 89a6cf7f3d6e..3c1698df6dec 100644 --- a/src/intrinsic/archs.rs +++ b/src/intrinsic/archs.rs @@ -24,6 +24,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "gcsss" => "__builtin_arm_gcsss", "isb" => "__builtin_arm_isb", "prefetch" => "__builtin_arm_prefetch", + "range.prefetch" => "__builtin_arm_range_prefetch", "sme.in.streaming.mode" => "__builtin_arm_in_streaming_mode", "sve.aesd" => "__builtin_sve_svaesd_u8", "sve.aese" => "__builtin_sve_svaese_u8", @@ -414,6 +415,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "s.wait.event.export.ready" => "__builtin_amdgcn_s_wait_event_export_ready", "s.wait.tensorcnt" => "__builtin_amdgcn_s_wait_tensorcnt", "s.waitcnt" => "__builtin_amdgcn_s_waitcnt", + "s.wakeup.barrier" => "__builtin_amdgcn_s_wakeup_barrier", "sad.hi.u8" => "__builtin_amdgcn_sad_hi_u8", "sad.u16" => "__builtin_amdgcn_sad_u16", "sad.u8" => "__builtin_amdgcn_sad_u8", @@ -4836,19 +4838,24 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "add.rm.d" => "__nvvm_add_rm_d", "add.rm.f" => "__nvvm_add_rm_f", "add.rm.ftz.f" => "__nvvm_add_rm_ftz_f", + "add.rm.ftz.sat.f" => "__nvvm_add_rm_ftz_sat_f", + "add.rm.sat.f" => "__nvvm_add_rm_sat_f", "add.rn.d" => "__nvvm_add_rn_d", "add.rn.f" => "__nvvm_add_rn_f", "add.rn.ftz.f" => "__nvvm_add_rn_ftz_f", + "add.rn.ftz.sat.f" => "__nvvm_add_rn_ftz_sat_f", + "add.rn.sat.f" => "__nvvm_add_rn_sat_f", "add.rp.d" => "__nvvm_add_rp_d", "add.rp.f" => "__nvvm_add_rp_f", "add.rp.ftz.f" => "__nvvm_add_rp_ftz_f", + "add.rp.ftz.sat.f" => "__nvvm_add_rp_ftz_sat_f", + "add.rp.sat.f" => "__nvvm_add_rp_sat_f", "add.rz.d" => "__nvvm_add_rz_d", "add.rz.f" => "__nvvm_add_rz_f", "add.rz.ftz.f" => "__nvvm_add_rz_ftz_f", + "add.rz.ftz.sat.f" => "__nvvm_add_rz_ftz_sat_f", + "add.rz.sat.f" => "__nvvm_add_rz_sat_f", "bar.warp.sync" => "__nvvm_bar_warp_sync", - "barrier0.and" => "__nvvm_bar0_and", - "barrier0.or" => "__nvvm_bar0_or", - "barrier0.popc" => "__nvvm_bar0_popc", "bf16x2.to.ue8m0x2.rp" => "__nvvm_bf16x2_to_ue8m0x2_rp", "bf16x2.to.ue8m0x2.rp.satfinite" => "__nvvm_bf16x2_to_ue8m0x2_rp_satfinite", "bf16x2.to.ue8m0x2.rz" => "__nvvm_bf16x2_to_ue8m0x2_rz", @@ -5050,6 +5057,8 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fma.rm.d" => "__nvvm_fma_rm_d", "fma.rm.f" => "__nvvm_fma_rm_f", "fma.rm.ftz.f" => "__nvvm_fma_rm_ftz_f", + "fma.rm.ftz.sat.f" => "__nvvm_fma_rm_ftz_sat_f", + "fma.rm.sat.f" => "__nvvm_fma_rm_sat_f", "fma.rn.bf16" => "__nvvm_fma_rn_bf16", "fma.rn.bf16x2" => "__nvvm_fma_rn_bf16x2", "fma.rn.d" => "__nvvm_fma_rn_d", @@ -5061,16 +5070,22 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fma.rn.ftz.relu.bf16x2" => "__nvvm_fma_rn_ftz_relu_bf16x2", "fma.rn.ftz.sat.bf16" => "__nvvm_fma_rn_ftz_sat_bf16", "fma.rn.ftz.sat.bf16x2" => "__nvvm_fma_rn_ftz_sat_bf16x2", + "fma.rn.ftz.sat.f" => "__nvvm_fma_rn_ftz_sat_f", "fma.rn.relu.bf16" => "__nvvm_fma_rn_relu_bf16", "fma.rn.relu.bf16x2" => "__nvvm_fma_rn_relu_bf16x2", "fma.rn.sat.bf16" => "__nvvm_fma_rn_sat_bf16", "fma.rn.sat.bf16x2" => "__nvvm_fma_rn_sat_bf16x2", + "fma.rn.sat.f" => "__nvvm_fma_rn_sat_f", "fma.rp.d" => "__nvvm_fma_rp_d", "fma.rp.f" => "__nvvm_fma_rp_f", "fma.rp.ftz.f" => "__nvvm_fma_rp_ftz_f", + "fma.rp.ftz.sat.f" => "__nvvm_fma_rp_ftz_sat_f", + "fma.rp.sat.f" => "__nvvm_fma_rp_sat_f", "fma.rz.d" => "__nvvm_fma_rz_d", "fma.rz.f" => "__nvvm_fma_rz_f", "fma.rz.ftz.f" => "__nvvm_fma_rz_ftz_f", + "fma.rz.ftz.sat.f" => "__nvvm_fma_rz_ftz_sat_f", + "fma.rz.sat.f" => "__nvvm_fma_rz_sat_f", "fmax.bf16" => "__nvvm_fmax_bf16", "fmax.bf16x2" => "__nvvm_fmax_bf16x2", "fmax.d" => "__nvvm_fmax_d", @@ -5274,6 +5289,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "read.ptx.sreg.pm1" => "__nvvm_read_ptx_sreg_pm1", "read.ptx.sreg.pm2" => "__nvvm_read_ptx_sreg_pm2", "read.ptx.sreg.pm3" => "__nvvm_read_ptx_sreg_pm3", + "read.ptx.sreg.pm4" => "__nvvm_read_ptx_sreg_pm4", "read.ptx.sreg.smid" => "__nvvm_read_ptx_sreg_smid", "read.ptx.sreg.tid.w" => "__nvvm_read_ptx_sreg_tid_w", "read.ptx.sreg.tid.x" => "__nvvm_read_ptx_sreg_tid_x", @@ -6370,6 +6386,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { fn spv(name: &str, full_name: &str) -> &'static str { match name { // spv + "group.memory.barrier.with.group.sync" => "__builtin_spirv_group_barrier", "num.subgroups" => "__builtin_spirv_num_subgroups", "subgroup.id" => "__builtin_spirv_subgroup_id", "subgroup.local.invocation.id" => { @@ -6377,6 +6394,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { } "subgroup.max.size" => "__builtin_spirv_subgroup_max_size", "subgroup.size" => "__builtin_spirv_subgroup_size", + "wave.ballot" => "__builtin_spirv_subgroup_ballot", _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } @@ -7711,8 +7729,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "avx.ptestnzc.256" => "__builtin_ia32_ptestnzc256", "avx.ptestz.256" => "__builtin_ia32_ptestz256", "avx.rcp.ps.256" => "__builtin_ia32_rcpps256", - "avx.round.pd.256" => "__builtin_ia32_roundpd256", - "avx.round.ps.256" => "__builtin_ia32_roundps256", "avx.rsqrt.ps.256" => "__builtin_ia32_rsqrtps256", "avx.vpermilvar.pd" => "__builtin_ia32_vpermilvarpd", "avx.vpermilvar.pd.256" => "__builtin_ia32_vpermilvarpd256", @@ -8829,10 +8845,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "sse41.ptestc" => "__builtin_ia32_ptestc128", "sse41.ptestnzc" => "__builtin_ia32_ptestnzc128", "sse41.ptestz" => "__builtin_ia32_ptestz128", - "sse41.round.pd" => "__builtin_ia32_roundpd", - "sse41.round.ps" => "__builtin_ia32_roundps", - "sse41.round.sd" => "__builtin_ia32_roundsd", - "sse41.round.ss" => "__builtin_ia32_roundss", "sse42.crc32.32.16" => "__builtin_ia32_crc32hi", "sse42.crc32.32.32" => "__builtin_ia32_crc32si", "sse42.crc32.32.8" => "__builtin_ia32_crc32qi", @@ -8869,10 +8881,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "ssse3.psign.w.128" => "__builtin_ia32_psignw128", "sttilecfg" => "__builtin_ia32_tile_storeconfig", "stui" => "__builtin_ia32_stui", - "t2rpntlvwz0rs" => "__builtin_ia32_t2rpntlvwz0rs", - "t2rpntlvwz0rst1" => "__builtin_ia32_t2rpntlvwz0rst1", - "t2rpntlvwz1rs" => "__builtin_ia32_t2rpntlvwz1rs", - "t2rpntlvwz1rst1" => "__builtin_ia32_t2rpntlvwz1rst1", "tbm.bextri.u32" => "__builtin_ia32_bextri_u32", "tbm.bextri.u64" => "__builtin_ia32_bextri_u64", "tcmmimfp16ps" => "__builtin_ia32_tcmmimfp16ps", @@ -8881,14 +8889,19 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "tcmmrlfp16ps.internal" => "__builtin_ia32_tcmmrlfp16ps_internal", "tcvtrowd2ps" => "__builtin_ia32_tcvtrowd2ps", "tcvtrowd2ps.internal" => "__builtin_ia32_tcvtrowd2ps_internal", + "tcvtrowd2psi" => "__builtin_ia32_tcvtrowd2psi", "tcvtrowps2bf16h" => "__builtin_ia32_tcvtrowps2bf16h", "tcvtrowps2bf16h.internal" => "__builtin_ia32_tcvtrowps2bf16h_internal", + "tcvtrowps2bf16hi" => "__builtin_ia32_tcvtrowps2bf16hi", "tcvtrowps2bf16l" => "__builtin_ia32_tcvtrowps2bf16l", "tcvtrowps2bf16l.internal" => "__builtin_ia32_tcvtrowps2bf16l_internal", + "tcvtrowps2bf16li" => "__builtin_ia32_tcvtrowps2bf16li", "tcvtrowps2phh" => "__builtin_ia32_tcvtrowps2phh", "tcvtrowps2phh.internal" => "__builtin_ia32_tcvtrowps2phh_internal", + "tcvtrowps2phhi" => "__builtin_ia32_tcvtrowps2phhi", "tcvtrowps2phl" => "__builtin_ia32_tcvtrowps2phl", "tcvtrowps2phl.internal" => "__builtin_ia32_tcvtrowps2phl_internal", + "tcvtrowps2phli" => "__builtin_ia32_tcvtrowps2phli", "tdpbf16ps" => "__builtin_ia32_tdpbf16ps", "tdpbf16ps.internal" => "__builtin_ia32_tdpbf16ps_internal", "tdpbf8ps" => "__builtin_ia32_tdpbf8ps", @@ -8920,6 +8933,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "tileloaddt164.internal" => "__builtin_ia32_tileloaddt164_internal", "tilemovrow" => "__builtin_ia32_tilemovrow", "tilemovrow.internal" => "__builtin_ia32_tilemovrow_internal", + "tilemovrowi" => "__builtin_ia32_tilemovrowi", "tilerelease" => "__builtin_ia32_tilerelease", "tilestored64" => "__builtin_ia32_tilestored64", "tilestored64.internal" => "__builtin_ia32_tilestored64_internal", From 2177aa9ac736b0c16c8ad73230508fcb273b980e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 16 Jan 2026 18:09:37 +0100 Subject: [PATCH 063/978] Manually include intrinsic conversion that is not present in LLVM files --- src/intrinsic/old_archs.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/intrinsic/old_archs.rs b/src/intrinsic/old_archs.rs index 3a59707b2ebe..8d3e3487b5cb 100644 --- a/src/intrinsic/old_archs.rs +++ b/src/intrinsic/old_archs.rs @@ -242,6 +242,8 @@ pub(crate) fn old_archs(arch: &str, name: &str) -> ArchCheckResult { "avx.cvt.ps2.pd.256" => "__builtin_ia32_cvtps2pd256", "avx.cvtdq2.pd.256" => "__builtin_ia32_cvtdq2pd256", "avx.cvtdq2.ps.256" => "__builtin_ia32_cvtdq2ps256", + "avx.round.pd.256" => "__builtin_ia32_roundpd256", + "avx.round.ps.256" => "__builtin_ia32_roundps256", "avx.sqrt.pd.256" => "__builtin_ia32_sqrtpd256", "avx.sqrt.ps.256" => "__builtin_ia32_sqrtps256", "avx.storeu.dq.256" => "__builtin_ia32_storedqu256", @@ -1352,6 +1354,10 @@ pub(crate) fn old_archs(arch: &str, name: &str) -> ArchCheckResult { "sse41.pmovzxwd" => "__builtin_ia32_pmovzxwd128", "sse41.pmovzxwq" => "__builtin_ia32_pmovzxwq128", "sse41.pmuldq" => "__builtin_ia32_pmuldq128", + "sse41.round.pd" => "__builtin_ia32_roundpd", + "sse41.round.ps" => "__builtin_ia32_roundps", + "sse41.round.sd" => "__builtin_ia32_roundsd", + "sse41.round.ss" => "__builtin_ia32_roundss", "sse4a.movnt.sd" => "__builtin_ia32_movntsd", "sse4a.movnt.ss" => "__builtin_ia32_movntss", "ssse3.pabs.b.128" => "__builtin_ia32_pabsb128", From ccdda582a84a2985a90374cb8720b0084b4c9408 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Fri, 16 Jan 2026 22:53:37 +0100 Subject: [PATCH 064/978] clean-up --- clippy_lints/src/methods/str_split.rs | 6 ++++-- tests/ui/str_split.fixed | 2 -- tests/ui/str_split.rs | 2 -- tests/ui/str_split.stderr | 20 ++++++++++---------- 4 files changed, 14 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/methods/str_split.rs b/clippy_lints/src/methods/str_split.rs index 479064a0671e..9644b2c774b5 100644 --- a/clippy_lints/src/methods/str_split.rs +++ b/clippy_lints/src/methods/str_split.rs @@ -19,8 +19,10 @@ pub(super) fn check<'a>(cx: &LateContext<'a>, expr: &'_ Expr<'_>, split_recv: &' && cx.typeck_results().expr_ty_adjusted(trim_recv).peel_refs().is_str() && !is_const_evaluatable(cx, trim_recv) && let ExprKind::Lit(split_lit) = split_arg.kind - && (matches!(split_lit.node, LitKind::Char('\n')) - || matches!(split_lit.node, LitKind::Str(sym::LF | sym::CRLF, _))) + && matches!( + split_lit.node, + LitKind::Char('\n') | LitKind::Str(sym::LF | sym::CRLF, _) + ) { let mut app = Applicability::MaybeIncorrect; span_lint_and_sugg( diff --git a/tests/ui/str_split.fixed b/tests/ui/str_split.fixed index 6aca5051c570..c93d4d4f818d 100644 --- a/tests/ui/str_split.fixed +++ b/tests/ui/str_split.fixed @@ -1,7 +1,5 @@ #![warn(clippy::str_split_at_newline)] -#![allow(clippy::needless_lifetimes)] -use core::str::Split; use std::ops::Deref; struct NotStr<'a> { diff --git a/tests/ui/str_split.rs b/tests/ui/str_split.rs index 11e9862da14b..5792ce04ec33 100644 --- a/tests/ui/str_split.rs +++ b/tests/ui/str_split.rs @@ -1,7 +1,5 @@ #![warn(clippy::str_split_at_newline)] -#![allow(clippy::needless_lifetimes)] -use core::str::Split; use std::ops::Deref; struct NotStr<'a> { diff --git a/tests/ui/str_split.stderr b/tests/ui/str_split.stderr index c4eca81004c5..40202c8ac47a 100644 --- a/tests/ui/str_split.stderr +++ b/tests/ui/str_split.stderr @@ -1,5 +1,5 @@ error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:60:13 + --> tests/ui/str_split.rs:58:13 | LL | let _ = s1.trim().split('\n'); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()` @@ -8,55 +8,55 @@ LL | let _ = s1.trim().split('\n'); = help: to override `-D warnings` add `#[allow(clippy::str_split_at_newline)]` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:63:13 + --> tests/ui/str_split.rs:61:13 | LL | let _ = s1.trim().split("\n"); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:65:13 + --> tests/ui/str_split.rs:63:13 | LL | let _ = s1.trim().split("\r\n"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:69:13 + --> tests/ui/str_split.rs:67:13 | LL | let _ = s2.trim().split('\n'); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:72:13 + --> tests/ui/str_split.rs:70:13 | LL | let _ = s2.trim().split("\n"); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:74:13 + --> tests/ui/str_split.rs:72:13 | LL | let _ = s2.trim().split("\r\n"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:79:13 + --> tests/ui/str_split.rs:77:13 | LL | let _ = s3.trim().split('\n'); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:82:13 + --> tests/ui/str_split.rs:80:13 | LL | let _ = s3.trim().split("\n"); | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:84:13 + --> tests/ui/str_split.rs:82:13 | LL | let _ = s3.trim().split("\r\n"); | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()` error: using `str.trim().split()` with hard-coded newlines - --> tests/ui/str_split.rs:88:13 + --> tests/ui/str_split.rs:86:13 | LL | let _ = make_str!(s1).trim().split('\n'); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `make_str!(s1).lines()` From bdc08aeb91626171a7dc5bfbc1e0d109770ee457 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 6 Jun 2024 12:49:31 -0700 Subject: [PATCH 065/978] Reword the caveats on `array::map` Thanks to 107634 and some improvements in LLVM (particularly `dead_on_unwind`), the method actually optimizes reasonably well now. So focus the discussion on the fundamental ordering differences where the optimizer might never be able to fix it because of the different behaviour, and encouraging `Iterator::map` where an array wasn't actually ever needed. --- library/core/src/array/mod.rs | 51 ++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 6cca2e6358b6..4a2cf1527744 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -516,20 +516,47 @@ impl [T; N] { /// /// # Note on performance and stack usage /// - /// Unfortunately, usages of this method are currently not always optimized - /// as well as they could be. This mainly concerns large arrays, as mapping - /// over small arrays seem to be optimized just fine. Also note that in - /// debug mode (i.e. without any optimizations), this method can use a lot - /// of stack space (a few times the size of the array or more). + /// Note that this method is *eager*. It evaluates `f` all `N` times before + /// returning the new array. /// - /// Therefore, in performance-critical code, try to avoid using this method - /// on large arrays or check the emitted code. Also try to avoid chained - /// maps (e.g. `arr.map(...).map(...)`). + /// That means that `arr.map(f).map(g)` is, in general, *not* equivalent to + /// `array.map(|x| g(f(x)))`, as the former calls `f` 4 times then `g` 4 times, + /// whereas the latter interleaves the calls (`fgfgfgfg`). /// - /// In many cases, you can instead use [`Iterator::map`] by calling `.iter()` - /// or `.into_iter()` on your array. `[T; N]::map` is only necessary if you - /// really need a new array of the same size as the result. Rust's lazy - /// iterators tend to get optimized very well. + /// A consequence of this is that it can have fairly-high stack usage, especially + /// in debug mode or for long arrays. The backend may be able to optimize it + /// away, but especially for complicated mappings it might not be able to. + /// + /// If you're doing a one-step `map` and really want an array as the result, + /// then absolutely use this method. Its implementation uses a bunch of tricks + /// to help the optimizer handle it well. Particularly for simple arrays, + /// like `[u8; 3]` or `[f32; 4]`, there's nothing to be concerned about. + /// + /// However, if you don't actually need an *array* of the results specifically, + /// just to process them, then you likely want [`Iterator::map`] instead. + /// + /// For example, rather than doing an array-to-array map of all the elements + /// in the array up-front and only iterating after that completes, + /// + /// ``` + /// # let my_array = [1, 2, 3]; + /// # let f = |x: i32| x + 1; + /// for x in my_array.map(f) { + /// // ... + /// } + /// ``` + /// + /// It's often better to use an iterator along the lines of + /// + /// ``` + /// # let my_array = [1, 2, 3]; + /// # let f = |x: i32| x + 1; + /// for x in my_array.into_iter().map(f) { + /// // ... + /// } + /// ``` + /// + /// as that's more likely to avoid large temporaries. /// /// /// # Examples From 345e9a089bde20917fb7cf1f9db5092d69d70b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 16 Jan 2026 22:04:53 +0100 Subject: [PATCH 066/978] Document `-Zcache-proc-macros` --- .../src/compiler-flags/cache-proc-macros.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/doc/unstable-book/src/compiler-flags/cache-proc-macros.md diff --git a/src/doc/unstable-book/src/compiler-flags/cache-proc-macros.md b/src/doc/unstable-book/src/compiler-flags/cache-proc-macros.md new file mode 100644 index 000000000000..eefaf9ca2f1b --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/cache-proc-macros.md @@ -0,0 +1,9 @@ +## `cache-proc-macros` + +The tracking issue for this feature is: [#151364] + +[#151364]: https://github.com/rust-lang/rust/issues/151364 + +------------------------ + +This option instructs `rustc` to cache (derive) proc-macro invocations using the incremental system. Note that the compiler does not currently check whether the proc-macro is actually "cacheable" or not. If you use this flag when compiling a crate that uses non-pure proc-macros, it can result in stale expansions being compiled. From f11abba6415b5d7bd82c92196e8cfea61a192abe Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 19 Jan 2026 00:42:38 +0100 Subject: [PATCH 067/978] add `simd_splat` intrinsic --- src/intrinsic/simd.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 39b4bb3ebefa..0606639d1731 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -121,6 +121,35 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(bx.vector_select(vector_mask, arg1, args[2].immediate())); } + if name == sym::simd_splat { + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); + let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); + + require!( + args[0].layout.ty == out_ty, + InvalidMonomorphization::ExpectedVectorElementType { + span, + name, + expected_element: out_ty, + vector_type: ret_ty, + } + ); + + let vec_ty = llret_ty.unqualified().dyncast_vector().expect("vector return type"); + let elem_ty = vec_ty.get_element_type(); + + // Cast pointer type to usize (GCC does not support pointer SIMD vectors). + let scalar = args[0].immediate(); + let scalar = if scalar.get_type().unqualified() != elem_ty.unqualified() { + bx.ptrtoint(scalar, elem_ty) + } else { + scalar + }; + + let elements = vec![scalar; out_len as usize]; + return Ok(bx.context.new_rvalue_from_vector(bx.location, llret_ty, &elements)); + } + // every intrinsic below takes a SIMD vector as its first argument require_simd!( args[0].layout.ty, From e0b87e4dd53c028e2db49fd8dc64e2f56d3548f8 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 19 Jan 2026 15:44:11 +0100 Subject: [PATCH 068/978] `simd_splat`: custom error in gcc backend for invalid element type --- src/intrinsic/simd.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 0606639d1731..eab067a02b7b 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -121,9 +121,9 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(bx.vector_select(vector_mask, arg1, args[2].immediate())); } + #[cfg(feature = "master")] if name == sym::simd_splat { - require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); - let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); + let (out_len, out_ty) = require_simd2!(ret_ty, SimdReturn); require!( args[0].layout.ty == out_ty, @@ -139,11 +139,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let elem_ty = vec_ty.get_element_type(); // Cast pointer type to usize (GCC does not support pointer SIMD vectors). - let scalar = args[0].immediate(); - let scalar = if scalar.get_type().unqualified() != elem_ty.unqualified() { - bx.ptrtoint(scalar, elem_ty) + let value = args[0]; + let scalar = if value.layout.ty.is_numeric() { + value.immediate() + } else if value.layout.ty.is_raw_ptr() { + bx.ptrtoint(value.immediate(), elem_ty) } else { - scalar + return_error!(InvalidMonomorphization::UnsupportedOperation { + span, + name, + in_ty: ret_ty, + in_elem: value.layout.ty + }); }; let elements = vec![scalar; out_len as usize]; From 635bacf46627409cb4569b93d38bdf23282966f3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Nov 2025 10:01:56 +0100 Subject: [PATCH 069/978] const-eval: always do mem-to-mem copies if there might be padding involved --- .../rustc_const_eval/src/interpret/place.rs | 25 +++++++++++-- .../src/interpret/projection.rs | 2 +- tests/ui/consts/const-eval/ptr_fragments.rs | 1 + .../const-eval/ptr_fragments_in_final.rs | 36 +++++++++++++++++++ .../const-eval/ptr_fragments_in_final.stderr | 10 +++++- 5 files changed, 69 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index d472c14253b5..70d10751dbb8 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -884,10 +884,29 @@ where dest.layout().ty, ); } + // If the source has padding, we want to always do the mem-to-mem copy to ensure consistent + // padding in the target independent of layout choices. + let src_has_padding = match src.layout().backend_repr { + BackendRepr::Scalar(_) => false, + BackendRepr::ScalarPair(left, right) => { + let left_size = left.size(self); + let right_size = right.size(self); + // We have padding if the sizes don't add up to the total. + left_size + right_size != src.layout().size + } + // Everything else can only exist in memory anyway. + _ => true, + }; - // Let us see if the layout is simple so we take a shortcut, - // avoid force_allocation. - let src = match self.read_immediate_raw(src)? { + let src_val = if src_has_padding { + // Do our best to get an mplace. If there's no mplace, then this is stored as an + // "optimized" local, so its padding is definitely uninitialized and we are fine. + src.to_op(self)?.as_mplace_or_imm() + } else { + // Do our best to get an immediate, to avoid having to force_allocate the destination. + self.read_immediate_raw(src)? + }; + let src = match src_val { Right(src_val) => { assert!(!src.layout().is_unsized()); assert!(!dest.layout().is_unsized()); diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 027e634ef7f7..db72c02e308c 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -97,7 +97,7 @@ pub trait Projectable<'tcx, Prov: Provenance>: Sized + std::fmt::Debug { } /// Convert this to an `OpTy`. This might be an irreversible transformation, but is useful for - /// reading from this thing. + /// reading from this thing. This will never actually do a read from memory! fn to_op>( &self, ecx: &InterpCx<'tcx, M>, diff --git a/tests/ui/consts/const-eval/ptr_fragments.rs b/tests/ui/consts/const-eval/ptr_fragments.rs index d27804084d73..f4d92127e189 100644 --- a/tests/ui/consts/const-eval/ptr_fragments.rs +++ b/tests/ui/consts/const-eval/ptr_fragments.rs @@ -70,6 +70,7 @@ const _PARTIAL_OVERWRITE: () = { #[allow(dead_code)] #[cfg(not(target_arch = "s390x"))] // u128 is less aligned on s390x, removing the padding fn fragment_in_dst_padding_gets_overwritten() { + // We can't use `repr(align)` here as that would make this not a `ScalarPair` any more. #[repr(C)] struct Pair { x: u128, diff --git a/tests/ui/consts/const-eval/ptr_fragments_in_final.rs b/tests/ui/consts/const-eval/ptr_fragments_in_final.rs index 4037a2d23722..76f292c3f8b5 100644 --- a/tests/ui/consts/const-eval/ptr_fragments_in_final.rs +++ b/tests/ui/consts/const-eval/ptr_fragments_in_final.rs @@ -37,4 +37,40 @@ const MIXED_PTR: MaybeUninit<*const u8> = { //~ERROR: partial pointer in final v } }; +/// This has pointer bytes in the padding of the memory that the final value is read from. +/// To ensure consistent behavior, we want to *always* copy that padding, even if the value +/// could be represented as a more efficient ScalarPair. Hence this must fail to compile. +fn fragment_in_padding() -> impl Copy { + // We can't use `repr(align)` here as that would make this not a `ScalarPair` any more. + #[repr(C)] + #[derive(Clone, Copy)] + struct Thing { + x: u128, + y: usize, + // at least one pointer worth of padding + } + // Ensure there is indeed padding. + const _: () = assert!(mem::size_of::() > 16 + mem::size_of::()); + + #[derive(Clone, Copy)] + union PreservePad { + thing: Thing, + bytes: [u8; mem::size_of::()], + } + + const A: Thing = unsafe { //~ERROR: partial pointer in final value + let mut buffer = [PreservePad { bytes: [0u8; mem::size_of::()] }; 2]; + // The offset half a pointer from the end, so that copying a `Thing` copies exactly + // half the pointer. + let offset = mem::size_of::() - mem::size_of::()/2; + // Ensure this is inside the padding. + assert!(offset >= std::mem::offset_of!(Thing, y) + mem::size_of::()); + + (&raw mut buffer).cast::<&i32>().byte_add(offset).write_unaligned(&1); + buffer[0].thing + }; + + A +} + fn main() {} diff --git a/tests/ui/consts/const-eval/ptr_fragments_in_final.stderr b/tests/ui/consts/const-eval/ptr_fragments_in_final.stderr index 41a822416581..de0cd4db7e15 100644 --- a/tests/ui/consts/const-eval/ptr_fragments_in_final.stderr +++ b/tests/ui/consts/const-eval/ptr_fragments_in_final.stderr @@ -14,5 +14,13 @@ LL | const MIXED_PTR: MaybeUninit<*const u8> = { | = note: while pointers can be broken apart into individual bytes during const-evaluation, only complete pointers (with all their bytes in the right order) are supported in the final value -error: aborting due to 2 previous errors +error: encountered partial pointer in final value of constant + --> $DIR/ptr_fragments_in_final.rs:61:5 + | +LL | const A: Thing = unsafe { + | ^^^^^^^^^^^^^^ + | + = note: while pointers can be broken apart into individual bytes during const-evaluation, only complete pointers (with all their bytes in the right order) are supported in the final value + +error: aborting due to 3 previous errors From 5a76a60d016d7ed5cd5fcecc131010dbce8148e0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 17 Nov 2025 09:10:45 +0100 Subject: [PATCH 070/978] add fast-path for wide pointers --- .../rustc_const_eval/src/interpret/place.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 70d10751dbb8..fb07d5f0d0d6 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -5,8 +5,8 @@ use either::{Either, Left, Right}; use rustc_abi::{BackendRepr, HasDataLayout, Size}; use rustc_data_structures::assert_matches; -use rustc_middle::ty::Ty; use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, mir, span_bug}; use tracing::field::Empty; use tracing::{instrument, trace}; @@ -884,18 +884,27 @@ where dest.layout().ty, ); } - // If the source has padding, we want to always do the mem-to-mem copy to ensure consistent + // If the source has padding, we want to always do a mem-to-mem copy to ensure consistent // padding in the target independent of layout choices. let src_has_padding = match src.layout().backend_repr { BackendRepr::Scalar(_) => false, + BackendRepr::ScalarPair(left, right) + if matches!(src.layout().ty.kind(), ty::Ref(..) | ty::RawPtr(..)) => + { + // Wide pointers never have padding, so we can avoid calling `size()`. + debug_assert_eq!(left.size(self) + right.size(self), src.layout().size); + false + } BackendRepr::ScalarPair(left, right) => { let left_size = left.size(self); let right_size = right.size(self); // We have padding if the sizes don't add up to the total. left_size + right_size != src.layout().size } - // Everything else can only exist in memory anyway. - _ => true, + // Everything else can only exist in memory anyway, so it doesn't matter. + BackendRepr::SimdVector { .. } + | BackendRepr::ScalableVector { .. } + | BackendRepr::Memory { .. } => true, }; let src_val = if src_has_padding { From 7f71511d58084e6eee2d904af265adad66dba4d0 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 20 Jan 2026 00:25:02 +0200 Subject: [PATCH 071/978] inline outlier links, for consistency --- src/doc/rustc-dev-guide/src/SUMMARY.md | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index daaaef42d909..a9ae1f707e53 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -197,7 +197,7 @@ - [Opaque types](./opaque-types-type-alias-impl-trait.md) - [Inference details](./opaque-types-impl-trait-inference.md) - [Return Position Impl Trait In Trait](./return-position-impl-trait-in-trait.md) - - [Region inference restrictions][opaque-infer] + - [Region inference restrictions](./borrow_check/opaque-types-region-inference-restrictions.md) - [Const condition checking](./effects.md) - [Pattern and exhaustiveness checking](./pat-exhaustive-checking.md) - [Unsafety checking](./unsafety-checking.md) @@ -212,7 +212,7 @@ - [Constraint propagation](./borrow_check/region_inference/constraint_propagation.md) - [Lifetime parameters](./borrow_check/region_inference/lifetime_parameters.md) - [Member constraints](./borrow_check/region_inference/member_constraints.md) - - [Placeholders and universes][pau] + - [Placeholders and universes](./borrow_check/region_inference/placeholders_and_universes.md) - [Closure constraints](./borrow_check/region_inference/closure_constraints.md) - [Error reporting](./borrow_check/region_inference/error_reporting.md) - [Two-phase-borrows](./borrow_check/two_phase_borrows.md) @@ -263,8 +263,3 @@ [Appendix E: Bibliography](./appendix/bibliography.md) [Appendix Z: HumorRust](./appendix/humorust.md) - ---- - -[pau]: ./borrow_check/region_inference/placeholders_and_universes.md -[opaque-infer]: ./borrow_check/opaque-types-region-inference-restrictions.md From ca5a25496fea0f9ece6440c1d23cd63b1c0e7e50 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 19 Jan 2026 15:48:35 -0600 Subject: [PATCH 072/978] rustdoc: change getVar signature This has two advantages: * removes a bunch of @ts-expect-error * typos of var names will cause type errors instead of runtime errors --- src/librustdoc/html/static/js/main.js | 3 --- src/librustdoc/html/static/js/rustdoc.d.ts | 12 ++++++++++++ src/librustdoc/html/static/js/storage.js | 10 +++++++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index f438fe173810..28d3522e47e8 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -231,7 +231,6 @@ function preLoadCss(cssUrl) { // When loading settings.html as a standalone page, the equivalent HTML is // generated in context.rs. setTimeout(() => { - // @ts-expect-error const themes = getVar("themes").split(","); for (const theme of themes) { // if there are no themes, do nothing @@ -415,12 +414,10 @@ function preLoadCss(cssUrl) { } window.StringdexOnload.push(() => { loadScript( - // @ts-expect-error getVar("static-root-path") + getVar("search-js"), sendSearchForm, ); }); - // @ts-expect-error loadScript(getVar("static-root-path") + getVar("stringdex-js"), sendSearchForm); loadScript(resourcePath("search.index/root", ".js"), sendSearchForm); } diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index 60df4fc10b8c..f53c98b9672d 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -576,4 +576,16 @@ declare namespace rustdoc { "typeNameIdOfHof": number, "typeNameIdOfNever": number, }; + + type VarName = "name" + | "root-path" + | "static-root-path" + | "current-crate" + | "themes" + | "resource-suffix" + | "rustdoc-version" + | "channel" + | "search-js" + | "stringdex-js" + | "settings-js"; } diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 40ab8be03c93..2d544eaa237a 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -199,12 +199,16 @@ function getCurrentValue(name) { * Get a value from the rustdoc-vars div, which is used to convey data from * Rust to the JS. If there is no such element, return null. * - * @param {string} name - * @returns {string|null} + * @param {rustdoc.VarName} name + * @returns {string} */ function getVar(name) { const el = document.querySelector("head > meta[name='rustdoc-vars']"); - return el ? el.getAttribute("data-" + name) : null; + const v = el ? el.getAttribute("data-" + name) : null; + if (v !== null) { + return v; + } + throw `rustdoc var "${name}" is missing`; } /** From b7ba80d2ad2d94e81e67e2063f33962aaa6aa760 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 19 Jan 2026 15:53:50 -0600 Subject: [PATCH 073/978] rustdoc(storage.js): add comment explaining use of @ts-ignore --- src/librustdoc/html/static/js/storage.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 2d544eaa237a..e722d8573783 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -298,6 +298,8 @@ const updateTheme = (function() { return updateTheme; })(); +// typescript thinks we're forgetting to call window.matchMedia, +// but we're checking browser support of media queries. // @ts-ignore if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) { // update the preferred dark theme if the user is already using a dark theme From 760d8868f045433d67a3c5e01754682da08f9e78 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 19 Jan 2026 16:00:46 -0600 Subject: [PATCH 074/978] rustdoc(main.js): use instanceof instead of tagName where applicable --- src/librustdoc/html/static/js/main.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 28d3522e47e8..4b37ae1f4296 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -619,8 +619,7 @@ function preLoadCss(cssUrl) { */ function openParentDetails(elem) { while (elem) { - if (elem.tagName === "DETAILS") { - // @ts-expect-error + if (elem instanceof HTMLDetailsElement) { elem.open = true; } elem = elem.parentElement; @@ -656,10 +655,8 @@ function preLoadCss(cssUrl) { } if (document.activeElement && - document.activeElement.tagName === "INPUT" && - // @ts-expect-error + document.activeElement instanceof HTMLInputElement && document.activeElement.type !== "checkbox" && - // @ts-expect-error document.activeElement.type !== "radio") { switch (getVirtualKey(ev)) { case "Escape": From 38d7b5309236c5a2898a378217455ad71f4b3aa9 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 19 Jan 2026 16:09:38 -0600 Subject: [PATCH 075/978] rustdoc(main.js): use nonnull to clear up type errors --- src/librustdoc/html/static/js/main.js | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 4b37ae1f4296..447aa1e02a4c 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -963,19 +963,19 @@ function preLoadCss(cssUrl) { const selfPath = script ? script.getAttribute("data-self-path") : null; // These sidebar blocks need filled in, too. - const mainContent = document.querySelector("#main-content"); - const sidebarSection = document.querySelector(".sidebar section"); + const mainContent = nonnull(document.querySelector("#main-content")); + const sidebarSection = nonnull(document.querySelector(".sidebar section")); let methods = document.querySelector(".sidebar .block.method"); let associatedTypes = document.querySelector(".sidebar .block.associatedtype"); let associatedConstants = document.querySelector(".sidebar .block.associatedconstant"); let sidebarTraitList = document.querySelector(".sidebar .block.trait-implementation"); - // @ts-expect-error - for (const impList of imp[window.currentCrate]) { + for (const impList of imp[nonnull(window.currentCrate)]) { const types = impList.slice(2); const text = impList[0]; const isTrait = impList[1] !== 0; const traitName = impList[1]; + // @ts-expect-error if (types.indexOf(selfPath) === -1) { continue; } @@ -999,33 +999,26 @@ function preLoadCss(cssUrl) { h.appendChild(link); trait_implementations = outputList; trait_implementations_header = outputListHeader; - // @ts-expect-error sidebarSection.appendChild(h); sidebarTraitList = document.createElement("ul"); sidebarTraitList.className = "block trait-implementation"; - // @ts-expect-error sidebarSection.appendChild(sidebarTraitList); - // @ts-expect-error mainContent.appendChild(outputListHeader); - // @ts-expect-error mainContent.appendChild(outputList); } else { implementations = outputList; if (trait_implementations) { - // @ts-expect-error mainContent.insertBefore(outputListHeader, trait_implementations_header); - // @ts-expect-error mainContent.insertBefore(outputList, trait_implementations_header); } else { - const mainContent = document.querySelector("#main-content"); - // @ts-expect-error + const mainContent = nonnull(document.querySelector("#main-content")); mainContent.appendChild(outputListHeader); - // @ts-expect-error mainContent.appendChild(outputList); } } } const template = document.createElement("template"); + // @ts-expect-error template.innerHTML = text; onEachLazy(template.content.querySelectorAll("a"), elem => { @@ -1065,8 +1058,8 @@ function preLoadCss(cssUrl) { if (isTrait) { const li = document.createElement("li"); const a = document.createElement("a"); + a.href = `#${nonnull(template.content.querySelector(".impl")).id}`; // @ts-expect-error - a.href = `#${template.content.querySelector(".impl").id}`; a.textContent = traitName; li.appendChild(a); // @ts-expect-error @@ -1093,14 +1086,10 @@ function preLoadCss(cssUrl) { const insertionReference = methods || sidebarTraitList; if (insertionReference) { const insertionReferenceH = insertionReference.previousElementSibling; - // @ts-expect-error sidebarSection.insertBefore(blockHeader, insertionReferenceH); - // @ts-expect-error sidebarSection.insertBefore(block, insertionReferenceH); } else { - // @ts-expect-error sidebarSection.appendChild(blockHeader); - // @ts-expect-error sidebarSection.appendChild(block); } if (hasClass(item, "associatedtype")) { From 3b4de4b21d93e349d83b5cb59b98cb832c764746 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 19 Jan 2026 16:44:05 -0600 Subject: [PATCH 076/978] rustdoc: make TypeImpls more specific. --- src/librustdoc/html/static/js/main.js | 1 - src/librustdoc/html/static/js/rustdoc.d.ts | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 447aa1e02a4c..eca1bd366d4b 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1018,7 +1018,6 @@ function preLoadCss(cssUrl) { } } const template = document.createElement("template"); - // @ts-expect-error template.innerHTML = text; onEachLazy(template.content.querySelectorAll("a"), elem => { diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index f53c98b9672d..a7dfaa61bfec 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -524,7 +524,8 @@ declare namespace rustdoc { } type TypeImpls = { - [cratename: string]: Array> + /* [text, traitName (0 if not a trait), ...types] */ + [cratename: string]: Array<[string, string|0, ...string[]]> } /** From 519c0d9d433debe17a877e6ee46e9d81fc603763 Mon Sep 17 00:00:00 2001 From: binarycat Date: Mon, 19 Jan 2026 17:07:31 -0600 Subject: [PATCH 077/978] rustdoc: remove redundant mainContent variable --- src/librustdoc/html/static/js/main.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index eca1bd366d4b..a26683e2e9bb 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1011,7 +1011,6 @@ function preLoadCss(cssUrl) { mainContent.insertBefore(outputListHeader, trait_implementations_header); mainContent.insertBefore(outputList, trait_implementations_header); } else { - const mainContent = nonnull(document.querySelector("#main-content")); mainContent.appendChild(outputListHeader); mainContent.appendChild(outputList); } From 9fad6f6d6088f7b0bd7002a98069452183843f63 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 20 Jan 2026 03:44:26 +0200 Subject: [PATCH 078/978] replace _ with - in path names (for consistency) --- src/doc/rustc-dev-guide/book.toml | 30 +++++++++- src/doc/rustc-dev-guide/src/SUMMARY.md | 56 +++++++++---------- .../src/appendix/background.md | 3 +- .../src/appendix/code-index.md | 2 +- .../rustc-dev-guide/src/appendix/glossary.md | 4 +- .../src/{borrow_check.md => borrow-check.md} | 4 +- .../drop-check.md} | 0 .../moves-and-initialization.md} | 12 ++-- .../moves-and-initialization/move-paths.md} | 0 ...que-types-region-inference-restrictions.md | 6 +- .../region-inference.md} | 6 +- .../region-inference/closure-constraints.md} | 0 .../constraint-propagation.md} | 6 +- .../region-inference/error-reporting.md} | 0 .../region-inference/lifetime-parameters.md} | 2 +- .../region-inference/member-constraints.md} | 0 .../placeholders-and-universes.md} | 0 .../two-phase-borrows.md} | 0 .../type-check.md} | 0 src/doc/rustc-dev-guide/src/const-eval.md | 2 +- src/doc/rustc-dev-guide/src/contributing.md | 2 +- ...parameters.md => early-late-parameters.md} | 0 src/doc/rustc-dev-guide/src/feature-gates.md | 6 +- ...mmary.md => generic-parameters-summary.md} | 4 +- ...atures.md => implementing-new-features.md} | 4 +- src/doc/rustc-dev-guide/src/memory.md | 6 +- src/doc/rustc-dev-guide/src/normalization.md | 20 +++---- .../src/opaque-types-impl-trait-inference.md | 2 +- src/doc/rustc-dev-guide/src/overview.md | 6 +- src/doc/rustc-dev-guide/src/profiling.md | 4 +- .../profiling/{with_perf.md => with-perf.md} | 2 +- ...{with_rustc_perf.md => with-rustc-perf.md} | 0 .../{wpa_profiling.md => wpa-profiling.md} | 0 .../rustc-dev-guide/src/solve/opaque-types.md | 4 +- .../src/stability-guarantees.md | 2 +- src/doc/rustc-dev-guide/src/stability.md | 2 +- ...zation_guide.md => stabilization-guide.md} | 2 +- ...te.md => stabilization-report-template.md} | 2 +- src/doc/rustc-dev-guide/src/tests/perf.md | 2 +- src/doc/rustc-dev-guide/src/traits/caching.md | 2 +- .../rustc-dev-guide/src/traits/resolution.md | 12 ++-- src/doc/rustc-dev-guide/src/ty-fold.md | 2 +- .../src/{ty_module => ty-module}/binders.md | 0 .../early-binder.md} | 0 .../generic-arguments.md} | 0 .../instantiating-binders.md} | 28 +++++----- .../param-ty-const-regions.md} | 10 ++-- ...meter_envs.md => typing-parameter-envs.md} | 0 src/doc/rustc-dev-guide/src/walkthrough.md | 2 +- 49 files changed, 143 insertions(+), 116 deletions(-) rename src/doc/rustc-dev-guide/src/{borrow_check.md => borrow-check.md} (95%) rename src/doc/rustc-dev-guide/src/{borrow_check/drop_check.md => borrow-check/drop-check.md} (100%) rename src/doc/rustc-dev-guide/src/{borrow_check/moves_and_initialization.md => borrow-check/moves-and-initialization.md} (94%) rename src/doc/rustc-dev-guide/src/{borrow_check/moves_and_initialization/move_paths.md => borrow-check/moves-and-initialization/move-paths.md} (100%) rename src/doc/rustc-dev-guide/src/{borrow_check => borrow-check}/opaque-types-region-inference-restrictions.md (99%) rename src/doc/rustc-dev-guide/src/{borrow_check/region_inference.md => borrow-check/region-inference.md} (98%) rename src/doc/rustc-dev-guide/src/{borrow_check/region_inference/closure_constraints.md => borrow-check/region-inference/closure-constraints.md} (100%) rename src/doc/rustc-dev-guide/src/{borrow_check/region_inference/constraint_propagation.md => borrow-check/region-inference/constraint-propagation.md} (98%) rename src/doc/rustc-dev-guide/src/{borrow_check/region_inference/error_reporting.md => borrow-check/region-inference/error-reporting.md} (100%) rename src/doc/rustc-dev-guide/src/{borrow_check/region_inference/lifetime_parameters.md => borrow-check/region-inference/lifetime-parameters.md} (98%) rename src/doc/rustc-dev-guide/src/{borrow_check/region_inference/member_constraints.md => borrow-check/region-inference/member-constraints.md} (100%) rename src/doc/rustc-dev-guide/src/{borrow_check/region_inference/placeholders_and_universes.md => borrow-check/region-inference/placeholders-and-universes.md} (100%) rename src/doc/rustc-dev-guide/src/{borrow_check/two_phase_borrows.md => borrow-check/two-phase-borrows.md} (100%) rename src/doc/rustc-dev-guide/src/{borrow_check/type_check.md => borrow-check/type-check.md} (100%) rename src/doc/rustc-dev-guide/src/{early_late_parameters.md => early-late-parameters.md} (100%) rename src/doc/rustc-dev-guide/src/{generic_parameters_summary.md => generic-parameters-summary.md} (96%) rename src/doc/rustc-dev-guide/src/{implementing_new_features.md => implementing-new-features.md} (99%) rename src/doc/rustc-dev-guide/src/profiling/{with_perf.md => with-perf.md} (99%) rename src/doc/rustc-dev-guide/src/profiling/{with_rustc_perf.md => with-rustc-perf.md} (100%) rename src/doc/rustc-dev-guide/src/profiling/{wpa_profiling.md => wpa-profiling.md} (100%) rename src/doc/rustc-dev-guide/src/{stabilization_guide.md => stabilization-guide.md} (99%) rename src/doc/rustc-dev-guide/src/{stabilization_report_template.md => stabilization-report-template.md} (99%) rename src/doc/rustc-dev-guide/src/{ty_module => ty-module}/binders.md (100%) rename src/doc/rustc-dev-guide/src/{ty_module/early_binder.md => ty-module/early-binder.md} (100%) rename src/doc/rustc-dev-guide/src/{ty_module/generic_arguments.md => ty-module/generic-arguments.md} (100%) rename src/doc/rustc-dev-guide/src/{ty_module/instantiating_binders.md => ty-module/instantiating-binders.md} (95%) rename src/doc/rustc-dev-guide/src/{ty_module/param_ty_const_regions.md => ty-module/param-ty-const-regions.md} (97%) rename src/doc/rustc-dev-guide/src/{typing_parameter_envs.md => typing-parameter-envs.md} (100%) diff --git a/src/doc/rustc-dev-guide/book.toml b/src/doc/rustc-dev-guide/book.toml index 15a597e5addb..18ca2c85a617 100644 --- a/src/doc/rustc-dev-guide/book.toml +++ b/src/doc/rustc-dev-guide/book.toml @@ -57,11 +57,39 @@ cache-timeout = 90000 warning-policy = "error" [output.html.redirect] +"/borrow_check.html" = "borrow-check.html" +"/borrow_check/drop_check.html" = "borrow-check/drop-check.html" +"/borrow_check/moves_and_initialization.html" = "borrow-check/moves-and-initialization.html" +"/borrow_check/moves_and_initialization/move_paths.html" = "borrow-check/moves-and-initialization/move-paths.html" +"/borrow_check/opaque-types-region-inference-restrictions.html" = "borrow-check/opaque-types-region-inference-restrictions.html" +"/borrow_check/region_inference.html" = "borrow-check/region-inference.html" +"/borrow_check/region_inference/closure_constraints.html" = "borrow-check/region-inference/closure-constraints.html" +"/borrow_check/region_inference/constraint_propagation.html" = "borrow-check/region-inference/constraint-propagation.html" +"/borrow_check/region_inference/error_reporting.html" = "borrow-check/region-inference/error-reporting.html" +"/borrow_check/region_inference/lifetime_parameters.html" = "borrow-check/region-inference/lifetime-parameters.html" +"/borrow_check/region_inference/member_constraints.html" = "borrow-check/region-inference/member-constraints.html" +"/borrow_check/region_inference/placeholders_and_universes.html" = "borrow-check/region-inference/placeholders-and-universes.html" +"/borrow_check/two_phase_borrows.html" = "borrow-check/two-phase-borrows.html" +"/borrow_check/type_check.html" = "borrow-check/type-check.html" "/compiletest.html" = "tests/compiletest.html" -"/diagnostics/sessiondiagnostic.html" = "diagnostic-structs.html" "/diagnostics/diagnostic-codes.html" = "error-codes.html" +"/diagnostics/sessiondiagnostic.html" = "diagnostic-structs.html" +"/early_late_parameters.html" = "early-late-parameters.html" +"/generic_parameters_summary.html" = "generic-parameters-summary.html" +"/implementing_new_features.html" = "implementing-new-features.html" "/miri.html" = "const-eval/interpret.html" +"/profiling/with_perf.html" = "profiling/with-perf.html" +"/profiling/with_rustc_perf.html" = "profiling/with-rustc-perf.html" +"/profiling/wpa_profiling.html" = "profiling/wpa-profiling.html" +"/stabilization_guide.html" = "stabilization-guide.html" +"/stabilization_report_template.html" = "stabilization-report-template.html" "/tests/fuchsia.html" = "ecosystem-test-jobs/fuchsia.html" "/tests/headers.html" = "directives.html" "/tests/integration.html" = "ecosystem.html" "/tests/rust-for-linux.html" = "ecosystem-test-jobs/rust-for-linux.html" +"/ty_module/binders.html" = "ty-module/binders.html" +"/ty_module/early_binder.html" = "ty-module/early-binder.html" +"/ty_module/generic_arguments.html" = "ty-module/generic-arguments.html" +"/ty_module/instantiating_binders.html" = "ty-module/instantiating-binders.html" +"/ty_module/param_ty_const_regions.html" = "ty-module/param-ty-const-regions.html" +"/typing_parameter_envs.html" = "typing-parameter-envs.html" diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index a9ae1f707e53..71c25003b193 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -39,9 +39,9 @@ - [Debugging the compiler](./compiler-debugging.md) - [Using the tracing/logging instrumentation](./tracing.md) - [Profiling the compiler](./profiling.md) - - [with the linux perf tool](./profiling/with_perf.md) - - [with Windows Performance Analyzer](./profiling/wpa_profiling.md) - - [with the Rust benchmark suite](./profiling/with_rustc_perf.md) + - [with the linux perf tool](./profiling/with-perf.md) + - [with Windows Performance Analyzer](./profiling/wpa-profiling.md) + - [with the Rust benchmark suite](./profiling/with-rustc-perf.md) - [crates.io dependencies](./crates-io.md) # Contributing to Rust @@ -51,11 +51,11 @@ - [Using Git](./git.md) - [Mastering @rustbot](./rustbot.md) - [Walkthrough: a typical contribution](./walkthrough.md) -- [Implementing new language features](./implementing_new_features.md) +- [Implementing new language features](./implementing-new-features.md) - [Stability guarantees](./stability-guarantees.md) - [Stability attributes](./stability.md) -- [Stabilizing language features](./stabilization_guide.md) - - [Stabilization report template](./stabilization_report_template.md) +- [Stabilizing language features](./stabilization-guide.md) + - [Stabilization report template](./stabilization-report-template.md) - [Feature Gates](./feature-gates.md) - [Coding conventions](./conventions.md) - [Procedures for breaking changes](./bug-fix-procedure.md) @@ -154,17 +154,17 @@ # Analysis - [Prologue](./part-4-intro.md) -- [Generic parameter definitions](./generic_parameters_summary.md) - - [`EarlyBinder` and instantiating parameters](./ty_module/early_binder.md) -- [Binders and Higher ranked regions](./ty_module/binders.md) - - [Instantiating binders](./ty_module/instantiating_binders.md) -- [Early vs Late bound parameters](./early_late_parameters.md) +- [Generic parameter definitions](./generic-parameters-summary.md) + - [`EarlyBinder` and instantiating parameters](./ty-module/early-binder.md) +- [Binders and Higher ranked regions](./ty-module/binders.md) + - [Instantiating binders](./ty-module/instantiating-binders.md) +- [Early vs Late bound parameters](./early-late-parameters.md) - [The `ty` module: representing types](./ty.md) - - [ADTs and Generic Arguments](./ty_module/generic_arguments.md) - - [Parameter types/consts/regions](./ty_module/param_ty_const_regions.md) + - [ADTs and Generic Arguments](./ty-module/generic-arguments.md) + - [Parameter types/consts/regions](./ty-module/param-ty-const-regions.md) - [`TypeFolder` and `TypeFoldable`](./ty-fold.md) - [Aliases and Normalization](./normalization.md) -- [Typing/Param Envs](./typing_parameter_envs.md) +- [Typing/Param Envs](./typing-parameter-envs.md) - [Type inference](./type-inference.md) - [Trait solving](./traits/resolution.md) - [Higher-ranked trait bounds](./traits/hrtb.md) @@ -197,25 +197,25 @@ - [Opaque types](./opaque-types-type-alias-impl-trait.md) - [Inference details](./opaque-types-impl-trait-inference.md) - [Return Position Impl Trait In Trait](./return-position-impl-trait-in-trait.md) - - [Region inference restrictions](./borrow_check/opaque-types-region-inference-restrictions.md) + - [Region inference restrictions](./borrow-check/opaque-types-region-inference-restrictions.md) - [Const condition checking](./effects.md) - [Pattern and exhaustiveness checking](./pat-exhaustive-checking.md) - [Unsafety checking](./unsafety-checking.md) - [MIR dataflow](./mir/dataflow.md) - [Drop elaboration](./mir/drop-elaboration.md) -- [The borrow checker](./borrow_check.md) - - [Tracking moves and initialization](./borrow_check/moves_and_initialization.md) - - [Move paths](./borrow_check/moves_and_initialization/move_paths.md) - - [MIR type checker](./borrow_check/type_check.md) - - [Drop check](./borrow_check/drop_check.md) - - [Region inference](./borrow_check/region_inference.md) - - [Constraint propagation](./borrow_check/region_inference/constraint_propagation.md) - - [Lifetime parameters](./borrow_check/region_inference/lifetime_parameters.md) - - [Member constraints](./borrow_check/region_inference/member_constraints.md) - - [Placeholders and universes](./borrow_check/region_inference/placeholders_and_universes.md) - - [Closure constraints](./borrow_check/region_inference/closure_constraints.md) - - [Error reporting](./borrow_check/region_inference/error_reporting.md) - - [Two-phase-borrows](./borrow_check/two_phase_borrows.md) +- [The borrow checker](./borrow-check.md) + - [Tracking moves and initialization](./borrow-check/moves-and-initialization.md) + - [Move paths](./borrow-check/moves-and-initialization/move-paths.md) + - [MIR type checker](./borrow-check/type-check.md) + - [Drop check](./borrow-check/drop-check.md) + - [Region inference](./borrow-check/region-inference.md) + - [Constraint propagation](./borrow-check/region-inference/constraint-propagation.md) + - [Lifetime parameters](./borrow-check/region-inference/lifetime-parameters.md) + - [Member constraints](./borrow-check/region-inference/member-constraints.md) + - [Placeholders and universes](./borrow-check/region-inference/placeholders-and-universes.md) + - [Closure constraints](./borrow-check/region-inference/closure-constraints.md) + - [Error reporting](./borrow-check/region-inference/error-reporting.md) + - [Two-phase-borrows](./borrow-check/two-phase-borrows.md) - [Closure capture inference](./closure.md) - [Async closures/"coroutine-closures"](coroutine-closures.md) diff --git a/src/doc/rustc-dev-guide/src/appendix/background.md b/src/doc/rustc-dev-guide/src/appendix/background.md index d36927e82f74..e76285080394 100644 --- a/src/doc/rustc-dev-guide/src/appendix/background.md +++ b/src/doc/rustc-dev-guide/src/appendix/background.md @@ -243,8 +243,7 @@ use in lambda calculus evaluation (see [this Wikipedia article][wikideb] for more). In `rustc`, we use de Bruijn indices to [represent generic types][sub]. [wikideb]: https://en.wikipedia.org/wiki/De_Bruijn_index -[sub]: ../ty_module/generic_arguments.md - +[sub]: ../ty-module/generic-arguments.md Here is a basic example of how de Bruijn indices might be used for closures (we don't actually do this in `rustc` though!): diff --git a/src/doc/rustc-dev-guide/src/appendix/code-index.md b/src/doc/rustc-dev-guide/src/appendix/code-index.md index bf9d3bd46564..3e1eed17eba6 100644 --- a/src/doc/rustc-dev-guide/src/appendix/code-index.md +++ b/src/doc/rustc-dev-guide/src/appendix/code-index.md @@ -39,5 +39,5 @@ Item | Kind | Short description | Chapter | [Emitting Diagnostics]: ../diagnostics.html [Macro expansion]: ../macro-expansion.html [Name resolution]: ../name-resolution.html -[Parameter Environment]: ../typing_parameter_envs.html +[Parameter Environment]: ../typing-parameter-envs.html [Trait Solving: Goals and Clauses]: ../traits/goals-and-clauses.html#domain-goals diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md index 901fb68c0513..43935b12a238 100644 --- a/src/doc/rustc-dev-guide/src/appendix/glossary.md +++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md @@ -53,10 +53,10 @@ Term | Meaning normalize | A general term for converting to a more canonical form, but in the case of rustc typically refers to [associated type normalization](../traits/goals-and-clauses.md#normalizeprojection---type). newtype | A wrapper around some other type (e.g., `struct Foo(T)` is a "newtype" for `T`). This is commonly used in Rust to give a stronger type for indices. niche | Invalid bit patterns for a type _that can be used_ for layout optimizations. Some types cannot have certain bit patterns. For example, the `NonZero*` integers or the reference `&T` cannot be represented by a 0 bitstring. This means the compiler can perform layout optimizations by taking advantage of the invalid "niche value". An example application for this is the [*Discriminant elision on `Option`-like enums*](https://rust-lang.github.io/unsafe-code-guidelines/layout/enums.html#discriminant-elision-on-option-like-enums), which allows using a type's niche as the ["tag"](#tag) for an `enum` without requiring a separate field. -NLL | Short for [non-lexical lifetimes](../borrow_check/region_inference.md), this is an extension to Rust's borrowing system to make it be based on the control-flow graph. +NLL | Short for [non-lexical lifetimes](../borrow-check/region-inference.md), this is an extension to Rust's borrowing system to make it be based on the control-flow graph. node-id or `NodeId` | An index identifying a particular node in the AST or HIR; gradually being phased out and replaced with `HirId`. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir). obligation | Something that must be proven by the trait system. ([see more](../traits/resolution.md)) -placeholder | **NOTE: skolemization is deprecated by placeholder** a way of handling subtyping around "for-all" types (e.g., `for<'a> fn(&'a u32)`) as well as solving higher-ranked trait bounds (e.g., `for<'a> T: Trait<'a>`). See [the chapter on placeholder and universes](../borrow_check/region_inference/placeholders_and_universes.md) for more details. +placeholder | **NOTE: skolemization is deprecated by placeholder** a way of handling subtyping around "for-all" types (e.g., `for<'a> fn(&'a u32)`) as well as solving higher-ranked trait bounds (e.g., `for<'a> T: Trait<'a>`). See [the chapter on placeholder and universes](../borrow-check/region-inference/placeholders-and-universes.md) for more details. point | Used in the NLL analysis to refer to some particular location in the MIR; typically used to refer to a node in the control-flow graph. projection | A general term for a "relative path", e.g. `x.f` is a "field projection", and `T::Item` is an ["associated type projection"](../traits/goals-and-clauses.md#trait-ref). promoted constants | Constants extracted from a function and lifted to static scope; see [this section](../mir/index.md#promoted) for more details. diff --git a/src/doc/rustc-dev-guide/src/borrow_check.md b/src/doc/rustc-dev-guide/src/borrow-check.md similarity index 95% rename from src/doc/rustc-dev-guide/src/borrow_check.md rename to src/doc/rustc-dev-guide/src/borrow-check.md index f206da42a82c..826bcf8582ca 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check.md +++ b/src/doc/rustc-dev-guide/src/borrow-check.md @@ -42,10 +42,10 @@ the [`mir_borrowck`] query. - Next, we perform a number of [dataflow analyses](./appendix/background.md#dataflow) that compute what data is moved and when. -- We then do a [second type check](borrow_check/type_check.md) across the MIR: +- We then do a [second type check](borrow-check/type-check.md) across the MIR: the purpose of this type check is to determine all of the constraints between different regions. -- Next, we do [region inference](borrow_check/region_inference.md), which computes +- Next, we do [region inference](borrow-check/region-inference.md), which computes the values of each region — basically, the points in the control-flow graph where each lifetime must be valid according to the constraints we collected. - At this point, we can compute the "borrows in scope" at each point. diff --git a/src/doc/rustc-dev-guide/src/borrow_check/drop_check.md b/src/doc/rustc-dev-guide/src/borrow-check/drop-check.md similarity index 100% rename from src/doc/rustc-dev-guide/src/borrow_check/drop_check.md rename to src/doc/rustc-dev-guide/src/borrow-check/drop-check.md diff --git a/src/doc/rustc-dev-guide/src/borrow_check/moves_and_initialization.md b/src/doc/rustc-dev-guide/src/borrow-check/moves-and-initialization.md similarity index 94% rename from src/doc/rustc-dev-guide/src/borrow_check/moves_and_initialization.md rename to src/doc/rustc-dev-guide/src/borrow-check/moves-and-initialization.md index 043db2f5354e..f9eaef8e2b46 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check/moves_and_initialization.md +++ b/src/doc/rustc-dev-guide/src/borrow-check/moves-and-initialization.md @@ -20,15 +20,15 @@ Consider this example: ```rust,ignore fn foo() { let a: Vec; - + // a is not initialized yet - + a = vec![22]; - + // a is initialized here - + std::mem::drop(a); // a is moved here - + // a is no longer initialized here let l = a.len(); //~ ERROR @@ -44,7 +44,7 @@ moves `a` into the call, and hence it becomes uninitialized again. To make it easier to peruse, this section is broken into a number of subsections: -- [Move paths](./moves_and_initialization/move_paths.html) the +- [Move paths](./moves-and-initialization/move-paths.md) the *move path* concept that we use to track which local variables (or parts of local variables, in some cases) are initialized. - TODO *Rest not yet written* =) diff --git a/src/doc/rustc-dev-guide/src/borrow_check/moves_and_initialization/move_paths.md b/src/doc/rustc-dev-guide/src/borrow-check/moves-and-initialization/move-paths.md similarity index 100% rename from src/doc/rustc-dev-guide/src/borrow_check/moves_and_initialization/move_paths.md rename to src/doc/rustc-dev-guide/src/borrow-check/moves-and-initialization/move-paths.md diff --git a/src/doc/rustc-dev-guide/src/borrow_check/opaque-types-region-inference-restrictions.md b/src/doc/rustc-dev-guide/src/borrow-check/opaque-types-region-inference-restrictions.md similarity index 99% rename from src/doc/rustc-dev-guide/src/borrow_check/opaque-types-region-inference-restrictions.md rename to src/doc/rustc-dev-guide/src/borrow-check/opaque-types-region-inference-restrictions.md index 9877dfc61e9c..3a060ccfa282 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check/opaque-types-region-inference-restrictions.md +++ b/src/doc/rustc-dev-guide/src/borrow-check/opaque-types-region-inference-restrictions.md @@ -158,7 +158,7 @@ See [#113971] for how we used to conflate the difference. [#113971]: https://github.com/rust-lang/rust/issues/113971 [SCC]: https://en.wikipedia.org/wiki/Strongly_connected_component -[member constraints]: ./region_inference/member_constraints.md +[member constraints]: region-inference/member-constraints.md **interaction with "once modulo regions" restriction** In the example above, note the opaque type in the signature is `Opaque<'a>` and the one in the @@ -195,7 +195,7 @@ fn test<'a>() -> Opaque<'a> { } ``` -**Motivation:** +**Motivation:** In closure bodies, external lifetimes, although being categorized as "universal" lifetimes, behave more like existential lifetimes in that the relations between them are not known ahead of time, instead their values are inferred just like existential lifetimes and the requirements are @@ -208,7 +208,7 @@ Here is an example that details how : ```rust type Opaque<'x, 'y> = impl Sized; -// +// fn test<'a, 'b>(s: &'a str) -> impl FnOnce() -> Opaque<'a, 'b> { move || { s } //~^ ERROR hidden type for `Opaque<'_, '_>` captures lifetime that does not appear in bounds diff --git a/src/doc/rustc-dev-guide/src/borrow_check/region_inference.md b/src/doc/rustc-dev-guide/src/borrow-check/region-inference.md similarity index 98% rename from src/doc/rustc-dev-guide/src/borrow_check/region_inference.md rename to src/doc/rustc-dev-guide/src/borrow-check/region-inference.md index ba67bec45b65..2a1c34df1a77 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check/region_inference.md +++ b/src/doc/rustc-dev-guide/src/borrow-check/region-inference.md @@ -34,14 +34,14 @@ The MIR-based region analysis consists of two major functions: - The [NLL RFC] also includes fairly thorough (and hopefully readable) coverage. -[cp]: ./region_inference/constraint_propagation.md +[cp]: ./region-inference/constraint-propagation.md [fvb]: ../appendix/background.md#free-vs-bound [`replace_regions_in_mir`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/nll/fn.replace_regions_in_mir.html [`compute_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/nll/fn.compute_regions.html [`RegionInferenceContext`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html [`solve`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#method.solve [NLL RFC]: https://rust-lang.github.io/rfcs/2094-nll.html -[MIR type checker]: ./type_check.md +[MIR type checker]: ./type-check.md ## Universal regions @@ -97,7 +97,7 @@ The kinds of region elements are as follows: - There is an element `!1` for each placeholder region `!1`. This corresponds (intuitively) to some unknown set of other elements – for details on placeholders, see the section - [placeholders and universes](region_inference/placeholders_and_universes.md). + [placeholders and universes](region-inference/placeholders-and-universes.md). ## Constraints diff --git a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/closure_constraints.md b/src/doc/rustc-dev-guide/src/borrow-check/region-inference/closure-constraints.md similarity index 100% rename from src/doc/rustc-dev-guide/src/borrow_check/region_inference/closure_constraints.md rename to src/doc/rustc-dev-guide/src/borrow-check/region-inference/closure-constraints.md diff --git a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/constraint_propagation.md b/src/doc/rustc-dev-guide/src/borrow-check/region-inference/constraint-propagation.md similarity index 98% rename from src/doc/rustc-dev-guide/src/borrow_check/region_inference/constraint_propagation.md rename to src/doc/rustc-dev-guide/src/borrow-check/region-inference/constraint-propagation.md index c3f8c03cb29f..580a0aebe9a4 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/constraint_propagation.md +++ b/src/doc/rustc-dev-guide/src/borrow-check/region-inference/constraint-propagation.md @@ -11,7 +11,7 @@ on one at a time (each of them is fairly independent from the others): - [member constraints][m_c] (`member R_m of [R_c...]`), which arise from impl Trait. [`propagate_constraints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/region_infer/struct.RegionInferenceContext.html#method.propagate_constraints -[m_c]: ./member_constraints.md +[m_c]: ./member-constraints.md In this chapter, we'll explain the "heart" of constraint propagation, covering both liveness and outlives constraints. @@ -29,7 +29,7 @@ given some set of constraints `{C}` and it computes a set of values - For each constraint C: - Update `Values` as needed to satisfy the constraint -[riv]: ../region_inference.md#region-variables +[riv]: ../region-inference.md#region-variables As a simple example, if we have a liveness constraint `R live at E`, then we can apply `Values(R) = Values(R) union {E}` to make the @@ -211,7 +211,7 @@ have already processed a given SCC or not. For each successor `S2`, once we have computed `S2`'s value, we can union those elements into the value for `S1`. (Although we have to be careful in this process to properly handle [higher-ranked -placeholders](./placeholders_and_universes.html). Note that the value +placeholders](./placeholders-and-universes.md). Note that the value for `S1` already contains the liveness constraints, since they were added in [`RegionInferenceContext::new`]. diff --git a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/error_reporting.md b/src/doc/rustc-dev-guide/src/borrow-check/region-inference/error-reporting.md similarity index 100% rename from src/doc/rustc-dev-guide/src/borrow_check/region_inference/error_reporting.md rename to src/doc/rustc-dev-guide/src/borrow-check/region-inference/error-reporting.md diff --git a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md b/src/doc/rustc-dev-guide/src/borrow-check/region-inference/lifetime-parameters.md similarity index 98% rename from src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md rename to src/doc/rustc-dev-guide/src/borrow-check/region-inference/lifetime-parameters.md index 2d337dbc020f..3795cea3c6bc 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md +++ b/src/doc/rustc-dev-guide/src/borrow-check/region-inference/lifetime-parameters.md @@ -54,7 +54,7 @@ In fact, the universal regions can be further subdivided based on where they were brought into scope (see the [`RegionClassification`] type). These subdivisions are not important for the topics discussed here, but become important when we consider [closure constraint -propagation](./closure_constraints.html), so we discuss them there. +propagation](./closure-constraints.md), so we discuss them there. [`RegionClassification`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/universal_regions/enum.RegionClassification.html#variant.Local diff --git a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/member_constraints.md b/src/doc/rustc-dev-guide/src/borrow-check/region-inference/member-constraints.md similarity index 100% rename from src/doc/rustc-dev-guide/src/borrow_check/region_inference/member_constraints.md rename to src/doc/rustc-dev-guide/src/borrow-check/region-inference/member-constraints.md diff --git a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/placeholders_and_universes.md b/src/doc/rustc-dev-guide/src/borrow-check/region-inference/placeholders-and-universes.md similarity index 100% rename from src/doc/rustc-dev-guide/src/borrow_check/region_inference/placeholders_and_universes.md rename to src/doc/rustc-dev-guide/src/borrow-check/region-inference/placeholders-and-universes.md diff --git a/src/doc/rustc-dev-guide/src/borrow_check/two_phase_borrows.md b/src/doc/rustc-dev-guide/src/borrow-check/two-phase-borrows.md similarity index 100% rename from src/doc/rustc-dev-guide/src/borrow_check/two_phase_borrows.md rename to src/doc/rustc-dev-guide/src/borrow-check/two-phase-borrows.md diff --git a/src/doc/rustc-dev-guide/src/borrow_check/type_check.md b/src/doc/rustc-dev-guide/src/borrow-check/type-check.md similarity index 100% rename from src/doc/rustc-dev-guide/src/borrow_check/type_check.md rename to src/doc/rustc-dev-guide/src/borrow-check/type-check.md diff --git a/src/doc/rustc-dev-guide/src/const-eval.md b/src/doc/rustc-dev-guide/src/const-eval.md index ca6a35a5e97e..a3fee034ec6e 100644 --- a/src/doc/rustc-dev-guide/src/const-eval.md +++ b/src/doc/rustc-dev-guide/src/const-eval.md @@ -35,7 +35,7 @@ They're the wrappers of the `const_eval` query. Statics are special; all other functions do not represent statics correctly and have thus assertions preventing their use on statics. -The `const_eval_*` functions use a [`ParamEnv`](./typing_parameter_envs.html) of environment +The `const_eval_*` functions use a [`ParamEnv`](./typing-parameter-envs.md) of environment in which the constant is evaluated (e.g. the function within which the constant is used) and a [`GlobalId`]. The `GlobalId` is made up of an `Instance` referring to a constant or static or of an `Instance` of a function and an index into the function's `Promoted` table. diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index 46d0dc23394a..83f4253a6a10 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -60,7 +60,7 @@ See [The Rust Book] for more details on Rust’s train release model. This is the only channel where unstable features are intended to be used, which happens via opt-in feature gates. -See [this chapter on implementing new features](./implementing_new_features.md) for more +See [this chapter on implementing new features](./implementing-new-features.md) for more information. [The Rust Book]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html diff --git a/src/doc/rustc-dev-guide/src/early_late_parameters.md b/src/doc/rustc-dev-guide/src/early-late-parameters.md similarity index 100% rename from src/doc/rustc-dev-guide/src/early_late_parameters.md rename to src/doc/rustc-dev-guide/src/early-late-parameters.md diff --git a/src/doc/rustc-dev-guide/src/feature-gates.md b/src/doc/rustc-dev-guide/src/feature-gates.md index 9806f73c483c..d2a517360714 100644 --- a/src/doc/rustc-dev-guide/src/feature-gates.md +++ b/src/doc/rustc-dev-guide/src/feature-gates.md @@ -12,7 +12,7 @@ mechanism][libs-gate]. See ["Stability in code"][adding] in the "Implementing new features" section for instructions. -[adding]: ./implementing_new_features.md#stability-in-code +[adding]: ./implementing-new-features.md#stability-in-code ## Removing a feature gate @@ -80,5 +80,5 @@ for instructions. There are additional steps you will need to take beyond just updating the declaration! -["Stability in code"]: ./implementing_new_features.md#stability-in-code -["Updating the feature-gate listing"]: ./stabilization_guide.md#updating-the-feature-gate-listing +["Stability in code"]: ./implementing-new-features.md#stability-in-code +["Updating the feature-gate listing"]: ./stabilization-guide.md#updating-the-feature-gate-listing diff --git a/src/doc/rustc-dev-guide/src/generic_parameters_summary.md b/src/doc/rustc-dev-guide/src/generic-parameters-summary.md similarity index 96% rename from src/doc/rustc-dev-guide/src/generic_parameters_summary.md rename to src/doc/rustc-dev-guide/src/generic-parameters-summary.md index da38ba0455c2..29a07e297e5e 100644 --- a/src/doc/rustc-dev-guide/src/generic_parameters_summary.md +++ b/src/doc/rustc-dev-guide/src/generic-parameters-summary.md @@ -16,7 +16,7 @@ trait Trait { The `ty::Generics` used for `foo` would contain `[U]` and a parent of `Some(Trait)`. `Trait` would have a `ty::Generics` containing `[Self, T]` with a parent of `None`. -The [`GenericParamDef`] struct is used to represent each individual generic parameter in a `ty::Generics` listing. The `GenericParamDef` struct contains information about the generic parameter, for example its name, defid, what kind of parameter it is (i.e. type, const, lifetime). +The [`GenericParamDef`] struct is used to represent each individual generic parameter in a `ty::Generics` listing. The `GenericParamDef` struct contains information about the generic parameter, for example its name, defid, what kind of parameter it is (i.e. type, const, lifetime). `GenericParamDef` also contains a `u32` index representing what position the parameter is (starting from the outermost parent), this is the value used to represent usages of generic parameters (more on this in the [chapter on representing types][ch_representing_types]). @@ -25,4 +25,4 @@ Interestingly, `ty::Generics` does not currently contain _every_ generic paramet [ch_representing_types]: ./ty.md [`ty::Generics`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Generics.html [`GenericParamDef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/generics/struct.GenericParamDef.html -[ch_binders]: ./ty_module/binders.md +[ch_binders]: ./ty-module/binders.md diff --git a/src/doc/rustc-dev-guide/src/implementing_new_features.md b/src/doc/rustc-dev-guide/src/implementing-new-features.md similarity index 99% rename from src/doc/rustc-dev-guide/src/implementing_new_features.md rename to src/doc/rustc-dev-guide/src/implementing-new-features.md index 4526a7af0f46..bb5c0bbba6e3 100644 --- a/src/doc/rustc-dev-guide/src/implementing_new_features.md +++ b/src/doc/rustc-dev-guide/src/implementing-new-features.md @@ -225,7 +225,7 @@ The below steps needs to be followed in order to implement a new unstable featur [`rustc_ast_passes::feature_gate::check_crate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast_passes/feature_gate/fn.check_crate.html [value the stability of Rust]: https://github.com/rust-lang/rfcs/blob/master/text/1122-language-semver.md [stability in code]: #stability-in-code -[here]: ./stabilization_guide.md +[here]: ./stabilization-guide.md [tracking issue]: #tracking-issues [add-feature-gate]: ./feature-gates.md#adding-a-feature-gate @@ -278,7 +278,7 @@ backward incompatible changes are generally no longer permitted To learn more about stabilization, see the [stabilization guide][stab]. -[stab]: ./stabilization_guide.md +[stab]: ./stabilization-guide.md [rust-blog]: https://github.com/rust-lang/blog.rust-lang.org/ [twir]: https://github.com/rust-lang/this-week-in-rust [twir-cft]: https://this-week-in-rust.org/blog/2025/01/22/this-week-in-rust-583/#calls-for-testing diff --git a/src/doc/rustc-dev-guide/src/memory.md b/src/doc/rustc-dev-guide/src/memory.md index f766a51898e4..24e7205a3565 100644 --- a/src/doc/rustc-dev-guide/src/memory.md +++ b/src/doc/rustc-dev-guide/src/memory.md @@ -54,14 +54,14 @@ represented as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`). defined and discussed in depth in the [`AdtDef and DefId`][adtdefid] section. - [`Predicate`] defines something the trait system has to prove (see [traits] module). -[`GenericArgs`]: ./ty_module/generic_arguments.md#the-genericargs-type -[adtdefid]: ./ty_module/generic_arguments.md#adtdef-and-defid +[`GenericArgs`]: ./ty-module/generic-arguments.md#the-genericargs-type +[adtdefid]: ./ty-module/generic-arguments.md#adtdef-and-defid [`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TraitRef.html [`AdtDef` and `DefId`]: ./ty.md#adts-representation [`def-id`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html [`GenericArgs`]: ./generic_arguments.html#GenericArgs [`mk_args`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.mk_args -[adtdefid]: ./ty_module/generic_arguments.md#adtdef-and-defid +[adtdefid]: ./ty-module/generic-arguments.md#adtdef-and-defid [`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html [`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TraitRef.html [`ty::TyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/sty/type.TyKind.html diff --git a/src/doc/rustc-dev-guide/src/normalization.md b/src/doc/rustc-dev-guide/src/normalization.md index 53e20f1c0db7..b458b04c1719 100644 --- a/src/doc/rustc-dev-guide/src/normalization.md +++ b/src/doc/rustc-dev-guide/src/normalization.md @@ -30,7 +30,7 @@ fn bar>() { } ``` -When an alias can't yet be normalized but may wind up normalizable in the [current environment](./typing_parameter_envs.md), we consider it to be an "ambiguous" alias. This can occur when an alias contains inference variables which prevent being able to determine how the trait is implemented: +When an alias can't yet be normalized but may wind up normalizable in the [current environment](./typing-parameter-envs.md), we consider it to be an "ambiguous" alias. This can occur when an alias contains inference variables which prevent being able to determine how the trait is implemented: ```rust fn foo() { // This alias is considered to be "ambiguous" @@ -113,7 +113,7 @@ fn bar() { foo::<{ FREE_CONST }>(); // The const arg is represented with some anonymous constant: // ```pseudo-rust - // const ANON: usize = FREE_CONST; + // const ANON: usize = FREE_CONST; // foo::(); // ``` } @@ -127,7 +127,7 @@ This is likely to change as const generics functionality is improved, for exampl There are two forms of normalization, structural (sometimes called *shallow*) and deep. Structural normalization should be thought of as only normalizing the "outermost" part of a type. On the other hand deep normalization will normalize *all* aliases in a type. -In practice structural normalization can result in more than just the outer layer of the type being normalized, but this behaviour should not be relied upon. Unnormalizable non-rigid aliases making use of bound variables (`for<'a>`) cannot be normalized by either kind of normalization. +In practice structural normalization can result in more than just the outer layer of the type being normalized, but this behaviour should not be relied upon. Unnormalizable non-rigid aliases making use of bound variables (`for<'a>`) cannot be normalized by either kind of normalization. As an example: conceptually, structurally normalizing the type `Vec<::Assoc>` would be a no-op, whereas deeply normalizing would give `Vec`. In practice even structural normalization would give `Vec`, though, again, this should not be relied upon. @@ -137,9 +137,9 @@ Changing the alias to use bound variables will result in different behaviour; `V Structurally normalizing aliases is a little bit more nuanced than replacing the alias with whatever it is defined as being equal to in its definition; the result of normalizing an alias should either be a rigid type or an inference variable (which will later be inferred to a rigid type). To accomplish this we do two things: -First, when normalizing an ambiguous alias it is normalized to an inference variable instead of leaving it as-is, this has two main effects: +First, when normalizing an ambiguous alias it is normalized to an inference variable instead of leaving it as-is, this has two main effects: - Even though an inference variable is not a rigid type, it will always wind up inferred *to* a rigid type so we ensure that the result of normalization will not need to be normalized again -- Inference variables are used in all cases where a type is non-rigid, allowing the rest of the compiler to not have to deal with *both* ambiguous aliases *and* inference variables +- Inference variables are used in all cases where a type is non-rigid, allowing the rest of the compiler to not have to deal with *both* ambiguous aliases *and* inference variables Secondly, instead of having normalization directly return the type specified in the definition of the alias, we normalize the type first before returning it[^1]. We do this so that normalization is idempotent/callers do not need to run it in a loop. @@ -207,7 +207,7 @@ In practice `query_normalize` is used for normalization in the borrow checker, a ##### `tcx.normalize_erasing_regions` -[`normalize_erasing_regions`][norm_erasing_regions] is generally used by parts of the compiler that are not doing type system analysis. This normalization entry point does not handle inference variables, lifetimes, or any diagnostics. Lints and codegen make heavy use of this entry point as they typically are working with fully inferred aliases that can be assumed to be well formed (or at least, are not responsible for erroring on). +[`normalize_erasing_regions`][norm_erasing_regions] is generally used by parts of the compiler that are not doing type system analysis. This normalization entry point does not handle inference variables, lifetimes, or any diagnostics. Lints and codegen make heavy use of this entry point as they typically are working with fully inferred aliases that can be assumed to be well formed (or at least, are not responsible for erroring on). [query_norm]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/at/struct.At.html#method.query_normalize [norm_erasing_regions]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.normalize_erasing_regions @@ -232,7 +232,7 @@ One of the big changes between the old and new solver is our approach to when we ### Old solver -All types are expected to be normalized as soon as possible, so that all types encountered in the type system are either rigid or an inference variable (which will later be inferred to a rigid term). +All types are expected to be normalized as soon as possible, so that all types encountered in the type system are either rigid or an inference variable (which will later be inferred to a rigid term). As a concrete example: equality of aliases is implemented by assuming they're rigid and recursively equating the generic arguments of the alias. @@ -242,7 +242,7 @@ It's expected that all types potentially contain ambiguous or unnormalized alias As a concrete example: equality of aliases is implemented by a custom goal kind ([`PredicateKind::AliasRelate`][aliasrelate]) so that it can handle normalization of the aliases itself instead of assuming all alias types being equated are rigid. -Despite this approach we still deeply normalize during [writeback][writeback] for performance/simplicity, so that types in the MIR can still be assumed to have been deeply normalized. +Despite this approach we still deeply normalize during [writeback][writeback] for performance/simplicity, so that types in the MIR can still be assumed to have been deeply normalized. [aliasrelate]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.PredicateKind.html#variant.AliasRelate [writeback]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/writeback/index.html @@ -257,7 +257,7 @@ It was a frequent occurrence that normalization calls would be missing, resultin ### Normalizing parameter environments -Another problem was that it was not possible to normalize `ParamEnv`s correctly in the old solver as normalization itself would expect a normalized `ParamEnv` in order to give correct results. See the chapter on `ParamEnv`s for more information: [`Typing/ParamEnv`s: Normalizing all bounds](./typing_parameter_envs.md#normalizing-all-bounds) +Another problem was that it was not possible to normalize `ParamEnv`s correctly in the old solver as normalization itself would expect a normalized `ParamEnv` in order to give correct results. See the chapter on `ParamEnv`s for more information: [`Typing/ParamEnv`s: Normalizing all bounds](./typing-parameter-envs.md#normalizing-all-bounds) ### Unnormalizable non-rigid aliases in higher ranked types @@ -269,7 +269,7 @@ Leaving the alias unnormalized would also be wrong as the old solver expects all Ultimately this means that it is not always possible to ensure all aliases inside of a value are rigid. -[universe]: borrow_check/region_inference/placeholders_and_universes.md#what-is-a-universe +[universe]: borrow-check/region-inference/placeholders-and-universes.md#what-is-a-universe [deeply_normalize]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/normalize/trait.NormalizeExt.html#tymethod.deeply_normalize ## Handling uses of diverging aliases diff --git a/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md b/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md index 42600ad87f8c..ac908493ee56 100644 --- a/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md +++ b/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md @@ -5,7 +5,7 @@ This kind of type inference is particularly complex because, unlike other kinds of type inference, it can work across functions and function bodies. -[hidden type]: ./borrow_check/region_inference/member_constraints.html?highlight=%22hidden%20type%22#member-constraints +[hidden type]: ./borrow-check/region-inference/member-constraints.html?highlight=%22hidden%20type%22#member-constraints [opaque type]: ./opaque-types-type-alias-impl-trait.md ## Running example diff --git a/src/doc/rustc-dev-guide/src/overview.md b/src/doc/rustc-dev-guide/src/overview.md index 1200a854f8ed..7858c09fe724 100644 --- a/src/doc/rustc-dev-guide/src/overview.md +++ b/src/doc/rustc-dev-guide/src/overview.md @@ -153,7 +153,7 @@ the final binary. [`simplify_try`]: https://github.com/rust-lang/rust/pull/66282 [`Lexer`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/lexer/struct.Lexer.html [`Ty<'tcx>`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html -[borrow checking]: borrow_check.md +[borrow checking]: borrow-check.md [codegen]: backend/codegen.md [hir]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/index.html [lex]: the-parser.md @@ -344,7 +344,7 @@ Compiler performance is a problem that we would like to improve on (and are always working on). One aspect of that is parallelizing `rustc` itself. -Currently, there is only one part of rustc that is parallel by default: +Currently, there is only one part of rustc that is parallel by default: [code generation](./parallel-rustc.md#Codegen). However, the rest of the compiler is still not yet parallel. There have been @@ -428,7 +428,7 @@ For more details on bootstrapping, see - Definition: [`rustc_middle/src/mir`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/index.html) - Definition of sources that manipulates the MIR: [`rustc_mir_build`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/index.html), [`rustc_mir_dataflow`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/index.html), [`rustc_mir_transform`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/index.html) - The Borrow Checker - - Guide: [MIR Borrow Check](borrow_check.md) + - Guide: [MIR Borrow Check](borrow-check.md) - Definition: [`rustc_borrowck`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/index.html) - Main entry point: [`mir_borrowck` query](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/fn.mir_borrowck.html) - `MIR` Optimizations diff --git a/src/doc/rustc-dev-guide/src/profiling.md b/src/doc/rustc-dev-guide/src/profiling.md index de06bd7cda7b..519d9b5488cb 100644 --- a/src/doc/rustc-dev-guide/src/profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling.md @@ -12,7 +12,7 @@ Depending on what you're trying to measure, there are several different approach See [their docs](https://github.com/rust-lang/measureme/blob/master/summarize/README.md) for more information. - If you want function level performance data or even just more details than the above approaches: - - Consider using a native code profiler such as [perf](profiling/with_perf.md) + - Consider using a native code profiler such as [perf](profiling/with-perf.md) - or [tracy](https://github.com/nagisa/rust_tracy_client) for a nanosecond-precision, full-featured graphical interface. @@ -23,7 +23,7 @@ Depending on what you're trying to measure, there are several different approach - If you want to profile memory usage, you can use various tools depending on what operating system you are using. - - For Windows, read our [WPA guide](profiling/wpa_profiling.md). + - For Windows, read our [WPA guide](profiling/wpa-profiling.md). ## Optimizing rustc's bootstrap times with `cargo-llvm-lines` diff --git a/src/doc/rustc-dev-guide/src/profiling/with_perf.md b/src/doc/rustc-dev-guide/src/profiling/with-perf.md similarity index 99% rename from src/doc/rustc-dev-guide/src/profiling/with_perf.md rename to src/doc/rustc-dev-guide/src/profiling/with-perf.md index e452dde5226d..50281b6b6008 100644 --- a/src/doc/rustc-dev-guide/src/profiling/with_perf.md +++ b/src/doc/rustc-dev-guide/src/profiling/with-perf.md @@ -62,7 +62,7 @@ cargo install addr2line --features="bin" Often we want to analyze a specific test from `perf.rust-lang.org`. The easiest way to do that is to use the [rustc-perf][rustc-perf] -benchmarking suite, this approach is described [here](with_rustc_perf.md). +benchmarking suite, this approach is described [here](with-rustc-perf.md). Instead of using the benchmark suite CLI, you can also profile the benchmarks manually. First, you need to clone the [rustc-perf][rustc-perf] repository: diff --git a/src/doc/rustc-dev-guide/src/profiling/with_rustc_perf.md b/src/doc/rustc-dev-guide/src/profiling/with-rustc-perf.md similarity index 100% rename from src/doc/rustc-dev-guide/src/profiling/with_rustc_perf.md rename to src/doc/rustc-dev-guide/src/profiling/with-rustc-perf.md diff --git a/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md b/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md similarity index 100% rename from src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md rename to src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md diff --git a/src/doc/rustc-dev-guide/src/solve/opaque-types.md b/src/doc/rustc-dev-guide/src/solve/opaque-types.md index ac038e354f53..6bb4534608db 100644 --- a/src/doc/rustc-dev-guide/src/solve/opaque-types.md +++ b/src/doc/rustc-dev-guide/src/solve/opaque-types.md @@ -51,7 +51,7 @@ We then check whether we're able to *semantically* unify the generic arguments o with the arguments of any opaque type already in the opaque types storage. If so, we unify the previously stored type with the expected type of this `normalizes-to` call: [source][eq-prev][^1]. -If not, we insert the expected type in the opaque types storage: [source][insert-storage][^2]. +If not, we insert the expected type in the opaque types storage: [source][insert-storage][^2]. Finally, we check whether the item bounds of the opaque hold for the expected type: [source][item-bounds-ck]. @@ -98,7 +98,7 @@ end up leaking placeholders. The handling of member constraints does not change in the new solver. See the [relevant existing chapter][member-constraints] for that. -[member-constraints]: ../borrow_check/region_inference/member_constraints.md +[member-constraints]: ../borrow-check/region-inference/member-constraints.md ## calling methods on opaque types diff --git a/src/doc/rustc-dev-guide/src/stability-guarantees.md b/src/doc/rustc-dev-guide/src/stability-guarantees.md index 21c4f3594d84..ed548c250c84 100644 --- a/src/doc/rustc-dev-guide/src/stability-guarantees.md +++ b/src/doc/rustc-dev-guide/src/stability-guarantees.md @@ -14,7 +14,7 @@ This page gives an overview of our stability guarantees. ## rustc-dev-guide links * [Stabilizing library features](./stability.md) -* [Stabilizing language features](./stabilization_guide.md) +* [Stabilizing language features](./stabilization-guide.md) * [What qualifies as a bug fix?](./bug-fix-procedure.md#what-qualifies-as-a-bug-fix) ## Exemptions diff --git a/src/doc/rustc-dev-guide/src/stability.md b/src/doc/rustc-dev-guide/src/stability.md index 3c4c65fdd5a8..f2f2dd909fae 100644 --- a/src/doc/rustc-dev-guide/src/stability.md +++ b/src/doc/rustc-dev-guide/src/stability.md @@ -4,7 +4,7 @@ This section is about the stability attributes and schemes that allow stable APIs to use unstable APIs internally in the rustc standard library. **NOTE**: this section is for *library* features, not *language* features. For instructions on -stabilizing a language feature see [Stabilizing Features](./stabilization_guide.md). +stabilizing a language feature see [Stabilizing Features](./stabilization-guide.md). ## unstable diff --git a/src/doc/rustc-dev-guide/src/stabilization_guide.md b/src/doc/rustc-dev-guide/src/stabilization-guide.md similarity index 99% rename from src/doc/rustc-dev-guide/src/stabilization_guide.md rename to src/doc/rustc-dev-guide/src/stabilization-guide.md index 6167546a2bc8..f159fad89596 100644 --- a/src/doc/rustc-dev-guide/src/stabilization_guide.md +++ b/src/doc/rustc-dev-guide/src/stabilization-guide.md @@ -49,7 +49,7 @@ The stabilization reports summarizes: The [*Stabilization Template*][srt] includes a series of questions that aim to surface connections between this feature and lang's subteams (e.g. types, opsem, lang-docs, etc.) and to identify items that are commonly overlooked. -[srt]: ./stabilization_report_template.md +[srt]: ./stabilization-report-template.md The stabilization report is typically posted as the main comment on the stabilization PR (see the next section). diff --git a/src/doc/rustc-dev-guide/src/stabilization_report_template.md b/src/doc/rustc-dev-guide/src/stabilization-report-template.md similarity index 99% rename from src/doc/rustc-dev-guide/src/stabilization_report_template.md rename to src/doc/rustc-dev-guide/src/stabilization-report-template.md index 793f7d7e45cf..328907904a6f 100644 --- a/src/doc/rustc-dev-guide/src/stabilization_report_template.md +++ b/src/doc/rustc-dev-guide/src/stabilization-report-template.md @@ -2,7 +2,7 @@ ## What is this? -This is a template for [stabilization reports](./stabilization_guide.md) of **language features**. The questions aim to solicit the details most often needed. These details help reviewers to identify potential problems upfront. Not all parts of the template will apply to every stabilization. If a question doesn't apply, explain briefly why. +This is a template for [stabilization reports](./stabilization-guide.md) of **language features**. The questions aim to solicit the details most often needed. These details help reviewers to identify potential problems upfront. Not all parts of the template will apply to every stabilization. If a question doesn't apply, explain briefly why. Copy everything after the separator and edit it as Markdown. Replace each *TODO* with your answer. diff --git a/src/doc/rustc-dev-guide/src/tests/perf.md b/src/doc/rustc-dev-guide/src/tests/perf.md index a0aa3c033174..567b2d7a97e4 100644 --- a/src/doc/rustc-dev-guide/src/tests/perf.md +++ b/src/doc/rustc-dev-guide/src/tests/perf.md @@ -19,7 +19,7 @@ The result of a perf run is a comparison between two versions of the compiler (by their commit hashes). You can also use `rustc-perf` to manually benchmark and profile the compiler -[locally](../profiling/with_rustc_perf.md). +[locally](../profiling/with-rustc-perf.md). ### Automatic perf runs diff --git a/src/doc/rustc-dev-guide/src/traits/caching.md b/src/doc/rustc-dev-guide/src/traits/caching.md index c44722a1d9a3..be72f6e89f9a 100644 --- a/src/doc/rustc-dev-guide/src/traits/caching.md +++ b/src/doc/rustc-dev-guide/src/traits/caching.md @@ -61,7 +61,7 @@ to be pretty clearly safe and also still retains a very high hit rate **TODO**: it looks like `pick_candidate_cache` no longer exists. In general, is this section still accurate at all? -[`ParamEnv`]: ../typing_parameter_envs.html +[`ParamEnv`]: ../typing-parameter-envs.html [`tcx`]: ../ty.html [#18290]: https://github.com/rust-lang/rust/issues/18290 [#22019]: https://github.com/rust-lang/rust/issues/22019 diff --git a/src/doc/rustc-dev-guide/src/traits/resolution.md b/src/doc/rustc-dev-guide/src/traits/resolution.md index ccb2b04268e8..f668d6ccf619 100644 --- a/src/doc/rustc-dev-guide/src/traits/resolution.md +++ b/src/doc/rustc-dev-guide/src/traits/resolution.md @@ -130,9 +130,9 @@ Once this first pass is done, we can examine the set of candidates. If it is a singleton set, then we are done: this is the only impl in scope that could possibly apply. Otherwise, we can **winnow** down the set of candidates by using where clauses and other conditions. Winnowing uses -`evaluate_candidate` to check whether the nested obligations may apply. -If this still leaves more than 1 candidate, we use ` fn candidate_should_be_dropped_in_favor_of` -to prefer some candidates over others. +`evaluate_candidate` to check whether the nested obligations may apply. +If this still leaves more than 1 candidate, we use ` fn candidate_should_be_dropped_in_favor_of` +to prefer some candidates over others. If this reduced set yields a single, unambiguous entry, we're good to go, @@ -181,7 +181,7 @@ in that list. If so, it is considered satisfied. More precisely, we want to check whether there is a where-clause obligation that is for the same trait (or some subtrait) and which can match against the obligation. -[parameter environment]: ../typing_parameter_envs.html +[parameter environment]: ../typing-parameter-envs.html Consider this simple example: @@ -240,8 +240,8 @@ confirmation is done based on (in this case) the `Target` type parameter. As mentioned above, during type checking, we do not store the results of trait selection. At codegen time, we repeat the trait selection to choose a particular -impl for each method call. This is done using `fn codegen_select_candidate`. -In this second selection, we do not consider any where-clauses to be in scope +impl for each method call. This is done using `fn codegen_select_candidate`. +In this second selection, we do not consider any where-clauses to be in scope because we know that each resolution will resolve to a particular impl. One interesting twist has to do with nested obligations. In general, in codegen, diff --git a/src/doc/rustc-dev-guide/src/ty-fold.md b/src/doc/rustc-dev-guide/src/ty-fold.md index 120a266e3536..bf0a51e6b7cf 100644 --- a/src/doc/rustc-dev-guide/src/ty-fold.md +++ b/src/doc/rustc-dev-guide/src/ty-fold.md @@ -99,7 +99,7 @@ it replaces it for something from the list of substitutions, otherwise recursive To replace it, calls [ty_for_param] and all that does is index into the list of substitutions with the index of the `Param`. -[a previous chapter]: ty_module/instantiating_binders.md +[a previous chapter]: ty-module/instantiating-binders.md [`TypeFoldable`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/trait.TypeFoldable.html [`TypeFolder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/trait.TypeFolder.html [`fold_ty`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/trait.TypeFolder.html#method.fold_ty diff --git a/src/doc/rustc-dev-guide/src/ty_module/binders.md b/src/doc/rustc-dev-guide/src/ty-module/binders.md similarity index 100% rename from src/doc/rustc-dev-guide/src/ty_module/binders.md rename to src/doc/rustc-dev-guide/src/ty-module/binders.md diff --git a/src/doc/rustc-dev-guide/src/ty_module/early_binder.md b/src/doc/rustc-dev-guide/src/ty-module/early-binder.md similarity index 100% rename from src/doc/rustc-dev-guide/src/ty_module/early_binder.md rename to src/doc/rustc-dev-guide/src/ty-module/early-binder.md diff --git a/src/doc/rustc-dev-guide/src/ty_module/generic_arguments.md b/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md similarity index 100% rename from src/doc/rustc-dev-guide/src/ty_module/generic_arguments.md rename to src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md diff --git a/src/doc/rustc-dev-guide/src/ty_module/instantiating_binders.md b/src/doc/rustc-dev-guide/src/ty-module/instantiating-binders.md similarity index 95% rename from src/doc/rustc-dev-guide/src/ty_module/instantiating_binders.md rename to src/doc/rustc-dev-guide/src/ty-module/instantiating-binders.md index 7e29b9543714..3c7408465c44 100644 --- a/src/doc/rustc-dev-guide/src/ty_module/instantiating_binders.md +++ b/src/doc/rustc-dev-guide/src/ty-module/instantiating-binders.md @@ -21,7 +21,7 @@ Unlike `EarlyBinder` we typically do not instantiate `Binder` with some concrete ## Instantiating with inference variables -We instantiate binders with inference variables when we are trying to infer a possible instantiation of the binder, e.g. calling higher ranked function pointers or attempting to use a higher ranked where-clause to prove some bound. For example, given the `higher_ranked_fn_ptr` from the example above, if we were to call it with `&10_u32` we would: +We instantiate binders with inference variables when we are trying to infer a possible instantiation of the binder, e.g. calling higher ranked function pointers or attempting to use a higher ranked where-clause to prove some bound. For example, given the `higher_ranked_fn_ptr` from the example above, if we were to call it with `&10_u32` we would: - Instantiate the binder with infer vars yielding a signature of `fn(&'?0 u32) -> &'?0 u32)` - Equate the type of the provided argument `&10_u32` (&'static u32) with the type in the signature, `&'?0 u32`, inferring `'?0 = 'static` - The provided arguments were correct as we were successfully able to unify the types of the provided arguments with the types of the arguments in fn ptr signature @@ -35,7 +35,7 @@ Instantiating binders with inference variables can be accomplished by using the ## Instantiating with placeholders -Placeholders are very similar to `Ty/ConstKind::Param`/`ReEarlyParam`, they represent some unknown type that is only equal to itself. `Ty`/`Const` and `Region` all have a [`Placeholder`] variant that is comprised of a [`Universe`] and a [`BoundVar`]. +Placeholders are very similar to `Ty/ConstKind::Param`/`ReEarlyParam`, they represent some unknown type that is only equal to itself. `Ty`/`Const` and `Region` all have a [`Placeholder`] variant that is comprised of a [`Universe`] and a [`BoundVar`]. The `Universe` tracks which binder the placeholder originated from, and the `BoundVar` tracks which parameter on said binder that this placeholder corresponds to. Equality of placeholders is determined solely by whether the universes are equal and the `BoundVar`s are equal. See the [chapter on Placeholders and Universes][ch_placeholders_universes] for more information. @@ -49,7 +49,7 @@ Note: in the original example of this chapter it was mentioned that we should no ### Why have both `RePlaceholder` and `ReBound`? -You may be wondering why we have both of these variants, afterall the data stored in `Placeholder` is effectively equivalent to that of `ReBound`: something to track which binder, and an index to track which parameter the `Binder` introduced. +You may be wondering why we have both of these variants, afterall the data stored in `Placeholder` is effectively equivalent to that of `ReBound`: something to track which binder, and an index to track which parameter the `Binder` introduced. The main reason for this is that `Bound` is a more syntactic representation of bound variables whereas `Placeholder` is a more semantic representation. As a concrete example: ```rust @@ -77,7 +77,7 @@ Given these trait implementations `u32: Bar` should _not_ hold. `&'a u32` only i This end result is incorrect as we had two separate binders introducing their own generic parameters, the trait bound should have ended up as something like `for<'a1, 'a2> &'^1 u32: Other<'^0>` which is _not_ satisfied by the `impl<'a> Other<'a> for &'a u32`. While in theory we could make this work it would be quite involved and more complex than the current setup, we would have to: -- "rewrite" bound variables to have a higher `DebruijnIndex` whenever instantiating a `Binder`/`EarlyBinder` with a `Bound` ty/const/region +- "rewrite" bound variables to have a higher `DebruijnIndex` whenever instantiating a `Binder`/`EarlyBinder` with a `Bound` ty/const/region - When inferring an inference variable to a bound var, if that bound var is from a binder entered after creating the infer var, we would have to lower the `DebruijnIndex` of the var. - Separately track what binder an inference variable was created inside of, also what the innermost binder it can name parameters from (currently we only have to track the latter) - When resolving inference variables rewrite any bound variables according to the current binder depth of the infcx @@ -90,18 +90,18 @@ where for<'a> T: Trait<'a, for<'b> fn(&'b T, &'a u32)> { ... } ``` -That where clause would be written as: -`for<'a> T: Trait<'^0, for<'b> fn(&'^0 T, &'^1_0 u32)>` +That where clause would be written as: +`for<'a> T: Trait<'^0, for<'b> fn(&'^0 T, &'^1_0 u32)>` Despite there being two references to the `'a` parameter they are both represented differently: `^0` and `^1_0`, due to the fact that the latter usage is nested under a second `Binder` for the inner function pointer type. This is in contrast to `Placeholder` ty/const/regions which do not have this limitation due to the fact that `Universe`s are specific to the current `InferCtxt` not the usage site of the parameter. -It is trivially possible to instantiate `EarlyBinder`s and unify inference variables with existing `Placeholder`s as no matter what context the `Placeholder` is in, it will have the same representation. As an example if we were to instantiate the binder on the higher ranked where clause from above, it would be represented like so: -`T: Trait<'!1_0, for<'b> fn(&'^0 T, &'!1_0 u32)>` +It is trivially possible to instantiate `EarlyBinder`s and unify inference variables with existing `Placeholder`s as no matter what context the `Placeholder` is in, it will have the same representation. As an example if we were to instantiate the binder on the higher ranked where clause from above, it would be represented like so: +`T: Trait<'!1_0, for<'b> fn(&'^0 T, &'!1_0 u32)>` the `RePlaceholder` representation for both usages of `'a` are the same despite one being underneath another `Binder`. -If we were to then instantiate the binder on the function pointer we would get a type such as: -`fn(&'!2_0 T, ^'!1_0 u32)` +If we were to then instantiate the binder on the function pointer we would get a type such as: +`fn(&'!2_0 T, ^'!1_0 u32)` the `RePlaceholder` for the `'b` parameter is in a higher universe to track the fact that its binder was instantiated after the binder for `'a`. ## Instantiating with `ReLateParam` @@ -119,8 +119,8 @@ impl Trait for Whatever { b } } -``` -the lifetime `'a` in the type `&'a u32` in the function body would be represented as: +``` +the lifetime `'a` in the type `&'a u32` in the function body would be represented as: ``` ReLateParam( {impl#0}::foo, @@ -135,10 +135,10 @@ Generally whenever we have a `Binder` for late bound parameters on a function/cl As a concrete example, accessing the signature of a function we are type checking will be represented as `EarlyBinder>`. As we are already "inside" of these binders, we would call `instantiate_identity` followed by `liberate_late_bound_regions`. [`liberate_late_bound_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.liberate_late_bound_regions -[representing-types]: param_ty_const_regions.md +[representing-types]: param-ty-const-regions.md [`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html [`enter_forall`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/struct.InferCtxt.html#method.enter_forall -[ch_placeholders_universes]: ../borrow_check/region_inference/placeholders_and_universes.md +[ch_placeholders_universes]: ../borrow-check/region-inference/placeholders-and-universes.md [`instantiate_binder_with_fresh_vars`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/struct.InferCtxt.html#method.instantiate_binder_with_fresh_vars [`InferCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/struct.InferCtxt.html [`EarlyBinder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.EarlyBinder.html diff --git a/src/doc/rustc-dev-guide/src/ty_module/param_ty_const_regions.md b/src/doc/rustc-dev-guide/src/ty-module/param-ty-const-regions.md similarity index 97% rename from src/doc/rustc-dev-guide/src/ty_module/param_ty_const_regions.md rename to src/doc/rustc-dev-guide/src/ty-module/param-ty-const-regions.md index 493693c9a440..ce4e887862c7 100644 --- a/src/doc/rustc-dev-guide/src/ty_module/param_ty_const_regions.md +++ b/src/doc/rustc-dev-guide/src/ty-module/param-ty-const-regions.md @@ -49,9 +49,9 @@ impl Foo { } ``` -Concretely given the `ty::Generics` for the item the parameter is defined on, if the index is `2` then starting from the root `parent`, it will be the third parameter to be introduced. For example in the above example, `Z` has index `2` and is the third generic parameter to be introduced, starting from the `impl` block. +Concretely given the `ty::Generics` for the item the parameter is defined on, if the index is `2` then starting from the root `parent`, it will be the third parameter to be introduced. For example in the above example, `Z` has index `2` and is the third generic parameter to be introduced, starting from the `impl` block. -The index fully defines the `Ty` and is the only part of `TyKind::Param` that matters for reasoning about the code we are compiling. +The index fully defines the `Ty` and is the only part of `TyKind::Param` that matters for reasoning about the code we are compiling. Generally we do not care what the name is and only use the index. The name is included for diagnostics and debug logs as otherwise it would be incredibly difficult to understand the output, i.e. `Vec: Sized` vs `Vec: Sized`. In debug output, parameter types are @@ -59,7 +59,7 @@ often printed out as `{name}/#{index}`, for example in the function `foo` if we An alternative representation would be to only have the name, however using an index is more efficient as it means we can index into `GenericArgs` when instantiating generic parameters with some arguments. We would otherwise have to store `GenericArgs` as a `HashMap` and do a hashmap lookup everytime we used a generic item. -In theory an index would also allow for having multiple distinct parameters that use the same name, e.g. +In theory an index would also allow for having multiple distinct parameters that use the same name, e.g. `impl Foo { fn bar() { .. } }`. The rules against shadowing make this difficult but those language rules could change in the future. @@ -85,9 +85,9 @@ fn foo<'a, 'b, T: 'a>(one: T, two: &'a &'b u32) -> &'b u32 { `RegionKind::LateParam` is discussed more in the chapter on [instantiating binders][ch_instantiating_binders]. -[ch_early_late_bound]: ../early_late_parameters.md +[ch_early_late_bound]: ../early-late-parameters.md [ch_binders]: ./binders.md -[ch_instantiating_binders]: ./instantiating_binders.md +[ch_instantiating_binders]: ./instantiating-binders.md [`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html [`RegionKind::EarlyParam`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.RegionKind.html#variant.ReEarlyParam [`RegionKind::LateParam`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.RegionKind.html#variant.ReLateParam diff --git a/src/doc/rustc-dev-guide/src/typing_parameter_envs.md b/src/doc/rustc-dev-guide/src/typing-parameter-envs.md similarity index 100% rename from src/doc/rustc-dev-guide/src/typing_parameter_envs.md rename to src/doc/rustc-dev-guide/src/typing-parameter-envs.md diff --git a/src/doc/rustc-dev-guide/src/walkthrough.md b/src/doc/rustc-dev-guide/src/walkthrough.md index 5ba89f984a70..94d7ec7376db 100644 --- a/src/doc/rustc-dev-guide/src/walkthrough.md +++ b/src/doc/rustc-dev-guide/src/walkthrough.md @@ -284,6 +284,6 @@ A note is added to the [Release notes][relnotes] about the feature. [stab]: https://github.com/rust-lang/rust/pull/56245 -Steps to stabilize the feature can be found at [Stabilizing Features](./stabilization_guide.md). +Steps to stabilize the feature can be found at [Stabilizing Features](./stabilization-guide.md). [relnotes]: https://github.com/rust-lang/rust/blob/HEAD/RELEASES.md From db142559a2a13bcaa0f987ce0d0978369b60cad8 Mon Sep 17 00:00:00 2001 From: Redddy Date: Tue, 20 Jan 2026 18:48:45 +0900 Subject: [PATCH 079/978] Add link to internals.rust-lang.org in walkthrough --- src/doc/rustc-dev-guide/src/walkthrough.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/walkthrough.md b/src/doc/rustc-dev-guide/src/walkthrough.md index 5ba89f984a70..7a36b3207633 100644 --- a/src/doc/rustc-dev-guide/src/walkthrough.md +++ b/src/doc/rustc-dev-guide/src/walkthrough.md @@ -97,7 +97,7 @@ If that sounds like a lot of work, it's because it is. But no fear! Even if you're not a compiler hacker, you can get great feedback by doing a _pre-RFC_. This is an _informal_ discussion of the idea. -The best place to do this is internals.rust-lang.org. +The best place to do this is [internals.rust-lang.org](https://internals.rust-lang.org). Your post doesn't have to follow any particular structure. It doesn't even need to be a cohesive idea. Generally, you will get tons of feedback that you can integrate back to produce a good RFC. From f28c32abc6209c342c8af8a36b6f518b0144e9c3 Mon Sep 17 00:00:00 2001 From: Redddy Date: Tue, 20 Jan 2026 21:43:50 +0900 Subject: [PATCH 080/978] Document experimental RFC process in walkthrough --- src/doc/rustc-dev-guide/src/walkthrough.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/walkthrough.md b/src/doc/rustc-dev-guide/src/walkthrough.md index 7a36b3207633..24a1e16a979c 100644 --- a/src/doc/rustc-dev-guide/src/walkthrough.md +++ b/src/doc/rustc-dev-guide/src/walkthrough.md @@ -159,6 +159,17 @@ Here is the tracking issue on for our [`?` macro feature][tracking]. [tracking]: https://github.com/rust-lang/rust/issues/48075 +## Experimental RFC (eRFC) + +An eRFC is a variant of the RFC process used for complex features wherethe high-level need +is clear, but the design space is too large to settle on a detailed specification upfront. +Instead of providing a final design, an eRFC outlines a high-level strategy to authorize +a period of active experimentation. This allows the team to implement the feature behind +a feature gate and gather practical data, which then informs a subsequent formal RFC for stabilization. +While this process was used for major features like coroutines, the explicit "eRFC" label +is rarely used today. The project now generally prefers approving a standard RFC for an initial +version and iterating on it through the nightly channel before final stabilization. + ## Implementation From 156cb44ab008da476a3a5dbe81d3517ebb5cb60d Mon Sep 17 00:00:00 2001 From: Redddy Date: Tue, 20 Jan 2026 21:53:25 +0900 Subject: [PATCH 081/978] Add link to RFC2033 in walkthrough --- src/doc/rustc-dev-guide/src/walkthrough.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/walkthrough.md b/src/doc/rustc-dev-guide/src/walkthrough.md index 24a1e16a979c..0522e9d444a9 100644 --- a/src/doc/rustc-dev-guide/src/walkthrough.md +++ b/src/doc/rustc-dev-guide/src/walkthrough.md @@ -166,9 +166,11 @@ is clear, but the design space is too large to settle on a detailed specificatio Instead of providing a final design, an eRFC outlines a high-level strategy to authorize a period of active experimentation. This allows the team to implement the feature behind a feature gate and gather practical data, which then informs a subsequent formal RFC for stabilization. -While this process was used for major features like coroutines, the explicit "eRFC" label -is rarely used today. The project now generally prefers approving a standard RFC for an initial -version and iterating on it through the nightly channel before final stabilization. +While this process was used for major features like coroutines ([see RFC2033][rfc2033]), +the explicit "eRFC" label is rarely used today. The project now generally prefers approving a standard +RFC for an initial version and iterating on it through the nightly channel before final stabilization. + +[rfc2033]: https://github.com/rust-lang/rfcs/pull/2033#issuecomment-309057591 From 012c4603b720f9d0a402d6ca2620006abcce2acb Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 27 Dec 2025 17:17:54 +0100 Subject: [PATCH 082/978] `c_variadic`: use `Clone` instead of LLVM `va_copy` --- src/intrinsic/mod.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 36ea76cbc51a..553e4d3d2fe0 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -391,9 +391,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc sym::breakpoint => { unimplemented!(); } - sym::va_copy => { - unimplemented!(); - } sym::va_arg => { unimplemented!(); } From 8fe3738c611c2f1d04b1a422e43c12d6741294f2 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Tue, 20 Jan 2026 18:39:02 +0000 Subject: [PATCH 083/978] Prepare for merging from rust-lang/rust This updates the rust-version file to 5c49c4f7c8393c861b849441d27f5d40e0f1e33b. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index b53a66c66751..d6e02b0dd2b2 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -44a5b55557c26353f388400d7da95527256fe260 +5c49c4f7c8393c861b849441d27f5d40e0f1e33b From 307b9d974a873e33fd3e67573881160007830b87 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 20 Jan 2026 20:50:10 +0200 Subject: [PATCH 084/978] fix dangling reference --- src/doc/rustc-dev-guide/src/tests/compiletest.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 7f22bc27600c..82708be16f03 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -439,6 +439,8 @@ The tests in [`tests/build-std`] check that `-Zbuild-std` works. This is current just a run-make test suite with a single recipe. The recipe generates test cases and runs them in parallel. +[`tests/build-std`]: https://github.com/rust-lang/rust/tree/HEAD/tests/build-std + #### Using Rust recipes Each test should be in a separate directory with a `rmake.rs` Rust program, From b75e040c76cedba7dcc8b6a0565c9a36ce32a1c6 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 20 Jan 2026 20:51:45 +0200 Subject: [PATCH 085/978] fix grammar --- src/doc/rustc-dev-guide/src/tests/compiletest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 82708be16f03..3d482ddc5423 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -80,7 +80,7 @@ The following test suites are available, with links for more information: ### The build-std test suite -[`build-std`](#build-std-tests) test that -Zbuild-std works. +[`build-std`](#build-std-tests) tests that -Zbuild-std works. ### Rustdoc test suites From 5c8ba2643a9b8c2734b998dbc888202f26ee521b Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 20 Jan 2026 20:53:14 +0200 Subject: [PATCH 086/978] missing pause --- src/doc/rustc-dev-guide/src/tests/ui.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index e13419d1e01c..8e3c4c133a3c 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -139,7 +139,7 @@ prefixing each source line are replaced with `LL`). In extremely rare situations, this mode can be disabled with the directive `//@ compile-flags: -Z ui-testing=no`. -When using `-Z ui-testing=no` the `--diagnostic-width` argument should also +When using `-Z ui-testing=no`, the `--diagnostic-width` argument should also be set to avoid tests failing or passing depending on the width of the terminal from which the UI test suite is being run. From 19bfad06939cea13de4729b448f8a2aa0c10abde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 6 Jan 2026 23:40:21 +0100 Subject: [PATCH 087/978] Introduce `AssocTag::descr` & refactor in the vicinity --- clippy_utils/src/ty/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index a90d64e972c1..c1be4acc7068 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -1226,7 +1226,7 @@ pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_n .associated_items(did) .filter_by_name_unhygienic(method_name) .next() - .filter(|item| item.as_tag() == AssocTag::Fn) + .filter(|item| item.tag() == AssocTag::Fn) }) } else { None From 454842a8d3320e3e7d4efa36164ef9468a4c0d90 Mon Sep 17 00:00:00 2001 From: joboet Date: Fri, 12 Dec 2025 13:23:48 +0100 Subject: [PATCH 088/978] update `dbg!` clippy lint --- clippy_lints/src/dbg_macro.rs | 80 +++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index 152516baf734..9197870cb695 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -5,7 +5,7 @@ use clippy_utils::macros::{MacroCall, macro_backtrace}; use clippy_utils::source::snippet_with_applicability; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::{Closure, ClosureKind, CoroutineKind, Expr, ExprKind, LetStmt, LocalSource, Node, Stmt, StmtKind}; +use rustc_hir::{Arm, Closure, ClosureKind, CoroutineKind, Expr, ExprKind, LetStmt, LocalSource, Node, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::{Span, SyntaxContext, sym}; @@ -90,33 +90,27 @@ impl LateLintPass<'_> for DbgMacro { (macro_call.span, String::from("()")) } }, - // dbg!(1) - ExprKind::Match(val, ..) => ( - macro_call.span, - snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability) - .to_string(), - ), - // dbg!(2, 3) - ExprKind::Tup( - [ - Expr { - kind: ExprKind::Match(first, ..), - .. - }, - .., - Expr { - kind: ExprKind::Match(last, ..), - .. - }, - ], - ) => { - let snippet = snippet_with_applicability( - cx, - first.span.source_callsite().to(last.span.source_callsite()), - "..", - &mut applicability, - ); - (macro_call.span, format!("({snippet})")) + ExprKind::Match(first, arms, _) => { + let vals = collect_vals(first, arms); + let suggestion = match vals.as_slice() { + // dbg!(1) => 1 + &[val] => { + snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability) + .to_string() + } + // dbg!(2, 3) => (2, 3) + &[first, .., last] => { + let snippet = snippet_with_applicability( + cx, + first.span.source_callsite().to(last.span.source_callsite()), + "..", + &mut applicability, + ); + format!("({snippet})") + } + _ => unreachable!(), + }; + (macro_call.span, suggestion) }, _ => unreachable!(), }; @@ -169,3 +163,33 @@ fn is_async_move_desugar<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx fn first_dbg_macro_in_expansion(cx: &LateContext<'_>, span: Span) -> Option { macro_backtrace(span).find(|mc| cx.tcx.is_diagnostic_item(sym::dbg_macro, mc.def_id)) } + +/// Extracts all value expressions from the `match`-tree generated by `dbg!`. +/// +/// E.g. from +/// ```rust, ignore +/// match 1 { +/// tmp_1 => match 2 { +/// tmp_2 => { +/// /* printing */ +/// (tmp_1, tmp_2) +/// } +/// } +/// } +/// ``` +/// this extracts `1` and `2`. +fn collect_vals<'hir>(first: &'hir Expr<'hir>, mut arms: &'hir [Arm<'hir>]) -> Vec<&'hir Expr<'hir>> { + let mut vals = vec![first]; + loop { + let [arm] = arms else { unreachable!("dbg! macro expansion only has single-arm matches") }; + + match is_async_move_desugar(arm.body).unwrap_or(arm.body).peel_drop_temps().kind { + ExprKind::Block(..) => return vals, + ExprKind::Match(val, a, _) => { + vals.push(val); + arms = a; + } + _ => unreachable!("dbg! macro expansion only results in block or match expressions"), + } + } +} From 7e39015fb549964a749557d66eeac0765442387e Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Wed, 21 Jan 2026 18:40:00 +0000 Subject: [PATCH 089/978] Fix `@needs-backends` compiletest directive --- src/tools/compiletest/src/directives/needs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/directives/needs.rs b/src/tools/compiletest/src/directives/needs.rs index 32ce6cf7b989..168d5e9eb649 100644 --- a/src/tools/compiletest/src/directives/needs.rs +++ b/src/tools/compiletest/src/directives/needs.rs @@ -290,7 +290,7 @@ pub(super) fn handle_needs( } // Handled elsewhere. - if name == "needs-llvm-components" { + if name == "needs-llvm-components" || name == "needs-backends" { return IgnoreDecision::Continue; } From 01290cc9ac126a6289e40028baa7fd53b689b651 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Wed, 21 Jan 2026 16:23:55 +0000 Subject: [PATCH 090/978] Fix `SourceFile::normalized_byte_pos` This method was broken by 258ace6, which changed `self.normalized_pos` to use relative offsets however this method continued to compare against an absolute offset. Also adds a regression test for the issue that this method was originally introduced to fix. --- compiler/rustc_span/src/lib.rs | 14 ++++++-------- src/tools/tidy/src/ui_tests.rs | 1 + tests/ui/asm/.gitattributes | 2 ++ tests/ui/asm/normalize-offsets-for-crlf.rs | 14 ++++++++++++++ tests/ui/asm/normalize-offsets-for-crlf.s | 13 +++++++++++++ tests/ui/asm/normalize-offsets-for-crlf.stderr | 10 ++++++++++ 6 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 tests/ui/asm/.gitattributes create mode 100644 tests/ui/asm/normalize-offsets-for-crlf.rs create mode 100644 tests/ui/asm/normalize-offsets-for-crlf.s create mode 100644 tests/ui/asm/normalize-offsets-for-crlf.stderr diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 1c430099835b..16d015638e0a 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -2426,14 +2426,12 @@ impl SourceFile { /// normalized one. Hence we need to convert those offsets to the normalized /// form when constructing spans. pub fn normalized_byte_pos(&self, offset: u32) -> BytePos { - let diff = match self - .normalized_pos - .binary_search_by(|np| (np.pos.0 + np.diff).cmp(&(self.start_pos.0 + offset))) - { - Ok(i) => self.normalized_pos[i].diff, - Err(0) => 0, - Err(i) => self.normalized_pos[i - 1].diff, - }; + let diff = + match self.normalized_pos.binary_search_by(|np| (np.pos.0 + np.diff).cmp(&offset)) { + Ok(i) => self.normalized_pos[i].diff, + Err(0) => 0, + Err(i) => self.normalized_pos[i - 1].diff, + }; BytePos::from_u32(self.start_pos.0 + offset - diff) } diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index bf51810810a6..e448fcdbd95a 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -150,6 +150,7 @@ fn check_unexpected_extension(check: &mut RunningCheck, file_path: &Path, ext: & const EXTENSION_EXCEPTION_PATHS: &[&str] = &[ "tests/ui/asm/named-asm-labels.s", // loading an external asm file to test named labels lint + "tests/ui/asm/normalize-offsets-for-crlf.s", // loading an external asm file to test CRLF normalization "tests/ui/codegen/mismatched-data-layout.json", // testing mismatched data layout w/ custom targets "tests/ui/check-cfg/my-awesome-platform.json", // testing custom targets with cfgs "tests/ui/argfile/commandline-argfile-badutf8.args", // passing args via a file diff --git a/tests/ui/asm/.gitattributes b/tests/ui/asm/.gitattributes new file mode 100644 index 000000000000..5d6f83c0e18c --- /dev/null +++ b/tests/ui/asm/.gitattributes @@ -0,0 +1,2 @@ +# Disable EOL normalization, as it is deliberately denormalized +normalize-offsets-for-crlf.s -text diff --git a/tests/ui/asm/normalize-offsets-for-crlf.rs b/tests/ui/asm/normalize-offsets-for-crlf.rs new file mode 100644 index 000000000000..7b4ec386ebb0 --- /dev/null +++ b/tests/ui/asm/normalize-offsets-for-crlf.rs @@ -0,0 +1,14 @@ +// Byte positions into inline assembly reported by codegen errors require normalization or else +// they may not identify the appropriate span. Worse still, an ICE can occur if the erroneous +// span begins or ends part-way through a multibyte character. +// +// Regression test for https://github.com/rust-lang/rust/issues/110885 + +// This test is tied to assembler syntax and errors, which can vary by backend and architecture. +//@only-x86_64 +//@needs-backends: llvm +//@build-fail + +//~? ERROR instruction mnemonic +std::arch::global_asm!(include_str!("normalize-offsets-for-crlf.s")); +fn main() {} diff --git a/tests/ui/asm/normalize-offsets-for-crlf.s b/tests/ui/asm/normalize-offsets-for-crlf.s new file mode 100644 index 000000000000..ec48aad44123 --- /dev/null +++ b/tests/ui/asm/normalize-offsets-for-crlf.s @@ -0,0 +1,13 @@ +// This file contains (some) CRLF line endings. When codegen reports an error, the byte +// offsets into this file that it identifies require normalization or else they will not +// identify the appropriate span. Worse still, an ICE can result if the erroneous span +// begins or ends part-way through a multibyte character such as £. +non_existent_mnemonic + +// Without normalization, the three CRLF line endings below cause the diagnostic on the +// `non_existent_mnemonic` above to be spanned three bytes backward, and thus begin +// part-way inside the multibyte character in the preceding comment. +// +// NOTE: The lines of this note DELIBERATELY end with CRLF - DO NOT strip/convert them! +// It may not be obvious if you accidentally do, eg `git diff` may appear to show +// that the lines have been updated to the exact same content. diff --git a/tests/ui/asm/normalize-offsets-for-crlf.stderr b/tests/ui/asm/normalize-offsets-for-crlf.stderr new file mode 100644 index 000000000000..28f5510308be --- /dev/null +++ b/tests/ui/asm/normalize-offsets-for-crlf.stderr @@ -0,0 +1,10 @@ +error: invalid instruction mnemonic 'non_existent_mnemonic' + | +note: instantiated into assembly here + --> :6:1 + | +LL | non_existent_mnemonic + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From e8c449dfbd2687eedf4a850b7e4e22460163c1ea Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Mon, 19 Jan 2026 10:33:40 +0100 Subject: [PATCH 091/978] Move assert_matches to planned stable path --- clippy_utils/src/ty/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index a90d64e972c1..53ad6675ab07 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -29,7 +29,10 @@ use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; use rustc_trait_selection::traits::{Obligation, ObligationCause}; +#[cfg(bootstrap)] use std::assert_matches::debug_assert_matches; +#[cfg(not(bootstrap))] +use std::debug_assert_matches; use std::collections::hash_map::Entry; use std::{iter, mem}; From 76a536c5901dbe8b5a805f96cd6f4f89cfec3ce3 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Thu, 22 Jan 2026 00:17:38 +0100 Subject: [PATCH 092/978] test: remove `unwrap.rs` The file is testing `unwrap_used`, but that's already covered by the `unwrap_expect_used.rs` test file --- tests/ui/unwrap.rs | 22 ---------------------- tests/ui/unwrap.stderr | 31 ------------------------------- 2 files changed, 53 deletions(-) delete mode 100644 tests/ui/unwrap.rs delete mode 100644 tests/ui/unwrap.stderr diff --git a/tests/ui/unwrap.rs b/tests/ui/unwrap.rs deleted file mode 100644 index 3191b396f99b..000000000000 --- a/tests/ui/unwrap.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![warn(clippy::unwrap_used)] -#![allow(clippy::unnecessary_literal_unwrap)] - -fn unwrap_option() { - let opt = Some(0); - let _ = opt.unwrap(); - //~^ unwrap_used -} - -fn unwrap_result() { - let res: Result = Ok(0); - let _ = res.unwrap(); - //~^ unwrap_used - - let _ = res.unwrap_err(); - //~^ unwrap_used -} - -fn main() { - unwrap_option(); - unwrap_result(); -} diff --git a/tests/ui/unwrap.stderr b/tests/ui/unwrap.stderr deleted file mode 100644 index c242541a6bd7..000000000000 --- a/tests/ui/unwrap.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error: used `unwrap()` on an `Option` value - --> tests/ui/unwrap.rs:6:13 - | -LL | let _ = opt.unwrap(); - | ^^^^^^^^^^^^ - | - = note: if this value is `None`, it will panic - = help: consider using `expect()` to provide a better panic message - = note: `-D clippy::unwrap-used` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::unwrap_used)]` - -error: used `unwrap()` on a `Result` value - --> tests/ui/unwrap.rs:12:13 - | -LL | let _ = res.unwrap(); - | ^^^^^^^^^^^^ - | - = note: if this value is an `Err`, it will panic - = help: consider using `expect()` to provide a better panic message - -error: used `unwrap_err()` on a `Result` value - --> tests/ui/unwrap.rs:15:13 - | -LL | let _ = res.unwrap_err(); - | ^^^^^^^^^^^^^^^^ - | - = note: if this value is an `Ok`, it will panic - = help: consider using `expect_err()` to provide a better panic message - -error: aborting due to 3 previous errors - From a0d33e07b058c19092f23f0e2dd6606608d0d591 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 20 Jan 2026 21:04:54 -0500 Subject: [PATCH 093/978] Bump stage0 --- clippy_lints/src/lib.rs | 1 - clippy_utils/src/lib.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index ae236ac25de7..a5e5ecb5fa19 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,4 +1,3 @@ -#![cfg_attr(bootstrap, feature(array_windows))] #![feature(box_patterns)] #![feature(macro_metavar_expr_concat)] #![feature(f128)] diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 9b6a9937b8ac..7e3b1ccd224e 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -5,7 +5,6 @@ #![feature(rustc_private)] #![feature(assert_matches)] #![feature(unwrap_infallible)] -#![cfg_attr(bootstrap, feature(array_windows))] #![recursion_limit = "512"] #![allow( clippy::missing_errors_doc, From bf1239e78c65918ba44f0338519be7048147a2a4 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Thu, 22 Jan 2026 19:09:48 +0900 Subject: [PATCH 094/978] Implement __sync builtins for thumbv6-none-eabi (#1050) This is a PR for thumbv6-none-eabi (bere-metal Armv6k in Thumb mode) which proposed to be added by https://github.com/rust-lang/rust/pull/150138. Armv6k supports atomic instructions, but they are unavailable in Thumb mode unless Thumb-2 instructions available (v6t2). Using Thumb interworking (can be used via `#[instruction_set]`) allows us to use these instructions even from Thumb mode without Thumb-2 instructions, but LLVM does not implement that processing (as of LLVM 21), so this PR implements it in compiler-builtins. The code around `__sync` builtins is basically copied from `arm_linux.rs` which uses kernel_user_helpers for atomic implementation. The atomic implementation is a port of my [atomic-maybe-uninit inline assembly code]. This PR has been tested on QEMU 10.2.0 using patched compiler-builtins and core that applied the changes in this PR and https://github.com/rust-lang/rust/pull/150138 and the [portable-atomic no-std test suite] (can be run with `./tools/no-std.sh thumbv6-none-eabi` on that repo) which tests wrappers around `core::sync::atomic`. (Note that the target-spec used in test sets max-atomic-width to 32 and atomic_cas to true, unlike the current https://github.com/rust-lang/rust/pull/150138.) The original atomic-maybe-uninit implementation has been tested on real Arm hardware. (Note that Armv6k also supports 64-bit atomic instructions, but they are skipped here. This is because there is no corresponding code in `arm_linux.rs` (since the kernel requirements increased in 1.64, it may be possible to implement 64-bit atomics there as well. see also https://github.com/taiki-e/portable-atomic/pull/82), the code becomes more complex than for 32-bit and smaller atomics.) [atomic-maybe-uninit inline assembly code]: https://github.com/taiki-e/atomic-maybe-uninit/blob/HEAD/src/arch/arm.rs [portable-atomic no-std test suite]: https://github.com/taiki-e/portable-atomic/tree/HEAD/tests/no-std-qemu --- .../.github/workflows/main.yaml | 19 ++ .../compiler-builtins/src/lib.rs | 8 +- .../src/{ => sync}/arm_linux.rs | 140 +----------- .../src/sync/arm_thumb_shared.rs | 134 +++++++++++ .../compiler-builtins/src/sync/mod.rs | 20 ++ .../compiler-builtins/src/sync/thumbv6k.rs | 213 ++++++++++++++++++ .../etc/thumbv6-none-eabi.json | 20 ++ 7 files changed, 416 insertions(+), 138 deletions(-) rename library/compiler-builtins/compiler-builtins/src/{ => sync}/arm_linux.rs (59%) create mode 100644 library/compiler-builtins/compiler-builtins/src/sync/arm_thumb_shared.rs create mode 100644 library/compiler-builtins/compiler-builtins/src/sync/mod.rs create mode 100644 library/compiler-builtins/compiler-builtins/src/sync/thumbv6k.rs create mode 100644 library/compiler-builtins/etc/thumbv6-none-eabi.json diff --git a/library/compiler-builtins/.github/workflows/main.yaml b/library/compiler-builtins/.github/workflows/main.yaml index 699a9c417dde..767566dd4147 100644 --- a/library/compiler-builtins/.github/workflows/main.yaml +++ b/library/compiler-builtins/.github/workflows/main.yaml @@ -230,6 +230,24 @@ jobs: --target etc/thumbv7em-none-eabi-renamed.json \ -Zbuild-std=core + # FIXME: move this target to test job once https://github.com/rust-lang/rust/pull/150138 merged. + build-thumbv6k: + name: Build thumbv6k + runs-on: ubuntu-24.04 + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + - name: Install Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + rustup component add rust-src + - uses: Swatinem/rust-cache@v2 + - run: | + cargo build -p compiler_builtins -p libm \ + --target etc/thumbv6-none-eabi.json \ + -Zbuild-std=core + benchmarks: name: Benchmarks timeout-minutes: 20 @@ -354,6 +372,7 @@ jobs: needs: - benchmarks - build-custom + - build-thumbv6k - clippy - extensive - miri diff --git a/library/compiler-builtins/compiler-builtins/src/lib.rs b/library/compiler-builtins/compiler-builtins/src/lib.rs index c993209699be..49ac35bd498c 100644 --- a/library/compiler-builtins/compiler-builtins/src/lib.rs +++ b/library/compiler-builtins/compiler-builtins/src/lib.rs @@ -45,6 +45,7 @@ pub mod float; pub mod int; pub mod math; pub mod mem; +pub mod sync; // `libm` expects its `support` module to be available in the crate root. use math::libm_math::support; @@ -58,13 +59,6 @@ pub mod aarch64; #[cfg(all(target_arch = "aarch64", target_feature = "outline-atomics"))] pub mod aarch64_outline_atomics; -#[cfg(all( - kernel_user_helpers, - any(target_os = "linux", target_os = "android"), - target_arch = "arm" -))] -pub mod arm_linux; - #[cfg(target_arch = "avr")] pub mod avr; diff --git a/library/compiler-builtins/compiler-builtins/src/arm_linux.rs b/library/compiler-builtins/compiler-builtins/src/sync/arm_linux.rs similarity index 59% rename from library/compiler-builtins/compiler-builtins/src/arm_linux.rs rename to library/compiler-builtins/compiler-builtins/src/sync/arm_linux.rs index ab9f86807390..7edd76c0b8b7 100644 --- a/library/compiler-builtins/compiler-builtins/src/arm_linux.rs +++ b/library/compiler-builtins/compiler-builtins/src/sync/arm_linux.rs @@ -125,14 +125,16 @@ unsafe fn atomic_cmpxchg(ptr: *mut T, oldval: u32, newval: u32) -> u32 { let (shift, mask) = get_shift_mask(ptr); loop { - // FIXME(safety): preconditions review needed + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. let curval_aligned = unsafe { atomic_load_aligned::(aligned_ptr) }; let curval = extract_aligned(curval_aligned, shift, mask); if curval != oldval { return curval; } let newval_aligned = insert_aligned(curval_aligned, newval, shift, mask); - // FIXME(safety): preconditions review needed + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. if unsafe { __kuser_cmpxchg(curval_aligned, newval_aligned, aligned_ptr) } { return oldval; } @@ -143,7 +145,8 @@ macro_rules! atomic_rmw { ($name:ident, $ty:ty, $op:expr, $fetch:expr) => { intrinsics! { pub unsafe extern "C" fn $name(ptr: *mut $ty, val: $ty) -> $ty { - // FIXME(safety): preconditions review needed + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. unsafe { atomic_rmw( ptr, @@ -167,140 +170,15 @@ macro_rules! atomic_cmpxchg { ($name:ident, $ty:ty) => { intrinsics! { pub unsafe extern "C" fn $name(ptr: *mut $ty, oldval: $ty, newval: $ty) -> $ty { - // FIXME(safety): preconditions review needed + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. unsafe { atomic_cmpxchg(ptr, oldval as u32, newval as u32) as $ty } } } }; } -atomic_rmw!(@old __sync_fetch_and_add_1, u8, |a: u8, b: u8| a.wrapping_add(b)); -atomic_rmw!(@old __sync_fetch_and_add_2, u16, |a: u16, b: u16| a - .wrapping_add(b)); -atomic_rmw!(@old __sync_fetch_and_add_4, u32, |a: u32, b: u32| a - .wrapping_add(b)); - -atomic_rmw!(@new __sync_add_and_fetch_1, u8, |a: u8, b: u8| a.wrapping_add(b)); -atomic_rmw!(@new __sync_add_and_fetch_2, u16, |a: u16, b: u16| a - .wrapping_add(b)); -atomic_rmw!(@new __sync_add_and_fetch_4, u32, |a: u32, b: u32| a - .wrapping_add(b)); - -atomic_rmw!(@old __sync_fetch_and_sub_1, u8, |a: u8, b: u8| a.wrapping_sub(b)); -atomic_rmw!(@old __sync_fetch_and_sub_2, u16, |a: u16, b: u16| a - .wrapping_sub(b)); -atomic_rmw!(@old __sync_fetch_and_sub_4, u32, |a: u32, b: u32| a - .wrapping_sub(b)); - -atomic_rmw!(@new __sync_sub_and_fetch_1, u8, |a: u8, b: u8| a.wrapping_sub(b)); -atomic_rmw!(@new __sync_sub_and_fetch_2, u16, |a: u16, b: u16| a - .wrapping_sub(b)); -atomic_rmw!(@new __sync_sub_and_fetch_4, u32, |a: u32, b: u32| a - .wrapping_sub(b)); - -atomic_rmw!(@old __sync_fetch_and_and_1, u8, |a: u8, b: u8| a & b); -atomic_rmw!(@old __sync_fetch_and_and_2, u16, |a: u16, b: u16| a & b); -atomic_rmw!(@old __sync_fetch_and_and_4, u32, |a: u32, b: u32| a & b); - -atomic_rmw!(@new __sync_and_and_fetch_1, u8, |a: u8, b: u8| a & b); -atomic_rmw!(@new __sync_and_and_fetch_2, u16, |a: u16, b: u16| a & b); -atomic_rmw!(@new __sync_and_and_fetch_4, u32, |a: u32, b: u32| a & b); - -atomic_rmw!(@old __sync_fetch_and_or_1, u8, |a: u8, b: u8| a | b); -atomic_rmw!(@old __sync_fetch_and_or_2, u16, |a: u16, b: u16| a | b); -atomic_rmw!(@old __sync_fetch_and_or_4, u32, |a: u32, b: u32| a | b); - -atomic_rmw!(@new __sync_or_and_fetch_1, u8, |a: u8, b: u8| a | b); -atomic_rmw!(@new __sync_or_and_fetch_2, u16, |a: u16, b: u16| a | b); -atomic_rmw!(@new __sync_or_and_fetch_4, u32, |a: u32, b: u32| a | b); - -atomic_rmw!(@old __sync_fetch_and_xor_1, u8, |a: u8, b: u8| a ^ b); -atomic_rmw!(@old __sync_fetch_and_xor_2, u16, |a: u16, b: u16| a ^ b); -atomic_rmw!(@old __sync_fetch_and_xor_4, u32, |a: u32, b: u32| a ^ b); - -atomic_rmw!(@new __sync_xor_and_fetch_1, u8, |a: u8, b: u8| a ^ b); -atomic_rmw!(@new __sync_xor_and_fetch_2, u16, |a: u16, b: u16| a ^ b); -atomic_rmw!(@new __sync_xor_and_fetch_4, u32, |a: u32, b: u32| a ^ b); - -atomic_rmw!(@old __sync_fetch_and_nand_1, u8, |a: u8, b: u8| !(a & b)); -atomic_rmw!(@old __sync_fetch_and_nand_2, u16, |a: u16, b: u16| !(a & b)); -atomic_rmw!(@old __sync_fetch_and_nand_4, u32, |a: u32, b: u32| !(a & b)); - -atomic_rmw!(@new __sync_nand_and_fetch_1, u8, |a: u8, b: u8| !(a & b)); -atomic_rmw!(@new __sync_nand_and_fetch_2, u16, |a: u16, b: u16| !(a & b)); -atomic_rmw!(@new __sync_nand_and_fetch_4, u32, |a: u32, b: u32| !(a & b)); - -atomic_rmw!(@old __sync_fetch_and_max_1, i8, |a: i8, b: i8| if a > b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_max_2, i16, |a: i16, b: i16| if a > b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_max_4, i32, |a: i32, b: i32| if a > b { - a -} else { - b -}); - -atomic_rmw!(@old __sync_fetch_and_umax_1, u8, |a: u8, b: u8| if a > b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_umax_2, u16, |a: u16, b: u16| if a > b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_umax_4, u32, |a: u32, b: u32| if a > b { - a -} else { - b -}); - -atomic_rmw!(@old __sync_fetch_and_min_1, i8, |a: i8, b: i8| if a < b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_min_2, i16, |a: i16, b: i16| if a < b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_min_4, i32, |a: i32, b: i32| if a < b { - a -} else { - b -}); - -atomic_rmw!(@old __sync_fetch_and_umin_1, u8, |a: u8, b: u8| if a < b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_umin_2, u16, |a: u16, b: u16| if a < b { - a -} else { - b -}); -atomic_rmw!(@old __sync_fetch_and_umin_4, u32, |a: u32, b: u32| if a < b { - a -} else { - b -}); - -atomic_rmw!(@old __sync_lock_test_and_set_1, u8, |_: u8, b: u8| b); -atomic_rmw!(@old __sync_lock_test_and_set_2, u16, |_: u16, b: u16| b); -atomic_rmw!(@old __sync_lock_test_and_set_4, u32, |_: u32, b: u32| b); - -atomic_cmpxchg!(__sync_val_compare_and_swap_1, u8); -atomic_cmpxchg!(__sync_val_compare_and_swap_2, u16); -atomic_cmpxchg!(__sync_val_compare_and_swap_4, u32); +include!("arm_thumb_shared.rs"); intrinsics! { pub unsafe extern "C" fn __sync_synchronize() { diff --git a/library/compiler-builtins/compiler-builtins/src/sync/arm_thumb_shared.rs b/library/compiler-builtins/compiler-builtins/src/sync/arm_thumb_shared.rs new file mode 100644 index 000000000000..812989c7bc85 --- /dev/null +++ b/library/compiler-builtins/compiler-builtins/src/sync/arm_thumb_shared.rs @@ -0,0 +1,134 @@ +// Used by both arm_linux.rs and thumbv6k.rs. + +// References: +// - https://llvm.org/docs/Atomics.html#libcalls-sync +// - https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html +// - https://refspecs.linuxfoundation.org/elf/IA64-SysV-psABI.pdf#page=58 + +atomic_rmw!(@old __sync_fetch_and_add_1, u8, |a: u8, b: u8| a.wrapping_add(b)); +atomic_rmw!(@old __sync_fetch_and_add_2, u16, |a: u16, b: u16| a + .wrapping_add(b)); +atomic_rmw!(@old __sync_fetch_and_add_4, u32, |a: u32, b: u32| a + .wrapping_add(b)); + +atomic_rmw!(@new __sync_add_and_fetch_1, u8, |a: u8, b: u8| a.wrapping_add(b)); +atomic_rmw!(@new __sync_add_and_fetch_2, u16, |a: u16, b: u16| a + .wrapping_add(b)); +atomic_rmw!(@new __sync_add_and_fetch_4, u32, |a: u32, b: u32| a + .wrapping_add(b)); + +atomic_rmw!(@old __sync_fetch_and_sub_1, u8, |a: u8, b: u8| a.wrapping_sub(b)); +atomic_rmw!(@old __sync_fetch_and_sub_2, u16, |a: u16, b: u16| a + .wrapping_sub(b)); +atomic_rmw!(@old __sync_fetch_and_sub_4, u32, |a: u32, b: u32| a + .wrapping_sub(b)); + +atomic_rmw!(@new __sync_sub_and_fetch_1, u8, |a: u8, b: u8| a.wrapping_sub(b)); +atomic_rmw!(@new __sync_sub_and_fetch_2, u16, |a: u16, b: u16| a + .wrapping_sub(b)); +atomic_rmw!(@new __sync_sub_and_fetch_4, u32, |a: u32, b: u32| a + .wrapping_sub(b)); + +atomic_rmw!(@old __sync_fetch_and_and_1, u8, |a: u8, b: u8| a & b); +atomic_rmw!(@old __sync_fetch_and_and_2, u16, |a: u16, b: u16| a & b); +atomic_rmw!(@old __sync_fetch_and_and_4, u32, |a: u32, b: u32| a & b); + +atomic_rmw!(@new __sync_and_and_fetch_1, u8, |a: u8, b: u8| a & b); +atomic_rmw!(@new __sync_and_and_fetch_2, u16, |a: u16, b: u16| a & b); +atomic_rmw!(@new __sync_and_and_fetch_4, u32, |a: u32, b: u32| a & b); + +atomic_rmw!(@old __sync_fetch_and_or_1, u8, |a: u8, b: u8| a | b); +atomic_rmw!(@old __sync_fetch_and_or_2, u16, |a: u16, b: u16| a | b); +atomic_rmw!(@old __sync_fetch_and_or_4, u32, |a: u32, b: u32| a | b); + +atomic_rmw!(@new __sync_or_and_fetch_1, u8, |a: u8, b: u8| a | b); +atomic_rmw!(@new __sync_or_and_fetch_2, u16, |a: u16, b: u16| a | b); +atomic_rmw!(@new __sync_or_and_fetch_4, u32, |a: u32, b: u32| a | b); + +atomic_rmw!(@old __sync_fetch_and_xor_1, u8, |a: u8, b: u8| a ^ b); +atomic_rmw!(@old __sync_fetch_and_xor_2, u16, |a: u16, b: u16| a ^ b); +atomic_rmw!(@old __sync_fetch_and_xor_4, u32, |a: u32, b: u32| a ^ b); + +atomic_rmw!(@new __sync_xor_and_fetch_1, u8, |a: u8, b: u8| a ^ b); +atomic_rmw!(@new __sync_xor_and_fetch_2, u16, |a: u16, b: u16| a ^ b); +atomic_rmw!(@new __sync_xor_and_fetch_4, u32, |a: u32, b: u32| a ^ b); + +atomic_rmw!(@old __sync_fetch_and_nand_1, u8, |a: u8, b: u8| !(a & b)); +atomic_rmw!(@old __sync_fetch_and_nand_2, u16, |a: u16, b: u16| !(a & b)); +atomic_rmw!(@old __sync_fetch_and_nand_4, u32, |a: u32, b: u32| !(a & b)); + +atomic_rmw!(@new __sync_nand_and_fetch_1, u8, |a: u8, b: u8| !(a & b)); +atomic_rmw!(@new __sync_nand_and_fetch_2, u16, |a: u16, b: u16| !(a & b)); +atomic_rmw!(@new __sync_nand_and_fetch_4, u32, |a: u32, b: u32| !(a & b)); + +atomic_rmw!(@old __sync_fetch_and_max_1, i8, |a: i8, b: i8| if a > b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_max_2, i16, |a: i16, b: i16| if a > b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_max_4, i32, |a: i32, b: i32| if a > b { + a +} else { + b +}); + +atomic_rmw!(@old __sync_fetch_and_umax_1, u8, |a: u8, b: u8| if a > b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_umax_2, u16, |a: u16, b: u16| if a > b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_umax_4, u32, |a: u32, b: u32| if a > b { + a +} else { + b +}); + +atomic_rmw!(@old __sync_fetch_and_min_1, i8, |a: i8, b: i8| if a < b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_min_2, i16, |a: i16, b: i16| if a < b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_min_4, i32, |a: i32, b: i32| if a < b { + a +} else { + b +}); + +atomic_rmw!(@old __sync_fetch_and_umin_1, u8, |a: u8, b: u8| if a < b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_umin_2, u16, |a: u16, b: u16| if a < b { + a +} else { + b +}); +atomic_rmw!(@old __sync_fetch_and_umin_4, u32, |a: u32, b: u32| if a < b { + a +} else { + b +}); + +atomic_rmw!(@old __sync_lock_test_and_set_1, u8, |_: u8, b: u8| b); +atomic_rmw!(@old __sync_lock_test_and_set_2, u16, |_: u16, b: u16| b); +atomic_rmw!(@old __sync_lock_test_and_set_4, u32, |_: u32, b: u32| b); + +atomic_cmpxchg!(__sync_val_compare_and_swap_1, u8); +atomic_cmpxchg!(__sync_val_compare_and_swap_2, u16); +atomic_cmpxchg!(__sync_val_compare_and_swap_4, u32); diff --git a/library/compiler-builtins/compiler-builtins/src/sync/mod.rs b/library/compiler-builtins/compiler-builtins/src/sync/mod.rs new file mode 100644 index 000000000000..590db14bb23b --- /dev/null +++ b/library/compiler-builtins/compiler-builtins/src/sync/mod.rs @@ -0,0 +1,20 @@ +#[cfg(all( + kernel_user_helpers, + any(target_os = "linux", target_os = "android"), + target_arch = "arm" +))] +pub mod arm_linux; + +// Armv6k supports atomic instructions, but they are unavailable in Thumb mode +// unless Thumb-2 instructions available (v6t2). +// Using Thumb interworking allows us to use these instructions even from Thumb mode +// without Thumb-2 instructions, but LLVM does not implement that processing (as of LLVM 21), +// so we implement it here at this time. +// (`not(target_feature = "mclass")` is unneeded because v6k is not set on thumbv6m.) +#[cfg(all( + target_arch = "arm", + target_feature = "thumb-mode", + target_feature = "v6k", + not(target_feature = "v6t2"), +))] +pub mod thumbv6k; diff --git a/library/compiler-builtins/compiler-builtins/src/sync/thumbv6k.rs b/library/compiler-builtins/compiler-builtins/src/sync/thumbv6k.rs new file mode 100644 index 000000000000..c47b4c2ec6b0 --- /dev/null +++ b/library/compiler-builtins/compiler-builtins/src/sync/thumbv6k.rs @@ -0,0 +1,213 @@ +// Armv6k supports atomic instructions, but they are unavailable in Thumb mode +// unless Thumb-2 instructions available (v6t2). +// Using Thumb interworking allows us to use these instructions even from Thumb mode +// without Thumb-2 instructions, but LLVM does not implement that processing (as of LLVM 21), +// so we implement it here at this time. + +use core::arch::asm; +use core::mem; + +// Data Memory Barrier (DMB) operation. +// +// Armv6 does not support DMB instruction, so use use special instruction equivalent to it. +// +// Refs: https://developer.arm.com/documentation/ddi0360/f/control-coprocessor-cp15/register-descriptions/c7--cache-operations-register +macro_rules! cp15_barrier { + () => { + "mcr p15, #0, {zero}, c7, c10, #5" + }; +} + +#[instruction_set(arm::a32)] +unsafe fn fence() { + unsafe { + asm!( + cp15_barrier!(), + // cp15_barrier! calls `mcr p15, 0, {zero}, c7, c10, 5`, and + // the value in the {zero} register should be zero (SBZ). + zero = inout(reg) 0_u32 => _, + options(nostack, preserves_flags), + ); + } +} + +trait Atomic: Copy + Eq { + unsafe fn load_relaxed(src: *const Self) -> Self; + unsafe fn cmpxchg(dst: *mut Self, current: Self, new: Self) -> Self; +} + +macro_rules! atomic { + ($ty:ident, $suffix:tt) => { + impl Atomic for $ty { + // #[instruction_set(arm::a32)] is unneeded for ldr. + #[inline] + unsafe fn load_relaxed( + src: *const Self, + ) -> Self { + let out: Self; + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. + unsafe { + asm!( + concat!("ldr", $suffix, " {out}, [{src}]"), // atomic { out = *src } + src = in(reg) src, + out = lateout(reg) out, + options(nostack, preserves_flags), + ); + } + out + } + #[inline] + #[instruction_set(arm::a32)] + unsafe fn cmpxchg( + dst: *mut Self, + old: Self, + new: Self, + ) -> Self { + let mut out: Self; + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. + // + // Instead of the common `fence; ll/sc loop; fence` form, we use the form used by + // LLVM, which omits the preceding fence if no write operation is performed. + unsafe { + asm!( + concat!("ldrex", $suffix, " {out}, [{dst}]"), // atomic { out = *dst; EXCLUSIVE = dst } + "cmp {out}, {old}", // if out == old { Z = 1 } else { Z = 0 } + "bne 3f", // if Z == 0 { jump 'cmp-fail } + cp15_barrier!(), // fence + "2:", // 'retry: + concat!("strex", $suffix, " {r}, {new}, [{dst}]"), // atomic { if EXCLUSIVE == dst { *dst = new; r = 0 } else { r = 1 }; EXCLUSIVE = None } + "cmp {r}, #0", // if r == 0 { Z = 1 } else { Z = 0 } + "beq 3f", // if Z == 1 { jump 'success } + concat!("ldrex", $suffix, " {out}, [{dst}]"), // atomic { out = *dst; EXCLUSIVE = dst } + "cmp {out}, {old}", // if out == old { Z = 1 } else { Z = 0 } + "beq 2b", // if Z == 1 { jump 'retry } + "3:", // 'cmp-fail | 'success: + cp15_barrier!(), // fence + dst = in(reg) dst, + // Note: this cast must be a zero-extend since loaded value + // which compared to it is zero-extended. + old = in(reg) u32::from(old), + new = in(reg) new, + out = out(reg) out, + r = out(reg) _, + // cp15_barrier! calls `mcr p15, 0, {zero}, c7, c10, 5`, and + // the value in the {zero} register should be zero (SBZ). + zero = inout(reg) 0_u32 => _, + // Do not use `preserves_flags` because CMP modifies the condition flags. + options(nostack), + ); + out + } + } + } + }; +} +atomic!(u8, "b"); +atomic!(u16, "h"); +atomic!(u32, ""); + +// To avoid the annoyance of sign extension, we implement signed CAS using +// unsigned CAS. (See note in cmpxchg impl in atomic! macro) +macro_rules! delegate_signed { + ($ty:ident, $base:ident) => { + const _: () = { + assert!(mem::size_of::<$ty>() == mem::size_of::<$base>()); + assert!(mem::align_of::<$ty>() == mem::align_of::<$base>()); + }; + impl Atomic for $ty { + #[inline] + unsafe fn load_relaxed(src: *const Self) -> Self { + // SAFETY: the caller must uphold the safety contract. + // casts are okay because $ty and $base implement the same layout. + unsafe { <$base as Atomic>::load_relaxed(src.cast::<$base>()).cast_signed() } + } + #[inline] + unsafe fn cmpxchg(dst: *mut Self, old: Self, new: Self) -> Self { + // SAFETY: the caller must uphold the safety contract. + // casts are okay because $ty and $base implement the same layout. + unsafe { + <$base as Atomic>::cmpxchg( + dst.cast::<$base>(), + old.cast_unsigned(), + new.cast_unsigned(), + ) + .cast_signed() + } + } + } + }; +} +delegate_signed!(i8, u8); +delegate_signed!(i16, u16); +delegate_signed!(i32, u32); + +// Generic atomic read-modify-write operation +// +// We could implement RMW more efficiently as an assembly LL/SC loop per operation, +// but we won't do that for now because it would make the implementation more complex. +// +// We also do not implement LL and SC as separate functions. This is because it +// is theoretically possible for the compiler to insert operations that might +// clear the reservation between LL and SC. See https://github.com/taiki-e/portable-atomic/blob/58ef7f27c9e20da4cc1ef0abf8b8ce9ac5219ec3/src/imp/atomic128/aarch64.rs#L44-L55 +// for more details. +unsafe fn atomic_rmw T, G: Fn(T, T) -> T>(ptr: *mut T, f: F, g: G) -> T { + loop { + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. + let curval = unsafe { T::load_relaxed(ptr) }; + let newval = f(curval); + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. + if unsafe { T::cmpxchg(ptr, curval, newval) } == curval { + return g(curval, newval); + } + } +} + +macro_rules! atomic_rmw { + ($name:ident, $ty:ty, $op:expr, $fetch:expr) => { + intrinsics! { + pub unsafe extern "C" fn $name(ptr: *mut $ty, val: $ty) -> $ty { + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. + unsafe { + atomic_rmw( + ptr, + |x| $op(x as $ty, val), + |old, new| $fetch(old, new) + ) as $ty + } + } + } + }; + + (@old $name:ident, $ty:ty, $op:expr) => { + atomic_rmw!($name, $ty, $op, |old, _| old); + }; + + (@new $name:ident, $ty:ty, $op:expr) => { + atomic_rmw!($name, $ty, $op, |_, new| new); + }; +} +macro_rules! atomic_cmpxchg { + ($name:ident, $ty:ty) => { + intrinsics! { + pub unsafe extern "C" fn $name(ptr: *mut $ty, oldval: $ty, newval: $ty) -> $ty { + // SAFETY: the caller must guarantee that the pointer is valid for read and write + // and aligned to the element size. + unsafe { <$ty as Atomic>::cmpxchg(ptr, oldval, newval) } + } + } + }; +} + +include!("arm_thumb_shared.rs"); + +intrinsics! { + pub unsafe extern "C" fn __sync_synchronize() { + // SAFETY: preconditions are the same as the calling function. + unsafe { fence() }; + } +} diff --git a/library/compiler-builtins/etc/thumbv6-none-eabi.json b/library/compiler-builtins/etc/thumbv6-none-eabi.json new file mode 100644 index 000000000000..4c1f760ac3e0 --- /dev/null +++ b/library/compiler-builtins/etc/thumbv6-none-eabi.json @@ -0,0 +1,20 @@ +{ + "abi": "eabi", + "arch": "arm", + "asm-args": ["-mthumb-interwork", "-march=armv6", "-mlittle-endian"], + "c-enum-min-bits": 8, + "crt-objects-fallback": "false", + "data-layout": "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64", + "emit-debug-gdb-scripts": false, + "features": "+soft-float,+strict-align,+v6k", + "frame-pointer": "always", + "has-thumb-interworking": true, + "linker": "rust-lld", + "linker-flavor": "gnu-lld", + "llvm-floatabi": "soft", + "llvm-target": "thumbv6-none-eabi", + "max-atomic-width": 32, + "panic-strategy": "abort", + "relocation-model": "static", + "target-pointer-width": 32 +} From 977eddef3f3293008f4a734cdf3a61deabceb15f Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 22 Jan 2026 17:10:24 +0100 Subject: [PATCH 095/978] Merge commit '54482290b5f32e6c6b57cc9e0a17153f432b0036' into clippy-subtree-update --- CHANGELOG.md | 64 +- Cargo.toml | 2 +- book/src/lint_configuration.md | 1 + clippy_config/Cargo.toml | 2 +- clippy_config/src/conf.rs | 1 + clippy_config/src/lib.rs | 5 +- clippy_dev/src/deprecate_lint.rs | 54 +- .../src/{rename_lint.rs => edit_lints.rs} | 351 +++++--- clippy_dev/src/lib.rs | 3 +- clippy_dev/src/main.rs | 42 +- clippy_dev/src/parse/cursor.rs | 16 + clippy_dev/src/serve.rs | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/attrs/mod.rs | 4 + clippy_lints/src/casts/mod.rs | 6 + clippy_lints/src/comparison_chain.rs | 4 - clippy_lints/src/declared_lints.rs | 3 + clippy_lints/src/derivable_impls.rs | 2 +- clippy_lints/src/doc/mod.rs | 6 + clippy_lints/src/duration_suboptimal_units.rs | 204 +++++ clippy_lints/src/floating_point_arithmetic.rs | 761 ------------------ .../floating_point_arithmetic/custom_abs.rs | 100 +++ .../src/floating_point_arithmetic/expm1.rs | 42 + .../src/floating_point_arithmetic/hypot.rs | 82 ++ .../src/floating_point_arithmetic/lib.rs | 42 + .../src/floating_point_arithmetic/ln1p.rs | 41 + .../src/floating_point_arithmetic/log_base.rs | 44 + .../floating_point_arithmetic/log_division.rs | 52 ++ .../src/floating_point_arithmetic/mod.rs | 141 ++++ .../src/floating_point_arithmetic/mul_add.rs | 94 +++ .../src/floating_point_arithmetic/powf.rs | 94 +++ .../src/floating_point_arithmetic/powi.rs | 70 ++ .../src/floating_point_arithmetic/radians.rs | 89 ++ clippy_lints/src/int_plus_one.rs | 191 +++-- clippy_lints/src/lib.rs | 12 +- clippy_lints/src/lifetimes.rs | 38 +- clippy_lints/src/loops/while_let_loop.rs | 30 +- clippy_lints/src/manual_checked_ops.rs | 170 ++++ clippy_lints/src/manual_take.rs | 114 +++ .../src/methods/manual_is_variant_and.rs | 129 +-- clippy_lints/src/methods/map_unwrap_or.rs | 249 ++++-- .../src/methods/map_unwrap_or_else.rs | 68 ++ clippy_lints/src/methods/mod.rs | 17 +- clippy_lints/src/methods/needless_collect.rs | 224 +++++- .../src/methods/option_map_unwrap_or.rs | 180 ----- .../src/methods/suspicious_to_owned.rs | 23 +- .../src/methods/unnecessary_map_or.rs | 38 +- .../src/methods/unnecessary_sort_by.rs | 376 ++++++--- clippy_lints/src/missing_trait_methods.rs | 10 +- clippy_lints/src/needless_continue.rs | 31 +- .../src/operators/arithmetic_side_effects.rs | 5 +- .../src/operators/double_comparison.rs | 12 + clippy_lints/src/redundant_test_prefix.rs | 4 + .../src/significant_drop_tightening.rs | 24 +- .../src/slow_vector_initialization.rs | 4 +- clippy_lints/src/strlen_on_c_strings.rs | 68 +- .../src/transmute/transmuting_null.rs | 12 + .../src/undocumented_unsafe_blocks.rs | 35 + clippy_lints/src/unnested_or_patterns.rs | 7 +- clippy_lints/src/useless_conversion.rs | 2 +- clippy_lints/src/utils/author.rs | 2 +- ...alls.rs => collapsible_span_lint_calls.rs} | 119 +-- clippy_lints_internal/src/lib.rs | 8 +- clippy_utils/Cargo.toml | 2 +- clippy_utils/README.md | 2 +- clippy_utils/src/attrs.rs | 5 +- clippy_utils/src/hir_utils.rs | 44 +- clippy_utils/src/lib.rs | 14 +- clippy_utils/src/msrvs.rs | 10 +- clippy_utils/src/sym.rs | 15 + clippy_utils/src/ty/mod.rs | 19 +- declare_clippy_lint/Cargo.toml | 2 +- lintcheck/src/input.rs | 3 +- rust-toolchain.toml | 2 +- src/driver.rs | 13 +- src/main.rs | 17 +- .../collapsible_span_lint_calls.fixed | 9 + .../collapsible_span_lint_calls.rs | 29 + .../collapsible_span_lint_calls.stderr | 50 +- .../undocumented_unsafe_blocks.default.stderr | 156 ++-- ...undocumented_unsafe_blocks.disabled.stderr | 168 ++-- .../undocumented_unsafe_blocks.rs | 67 ++ tests/ui/arithmetic_side_effects.rs | 1 - tests/ui/arithmetic_side_effects.stderr | 266 +++--- tests/ui/cognitive_complexity.rs | 25 + tests/ui/cognitive_complexity.stderr | 18 +- .../entrypoint_recursion.rs | 7 +- .../entrypoint_recursion.stderr | 12 + .../no_std_main_recursion.rs | 13 + tests/ui/double_comparison.fixed | 16 + tests/ui/double_comparison.rs | 16 + tests/ui/double_comparison.stderr | 26 +- tests/ui/duration_suboptimal_units.fixed | 91 +++ tests/ui/duration_suboptimal_units.rs | 91 +++ tests/ui/duration_suboptimal_units.stderr | 152 ++++ ...duration_suboptimal_units_days_weeks.fixed | 17 + .../duration_suboptimal_units_days_weeks.rs | 17 + ...uration_suboptimal_units_days_weeks.stderr | 40 + tests/ui/extra_unused_lifetimes.rs | 32 + tests/ui/extra_unused_lifetimes.stderr | 14 +- tests/ui/if_same_then_else.rs | 84 +- tests/ui/if_same_then_else.stderr | 230 +++++- tests/ui/int_plus_one.fixed | 16 +- tests/ui/int_plus_one.rs | 16 +- tests/ui/int_plus_one.stderr | 26 +- tests/ui/manual_checked_ops.rs | 72 ++ tests/ui/manual_checked_ops.stderr | 50 ++ tests/ui/manual_take.fixed | 57 ++ tests/ui/manual_take.rs | 69 ++ tests/ui/manual_take.stderr | 53 ++ tests/ui/manual_take_nocore.rs | 37 + tests/ui/manual_take_nostd.fixed | 10 + tests/ui/manual_take_nostd.rs | 22 + tests/ui/manual_take_nostd.stderr | 54 ++ tests/ui/map_unwrap_or.rs | 8 + tests/ui/map_unwrap_or.stderr | 8 +- tests/ui/map_unwrap_or_fixable.fixed | 39 + tests/ui/map_unwrap_or_fixable.rs | 39 + tests/ui/map_unwrap_or_fixable.stderr | 90 ++- tests/ui/missing_trait_methods.rs | 7 + tests/ui/missing_trait_methods.stderr | 10 +- tests/ui/needless_collect.fixed | 76 ++ tests/ui/needless_collect.rs | 76 ++ tests/ui/needless_collect.stderr | 112 ++- tests/ui/needless_continue.rs | 35 + tests/ui/needless_lifetimes.fixed | 25 +- tests/ui/needless_lifetimes.rs | 25 +- tests/ui/significant_drop_tightening.fixed | 36 + tests/ui/significant_drop_tightening.rs | 33 + tests/ui/significant_drop_tightening.stderr | 71 +- tests/ui/strlen_on_c_strings.fixed | 61 +- tests/ui/strlen_on_c_strings.rs | 47 +- tests/ui/strlen_on_c_strings.stderr | 86 +- tests/ui/suspicious_to_owned.1.fixed | 73 ++ tests/ui/suspicious_to_owned.2.fixed | 73 ++ tests/ui/suspicious_to_owned.rs | 1 - tests/ui/suspicious_to_owned.stderr | 36 +- tests/ui/transmuting_null.rs | 11 + tests/ui/transmuting_null.stderr | 14 +- tests/ui/unnecessary_map_or.fixed | 2 +- tests/ui/unnecessary_map_or.rs | 2 +- tests/ui/unnecessary_map_or.stderr | 38 +- tests/ui/unnecessary_sort_by.fixed | 62 ++ tests/ui/unnecessary_sort_by.rs | 62 ++ tests/ui/unnecessary_sort_by.stderr | 217 ++++- tests/ui/unnecessary_sort_by_no_core.rs | 26 + tests/ui/unnecessary_sort_by_no_std.stderr | 15 +- tests/ui/while_let_loop.rs | 21 + 148 files changed, 6333 insertions(+), 2109 deletions(-) rename clippy_dev/src/{rename_lint.rs => edit_lints.rs} (52%) create mode 100644 clippy_lints/src/duration_suboptimal_units.rs delete mode 100644 clippy_lints/src/floating_point_arithmetic.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/custom_abs.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/expm1.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/hypot.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/lib.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/ln1p.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/log_base.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/log_division.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/mod.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/mul_add.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/powf.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/powi.rs create mode 100644 clippy_lints/src/floating_point_arithmetic/radians.rs create mode 100644 clippy_lints/src/manual_checked_ops.rs create mode 100644 clippy_lints/src/manual_take.rs create mode 100644 clippy_lints/src/methods/map_unwrap_or_else.rs delete mode 100644 clippy_lints/src/methods/option_map_unwrap_or.rs rename clippy_lints_internal/src/{collapsible_calls.rs => collapsible_span_lint_calls.rs} (66%) create mode 100644 tests/ui/crate_level_checks/entrypoint_recursion.stderr create mode 100644 tests/ui/crate_level_checks/no_std_main_recursion.rs create mode 100644 tests/ui/duration_suboptimal_units.fixed create mode 100644 tests/ui/duration_suboptimal_units.rs create mode 100644 tests/ui/duration_suboptimal_units.stderr create mode 100644 tests/ui/duration_suboptimal_units_days_weeks.fixed create mode 100644 tests/ui/duration_suboptimal_units_days_weeks.rs create mode 100644 tests/ui/duration_suboptimal_units_days_weeks.stderr create mode 100644 tests/ui/manual_checked_ops.rs create mode 100644 tests/ui/manual_checked_ops.stderr create mode 100644 tests/ui/manual_take.fixed create mode 100644 tests/ui/manual_take.rs create mode 100644 tests/ui/manual_take.stderr create mode 100644 tests/ui/manual_take_nocore.rs create mode 100644 tests/ui/manual_take_nostd.fixed create mode 100644 tests/ui/manual_take_nostd.rs create mode 100644 tests/ui/manual_take_nostd.stderr create mode 100644 tests/ui/suspicious_to_owned.1.fixed create mode 100644 tests/ui/suspicious_to_owned.2.fixed create mode 100644 tests/ui/unnecessary_sort_by_no_core.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 91d793489be2..795eba1dfeaf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,66 @@ document. ## Unreleased / Beta / In Rust Nightly -[d9fb15c...master](https://github.com/rust-lang/rust-clippy/compare/d9fb15c...master) +[92b4b68...master](https://github.com/rust-lang/rust-clippy/compare/92b4b68...master) + +## Rust 1.93 + +Current stable, released 2026-01-22 + +[View all 96 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2025-10-17T15%3A48%3A11Z..2025-11-28T19%3A22%3A54Z+base%3Amaster) + +### New Lints + +* Added [`doc_paragraphs_missing_punctuation`] to `restriction` + [#15758](https://github.com/rust-lang/rust-clippy/pull/15758) + +### Moves and Deprecations + +* Renamed [`needless_if`] to [`needless_ifs`] + [#15961](https://github.com/rust-lang/rust-clippy/pull/15961) +* Renamed [`empty_enum`] to [`empty_enums`] + [#15912](https://github.com/rust-lang/rust-clippy/pull/15912) + +### Enhancements + +* [`result_large_err`] added `large_error_ignored` configuration + [#15697](https://github.com/rust-lang/rust-clippy/pull/15697) +* [`explicit_deref_methods`] don't lint in `impl Deref(Mut)` + [#16113](https://github.com/rust-lang/rust-clippy/pull/16113) +* [`missing_docs_in_private_items`] don't lint items in bodies and automatically derived impls; + better detect when things are accessible from the crate root; lint unnameable items which are + accessible outside the crate + [#14741](https://github.com/rust-lang/rust-clippy/pull/14741) +* [`unnecessary_unwrap`] and [`panicking_unwrap`] lint field accesses + [#15949](https://github.com/rust-lang/rust-clippy/pull/15949) +* [`ok_expect`] add autofix + [#15867](https://github.com/rust-lang/rust-clippy/pull/15867) +* [`let_and_return`] disallow _any_ text between let and return + [#16006](https://github.com/rust-lang/rust-clippy/pull/16006) +* [`needless_collect`] extend to lint more cases + [#14361](https://github.com/rust-lang/rust-clippy/pull/14361) +* [`needless_doctest_main`] and [`test_attr_in_doctest`] now handle whitespace in language tags + [#15967](https://github.com/rust-lang/rust-clippy/pull/15967) +* [`search_is_some`] now fixes code spanning multiple lines + [#15902](https://github.com/rust-lang/rust-clippy/pull/15902) +* [`unnecessary_find_map`] and [`unnecessary_filter_map`] make diagnostic spans more precise + [#15929](https://github.com/rust-lang/rust-clippy/pull/15929) +* [`precedence`] warn about ambiguity when a closure is used as a method call receiver + [#14421](https://github.com/rust-lang/rust-clippy/pull/14421) +* [`match_as_ref`] suggest `as_ref` when the reference needs to be cast; improve diagnostics + [#15934](https://github.com/rust-lang/rust-clippy/pull/15934) + [#15928](https://github.com/rust-lang/rust-clippy/pull/15928) + +### False Positive Fixes + +* [`single_range_in_vec_init`] fix FP for explicit `Range` + [#16043](https://github.com/rust-lang/rust-clippy/pull/16043) +* [`mod_module_files`] fix false positive for integration tests in workspace crates + [#16048](https://github.com/rust-lang/rust-clippy/pull/16048) +* [`replace_box`] fix FP when the box is moved + [#15984](https://github.com/rust-lang/rust-clippy/pull/15984) +* [`len_zero`] fix FP on unstable methods + [#15894](https://github.com/rust-lang/rust-clippy/pull/15894) ## Rust 1.92 @@ -6406,6 +6465,7 @@ Released 2018-09-13 [`duplicate_mod`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_mod [`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument [`duplicated_attributes`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicated_attributes +[`duration_suboptimal_units`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_suboptimal_units [`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec [`eager_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#eager_transmute [`elidable_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#elidable_lifetime_names @@ -6607,6 +6667,7 @@ Released 2018-09-13 [`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn [`manual_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits [`manual_c_str_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals +[`manual_checked_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_checked_ops [`manual_clamp`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp [`manual_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_contains [`manual_dangling_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_dangling_ptr @@ -6652,6 +6713,7 @@ Released 2018-09-13 [`manual_string_new`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_string_new [`manual_strip`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap +[`manual_take`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_take [`manual_try_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold [`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or [`manual_unwrap_or_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or_default diff --git a/Cargo.toml b/Cargo.toml index 7379dcbb7b37..560f1e8d7fbe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.94" +version = "0.1.95" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index a1c079898594..f81dd421f59b 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -905,6 +905,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio * [`manual_split_once`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once) * [`manual_str_repeat`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat) * [`manual_strip`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip) +* [`manual_take`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_take) * [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold) * [`map_clone`](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone) * [`map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or) diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml index a65fe7bcbda5..da5166392b4e 100644 --- a/clippy_config/Cargo.toml +++ b/clippy_config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_config" -version = "0.1.94" +version = "0.1.95" edition = "2024" publish = false diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index e1d7c1d88eb9..849d9a613d80 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -780,6 +780,7 @@ define_Conf! { manual_split_once, manual_str_repeat, manual_strip, + manual_take, manual_try_fold, map_clone, map_unwrap_or, diff --git a/clippy_config/src/lib.rs b/clippy_config/src/lib.rs index a565a21a0e77..f18272ecf5a0 100644 --- a/clippy_config/src/lib.rs +++ b/clippy_config/src/lib.rs @@ -6,10 +6,7 @@ unused_lifetimes, unused_qualifications )] -#![allow( - clippy::must_use_candidate, - clippy::missing_panics_doc, -)] +#![allow(clippy::must_use_candidate, clippy::missing_panics_doc)] #![deny(clippy::derive_deserialize_allowing_unknown)] extern crate rustc_data_structures; diff --git a/clippy_dev/src/deprecate_lint.rs b/clippy_dev/src/deprecate_lint.rs index 0401cfda7080..bee7508dabb9 100644 --- a/clippy_dev/src/deprecate_lint.rs +++ b/clippy_dev/src/deprecate_lint.rs @@ -1,4 +1,4 @@ -use crate::parse::{DeprecatedLint, Lint, ParseCx}; +use crate::parse::{DeprecatedLint, Lint, ParseCx, RenamedLint}; use crate::update_lints::generate_lint_files; use crate::utils::{UpdateMode, Version}; use std::ffi::OsStr; @@ -61,6 +61,58 @@ pub fn deprecate<'cx>(cx: ParseCx<'cx>, clippy_version: Version, name: &'cx str, } } +pub fn uplift<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'env str, new_name: &'env str) { + let mut lints = cx.find_lint_decls(); + let (deprecated_lints, mut renamed_lints) = cx.read_deprecated_lints(); + + let Some(lint) = lints.iter().find(|l| l.name == old_name) else { + eprintln!("error: failed to find lint `{old_name}`"); + return; + }; + + let old_name_prefixed = cx.str_buf.with(|buf| { + buf.extend(["clippy::", old_name]); + cx.arena.alloc_str(buf) + }); + for lint in &mut renamed_lints { + if lint.new_name == old_name_prefixed { + lint.new_name = new_name; + } + } + match renamed_lints.binary_search_by(|x| x.old_name.cmp(old_name_prefixed)) { + Ok(_) => { + println!("`{old_name}` is already deprecated"); + return; + }, + Err(idx) => renamed_lints.insert( + idx, + RenamedLint { + old_name: old_name_prefixed, + new_name, + version: cx.str_buf.alloc_display(cx.arena, clippy_version.rust_display()), + }, + ), + } + + let mod_path = { + let mut mod_path = PathBuf::from(format!("clippy_lints/src/{}", lint.module)); + if mod_path.is_dir() { + mod_path = mod_path.join("mod"); + } + + mod_path.set_extension("rs"); + mod_path + }; + + if remove_lint_declaration(old_name, &mod_path, &mut lints).unwrap_or(false) { + generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints); + println!("info: `{old_name}` has successfully been uplifted"); + println!("note: you must run `cargo uitest` to update the test results"); + } else { + eprintln!("error: lint not found"); + } +} + fn remove_lint_declaration(name: &str, path: &Path, lints: &mut Vec>) -> io::Result { fn remove_lint(name: &str, lints: &mut Vec>) { lints.iter().position(|l| l.name == name).map(|pos| lints.remove(pos)); diff --git a/clippy_dev/src/rename_lint.rs b/clippy_dev/src/edit_lints.rs similarity index 52% rename from clippy_dev/src/rename_lint.rs rename to clippy_dev/src/edit_lints.rs index 8e30eb7ce95b..fb1c1458c50c 100644 --- a/clippy_dev/src/rename_lint.rs +++ b/clippy_dev/src/edit_lints.rs @@ -1,5 +1,5 @@ use crate::parse::cursor::{self, Capture, Cursor}; -use crate::parse::{ParseCx, RenamedLint}; +use crate::parse::{DeprecatedLint, Lint, ParseCx, RenamedLint}; use crate::update_lints::generate_lint_files; use crate::utils::{ ErrAction, FileUpdater, UpdateMode, UpdateStatus, Version, delete_dir_if_exists, delete_file_if_exists, @@ -10,6 +10,96 @@ use std::ffi::OsString; use std::fs; use std::path::Path; +/// Runs the `deprecate` command +/// +/// This does the following: +/// * Adds an entry to `deprecated_lints.rs`. +/// * Removes the lint declaration (and the entire file if applicable) +/// +/// # Panics +/// +/// If a file path could not read from or written to +pub fn deprecate<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, name: &'env str, reason: &'env str) { + let mut lints = cx.find_lint_decls(); + let (mut deprecated_lints, renamed_lints) = cx.read_deprecated_lints(); + + let Some(lint_idx) = lints.iter().position(|l| l.name == name) else { + eprintln!("error: failed to find lint `{name}`"); + return; + }; + + let prefixed_name = cx.str_buf.with(|buf| { + buf.extend(["clippy::", name]); + cx.arena.alloc_str(buf) + }); + match deprecated_lints.binary_search_by(|x| x.name.cmp(prefixed_name)) { + Ok(_) => { + println!("`{name}` is already deprecated"); + return; + }, + Err(idx) => deprecated_lints.insert( + idx, + DeprecatedLint { + name: prefixed_name, + reason, + version: cx.str_buf.alloc_display(cx.arena, clippy_version.rust_display()), + }, + ), + } + + remove_lint_declaration(lint_idx, &mut lints, &mut FileUpdater::default()); + generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints); + println!("info: `{name}` has successfully been deprecated"); + println!("note: you must run `cargo uitest` to update the test results"); +} + +pub fn uplift<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'env str, new_name: &'env str) { + let mut lints = cx.find_lint_decls(); + let (deprecated_lints, mut renamed_lints) = cx.read_deprecated_lints(); + + let Some(lint_idx) = lints.iter().position(|l| l.name == old_name) else { + eprintln!("error: failed to find lint `{old_name}`"); + return; + }; + + let old_name_prefixed = cx.str_buf.with(|buf| { + buf.extend(["clippy::", old_name]); + cx.arena.alloc_str(buf) + }); + for lint in &mut renamed_lints { + if lint.new_name == old_name_prefixed { + lint.new_name = new_name; + } + } + match renamed_lints.binary_search_by(|x| x.old_name.cmp(old_name_prefixed)) { + Ok(_) => { + println!("`{old_name}` is already deprecated"); + return; + }, + Err(idx) => renamed_lints.insert( + idx, + RenamedLint { + old_name: old_name_prefixed, + new_name, + version: cx.str_buf.alloc_display(cx.arena, clippy_version.rust_display()), + }, + ), + } + + let mut updater = FileUpdater::default(); + let remove_mod = remove_lint_declaration(lint_idx, &mut lints, &mut updater); + let mut update_fn = uplift_update_fn(old_name, new_name, remove_mod); + for e in walk_dir_no_dot_or_target(".") { + let e = expect_action(e, ErrAction::Read, "."); + if e.path().as_os_str().as_encoded_bytes().ends_with(b".rs") { + updater.update_file(e.path(), &mut update_fn); + } + } + generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints); + println!("info: `{old_name}` has successfully been uplifted as `{new_name}`"); + println!("note: you must run `cargo uitest` to update the test results"); +} + /// Runs the `rename_lint` command. /// /// This does the following: @@ -25,8 +115,7 @@ use std::path::Path; /// * If either lint name has a prefix /// * If `old_name` doesn't name an existing lint. /// * If `old_name` names a deprecated or renamed lint. -#[expect(clippy::too_many_lines)] -pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str, new_name: &'cx str, uplift: bool) { +pub fn rename<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'env str, new_name: &'env str) { let mut updater = FileUpdater::default(); let mut lints = cx.find_lint_decls(); let (deprecated_lints, mut renamed_lints) = cx.read_deprecated_lints(); @@ -34,20 +123,15 @@ pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str let Ok(lint_idx) = lints.binary_search_by(|x| x.name.cmp(old_name)) else { panic!("could not find lint `{old_name}`"); }; - let lint = &lints[lint_idx]; let old_name_prefixed = cx.str_buf.with(|buf| { buf.extend(["clippy::", old_name]); cx.arena.alloc_str(buf) }); - let new_name_prefixed = if uplift { - new_name - } else { - cx.str_buf.with(|buf| { - buf.extend(["clippy::", new_name]); - cx.arena.alloc_str(buf) - }) - }; + let new_name_prefixed = cx.str_buf.with(|buf| { + buf.extend(["clippy::", new_name]); + cx.arena.alloc_str(buf) + }); for lint in &mut renamed_lints { if lint.new_name == old_name_prefixed { @@ -71,37 +155,8 @@ pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str }, } - // Some tests are named `lint_name_suffix` which should also be renamed, - // but we can't do that if the renamed lint's name overlaps with another - // lint. e.g. renaming 'foo' to 'bar' when a lint 'foo_bar' also exists. - let change_prefixed_tests = lints.get(lint_idx + 1).is_none_or(|l| !l.name.starts_with(old_name)); - - let mut mod_edit = ModEdit::None; - if uplift { - let is_unique_mod = lints[..lint_idx].iter().any(|l| l.module == lint.module) - || lints[lint_idx + 1..].iter().any(|l| l.module == lint.module); - if is_unique_mod { - if delete_file_if_exists(lint.path.as_ref()) { - mod_edit = ModEdit::Delete; - } - } else { - updater.update_file(&lint.path, &mut |_, src, dst| -> UpdateStatus { - let mut start = &src[..lint.declaration_range.start]; - if start.ends_with("\n\n") { - start = &start[..start.len() - 1]; - } - let mut end = &src[lint.declaration_range.end..]; - if end.starts_with("\n\n") { - end = &end[1..]; - } - dst.push_str(start); - dst.push_str(end); - UpdateStatus::Changed - }); - } - delete_test_files(old_name, change_prefixed_tests); - lints.remove(lint_idx); - } else if lints.binary_search_by(|x| x.name.cmp(new_name)).is_err() { + let mut rename_mod = false; + if lints.binary_search_by(|x| x.name.cmp(new_name)).is_err() { let lint = &mut lints[lint_idx]; if lint.module.ends_with(old_name) && lint @@ -112,7 +167,7 @@ pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str let mut new_path = lint.path.with_file_name(new_name).into_os_string(); new_path.push(".rs"); if try_rename_file(lint.path.as_ref(), new_path.as_ref()) { - mod_edit = ModEdit::Rename; + rename_mod = true; } lint.module = cx.str_buf.with(|buf| { @@ -121,7 +176,16 @@ pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str cx.arena.alloc_str(buf) }); } - rename_test_files(old_name, new_name, change_prefixed_tests); + + rename_test_files( + old_name, + new_name, + &lints[lint_idx + 1..] + .iter() + .map(|l| l.name) + .take_while(|&n| n.starts_with(old_name)) + .collect::>(), + ); lints[lint_idx].name = new_name; lints.sort_by(|lhs, rhs| lhs.name.cmp(rhs.name)); } else { @@ -130,7 +194,7 @@ pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str return; } - let mut update_fn = file_update_fn(old_name, new_name, mod_edit); + let mut update_fn = rename_update_fn(old_name, new_name, rename_mod); for e in walk_dir_no_dot_or_target(".") { let e = expect_action(e, ErrAction::Read, "."); if e.path().as_os_str().as_encoded_bytes().ends_with(b".rs") { @@ -139,67 +203,85 @@ pub fn rename<'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'cx str } generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints); - if uplift { - println!("Uplifted `clippy::{old_name}` as `{new_name}`"); - if matches!(mod_edit, ModEdit::None) { - println!("Only the rename has been registered, the code will need to be edited manually"); - } else { - println!("All the lint's code has been deleted"); - println!("Make sure to inspect the results as some things may have been missed"); - } - } else { - println!("Renamed `clippy::{old_name}` to `clippy::{new_name}`"); - println!("All code referencing the old name has been updated"); - println!("Make sure to inspect the results as some things may have been missed"); - } + println!("Renamed `clippy::{old_name}` to `clippy::{new_name}`"); + println!("All code referencing the old name has been updated"); + println!("Make sure to inspect the results as some things may have been missed"); println!("note: `cargo uibless` still needs to be run to update the test results"); } -#[derive(Clone, Copy)] -enum ModEdit { - None, - Delete, - Rename, +/// Removes a lint's declaration and test files. Returns whether the module containing the +/// lint was deleted. +fn remove_lint_declaration(lint_idx: usize, lints: &mut Vec>, updater: &mut FileUpdater) -> bool { + let lint = lints.remove(lint_idx); + let delete_mod = if lints.iter().all(|l| l.module != lint.module) { + delete_file_if_exists(lint.path.as_ref()) + } else { + updater.update_file(&lint.path, &mut |_, src, dst| -> UpdateStatus { + let mut start = &src[..lint.declaration_range.start]; + if start.ends_with("\n\n") { + start = &start[..start.len() - 1]; + } + let mut end = &src[lint.declaration_range.end..]; + if end.starts_with("\n\n") { + end = &end[1..]; + } + dst.push_str(start); + dst.push_str(end); + UpdateStatus::Changed + }); + false + }; + delete_test_files( + lint.name, + &lints[lint_idx..] + .iter() + .map(|l| l.name) + .take_while(|&n| n.starts_with(lint.name)) + .collect::>(), + ); + + delete_mod } -fn collect_ui_test_names(lint: &str, rename_prefixed: bool, dst: &mut Vec<(OsString, bool)>) { +fn collect_ui_test_names(lint: &str, ignored_prefixes: &[&str], dst: &mut Vec<(OsString, bool)>) { for e in fs::read_dir("tests/ui").expect("error reading `tests/ui`") { let e = e.expect("error reading `tests/ui`"); let name = e.file_name(); - if let Some((name_only, _)) = name.as_encoded_bytes().split_once(|&x| x == b'.') { - if name_only.starts_with(lint.as_bytes()) && (rename_prefixed || name_only.len() == lint.len()) { - dst.push((name, true)); - } - } else if name.as_encoded_bytes().starts_with(lint.as_bytes()) && (rename_prefixed || name.len() == lint.len()) + if name.as_encoded_bytes().starts_with(lint.as_bytes()) + && !ignored_prefixes + .iter() + .any(|&pre| name.as_encoded_bytes().starts_with(pre.as_bytes())) + && let Ok(ty) = e.file_type() + && (ty.is_file() || ty.is_dir()) + { + dst.push((name, ty.is_file())); + } + } +} + +fn collect_ui_toml_test_names(lint: &str, ignored_prefixes: &[&str], dst: &mut Vec<(OsString, bool)>) { + for e in fs::read_dir("tests/ui-toml").expect("error reading `tests/ui-toml`") { + let e = e.expect("error reading `tests/ui-toml`"); + let name = e.file_name(); + if name.as_encoded_bytes().starts_with(lint.as_bytes()) + && !ignored_prefixes + .iter() + .any(|&pre| name.as_encoded_bytes().starts_with(pre.as_bytes())) + && e.file_type().is_ok_and(|ty| ty.is_dir()) { dst.push((name, false)); } } } -fn collect_ui_toml_test_names(lint: &str, rename_prefixed: bool, dst: &mut Vec<(OsString, bool)>) { - if rename_prefixed { - for e in fs::read_dir("tests/ui-toml").expect("error reading `tests/ui-toml`") { - let e = e.expect("error reading `tests/ui-toml`"); - let name = e.file_name(); - if name.as_encoded_bytes().starts_with(lint.as_bytes()) && e.file_type().is_ok_and(|ty| ty.is_dir()) { - dst.push((name, false)); - } - } - } else { - dst.push((lint.into(), false)); - } -} - -/// Renames all test files for the given lint. -/// -/// If `rename_prefixed` is `true` this will also rename tests which have the lint name as a prefix. -fn rename_test_files(old_name: &str, new_name: &str, rename_prefixed: bool) { - let mut tests = Vec::new(); +/// Renames all test files for the given lint where the file name does not start with any +/// of the given prefixes. +fn rename_test_files(old_name: &str, new_name: &str, ignored_prefixes: &[&str]) { + let mut tests: Vec<(OsString, bool)> = Vec::new(); let mut old_buf = OsString::from("tests/ui/"); let mut new_buf = OsString::from("tests/ui/"); - collect_ui_test_names(old_name, rename_prefixed, &mut tests); + collect_ui_test_names(old_name, ignored_prefixes, &mut tests); for &(ref name, is_file) in &tests { old_buf.push(name); new_buf.extend([new_name.as_ref(), name.slice_encoded_bytes(old_name.len()..)]); @@ -217,7 +299,7 @@ fn rename_test_files(old_name: &str, new_name: &str, rename_prefixed: bool) { new_buf.truncate("tests/ui".len()); old_buf.push("-toml/"); new_buf.push("-toml/"); - collect_ui_toml_test_names(old_name, rename_prefixed, &mut tests); + collect_ui_toml_test_names(old_name, ignored_prefixes, &mut tests); for (name, _) in &tests { old_buf.push(name); new_buf.extend([new_name.as_ref(), name.slice_encoded_bytes(old_name.len()..)]); @@ -227,11 +309,13 @@ fn rename_test_files(old_name: &str, new_name: &str, rename_prefixed: bool) { } } -fn delete_test_files(lint: &str, rename_prefixed: bool) { +/// Deletes all test files for the given lint where the file name does not start with any +/// of the given prefixes. +fn delete_test_files(lint: &str, ignored_prefixes: &[&str]) { let mut tests = Vec::new(); let mut buf = OsString::from("tests/ui/"); - collect_ui_test_names(lint, rename_prefixed, &mut tests); + collect_ui_test_names(lint, ignored_prefixes, &mut tests); for &(ref name, is_file) in &tests { buf.push(name); if is_file { @@ -246,7 +330,7 @@ fn delete_test_files(lint: &str, rename_prefixed: bool) { buf.push("-toml/"); tests.clear(); - collect_ui_toml_test_names(lint, rename_prefixed, &mut tests); + collect_ui_toml_test_names(lint, ignored_prefixes, &mut tests); for (name, _) in &tests { buf.push(name); delete_dir_if_exists(buf.as_ref()); @@ -271,12 +355,50 @@ fn snake_to_pascal(s: &str) -> String { String::from_utf8(dst).unwrap() } -#[expect(clippy::too_many_lines)] -fn file_update_fn<'a, 'b>( +/// Creates an update function which replaces all instances of `clippy::old_name` with +/// `new_name`. +fn uplift_update_fn<'a>( old_name: &'a str, - new_name: &'b str, - mod_edit: ModEdit, -) -> impl use<'a, 'b> + FnMut(&Path, &str, &mut String) -> UpdateStatus { + new_name: &'a str, + remove_mod: bool, +) -> impl use<'a> + FnMut(&Path, &str, &mut String) -> UpdateStatus { + move |_, src, dst| { + let mut copy_pos = 0u32; + let mut changed = false; + let mut cursor = Cursor::new(src); + while let Some(ident) = cursor.find_any_ident() { + match cursor.get_text(ident) { + "mod" + if remove_mod && cursor.match_all(&[cursor::Pat::Ident(old_name), cursor::Pat::Semi], &mut []) => + { + dst.push_str(&src[copy_pos as usize..ident.pos as usize]); + dst.push_str(new_name); + copy_pos = cursor.pos(); + if src[copy_pos as usize..].starts_with('\n') { + copy_pos += 1; + } + changed = true; + }, + "clippy" if cursor.match_all(&[cursor::Pat::DoubleColon, cursor::Pat::Ident(old_name)], &mut []) => { + dst.push_str(&src[copy_pos as usize..ident.pos as usize]); + dst.push_str(new_name); + copy_pos = cursor.pos(); + changed = true; + }, + + _ => {}, + } + } + dst.push_str(&src[copy_pos as usize..]); + UpdateStatus::from_changed(changed) + } +} + +fn rename_update_fn<'a>( + old_name: &'a str, + new_name: &'a str, + rename_mod: bool, +) -> impl use<'a> + FnMut(&Path, &str, &mut String) -> UpdateStatus { let old_name_pascal = snake_to_pascal(old_name); let new_name_pascal = snake_to_pascal(new_name); let old_name_upper = old_name.to_ascii_uppercase(); @@ -307,34 +429,15 @@ fn file_update_fn<'a, 'b>( }, // mod lint_name "mod" => { - if !matches!(mod_edit, ModEdit::None) - && let Some(pos) = cursor.find_ident(old_name) - { - match mod_edit { - ModEdit::Rename => { - dst.push_str(&src[copy_pos as usize..pos as usize]); - dst.push_str(new_name); - copy_pos = cursor.pos(); - changed = true; - }, - ModEdit::Delete if cursor.match_pat(cursor::Pat::Semi) => { - let mut start = &src[copy_pos as usize..match_start as usize]; - if start.ends_with("\n\n") { - start = &start[..start.len() - 1]; - } - dst.push_str(start); - copy_pos = cursor.pos(); - if src[copy_pos as usize..].starts_with("\n\n") { - copy_pos += 1; - } - changed = true; - }, - ModEdit::Delete | ModEdit::None => {}, - } + if rename_mod && let Some(pos) = cursor.match_ident(old_name) { + dst.push_str(&src[copy_pos as usize..pos as usize]); + dst.push_str(new_name); + copy_pos = cursor.pos(); + changed = true; } }, // lint_name:: - name if matches!(mod_edit, ModEdit::Rename) && name == old_name => { + name if rename_mod && name == old_name => { let name_end = cursor.pos(); if cursor.match_pat(cursor::Pat::DoubleColon) { dst.push_str(&src[copy_pos as usize..match_start as usize]); diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index cd103908be03..69309403c8d0 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -23,13 +23,12 @@ extern crate rustc_arena; extern crate rustc_driver; extern crate rustc_lexer; -pub mod deprecate_lint; pub mod dogfood; +pub mod edit_lints; pub mod fmt; pub mod lint; pub mod new_lint; pub mod release; -pub mod rename_lint; pub mod serve; pub mod setup; pub mod sync; diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 392c3aabf193..8dc2290df8e4 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -4,8 +4,8 @@ use clap::{Args, Parser, Subcommand}; use clippy_dev::{ - ClippyInfo, UpdateMode, deprecate_lint, dogfood, fmt, lint, new_lint, new_parse_cx, release, rename_lint, serve, - setup, sync, update_lints, + ClippyInfo, UpdateMode, dogfood, edit_lints, fmt, lint, new_lint, new_parse_cx, release, serve, setup, sync, + update_lints, }; use std::env; @@ -74,21 +74,14 @@ fn main() { }, DevCommand::Serve { port, lint } => serve::run(port, lint), DevCommand::Lint { path, edition, args } => lint::run(&path, &edition, args.iter()), - DevCommand::RenameLint { - old_name, - new_name, - uplift, - } => new_parse_cx(|cx| { - rename_lint::rename( - cx, - clippy.version, - &old_name, - new_name.as_ref().unwrap_or(&old_name), - uplift, - ); + DevCommand::RenameLint { old_name, new_name } => new_parse_cx(|cx| { + edit_lints::rename(cx, clippy.version, &old_name, &new_name); + }), + DevCommand::Uplift { old_name, new_name } => new_parse_cx(|cx| { + edit_lints::uplift(cx, clippy.version, &old_name, new_name.as_deref().unwrap_or(&old_name)); }), DevCommand::Deprecate { name, reason } => { - new_parse_cx(|cx| deprecate_lint::deprecate(cx, clippy.version, &name, &reason)); + new_parse_cx(|cx| edit_lints::deprecate(cx, clippy.version, &name, &reason)); }, DevCommand::Sync(SyncCommand { subcommand }) => match subcommand { SyncSubcommand::UpdateNightly => sync::update_nightly(), @@ -243,15 +236,9 @@ enum DevCommand { /// The name of the lint to rename #[arg(value_parser = lint_name)] old_name: String, - #[arg( - required_unless_present = "uplift", - value_parser = lint_name, - )] + #[arg(value_parser = lint_name)] /// The new name of the lint - new_name: Option, - #[arg(long)] - /// This lint will be uplifted into rustc - uplift: bool, + new_name: String, }, /// Deprecate the given lint Deprecate { @@ -266,6 +253,15 @@ enum DevCommand { Sync(SyncCommand), /// Manage Clippy releases Release(ReleaseCommand), + /// Marks a lint as uplifted into rustc and removes its code + Uplift { + /// The name of the lint to uplift + #[arg(value_parser = lint_name)] + old_name: String, + /// The name of the lint in rustc + #[arg(value_parser = lint_name)] + new_name: Option, + }, } #[derive(Args)] diff --git a/clippy_dev/src/parse/cursor.rs b/clippy_dev/src/parse/cursor.rs index 6dc003f326de..2c142af4883a 100644 --- a/clippy_dev/src/parse/cursor.rs +++ b/clippy_dev/src/parse/cursor.rs @@ -219,6 +219,22 @@ impl<'txt> Cursor<'txt> { } } + /// Consume the returns the position of the next non-whitespace token if it's an + /// identifier. Returns `None` otherwise. + pub fn match_ident(&mut self, s: &str) -> Option { + loop { + match self.next_token.kind { + TokenKind::Ident if s == self.peek_text() => { + let pos = self.pos; + self.step(); + return Some(pos); + }, + TokenKind::Whitespace => self.step(), + _ => return None, + } + } + } + /// Continually attempt to match the pattern on subsequent tokens until a match is /// found. Returns whether the pattern was successfully matched. /// diff --git a/clippy_dev/src/serve.rs b/clippy_dev/src/serve.rs index d9e018133813..b99289672420 100644 --- a/clippy_dev/src/serve.rs +++ b/clippy_dev/src/serve.rs @@ -54,7 +54,7 @@ pub fn run(port: u16, lint: Option) -> ! { } // Delay to avoid updating the metadata too aggressively. - thread::sleep(Duration::from_millis(1000)); + thread::sleep(Duration::from_secs(1)); } } diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 7a78ef32bf3c..c0804dbb0492 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.94" +version = "0.1.95" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index 42c321df61c1..fa2951d91934 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -468,6 +468,10 @@ declare_clippy_lint! { /// #[ignore = "Some good reason"] /// fn test() {} /// ``` + /// + /// ### Note + /// Clippy can only lint compiled code. For this lint to trigger, you must configure `cargo clippy` + /// to include test compilation, for instance, by using flags such as `--tests` or `--all-targets`. #[clippy::version = "1.88.0"] pub IGNORE_WITHOUT_REASON, pedantic, diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 7220a8a80066..3c9ebef73f0d 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -145,6 +145,12 @@ declare_clippy_lint! { /// let _ = i32::try_from(u32::MAX).ok(); /// ``` /// + /// If the wrapping is intended, you can use: + /// ```no_run + /// let _ = u32::MAX.cast_signed(); + /// let _ = (-1i32).cast_unsigned(); + /// ``` + /// #[clippy::version = "pre 1.29.0"] pub CAST_POSSIBLE_WRAP, pedantic, diff --git a/clippy_lints/src/comparison_chain.rs b/clippy_lints/src/comparison_chain.rs index 238ebd4a444c..a2ddf3dad7a2 100644 --- a/clippy_lints/src/comparison_chain.rs +++ b/clippy_lints/src/comparison_chain.rs @@ -17,10 +17,6 @@ declare_clippy_lint! { /// `if` is not guaranteed to be exhaustive and conditionals can get /// repetitive /// - /// ### Known problems - /// The match statement may be slower due to the compiler - /// not inlining the call to cmp. See issue [#5354](https://github.com/rust-lang/rust-clippy/issues/5354) - /// /// ### Example /// ```rust,ignore /// # fn a() {} diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 6b68940c6423..a04d133b0d72 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -135,6 +135,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::drop_forget_ref::FORGET_NON_DROP_INFO, crate::drop_forget_ref::MEM_FORGET_INFO, crate::duplicate_mod::DUPLICATE_MOD_INFO, + crate::duration_suboptimal_units::DURATION_SUBOPTIMAL_UNITS_INFO, crate::else_if_without_else::ELSE_IF_WITHOUT_ELSE_INFO, crate::empty_drop::EMPTY_DROP_INFO, crate::empty_enums::EMPTY_ENUMS_INFO, @@ -296,6 +297,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::manual_assert::MANUAL_ASSERT_INFO, crate::manual_async_fn::MANUAL_ASYNC_FN_INFO, crate::manual_bits::MANUAL_BITS_INFO, + crate::manual_checked_ops::MANUAL_CHECKED_OPS_INFO, crate::manual_clamp::MANUAL_CLAMP_INFO, crate::manual_float_methods::MANUAL_IS_FINITE_INFO, crate::manual_float_methods::MANUAL_IS_INFINITE_INFO, @@ -315,6 +317,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::manual_slice_size_calculation::MANUAL_SLICE_SIZE_CALCULATION_INFO, crate::manual_string_new::MANUAL_STRING_NEW_INFO, crate::manual_strip::MANUAL_STRIP_INFO, + crate::manual_take::MANUAL_TAKE_INFO, crate::map_unit_fn::OPTION_MAP_UNIT_FN_INFO, crate::map_unit_fn::RESULT_MAP_UNIT_FN_INFO, crate::match_result_ok::MATCH_RESULT_OK_INFO, diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index 6b8a6aec92fa..992ed320ce68 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -105,7 +105,7 @@ fn check_struct<'tcx>( if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind && let Some(PathSegment { args, .. }) = p.segments.last() { - let args = args.map(|a| a.args).unwrap_or(&[]); + let args = args.map(|a| a.args).unwrap_or_default(); // ty_args contains the generic parameters of the type declaration, while args contains the // arguments used at instantiation time. If both len are not equal, it means that some diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 2b41275ee3a4..ecf7acbd7ce6 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -692,6 +692,12 @@ declare_clippy_lint! { /// /// /// /// It was chosen by a fair dice roll. /// ``` + /// + /// ### Terminal punctuation marks + /// This lint treats these characters as end markers: '.', '?', '!', '…' and ':'. + /// + /// The colon is not exactly a terminal punctuation mark, but this is required for paragraphs that + /// introduce a table or a list for example. #[clippy::version = "1.93.0"] pub DOC_PARAGRAPHS_MISSING_PUNCTUATION, restriction, diff --git a/clippy_lints/src/duration_suboptimal_units.rs b/clippy_lints/src/duration_suboptimal_units.rs new file mode 100644 index 000000000000..8140585b70d3 --- /dev/null +++ b/clippy_lints/src/duration_suboptimal_units.rs @@ -0,0 +1,204 @@ +use std::ops::ControlFlow; + +use clippy_config::Conf; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::res::MaybeDef; +use clippy_utils::sym; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, QPath, RustcVersion}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::ty::TyCtxt; +use rustc_session::impl_lint_pass; +use rustc_span::Symbol; + +declare_clippy_lint! { + /// ### What it does + /// + /// Checks for instances where a `std::time::Duration` is constructed using a smaller time unit + /// when the value could be expressed more clearly using a larger unit. + /// + /// ### Why is this bad? + /// + /// Using a smaller unit for a duration that is evenly divisible by a larger unit reduces + /// readability. Readers have to mentally convert values, which can be error-prone and makes + /// the code less clear. + /// + /// ### Example + /// ``` + /// use std::time::Duration; + /// + /// let dur = Duration::from_millis(5_000); + /// let dur = Duration::from_secs(180); + /// let dur = Duration::from_mins(10 * 60); + /// ``` + /// + /// Use instead: + /// ``` + /// use std::time::Duration; + /// + /// let dur = Duration::from_secs(5); + /// let dur = Duration::from_mins(3); + /// let dur = Duration::from_hours(10); + /// ``` + #[clippy::version = "1.95.0"] + pub DURATION_SUBOPTIMAL_UNITS, + pedantic, + "constructing a `Duration` using a smaller unit when a larger unit would be more readable" +} + +impl_lint_pass!(DurationSuboptimalUnits => [DURATION_SUBOPTIMAL_UNITS]); + +pub struct DurationSuboptimalUnits { + msrv: Msrv, + units: Vec, +} + +impl DurationSuboptimalUnits { + pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { + // The order of the units matters, as they are walked top to bottom + let mut units = UNITS.to_vec(); + if tcx.features().enabled(sym::duration_constructors) { + units.extend(EXTENDED_UNITS); + } + Self { msrv: conf.msrv, units } + } +} + +impl LateLintPass<'_> for DurationSuboptimalUnits { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { + if !expr.span.in_external_macro(cx.sess().source_map()) + // Check if a function on std::time::Duration is called + && let ExprKind::Call(func, [arg]) = expr.kind + && let ExprKind::Path(QPath::TypeRelative(func_ty, func_name)) = func.kind + && cx + .typeck_results() + .node_type(func_ty.hir_id) + .is_diag_item(cx, sym::Duration) + // We intentionally don't want to evaluate referenced constants, as we don't want to + // recommend a literal value over using constants: + // + // let dur = Duration::from_secs(SIXTY); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Duration::from_mins(1)` + && let Some(Constant::Int(value)) = ConstEvalCtxt::new(cx).eval_local(arg, expr.span.ctxt()) + && let value = u64::try_from(value).expect("All Duration::from_ constructors take a u64") + // There is no need to promote e.g. 0 seconds to 0 hours + && value != 0 + && let Some((promoted_constructor, promoted_value)) = self.promote(cx, func_name.ident.name, value) + { + span_lint_and_then( + cx, + DURATION_SUBOPTIMAL_UNITS, + expr.span, + "constructing a `Duration` using a smaller unit when a larger unit would be more readable", + |diag| { + let suggestions = vec![ + (func_name.ident.span, promoted_constructor.to_string()), + (arg.span, promoted_value.to_string()), + ]; + diag.multipart_suggestion_verbose( + format!("try using {promoted_constructor}"), + suggestions, + Applicability::MachineApplicable, + ); + }, + ); + } + } +} + +impl DurationSuboptimalUnits { + /// Tries to promote the given constructor and value to a bigger time unit and returns the + /// promoted constructor name and value. + /// + /// Returns [`None`] in case no promotion could be done. + fn promote(&self, cx: &LateContext<'_>, constructor_name: Symbol, value: u64) -> Option<(Symbol, u64)> { + let (best_unit, best_value) = self + .units + .iter() + .skip_while(|unit| unit.constructor_name != constructor_name) + .skip(1) + .try_fold( + (constructor_name, value), + |(current_unit, current_value), bigger_unit| { + if let Some(bigger_value) = current_value.div_exact(u64::from(bigger_unit.factor)) + && bigger_unit.stable_since.is_none_or(|v| self.msrv.meets(cx, v)) + { + ControlFlow::Continue((bigger_unit.constructor_name, bigger_value)) + } else { + // We have to break early, as we can't skip versions, as they are needed to + // correctly calculate the promoted value. + ControlFlow::Break((current_unit, current_value)) + } + }, + ) + .into_value(); + (best_unit != constructor_name).then_some((best_unit, best_value)) + } +} + +#[derive(Clone, Copy)] +struct Unit { + /// Name of the constructor on [`Duration`](std::time::Duration) to construct it from the given + /// unit, e.g. [`Duration::from_secs`](std::time::Duration::from_secs) + constructor_name: Symbol, + + /// The increase factor over the previous (smaller) unit + factor: u16, + + /// In what rustc version stable support for this constructor was added. + /// We do not need to track the version stable support in const contexts was added, as the const + /// stabilization was done in an ascending order of the time unites, so it's always valid to + /// promote a const constructor. + stable_since: Option, +} + +/// Time unit constructors available on stable. The order matters! +const UNITS: [Unit; 6] = [ + Unit { + constructor_name: sym::from_nanos, + // The value doesn't matter, as there is no previous unit + factor: 0, + stable_since: Some(msrvs::DURATION_FROM_NANOS_MICROS), + }, + Unit { + constructor_name: sym::from_micros, + factor: 1_000, + stable_since: Some(msrvs::DURATION_FROM_NANOS_MICROS), + }, + Unit { + constructor_name: sym::from_millis, + factor: 1_000, + stable_since: Some(msrvs::DURATION_FROM_MILLIS_SECS), + }, + Unit { + constructor_name: sym::from_secs, + factor: 1_000, + stable_since: Some(msrvs::DURATION_FROM_MILLIS_SECS), + }, + Unit { + constructor_name: sym::from_mins, + factor: 60, + stable_since: Some(msrvs::DURATION_FROM_MINUTES_HOURS), + }, + Unit { + constructor_name: sym::from_hours, + factor: 60, + stable_since: Some(msrvs::DURATION_FROM_MINUTES_HOURS), + }, +]; + +/// Time unit constructors behind the `duration_constructors` feature. The order matters! +const EXTENDED_UNITS: [Unit; 2] = [ + Unit { + constructor_name: sym::from_days, + factor: 24, + stable_since: None, + }, + Unit { + constructor_name: sym::from_weeks, + factor: 7, + stable_since: None, + }, +]; diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs deleted file mode 100644 index 5f022ba307ff..000000000000 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ /dev/null @@ -1,761 +0,0 @@ -use clippy_utils::consts::Constant::{F32, F64, Int}; -use clippy_utils::consts::{ConstEvalCtxt, Constant}; -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; -use clippy_utils::{ - eq_expr_value, get_parent_expr, has_ambiguous_literal_in_expr, higher, is_in_const_context, is_no_std_crate, - numeric_literal, peel_blocks, sugg, sym, -}; -use rustc_ast::ast; -use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty; -use rustc_session::declare_lint_pass; -use rustc_span::SyntaxContext; -use rustc_span::source_map::Spanned; -use std::f32::consts as f32_consts; -use std::f64::consts as f64_consts; -use sugg::Sugg; - -declare_clippy_lint! { - /// ### What it does - /// Looks for floating-point expressions that - /// can be expressed using built-in methods to improve accuracy - /// at the cost of performance. - /// - /// ### Why is this bad? - /// Negatively impacts accuracy. - /// - /// ### Example - /// ```no_run - /// let a = 3f32; - /// let _ = a.powf(1.0 / 3.0); - /// let _ = (1.0 + a).ln(); - /// let _ = a.exp() - 1.0; - /// ``` - /// - /// Use instead: - /// ```no_run - /// let a = 3f32; - /// let _ = a.cbrt(); - /// let _ = a.ln_1p(); - /// let _ = a.exp_m1(); - /// ``` - #[clippy::version = "1.43.0"] - pub IMPRECISE_FLOPS, - nursery, - "usage of imprecise floating point operations" -} - -declare_clippy_lint! { - /// ### What it does - /// Looks for floating-point expressions that - /// can be expressed using built-in methods to improve both - /// accuracy and performance. - /// - /// ### Why is this bad? - /// Negatively impacts accuracy and performance. - /// - /// ### Example - /// ```no_run - /// use std::f32::consts::E; - /// - /// let a = 3f32; - /// let _ = (2f32).powf(a); - /// let _ = E.powf(a); - /// let _ = a.powf(1.0 / 2.0); - /// let _ = a.log(2.0); - /// let _ = a.log(10.0); - /// let _ = a.log(E); - /// let _ = a.powf(2.0); - /// let _ = a * 2.0 + 4.0; - /// let _ = if a < 0.0 { - /// -a - /// } else { - /// a - /// }; - /// let _ = if a < 0.0 { - /// a - /// } else { - /// -a - /// }; - /// ``` - /// - /// is better expressed as - /// - /// ```no_run - /// use std::f32::consts::E; - /// - /// let a = 3f32; - /// let _ = a.exp2(); - /// let _ = a.exp(); - /// let _ = a.sqrt(); - /// let _ = a.log2(); - /// let _ = a.log10(); - /// let _ = a.ln(); - /// let _ = a.powi(2); - /// let _ = a.mul_add(2.0, 4.0); - /// let _ = a.abs(); - /// let _ = -a.abs(); - /// ``` - #[clippy::version = "1.43.0"] - pub SUBOPTIMAL_FLOPS, - nursery, - "usage of sub-optimal floating point operations" -} - -declare_lint_pass!(FloatingPointArithmetic => [ - IMPRECISE_FLOPS, - SUBOPTIMAL_FLOPS -]); - -// Returns the specialized log method for a given base if base is constant -// and is one of 2, 10 and e -fn get_specialized_log_method(cx: &LateContext<'_>, base: &Expr<'_>, ctxt: SyntaxContext) -> Option<&'static str> { - if let Some(value) = ConstEvalCtxt::new(cx).eval_local(base, ctxt) { - if F32(2.0) == value || F64(2.0) == value { - return Some("log2"); - } else if F32(10.0) == value || F64(10.0) == value { - return Some("log10"); - } else if F32(f32_consts::E) == value || F64(f64_consts::E) == value { - return Some("ln"); - } - } - - None -} - -// Adds type suffixes and parenthesis to method receivers if necessary -fn prepare_receiver_sugg<'a>(cx: &LateContext<'_>, mut expr: &'a Expr<'a>) -> Sugg<'a> { - let mut suggestion = Sugg::hir(cx, expr, ".."); - - if let ExprKind::Unary(UnOp::Neg, inner_expr) = &expr.kind { - expr = inner_expr; - } - - if let ty::Float(float_ty) = cx.typeck_results().expr_ty(expr).kind() - // if the expression is a float literal and it is unsuffixed then - // add a suffix so the suggestion is valid and unambiguous - && let ExprKind::Lit(lit) = &expr.kind - && let ast::LitKind::Float(sym, ast::LitFloatType::Unsuffixed) = lit.node - { - let op = format!( - "{suggestion}{}{}", - // Check for float literals without numbers following the decimal - // separator such as `2.` and adds a trailing zero - if sym.as_str().ends_with('.') { "0" } else { "" }, - float_ty.name_str() - ) - .into(); - - suggestion = match suggestion { - Sugg::MaybeParen(_) | Sugg::UnOp(UnOp::Neg, _) => Sugg::MaybeParen(op), - _ => Sugg::NonParen(op), - }; - } - - suggestion.maybe_paren() -} - -fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { - if let Some(method) = get_specialized_log_method(cx, &args[0], expr.span.ctxt()) { - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "logarithm for bases 2, 10 and e can be computed more accurately", - "consider using", - format!("{}.{method}()", Sugg::hir(cx, receiver, "..").maybe_paren()), - Applicability::MachineApplicable, - ); - } -} - -// TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and -// suggest usage of `(x + (y - 1)).ln_1p()` instead -fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) { - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Add, .. - }, - lhs, - rhs, - ) = receiver.kind - { - let ecx = ConstEvalCtxt::new(cx); - let recv = match (ecx.eval(lhs), ecx.eval(rhs)) { - (Some(value), _) if F32(1.0) == value || F64(1.0) == value => rhs, - (_, Some(value)) if F32(1.0) == value || F64(1.0) == value => lhs, - _ => return, - }; - - span_lint_and_sugg( - cx, - IMPRECISE_FLOPS, - expr.span, - "ln(1 + x) can be computed more accurately", - "consider using", - format!("{}.ln_1p()", prepare_receiver_sugg(cx, recv)), - Applicability::MachineApplicable, - ); - } -} - -// Returns an integer if the float constant is a whole number and it can be -// converted to an integer without loss of precision. For now we only check -// ranges [-16777215, 16777216) for type f32 as whole number floats outside -// this range are lossy and ambiguous. -#[expect(clippy::cast_possible_truncation)] -fn get_integer_from_float_constant(value: &Constant) -> Option { - match value { - F32(num) if num.fract() == 0.0 => { - if (-16_777_215.0..16_777_216.0).contains(num) { - Some(num.round() as i32) - } else { - None - } - }, - F64(num) if num.fract() == 0.0 => { - if (-2_147_483_648.0..2_147_483_648.0).contains(num) { - Some(num.round() as i32) - } else { - None - } - }, - _ => None, - } -} - -fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { - // Check receiver - if let Some(value) = ConstEvalCtxt::new(cx).eval(receiver) - && let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value { - Some("exp") - } else if F32(2.0) == value || F64(2.0) == value { - Some("exp2") - } else { - None - } - { - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "exponent for bases 2 and e can be computed more accurately", - "consider using", - format!("{}.{method}()", prepare_receiver_sugg(cx, &args[0])), - Applicability::MachineApplicable, - ); - } - - // Check argument - if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) { - let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value { - ( - SUBOPTIMAL_FLOPS, - "square-root of a number can be computed more efficiently and accurately", - format!("{}.sqrt()", Sugg::hir(cx, receiver, "..").maybe_paren()), - ) - } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value { - ( - IMPRECISE_FLOPS, - "cube-root of a number can be computed more accurately", - format!("{}.cbrt()", Sugg::hir(cx, receiver, "..").maybe_paren()), - ) - } else if let Some(exponent) = get_integer_from_float_constant(&value) { - ( - SUBOPTIMAL_FLOPS, - "exponentiation with integer powers can be computed more efficiently", - format!( - "{}.powi({})", - Sugg::hir(cx, receiver, "..").maybe_paren(), - numeric_literal::format(&exponent.to_string(), None, false) - ), - ) - } else { - return; - }; - - span_lint_and_sugg( - cx, - lint, - expr.span, - help, - "consider using", - suggestion, - Applicability::MachineApplicable, - ); - } -} - -fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { - if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) - && value == Int(2) - && let Some(parent) = get_parent_expr(cx, expr) - { - if let Some(grandparent) = get_parent_expr(cx, parent) - && let ExprKind::MethodCall(PathSegment { ident: method, .. }, receiver, ..) = grandparent.kind - && method.name == sym::sqrt - && detect_hypot(cx, receiver).is_some() - { - return; - } - - if let ExprKind::Binary( - Spanned { - node: op @ (BinOpKind::Add | BinOpKind::Sub), - .. - }, - lhs, - rhs, - ) = parent.kind - { - let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs }; - - // Negate expr if original code has subtraction and expr is on the right side - let maybe_neg_sugg = |expr, hir_id| { - let sugg = Sugg::hir(cx, expr, ".."); - if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id { - -sugg - } else { - sugg - } - }; - - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - parent.span, - "multiply and add expressions can be calculated more efficiently and accurately", - "consider using", - format!( - "{}.mul_add({}, {})", - Sugg::hir(cx, receiver, "..").maybe_paren(), - maybe_neg_sugg(receiver, expr.hir_id), - maybe_neg_sugg(other_addend, other_addend.hir_id), - ), - Applicability::MachineApplicable, - ); - } - } -} - -fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option { - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Add, .. - }, - add_lhs, - add_rhs, - ) = receiver.kind - { - // check if expression of the form x * x + y * y - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Mul, .. - }, - lmul_lhs, - lmul_rhs, - ) = add_lhs.kind - && let ExprKind::Binary( - Spanned { - node: BinOpKind::Mul, .. - }, - rmul_lhs, - rmul_rhs, - ) = add_rhs.kind - && eq_expr_value(cx, lmul_lhs, lmul_rhs) - && eq_expr_value(cx, rmul_lhs, rmul_rhs) - { - return Some(format!( - "{}.hypot({})", - Sugg::hir(cx, lmul_lhs, "..").maybe_paren(), - Sugg::hir(cx, rmul_lhs, "..") - )); - } - - // check if expression of the form x.powi(2) + y.powi(2) - if let ExprKind::MethodCall(PathSegment { ident: lmethod, .. }, largs_0, [largs_1, ..], _) = &add_lhs.kind - && let ExprKind::MethodCall(PathSegment { ident: rmethod, .. }, rargs_0, [rargs_1, ..], _) = &add_rhs.kind - && lmethod.name == sym::powi - && rmethod.name == sym::powi - && let ecx = ConstEvalCtxt::new(cx) - && let Some(lvalue) = ecx.eval(largs_1) - && let Some(rvalue) = ecx.eval(rargs_1) - && Int(2) == lvalue - && Int(2) == rvalue - { - return Some(format!( - "{}.hypot({})", - Sugg::hir(cx, largs_0, "..").maybe_paren(), - Sugg::hir(cx, rargs_0, "..") - )); - } - } - - None -} - -fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) { - if let Some(message) = detect_hypot(cx, receiver) { - span_lint_and_sugg( - cx, - IMPRECISE_FLOPS, - expr.span, - "hypotenuse can be computed more accurately", - "consider using", - message, - Applicability::MachineApplicable, - ); - } -} - -// TODO: Lint expressions of the form `x.exp() - y` where y > 1 -// and suggest usage of `x.exp_m1() - (y - 1)` instead -fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) { - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Sub, .. - }, - lhs, - rhs, - ) = expr.kind - && let ExprKind::MethodCall(path, self_arg, [], _) = &lhs.kind - && path.ident.name == sym::exp - && cx.typeck_results().expr_ty(lhs).is_floating_point() - && let Some(value) = ConstEvalCtxt::new(cx).eval(rhs) - && (F32(1.0) == value || F64(1.0) == value) - && cx.typeck_results().expr_ty(self_arg).is_floating_point() - { - span_lint_and_sugg( - cx, - IMPRECISE_FLOPS, - expr.span, - "(e.pow(x) - 1) can be computed more accurately", - "consider using", - format!("{}.exp_m1()", Sugg::hir(cx, self_arg, "..").maybe_paren()), - Applicability::MachineApplicable, - ); - } -} - -fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> { - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Mul, .. - }, - lhs, - rhs, - ) = &expr.kind - && cx.typeck_results().expr_ty(lhs).is_floating_point() - && cx.typeck_results().expr_ty(rhs).is_floating_point() - { - return Some((lhs, rhs)); - } - - None -} - -fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) { - if let ExprKind::Binary( - Spanned { - node: op @ (BinOpKind::Add | BinOpKind::Sub), - .. - }, - lhs, - rhs, - ) = &expr.kind - { - if let Some(parent) = get_parent_expr(cx, expr) - && let ExprKind::MethodCall(PathSegment { ident: method, .. }, receiver, ..) = parent.kind - && method.name == sym::sqrt - && detect_hypot(cx, receiver).is_some() - { - return; - } - - let maybe_neg_sugg = |expr| { - let sugg = Sugg::hir(cx, expr, ".."); - if let BinOpKind::Sub = op { -sugg } else { sugg } - }; - - let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) - && cx.typeck_results().expr_ty(rhs).is_floating_point() - { - (inner_lhs, Sugg::hir(cx, inner_rhs, ".."), maybe_neg_sugg(rhs)) - } else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) - && cx.typeck_results().expr_ty(lhs).is_floating_point() - { - (inner_lhs, maybe_neg_sugg(inner_rhs), Sugg::hir(cx, lhs, "..")) - } else { - return; - }; - - // Check if any variable in the expression has an ambiguous type (could be f32 or f64) - // see: https://github.com/rust-lang/rust-clippy/issues/14897 - if (matches!(recv.kind, ExprKind::Path(_)) || matches!(recv.kind, ExprKind::Call(_, _))) - && has_ambiguous_literal_in_expr(cx, recv) - { - return; - } - - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "multiply and add expressions can be calculated more efficiently and accurately", - "consider using", - format!("{}.mul_add({arg1}, {arg2})", prepare_receiver_sugg(cx, recv)), - Applicability::MachineApplicable, - ); - } -} - -/// Returns true iff expr is an expression which tests whether or not -/// test is positive or an expression which tests whether or not test -/// is nonnegative. -/// Used for check-custom-abs function below -fn is_testing_positive(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { - if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { - match op { - BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, right, expr.span.ctxt()) && eq_expr_value(cx, left, test), - BinOpKind::Lt | BinOpKind::Le => is_zero(cx, left, expr.span.ctxt()) && eq_expr_value(cx, right, test), - _ => false, - } - } else { - false - } -} - -/// See [`is_testing_positive`] -fn is_testing_negative(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { - if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { - match op { - BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, left, expr.span.ctxt()) && eq_expr_value(cx, right, test), - BinOpKind::Lt | BinOpKind::Le => is_zero(cx, right, expr.span.ctxt()) && eq_expr_value(cx, left, test), - _ => false, - } - } else { - false - } -} - -/// Returns true iff expr is some zero literal -fn is_zero(cx: &LateContext<'_>, expr: &Expr<'_>, ctxt: SyntaxContext) -> bool { - match ConstEvalCtxt::new(cx).eval_local(expr, ctxt) { - Some(Int(i)) => i == 0, - Some(F32(f)) => f == 0.0, - Some(F64(f)) => f == 0.0, - _ => false, - } -} - -/// If the two expressions are negations of each other, then it returns -/// a tuple, in which the first element is true iff expr1 is the -/// positive expressions, and the second element is the positive -/// one of the two expressions -/// If the two expressions are not negations of each other, then it -/// returns None. -fn are_negated<'a>(cx: &LateContext<'_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a>) -> Option<(bool, &'a Expr<'a>)> { - if let ExprKind::Unary(UnOp::Neg, expr1_negated) = &expr1.kind - && eq_expr_value(cx, expr1_negated, expr2) - { - return Some((false, expr2)); - } - if let ExprKind::Unary(UnOp::Neg, expr2_negated) = &expr2.kind - && eq_expr_value(cx, expr1, expr2_negated) - { - return Some((true, expr1)); - } - None -} - -fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) { - if let Some(higher::If { - cond, - then, - r#else: Some(r#else), - }) = higher::If::hir(expr) - && let if_body_expr = peel_blocks(then) - && let else_body_expr = peel_blocks(r#else) - && let Some((if_expr_positive, body)) = are_negated(cx, if_body_expr, else_body_expr) - { - let positive_abs_sugg = ( - "manual implementation of `abs` method", - format!("{}.abs()", Sugg::hir(cx, body, "..").maybe_paren()), - ); - let negative_abs_sugg = ( - "manual implementation of negation of `abs` method", - format!("-{}.abs()", Sugg::hir(cx, body, "..").maybe_paren()), - ); - let sugg = if is_testing_positive(cx, cond, body) { - if if_expr_positive { - positive_abs_sugg - } else { - negative_abs_sugg - } - } else if is_testing_negative(cx, cond, body) { - if if_expr_positive { - negative_abs_sugg - } else { - positive_abs_sugg - } - } else { - return; - }; - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - sugg.0, - "try", - sugg.1, - Applicability::MachineApplicable, - ); - } -} - -fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool { - if let ExprKind::MethodCall(PathSegment { ident: method_a, .. }, _, args_a, _) = expr_a.kind - && let ExprKind::MethodCall(PathSegment { ident: method_b, .. }, _, args_b, _) = expr_b.kind - { - return method_a.name == method_b.name - && args_a.len() == args_b.len() - && (matches!(method_a.name, sym::ln | sym::log2 | sym::log10) - || method_a.name == sym::log && args_a.len() == 1 && eq_expr_value(cx, &args_a[0], &args_b[0])); - } - - false -} - -fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) { - // check if expression of the form x.logN() / y.logN() - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Div, .. - }, - lhs, - rhs, - ) = &expr.kind - && are_same_base_logs(cx, lhs, rhs) - && let ExprKind::MethodCall(_, largs_self, ..) = &lhs.kind - && let ExprKind::MethodCall(_, rargs_self, ..) = &rhs.kind - { - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "log base can be expressed more clearly", - "consider using", - format!( - "{}.log({})", - Sugg::hir(cx, largs_self, "..").maybe_paren(), - Sugg::hir(cx, rargs_self, ".."), - ), - Applicability::MachineApplicable, - ); - } -} - -fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) { - if let ExprKind::Binary( - Spanned { - node: BinOpKind::Div, .. - }, - div_lhs, - div_rhs, - ) = &expr.kind - && let ExprKind::Binary( - Spanned { - node: BinOpKind::Mul, .. - }, - mul_lhs, - mul_rhs, - ) = &div_lhs.kind - && let ecx = ConstEvalCtxt::new(cx) - && let Some(rvalue) = ecx.eval(div_rhs) - && let Some(lvalue) = ecx.eval(mul_rhs) - { - // TODO: also check for constant values near PI/180 or 180/PI - if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) - && (F32(180_f32) == lvalue || F64(180_f64) == lvalue) - { - let mut proposal = format!("{}.to_degrees()", Sugg::hir(cx, mul_lhs, "..").maybe_paren()); - if let ExprKind::Lit(literal) = mul_lhs.kind - && let ast::LitKind::Float(ref value, float_type) = literal.node - && float_type == ast::LitFloatType::Unsuffixed - { - if value.as_str().ends_with('.') { - proposal = format!("{}0_f64.to_degrees()", Sugg::hir(cx, mul_lhs, "..")); - } else { - proposal = format!("{}_f64.to_degrees()", Sugg::hir(cx, mul_lhs, "..")); - } - } - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "conversion to degrees can be done more accurately", - "consider using", - proposal, - Applicability::MachineApplicable, - ); - } else if (F32(180_f32) == rvalue || F64(180_f64) == rvalue) - && (F32(f32_consts::PI) == lvalue || F64(f64_consts::PI) == lvalue) - { - let mut proposal = format!("{}.to_radians()", Sugg::hir(cx, mul_lhs, "..").maybe_paren()); - if let ExprKind::Lit(literal) = mul_lhs.kind - && let ast::LitKind::Float(ref value, float_type) = literal.node - && float_type == ast::LitFloatType::Unsuffixed - { - if value.as_str().ends_with('.') { - proposal = format!("{}0_f64.to_radians()", Sugg::hir(cx, mul_lhs, "..")); - } else { - proposal = format!("{}_f64.to_radians()", Sugg::hir(cx, mul_lhs, "..")); - } - } - span_lint_and_sugg( - cx, - SUBOPTIMAL_FLOPS, - expr.span, - "conversion to radians can be done more accurately", - "consider using", - proposal, - Applicability::MachineApplicable, - ); - } - } -} - -impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - // All of these operations are currently not const and are in std. - if is_in_const_context(cx) { - return; - } - - if let ExprKind::MethodCall(path, receiver, args, _) = &expr.kind { - let recv_ty = cx.typeck_results().expr_ty(receiver); - - if recv_ty.is_floating_point() && !is_no_std_crate(cx) && cx.ty_based_def(expr).opt_parent(cx).is_impl(cx) { - match path.ident.name { - sym::ln => check_ln1p(cx, expr, receiver), - sym::log => check_log_base(cx, expr, receiver, args), - sym::powf => check_powf(cx, expr, receiver, args), - sym::powi => check_powi(cx, expr, receiver, args), - sym::sqrt => check_hypot(cx, expr, receiver), - _ => {}, - } - } - } else { - if !is_no_std_crate(cx) { - check_expm1(cx, expr); - check_mul_add(cx, expr); - check_custom_abs(cx, expr); - check_log_division(cx, expr); - } - check_radians(cx, expr); - } - } -} diff --git a/clippy_lints/src/floating_point_arithmetic/custom_abs.rs b/clippy_lints/src/floating_point_arithmetic/custom_abs.rs new file mode 100644 index 000000000000..d12a32e15881 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/custom_abs.rs @@ -0,0 +1,100 @@ +use clippy_utils::consts::ConstEvalCtxt; +use clippy_utils::consts::Constant::{F32, F64, Int}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use clippy_utils::{eq_expr_value, higher, peel_blocks}; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; +use rustc_lint::LateContext; +use rustc_span::SyntaxContext; +use rustc_span::source_map::Spanned; + +use super::SUBOPTIMAL_FLOPS; + +/// Returns true iff expr is an expression which tests whether or not +/// test is positive or an expression which tests whether or not test +/// is nonnegative. +/// Used for check-custom-abs function below +fn is_testing_positive(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { + if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { + match op { + BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, right, expr.span.ctxt()) && eq_expr_value(cx, left, test), + BinOpKind::Lt | BinOpKind::Le => is_zero(cx, left, expr.span.ctxt()) && eq_expr_value(cx, right, test), + _ => false, + } + } else { + false + } +} + +/// See [`is_testing_positive`] +fn is_testing_negative(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool { + if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind { + match op { + BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, left, expr.span.ctxt()) && eq_expr_value(cx, right, test), + BinOpKind::Lt | BinOpKind::Le => is_zero(cx, right, expr.span.ctxt()) && eq_expr_value(cx, left, test), + _ => false, + } + } else { + false + } +} + +/// Returns true iff expr is some zero literal +fn is_zero(cx: &LateContext<'_>, expr: &Expr<'_>, ctxt: SyntaxContext) -> bool { + match ConstEvalCtxt::new(cx).eval_local(expr, ctxt) { + Some(Int(i)) => i == 0, + Some(F32(f)) => f == 0.0, + Some(F64(f)) => f == 0.0, + _ => false, + } +} + +/// If the two expressions are negations of each other, then it returns +/// a tuple, in which the first element is true iff expr1 is the +/// positive expressions, and the second element is the positive +/// one of the two expressions +/// If the two expressions are not negations of each other, then it +/// returns None. +fn are_negated<'a>(cx: &LateContext<'_>, expr1: &'a Expr<'a>, expr2: &'a Expr<'a>) -> Option<(bool, &'a Expr<'a>)> { + if let ExprKind::Unary(UnOp::Neg, expr1_negated) = expr1.kind + && eq_expr_value(cx, expr1_negated, expr2) + { + return Some((false, expr2)); + } + if let ExprKind::Unary(UnOp::Neg, expr2_negated) = expr2.kind + && eq_expr_value(cx, expr1, expr2_negated) + { + return Some((true, expr1)); + } + None +} + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { + if let Some(higher::If { + cond, + then, + r#else: Some(r#else), + }) = higher::If::hir(expr) + && let if_body_expr = peel_blocks(then) + && let else_body_expr = peel_blocks(r#else) + && let Some((if_expr_positive, body)) = are_negated(cx, if_body_expr, else_body_expr) + { + let sugg_positive_abs = if is_testing_positive(cx, cond, body) { + if_expr_positive + } else if is_testing_negative(cx, cond, body) { + !if_expr_positive + } else { + return; + }; + let mut app = Applicability::MachineApplicable; + let body = Sugg::hir_with_applicability(cx, body, "_", &mut app).maybe_paren(); + let sugg = if sugg_positive_abs { + ("manual implementation of `abs` method", format!("{body}.abs()")) + } else { + #[rustfmt::skip] + ("manual implementation of negation of `abs` method", format!("-{body}.abs()")) + }; + span_lint_and_sugg(cx, SUBOPTIMAL_FLOPS, expr.span, sugg.0, "try", sugg.1, app); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/expm1.rs b/clippy_lints/src/floating_point_arithmetic/expm1.rs new file mode 100644 index 000000000000..9a4c97569308 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/expm1.rs @@ -0,0 +1,42 @@ +use clippy_utils::consts::ConstEvalCtxt; +use clippy_utils::consts::Constant::{F32, F64}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg::Sugg; +use clippy_utils::sym; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; + +use super::IMPRECISE_FLOPS; + +// TODO: Lint expressions of the form `x.exp() - y` where y > 1 +// and suggest usage of `x.exp_m1() - (y - 1)` instead +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Sub, .. + }, + lhs, + rhs, + ) = expr.kind + && let ExprKind::MethodCall(path, self_arg, [], _) = lhs.kind + && path.ident.name == sym::exp + && cx.typeck_results().expr_ty(lhs).is_floating_point() + && let Some(value) = ConstEvalCtxt::new(cx).eval(rhs) + && (F32(1.0) == value || F64(1.0) == value) + && cx.typeck_results().expr_ty(self_arg).is_floating_point() + { + span_lint_and_then( + cx, + IMPRECISE_FLOPS, + expr.span, + "(e.pow(x) - 1) can be computed more accurately", + |diag| { + let mut app = Applicability::MachineApplicable; + let recv = Sugg::hir_with_applicability(cx, self_arg, "_", &mut app).maybe_paren(); + diag.span_suggestion(expr.span, "consider using", format!("{recv}.exp_m1()"), app); + }, + ); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/hypot.rs b/clippy_lints/src/floating_point_arithmetic/hypot.rs new file mode 100644 index 000000000000..49f8ba4bf825 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/hypot.rs @@ -0,0 +1,82 @@ +use clippy_utils::consts::ConstEvalCtxt; +use clippy_utils::consts::Constant::Int; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use clippy_utils::{eq_expr_value, sym}; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; + +use super::IMPRECISE_FLOPS; + +pub(super) fn detect(cx: &LateContext<'_>, receiver: &Expr<'_>, app: &mut Applicability) -> Option { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Add, .. + }, + add_lhs, + add_rhs, + ) = receiver.kind + { + // check if expression of the form x * x + y * y + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Mul, .. + }, + lmul_lhs, + lmul_rhs, + ) = add_lhs.kind + && let ExprKind::Binary( + Spanned { + node: BinOpKind::Mul, .. + }, + rmul_lhs, + rmul_rhs, + ) = add_rhs.kind + && eq_expr_value(cx, lmul_lhs, lmul_rhs) + && eq_expr_value(cx, rmul_lhs, rmul_rhs) + { + return Some(format!( + "{}.hypot({})", + Sugg::hir_with_applicability(cx, lmul_lhs, "_", app).maybe_paren(), + Sugg::hir_with_applicability(cx, rmul_lhs, "_", app) + )); + } + + // check if expression of the form x.powi(2) + y.powi(2) + if let ExprKind::MethodCall(PathSegment { ident: lmethod, .. }, largs_0, [largs_1, ..], _) = add_lhs.kind + && let ExprKind::MethodCall(PathSegment { ident: rmethod, .. }, rargs_0, [rargs_1, ..], _) = add_rhs.kind + && lmethod.name == sym::powi + && rmethod.name == sym::powi + && let ecx = ConstEvalCtxt::new(cx) + && let Some(lvalue) = ecx.eval(largs_1) + && let Some(rvalue) = ecx.eval(rargs_1) + && Int(2) == lvalue + && Int(2) == rvalue + { + return Some(format!( + "{}.hypot({})", + Sugg::hir_with_applicability(cx, largs_0, "_", app).maybe_paren(), + Sugg::hir_with_applicability(cx, rargs_0, "_", app) + )); + } + } + + None +} + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) { + let mut app = Applicability::MachineApplicable; + if let Some(message) = detect(cx, receiver, &mut app) { + span_lint_and_sugg( + cx, + IMPRECISE_FLOPS, + expr.span, + "hypotenuse can be computed more accurately", + "consider using", + message, + app, + ); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/lib.rs b/clippy_lints/src/floating_point_arithmetic/lib.rs new file mode 100644 index 000000000000..3fa041f97802 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/lib.rs @@ -0,0 +1,42 @@ +use clippy_utils::sugg::Sugg; +use rustc_ast::ast; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, UnOp}; +use rustc_lint::LateContext; +use rustc_middle::ty; + +// Adds type suffixes and parenthesis to method receivers if necessary +pub(super) fn prepare_receiver_sugg<'a>( + cx: &LateContext<'_>, + mut expr: &'a Expr<'a>, + app: &mut Applicability, +) -> Sugg<'a> { + let mut suggestion = Sugg::hir_with_applicability(cx, expr, "_", app); + + if let ExprKind::Unary(UnOp::Neg, inner_expr) = expr.kind { + expr = inner_expr; + } + + if let ty::Float(float_ty) = cx.typeck_results().expr_ty(expr).kind() + // if the expression is a float literal and it is unsuffixed then + // add a suffix so the suggestion is valid and unambiguous + && let ExprKind::Lit(lit) = expr.kind + && let ast::LitKind::Float(sym, ast::LitFloatType::Unsuffixed) = lit.node + { + let op = format!( + "{suggestion}{}{}", + // Check for float literals without numbers following the decimal + // separator such as `2.` and adds a trailing zero + if sym.as_str().ends_with('.') { "0" } else { "" }, + float_ty.name_str() + ) + .into(); + + suggestion = match suggestion { + Sugg::MaybeParen(_) | Sugg::UnOp(UnOp::Neg, _) => Sugg::MaybeParen(op), + _ => Sugg::NonParen(op), + }; + } + + suggestion.maybe_paren() +} diff --git a/clippy_lints/src/floating_point_arithmetic/ln1p.rs b/clippy_lints/src/floating_point_arithmetic/ln1p.rs new file mode 100644 index 000000000000..4c9aa96b5042 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/ln1p.rs @@ -0,0 +1,41 @@ +use clippy_utils::consts::ConstEvalCtxt; +use clippy_utils::consts::Constant::{F32, F64}; +use clippy_utils::diagnostics::span_lint_and_then; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; + +use super::IMPRECISE_FLOPS; + +// TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and +// suggest usage of `(x + (y - 1)).ln_1p()` instead +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Add, .. + }, + lhs, + rhs, + ) = receiver.kind + { + let ecx = ConstEvalCtxt::new(cx); + let recv = match (ecx.eval(lhs), ecx.eval(rhs)) { + (Some(value), _) if F32(1.0) == value || F64(1.0) == value => rhs, + (_, Some(value)) if F32(1.0) == value || F64(1.0) == value => lhs, + _ => return, + }; + + span_lint_and_then( + cx, + IMPRECISE_FLOPS, + expr.span, + "ln(1 + x) can be computed more accurately", + |diag| { + let mut app = Applicability::MachineApplicable; + let recv = super::lib::prepare_receiver_sugg(cx, recv, &mut app); + diag.span_suggestion(expr.span, "consider using", format!("{recv}.ln_1p()"), app); + }, + ); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/log_base.rs b/clippy_lints/src/floating_point_arithmetic/log_base.rs new file mode 100644 index 000000000000..4ccc784655ed --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/log_base.rs @@ -0,0 +1,44 @@ +use clippy_utils::consts::ConstEvalCtxt; +use clippy_utils::consts::Constant::{F32, F64}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg::Sugg; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_span::SyntaxContext; +use std::f32::consts as f32_consts; +use std::f64::consts as f64_consts; + +use super::SUBOPTIMAL_FLOPS; + +// Returns the specialized log method for a given base if base is constant +// and is one of 2, 10 and e +fn get_specialized_log_method(cx: &LateContext<'_>, base: &Expr<'_>, ctxt: SyntaxContext) -> Option<&'static str> { + if let Some(value) = ConstEvalCtxt::new(cx).eval_local(base, ctxt) { + if F32(2.0) == value || F64(2.0) == value { + return Some("log2"); + } else if F32(10.0) == value || F64(10.0) == value { + return Some("log10"); + } else if F32(f32_consts::E) == value || F64(f64_consts::E) == value { + return Some("ln"); + } + } + + None +} + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { + if let Some(method) = get_specialized_log_method(cx, &args[0], expr.span.ctxt()) { + span_lint_and_then( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "logarithm for bases 2, 10 and e can be computed more accurately", + |diag| { + let mut app = Applicability::MachineApplicable; + let recv = Sugg::hir_with_applicability(cx, receiver, "_", &mut app).maybe_paren(); + diag.span_suggestion(expr.span, "consider using", format!("{recv}.{method}()"), app); + }, + ); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/log_division.rs b/clippy_lints/src/floating_point_arithmetic/log_division.rs new file mode 100644 index 000000000000..e3419ffad72a --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/log_division.rs @@ -0,0 +1,52 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use clippy_utils::{eq_expr_value, sym}; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; + +use super::SUBOPTIMAL_FLOPS; + +fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool { + if let ExprKind::MethodCall(PathSegment { ident: method_a, .. }, _, args_a, _) = expr_a.kind + && let ExprKind::MethodCall(PathSegment { ident: method_b, .. }, _, args_b, _) = expr_b.kind + { + return method_a.name == method_b.name + && args_a.len() == args_b.len() + && (matches!(method_a.name, sym::ln | sym::log2 | sym::log10) + || method_a.name == sym::log && args_a.len() == 1 && eq_expr_value(cx, &args_a[0], &args_b[0])); + } + + false +} + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { + // check if expression of the form x.logN() / y.logN() + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Div, .. + }, + lhs, + rhs, + ) = expr.kind + && are_same_base_logs(cx, lhs, rhs) + && let ExprKind::MethodCall(_, largs_self, ..) = lhs.kind + && let ExprKind::MethodCall(_, rargs_self, ..) = rhs.kind + { + let mut app = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "log base can be expressed more clearly", + "consider using", + format!( + "{}.log({})", + Sugg::hir_with_applicability(cx, largs_self, "_", &mut app).maybe_paren(), + Sugg::hir_with_applicability(cx, rargs_self, "_", &mut app), + ), + app, + ); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/mod.rs b/clippy_lints/src/floating_point_arithmetic/mod.rs new file mode 100644 index 000000000000..edc638c96bbf --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/mod.rs @@ -0,0 +1,141 @@ +use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; +use clippy_utils::{is_in_const_context, is_no_std_crate, sym}; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::declare_lint_pass; + +mod custom_abs; +mod expm1; +mod hypot; +mod lib; +mod ln1p; +mod log_base; +mod log_division; +mod mul_add; +mod powf; +mod powi; +mod radians; + +declare_clippy_lint! { + /// ### What it does + /// Looks for floating-point expressions that + /// can be expressed using built-in methods to improve accuracy + /// at the cost of performance. + /// + /// ### Why is this bad? + /// Negatively impacts accuracy. + /// + /// ### Example + /// ```no_run + /// let a = 3f32; + /// let _ = a.powf(1.0 / 3.0); + /// let _ = (1.0 + a).ln(); + /// let _ = a.exp() - 1.0; + /// ``` + /// + /// Use instead: + /// ```no_run + /// let a = 3f32; + /// let _ = a.cbrt(); + /// let _ = a.ln_1p(); + /// let _ = a.exp_m1(); + /// ``` + #[clippy::version = "1.43.0"] + pub IMPRECISE_FLOPS, + nursery, + "usage of imprecise floating point operations" +} + +declare_clippy_lint! { + /// ### What it does + /// Looks for floating-point expressions that + /// can be expressed using built-in methods to improve both + /// accuracy and performance. + /// + /// ### Why is this bad? + /// Negatively impacts accuracy and performance. + /// + /// ### Example + /// ```no_run + /// use std::f32::consts::E; + /// + /// let a = 3f32; + /// let _ = (2f32).powf(a); + /// let _ = E.powf(a); + /// let _ = a.powf(1.0 / 2.0); + /// let _ = a.log(2.0); + /// let _ = a.log(10.0); + /// let _ = a.log(E); + /// let _ = a.powf(2.0); + /// let _ = a * 2.0 + 4.0; + /// let _ = if a < 0.0 { + /// -a + /// } else { + /// a + /// }; + /// let _ = if a < 0.0 { + /// a + /// } else { + /// -a + /// }; + /// ``` + /// + /// is better expressed as + /// + /// ```no_run + /// use std::f32::consts::E; + /// + /// let a = 3f32; + /// let _ = a.exp2(); + /// let _ = a.exp(); + /// let _ = a.sqrt(); + /// let _ = a.log2(); + /// let _ = a.log10(); + /// let _ = a.ln(); + /// let _ = a.powi(2); + /// let _ = a.mul_add(2.0, 4.0); + /// let _ = a.abs(); + /// let _ = -a.abs(); + /// ``` + #[clippy::version = "1.43.0"] + pub SUBOPTIMAL_FLOPS, + nursery, + "usage of sub-optimal floating point operations" +} + +declare_lint_pass!(FloatingPointArithmetic => [ + IMPRECISE_FLOPS, + SUBOPTIMAL_FLOPS +]); + +impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + // All of these operations are currently not const and are in std. + if is_in_const_context(cx) { + return; + } + + if let ExprKind::MethodCall(path, receiver, args, _) = expr.kind { + let recv_ty = cx.typeck_results().expr_ty(receiver); + + if recv_ty.is_floating_point() && !is_no_std_crate(cx) && cx.ty_based_def(expr).opt_parent(cx).is_impl(cx) { + match path.ident.name { + sym::ln => ln1p::check(cx, expr, receiver), + sym::log => log_base::check(cx, expr, receiver, args), + sym::powf => powf::check(cx, expr, receiver, args), + sym::powi => powi::check(cx, expr, receiver, args), + sym::sqrt => hypot::check(cx, expr, receiver), + _ => {}, + } + } + } else { + if !is_no_std_crate(cx) { + expm1::check(cx, expr); + mul_add::check(cx, expr); + custom_abs::check(cx, expr); + log_division::check(cx, expr); + } + radians::check(cx, expr); + } + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/mul_add.rs b/clippy_lints/src/floating_point_arithmetic/mul_add.rs new file mode 100644 index 000000000000..03a9d3b05f88 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/mul_add.rs @@ -0,0 +1,94 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sugg::Sugg; +use clippy_utils::{get_parent_expr, has_ambiguous_literal_in_expr, sym}; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; + +use super::SUBOPTIMAL_FLOPS; + +fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Mul, .. + }, + lhs, + rhs, + ) = expr.kind + && cx.typeck_results().expr_ty(lhs).is_floating_point() + && cx.typeck_results().expr_ty(rhs).is_floating_point() + { + return Some((lhs, rhs)); + } + + None +} + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { + if let ExprKind::Binary( + Spanned { + node: op @ (BinOpKind::Add | BinOpKind::Sub), + .. + }, + lhs, + rhs, + ) = &expr.kind + { + if let Some(parent) = get_parent_expr(cx, expr) + && let ExprKind::MethodCall(PathSegment { ident: method, .. }, receiver, ..) = parent.kind + && method.name == sym::sqrt + // we don't care about the applicability as this is an early-return condition + && super::hypot::detect(cx, receiver, &mut Applicability::Unspecified).is_some() + { + return; + } + + let maybe_neg_sugg = |expr, app: &mut _| { + let sugg = Sugg::hir_with_applicability(cx, expr, "_", app); + if let BinOpKind::Sub = op { -sugg } else { sugg } + }; + + let mut app = Applicability::MachineApplicable; + let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) + && cx.typeck_results().expr_ty(rhs).is_floating_point() + { + ( + inner_lhs, + Sugg::hir_with_applicability(cx, inner_rhs, "_", &mut app), + maybe_neg_sugg(rhs, &mut app), + ) + } else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) + && cx.typeck_results().expr_ty(lhs).is_floating_point() + { + ( + inner_lhs, + maybe_neg_sugg(inner_rhs, &mut app), + Sugg::hir_with_applicability(cx, lhs, "_", &mut app), + ) + } else { + return; + }; + + // Check if any variable in the expression has an ambiguous type (could be f32 or f64) + // see: https://github.com/rust-lang/rust-clippy/issues/14897 + if (matches!(recv.kind, ExprKind::Path(_)) || matches!(recv.kind, ExprKind::Call(_, _))) + && has_ambiguous_literal_in_expr(cx, recv) + { + return; + } + + span_lint_and_sugg( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "multiply and add expressions can be calculated more efficiently and accurately", + "consider using", + format!( + "{}.mul_add({arg1}, {arg2})", + super::lib::prepare_receiver_sugg(cx, recv, &mut app) + ), + app, + ); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/powf.rs b/clippy_lints/src/floating_point_arithmetic/powf.rs new file mode 100644 index 000000000000..8e4a7388e784 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/powf.rs @@ -0,0 +1,94 @@ +use clippy_utils::consts::Constant::{F32, F64}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::numeric_literal; +use clippy_utils::sugg::Sugg; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use std::f32::consts as f32_consts; +use std::f64::consts as f64_consts; + +use super::{IMPRECISE_FLOPS, SUBOPTIMAL_FLOPS}; + +// Returns an integer if the float constant is a whole number and it can be +// converted to an integer without loss of precision. For now we only check +// ranges [-16777215, 16777216) for type f32 as whole number floats outside +// this range are lossy and ambiguous. +#[expect(clippy::cast_possible_truncation)] +fn get_integer_from_float_constant(value: &Constant) -> Option { + match value { + F32(num) if num.fract() == 0.0 => { + if (-16_777_215.0..16_777_216.0).contains(num) { + Some(num.round() as i32) + } else { + None + } + }, + F64(num) if num.fract() == 0.0 => { + if (-2_147_483_648.0..2_147_483_648.0).contains(num) { + Some(num.round() as i32) + } else { + None + } + }, + _ => None, + } +} + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { + // Check receiver + if let Some(value) = ConstEvalCtxt::new(cx).eval(receiver) + && let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value { + Some("exp") + } else if F32(2.0) == value || F64(2.0) == value { + Some("exp2") + } else { + None + } + { + span_lint_and_then( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "exponent for bases 2 and e can be computed more accurately", + |diag| { + let mut app = Applicability::MachineApplicable; + let recv = super::lib::prepare_receiver_sugg(cx, &args[0], &mut app); + diag.span_suggestion(expr.span, "consider using", format!("{recv}.{method}()"), app); + }, + ); + } + + // Check argument + if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) { + let mut app = Applicability::MachineApplicable; + let recv = Sugg::hir_with_applicability(cx, receiver, "_", &mut app).maybe_paren(); + let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value { + ( + SUBOPTIMAL_FLOPS, + "square-root of a number can be computed more efficiently and accurately", + format!("{recv}.sqrt()"), + ) + } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value { + ( + IMPRECISE_FLOPS, + "cube-root of a number can be computed more accurately", + format!("{recv}.cbrt()"), + ) + } else if let Some(exponent) = get_integer_from_float_constant(&value) { + ( + SUBOPTIMAL_FLOPS, + "exponentiation with integer powers can be computed more efficiently", + format!( + "{recv}.powi({})", + numeric_literal::format(&exponent.to_string(), None, false) + ), + ) + } else { + return; + }; + + span_lint_and_sugg(cx, lint, expr.span, help, "consider using", suggestion, app); + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/powi.rs b/clippy_lints/src/floating_point_arithmetic/powi.rs new file mode 100644 index 000000000000..a61a2a82c023 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/powi.rs @@ -0,0 +1,70 @@ +use clippy_utils::consts::ConstEvalCtxt; +use clippy_utils::consts::Constant::Int; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg::Sugg; +use clippy_utils::{get_parent_expr, sym}; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; + +use super::SUBOPTIMAL_FLOPS; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { + if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) + && value == Int(2) + && let Some(parent) = get_parent_expr(cx, expr) + { + if let Some(grandparent) = get_parent_expr(cx, parent) + && let ExprKind::MethodCall(PathSegment { ident: method, .. }, receiver, ..) = grandparent.kind + && method.name == sym::sqrt + // we don't care about the applicability as this is an early-return condition + && super::hypot::detect(cx, receiver, &mut Applicability::Unspecified).is_some() + { + return; + } + + if let ExprKind::Binary( + Spanned { + node: op @ (BinOpKind::Add | BinOpKind::Sub), + .. + }, + lhs, + rhs, + ) = parent.kind + { + span_lint_and_then( + cx, + SUBOPTIMAL_FLOPS, + parent.span, + "multiply and add expressions can be calculated more efficiently and accurately", + |diag| { + let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs }; + + // Negate expr if original code has subtraction and expr is on the right side + let maybe_neg_sugg = |expr, hir_id, app: &mut _| { + let sugg = Sugg::hir_with_applicability(cx, expr, "_", app); + if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id { + -sugg + } else { + sugg + } + }; + + let mut app = Applicability::MachineApplicable; + diag.span_suggestion( + parent.span, + "consider using", + format!( + "{}.mul_add({}, {})", + Sugg::hir_with_applicability(cx, receiver, "_", &mut app).maybe_paren(), + maybe_neg_sugg(receiver, expr.hir_id, &mut app), + maybe_neg_sugg(other_addend, other_addend.hir_id, &mut app), + ), + app, + ); + }, + ); + } + } +} diff --git a/clippy_lints/src/floating_point_arithmetic/radians.rs b/clippy_lints/src/floating_point_arithmetic/radians.rs new file mode 100644 index 000000000000..2021f00a97e8 --- /dev/null +++ b/clippy_lints/src/floating_point_arithmetic/radians.rs @@ -0,0 +1,89 @@ +use clippy_utils::consts::ConstEvalCtxt; +use clippy_utils::consts::Constant::{F32, F64}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg::Sugg; +use rustc_ast::ast; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::source_map::Spanned; +use std::f32::consts as f32_consts; +use std::f64::consts as f64_consts; + +use super::SUBOPTIMAL_FLOPS; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { + if let ExprKind::Binary( + Spanned { + node: BinOpKind::Div, .. + }, + div_lhs, + div_rhs, + ) = expr.kind + && let ExprKind::Binary( + Spanned { + node: BinOpKind::Mul, .. + }, + mul_lhs, + mul_rhs, + ) = div_lhs.kind + && let ecx = ConstEvalCtxt::new(cx) + && let Some(rvalue) = ecx.eval(div_rhs) + && let Some(lvalue) = ecx.eval(mul_rhs) + { + // TODO: also check for constant values near PI/180 or 180/PI + if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) + && (F32(180_f32) == lvalue || F64(180_f64) == lvalue) + { + span_lint_and_then( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "conversion to degrees can be done more accurately", + |diag| { + let mut app = Applicability::MachineApplicable; + let recv = Sugg::hir_with_applicability(cx, mul_lhs, "num", &mut app); + let proposal = if let ExprKind::Lit(literal) = mul_lhs.kind + && let ast::LitKind::Float(ref value, float_type) = literal.node + && float_type == ast::LitFloatType::Unsuffixed + { + if value.as_str().ends_with('.') { + format!("{recv}0_f64.to_degrees()") + } else { + format!("{recv}_f64.to_degrees()") + } + } else { + format!("{}.to_degrees()", recv.maybe_paren()) + }; + diag.span_suggestion(expr.span, "consider using", proposal, app); + }, + ); + } else if (F32(180_f32) == rvalue || F64(180_f64) == rvalue) + && (F32(f32_consts::PI) == lvalue || F64(f64_consts::PI) == lvalue) + { + span_lint_and_then( + cx, + SUBOPTIMAL_FLOPS, + expr.span, + "conversion to radians can be done more accurately", + |diag| { + let mut app = Applicability::MachineApplicable; + let recv = Sugg::hir_with_applicability(cx, mul_lhs, "num", &mut app); + let proposal = if let ExprKind::Lit(literal) = mul_lhs.kind + && let ast::LitKind::Float(ref value, float_type) = literal.node + && float_type == ast::LitFloatType::Unsuffixed + { + if value.as_str().ends_with('.') { + format!("{recv}0_f64.to_radians()") + } else { + format!("{recv}_f64.to_radians()") + } + } else { + format!("{}.to_radians()", recv.maybe_paren()) + }; + diag.span_suggestion(expr.span, "consider using", proposal, app); + }, + ); + } + } +} diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index 67ce57de254d..f8184b30f400 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -1,7 +1,7 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::SpanRangeExt; -use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind}; -use rustc_ast::token; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::sugg; +use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind, UnOp}; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::declare_lint_pass; @@ -35,132 +35,125 @@ declare_clippy_lint! { declare_lint_pass!(IntPlusOne => [INT_PLUS_ONE]); // cases: -// BinOpKind::Ge +// LeOrGe::Ge // x >= y + 1 // x - 1 >= y // -// BinOpKind::Le +// LeOrGe::Le // x + 1 <= y // x <= y - 1 #[derive(Copy, Clone)] -enum Side { - Lhs, - Rhs, +enum LeOrGe { + Le, + Ge, +} + +impl TryFrom for LeOrGe { + type Error = (); + fn try_from(value: BinOpKind) -> Result { + match value { + BinOpKind::Le => Ok(Self::Le), + BinOpKind::Ge => Ok(Self::Ge), + _ => Err(()), + } + } } impl IntPlusOne { - #[expect(clippy::cast_sign_loss)] - fn check_lit(token_lit: token::Lit, target_value: i128) -> bool { - if let Ok(LitKind::Int(value, ..)) = LitKind::from_token_lit(token_lit) { - return value == (target_value as u128); + fn is_one(expr: &Expr) -> bool { + if let ExprKind::Lit(token_lit) = expr.kind + && matches!(LitKind::from_token_lit(token_lit), Ok(LitKind::Int(Pu128(1), ..))) + { + return true; } false } - fn check_binop(cx: &EarlyContext<'_>, binop: BinOpKind, lhs: &Expr, rhs: &Expr) -> Option { - match (binop, &lhs.kind, &rhs.kind) { - // case where `x - 1 >= ...` or `-1 + x >= ...` - (BinOpKind::Ge, ExprKind::Binary(lhskind, lhslhs, lhsrhs), _) => { - match (lhskind.node, &lhslhs.kind, &lhsrhs.kind) { - // `-1 + x` - (BinOpKind::Add, ExprKind::Lit(lit), _) if Self::check_lit(*lit, -1) => { - Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::Lhs) - }, - // `x - 1` - (BinOpKind::Sub, _, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => { - Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs) - }, - _ => None, - } - }, - // case where `... >= y + 1` or `... >= 1 + y` - (BinOpKind::Ge, _, ExprKind::Binary(rhskind, rhslhs, rhsrhs)) if rhskind.node == BinOpKind::Add => { - match (&rhslhs.kind, &rhsrhs.kind) { - // `y + 1` and `1 + y` - (ExprKind::Lit(lit), _) if Self::check_lit(*lit, 1) => { - Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::Rhs) - }, - (_, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => { - Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs) - }, - _ => None, - } - }, - // case where `x + 1 <= ...` or `1 + x <= ...` - (BinOpKind::Le, ExprKind::Binary(lhskind, lhslhs, lhsrhs), _) if lhskind.node == BinOpKind::Add => { - match (&lhslhs.kind, &lhsrhs.kind) { - // `1 + x` and `x + 1` - (ExprKind::Lit(lit), _) if Self::check_lit(*lit, 1) => { - Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::Lhs) - }, - (_, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => { - Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs) - }, - _ => None, - } - }, - // case where `... >= y - 1` or `... >= -1 + y` - (BinOpKind::Le, _, ExprKind::Binary(rhskind, rhslhs, rhsrhs)) => { - match (rhskind.node, &rhslhs.kind, &rhsrhs.kind) { - // `-1 + y` - (BinOpKind::Add, ExprKind::Lit(lit), _) if Self::check_lit(*lit, -1) => { - Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::Rhs) - }, - // `y - 1` - (BinOpKind::Sub, _, ExprKind::Lit(lit)) if Self::check_lit(*lit, 1) => { - Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs) - }, - _ => None, - } - }, - _ => None, + fn is_neg_one(expr: &Expr) -> bool { + if let ExprKind::Unary(UnOp::Neg, expr) = &expr.kind { + Self::is_one(expr) + } else { + false } } - fn generate_recommendation( - cx: &EarlyContext<'_>, - binop: BinOpKind, - node: &Expr, - other_side: &Expr, - side: Side, - ) -> Option { - let binop_string = match binop { - BinOpKind::Ge => ">", - BinOpKind::Le => "<", - _ => return None, - }; - if let Some(snippet) = node.span.get_source_text(cx) - && let Some(other_side_snippet) = other_side.span.get_source_text(cx) + /// Checks whether `expr` is `x + 1` or `1 + x`, and if so, returns `x` + fn as_x_plus_one(expr: &Expr) -> Option<&Expr> { + if let ExprKind::Binary(op, lhs, rhs) = &expr.kind + && op.node == BinOpKind::Add { - let rec = match side { - Side::Lhs => Some(format!("{snippet} {binop_string} {other_side_snippet}")), - Side::Rhs => Some(format!("{other_side_snippet} {binop_string} {snippet}")), - }; - return rec; + if Self::is_one(rhs) { + // x + 1 + return Some(lhs); + } else if Self::is_one(lhs) { + // 1 + x + return Some(rhs); + } } None } - fn emit_warning(cx: &EarlyContext<'_>, block: &Expr, recommendation: String) { - span_lint_and_sugg( + /// Checks whether `expr` is `x - 1` or `-1 + x`, and if so, returns `x` + fn as_x_minus_one(expr: &Expr) -> Option<&Expr> { + if let ExprKind::Binary(op, lhs, rhs) = &expr.kind { + if op.node == BinOpKind::Sub && Self::is_one(rhs) { + // x - 1 + return Some(lhs); + } else if op.node == BinOpKind::Add && Self::is_neg_one(lhs) { + // -1 + x + return Some(rhs); + } + } + None + } + + fn check_binop<'tcx>(le_or_ge: LeOrGe, lhs: &'tcx Expr, rhs: &'tcx Expr) -> Option<(&'tcx Expr, &'tcx Expr)> { + match le_or_ge { + LeOrGe::Ge => { + // case where `x - 1 >= ...` or `-1 + x >= ...` + (Self::as_x_minus_one(lhs).map(|new_lhs| (new_lhs, rhs))) + // case where `... >= y + 1` or `... >= 1 + y` + .or_else(|| Self::as_x_plus_one(rhs).map(|new_rhs| (lhs, new_rhs))) + }, + LeOrGe::Le => { + // case where `x + 1 <= ...` or `1 + x <= ...` + (Self::as_x_plus_one(lhs).map(|new_lhs| (new_lhs, rhs))) + // case where `... <= y - 1` or `... <= -1 + y` + .or_else(|| Self::as_x_minus_one(rhs).map(|new_rhs| (lhs, new_rhs))) + }, + } + } + + fn emit_warning(cx: &EarlyContext<'_>, expr: &Expr, new_lhs: &Expr, le_or_ge: LeOrGe, new_rhs: &Expr) { + span_lint_and_then( cx, INT_PLUS_ONE, - block.span, + expr.span, "unnecessary `>= y + 1` or `x - 1 >=`", - "change it to", - recommendation, - Applicability::MachineApplicable, // snippet + |diag| { + let mut app = Applicability::MachineApplicable; + let ctxt = expr.span.ctxt(); + let new_lhs = sugg::Sugg::ast(cx, new_lhs, "_", ctxt, &mut app); + let new_rhs = sugg::Sugg::ast(cx, new_rhs, "_", ctxt, &mut app); + let new_binop = match le_or_ge { + LeOrGe::Ge => BinOpKind::Gt, + LeOrGe::Le => BinOpKind::Lt, + }; + let rec = sugg::make_binop(new_binop, &new_lhs, &new_rhs); + diag.span_suggestion(expr.span, "change it to", rec, app); + }, ); } } impl EarlyLintPass for IntPlusOne { - fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) { - if let ExprKind::Binary(ref kind, ref lhs, ref rhs) = item.kind - && let Some(rec) = Self::check_binop(cx, kind.node, lhs, rhs) + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + if let ExprKind::Binary(binop, lhs, rhs) = &expr.kind + && let Ok(le_or_ge) = LeOrGe::try_from(binop.node) + && let Some((new_lhs, new_rhs)) = Self::check_binop(le_or_ge, lhs, rhs) { - Self::emit_warning(cx, item, rec); + Self::emit_warning(cx, expr, new_lhs, le_or_ge, new_rhs); } } } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a5e5ecb5fa19..40b7c3a3fc22 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,10 +1,12 @@ #![feature(box_patterns)] -#![feature(macro_metavar_expr_concat)] +#![feature(control_flow_into_value)] +#![feature(exact_div)] #![feature(f128)] #![feature(f16)] #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(iter_partition_in_place)] +#![feature(macro_metavar_expr_concat)] #![feature(never_type)] #![feature(rustc_private)] #![feature(stmt_expr_attributes)] @@ -110,6 +112,7 @@ mod doc; mod double_parens; mod drop_forget_ref; mod duplicate_mod; +mod duration_suboptimal_units; mod else_if_without_else; mod empty_drop; mod empty_enums; @@ -195,6 +198,7 @@ mod manual_abs_diff; mod manual_assert; mod manual_async_fn; mod manual_bits; +mod manual_checked_ops; mod manual_clamp; mod manual_float_methods; mod manual_hash_one; @@ -213,6 +217,7 @@ mod manual_rotate; mod manual_slice_size_calculation; mod manual_string_new; mod manual_strip; +mod manual_take; mod map_unit_fn; mod match_result_ok; mod matches; @@ -712,7 +717,7 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co Box::new(|_| Box::::default()), Box::new(move |tcx| Box::new(disallowed_types::DisallowedTypes::new(tcx, conf))), Box::new(move |tcx| Box::new(missing_enforced_import_rename::ImportRename::new(tcx, conf))), - Box::new(|_| Box::new(strlen_on_c_strings::StrlenOnCStrings)), + Box::new(move |_| Box::new(strlen_on_c_strings::StrlenOnCStrings::new(conf))), Box::new(move |_| Box::new(self_named_constructors::SelfNamedConstructors)), Box::new(move |_| Box::new(iter_not_returning_iterator::IterNotReturningIterator)), Box::new(move |_| Box::new(manual_assert::ManualAssert)), @@ -854,6 +859,9 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co Box::new(|_| Box::::default()), Box::new(move |_| Box::new(manual_ilog2::ManualIlog2::new(conf))), Box::new(|_| Box::new(same_length_and_capacity::SameLengthAndCapacity)), + Box::new(move |tcx| Box::new(duration_suboptimal_units::DurationSuboptimalUnits::new(tcx, conf))), + Box::new(move |_| Box::new(manual_take::ManualTake::new(conf))), + Box::new(|_| Box::new(manual_checked_ops::ManualCheckedOps)), // add late passes here, used by `cargo dev new_lint` ]; store.late_passes.extend(late_lints); diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 727e9b172a87..679fb983d532 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::trait_ref_of_method; +use clippy_utils::{is_from_proc_macro, trait_ref_of_method}; use itertools::Itertools; use rustc_ast::visit::{try_visit, walk_list}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; @@ -149,9 +149,12 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { .. } = item.kind { - check_fn_inner(cx, sig, Some(id), None, generics, item.span, true, self.msrv); + check_fn_inner(cx, sig, Some(id), None, generics, item.span, true, self.msrv, || { + is_from_proc_macro(cx, item) + }); } else if let ItemKind::Impl(impl_) = &item.kind && !item.span.from_expansion() + && !is_from_proc_macro(cx, item) { report_extra_impl_lifetimes(cx, impl_); } @@ -169,6 +172,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { item.span, report_extra_lifetimes, self.msrv, + || is_from_proc_macro(cx, item), ); } } @@ -179,7 +183,17 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { TraitFn::Required(sig) => (None, Some(sig)), TraitFn::Provided(id) => (Some(id), None), }; - check_fn_inner(cx, sig, body, trait_sig, item.generics, item.span, true, self.msrv); + check_fn_inner( + cx, + sig, + body, + trait_sig, + item.generics, + item.span, + true, + self.msrv, + || is_from_proc_macro(cx, item), + ); } } } @@ -194,6 +208,7 @@ fn check_fn_inner<'tcx>( span: Span, report_extra_lifetimes: bool, msrv: Msrv, + is_from_proc_macro: impl FnOnce() -> bool, ) { if span.in_external_macro(cx.sess().source_map()) || has_where_lifetimes(cx, generics) { return; @@ -245,10 +260,19 @@ fn check_fn_inner<'tcx>( } } - if let Some((elidable_lts, usages)) = could_use_elision(cx, sig.decl, body, trait_sig, generics.params, msrv) { - if usages.iter().any(|usage| !usage.ident.span.eq_ctxt(span)) { - return; - } + let elidable = could_use_elision(cx, sig.decl, body, trait_sig, generics.params, msrv); + let has_elidable_lts = elidable + .as_ref() + .is_some_and(|(_, usages)| !usages.iter().any(|usage| !usage.ident.span.eq_ctxt(span))); + + // Only check is_from_proc_macro if we're about to emit a lint (it's an expensive check) + if (has_elidable_lts || report_extra_lifetimes) && is_from_proc_macro() { + return; + } + + if let Some((elidable_lts, usages)) = elidable + && has_elidable_lts + { // async functions have usages whose spans point at the lifetime declaration which messes up // suggestions let include_suggestions = !sig.header.is_async(); diff --git a/clippy_lints/src/loops/while_let_loop.rs b/clippy_lints/src/loops/while_let_loop.rs index d4285db0abfc..e2ea24c39980 100644 --- a/clippy_lints/src/loops/while_let_loop.rs +++ b/clippy_lints/src/loops/while_let_loop.rs @@ -40,7 +40,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_blo let_info, Some(if_let.if_then), ); - } else if els.and_then(|x| x.expr).is_some_and(is_simple_break_expr) + } else if els.is_some_and(is_simple_break_block) && let Some((pat, _)) = let_info { could_be_while_let(cx, expr, pat, init, has_trailing_exprs, let_info, None); @@ -61,17 +61,23 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_blo } } -/// Returns `true` if expr contains a single break expression without a label or sub-expression, -/// possibly embedded in blocks. -fn is_simple_break_expr(e: &Expr<'_>) -> bool { - if let ExprKind::Block(b, _) = e.kind { - match (b.stmts, b.expr) { - ([s], None) => matches!(s.kind, StmtKind::Expr(e) | StmtKind::Semi(e) if is_simple_break_expr(e)), - ([], Some(e)) => is_simple_break_expr(e), - _ => false, - } - } else { - matches!(e.kind, ExprKind::Break(dest, None) if dest.label.is_none()) +/// Checks if `block` contains a single unlabeled `break` expression or statement, possibly embedded +/// inside other blocks. +fn is_simple_break_block(block: &Block<'_>) -> bool { + match (block.stmts, block.expr) { + ([s], None) => matches!(s.kind, StmtKind::Expr(e) | StmtKind::Semi(e) if is_simple_break_expr(e)), + ([], Some(e)) => is_simple_break_expr(e), + _ => false, + } +} + +/// Checks if `expr` contains a single unlabeled `break` expression or statement, possibly embedded +/// inside other blocks. +fn is_simple_break_expr(expr: &Expr<'_>) -> bool { + match expr.kind { + ExprKind::Block(b, _) => is_simple_break_block(b), + ExprKind::Break(dest, None) => dest.label.is_none(), + _ => false, } } diff --git a/clippy_lints/src/manual_checked_ops.rs b/clippy_lints/src/manual_checked_ops.rs new file mode 100644 index 000000000000..6327567df336 --- /dev/null +++ b/clippy_lints/src/manual_checked_ops.rs @@ -0,0 +1,170 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::visitors::{Descend, for_each_expr_without_closures}; +use clippy_utils::{SpanlessEq, is_integer_literal}; +use rustc_hir::{AssignOpKind, BinOpKind, Block, Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; +use rustc_session::declare_lint_pass; +use std::ops::ControlFlow; + +declare_clippy_lint! { + /// ### What it does + /// Detects manual zero checks before dividing integers, such as `if x != 0 { y / x }`. + /// + /// ### Why is this bad? + /// `checked_div` already handles the zero case and makes the intent clearer while avoiding a + /// panic from a manual division. + /// + /// ### Example + /// ```no_run + /// # let (a, b) = (10u32, 5u32); + /// if b != 0 { + /// let result = a / b; + /// println!("{result}"); + /// } + /// ``` + /// Use instead: + /// ```no_run + /// # let (a, b) = (10u32, 5u32); + /// if let Some(result) = a.checked_div(b) { + /// println!("{result}"); + /// } + /// ``` + #[clippy::version = "1.95.0"] + pub MANUAL_CHECKED_OPS, + complexity, + "manual zero checks before dividing integers" +} +declare_lint_pass!(ManualCheckedOps => [MANUAL_CHECKED_OPS]); + +#[derive(Copy, Clone)] +enum NonZeroBranch { + Then, + Else, +} + +impl LateLintPass<'_> for ManualCheckedOps { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + if let ExprKind::If(cond, then, r#else) = expr.kind + && !expr.span.from_expansion() + && let Some((divisor, branch)) = divisor_from_condition(cond) + // This lint is intended for unsigned integers only. + // + // For signed integers, the most direct refactor to `checked_div` is often not + // semantically equivalent to the original guard. For example, `rhs > 0` deliberately + // excludes negative divisors, while `checked_div` would return `Some` for `rhs = -2`. + // Also, `checked_div` can return `None` for `MIN / -1`, which requires additional + // handling beyond the zero check. + && is_unsigned_integer(cx, divisor) + && let Some(block) = branch_block(then, r#else, branch) + { + let mut eq = SpanlessEq::new(cx).deny_side_effects().paths_by_resolution(); + if !eq.eq_expr(divisor, divisor) { + return; + } + + let mut division_spans = Vec::new(); + let mut first_use = None; + + let found_early_use = for_each_expr_without_closures(block, |e| { + if let ExprKind::Binary(binop, lhs, rhs) = e.kind + && binop.node == BinOpKind::Div + && eq.eq_expr(rhs, divisor) + && is_unsigned_integer(cx, lhs) + { + match first_use { + None => first_use = Some(UseKind::Division), + Some(UseKind::Other) => return ControlFlow::Break(()), + Some(UseKind::Division) => {}, + } + + division_spans.push(e.span); + + ControlFlow::<(), _>::Continue(Descend::No) + } else if let ExprKind::AssignOp(op, lhs, rhs) = e.kind + && op.node == AssignOpKind::DivAssign + && eq.eq_expr(rhs, divisor) + && is_unsigned_integer(cx, lhs) + { + match first_use { + None => first_use = Some(UseKind::Division), + Some(UseKind::Other) => return ControlFlow::Break(()), + Some(UseKind::Division) => {}, + } + + division_spans.push(e.span); + + ControlFlow::<(), _>::Continue(Descend::No) + } else if eq.eq_expr(e, divisor) { + if first_use.is_none() { + first_use = Some(UseKind::Other); + return ControlFlow::Break(()); + } + ControlFlow::<(), _>::Continue(Descend::Yes) + } else { + ControlFlow::<(), _>::Continue(Descend::Yes) + } + }); + + if found_early_use.is_some() || first_use != Some(UseKind::Division) || division_spans.is_empty() { + return; + } + + span_lint_and_then(cx, MANUAL_CHECKED_OPS, cond.span, "manual checked division", |diag| { + diag.span_label(cond.span, "check performed here"); + if let Some((first, rest)) = division_spans.split_first() { + diag.span_label(*first, "division performed here"); + if !rest.is_empty() { + diag.span_labels(rest.to_vec(), "... and here"); + } + } + diag.help("consider using `checked_div`"); + }); + } + } +} + +#[derive(Copy, Clone, Eq, PartialEq)] +enum UseKind { + Division, + Other, +} + +fn divisor_from_condition<'tcx>(cond: &'tcx Expr<'tcx>) -> Option<(&'tcx Expr<'tcx>, NonZeroBranch)> { + let ExprKind::Binary(binop, lhs, rhs) = cond.kind else { + return None; + }; + + match binop.node { + BinOpKind::Ne | BinOpKind::Lt if is_zero(lhs) => Some((rhs, NonZeroBranch::Then)), + BinOpKind::Ne | BinOpKind::Gt if is_zero(rhs) => Some((lhs, NonZeroBranch::Then)), + BinOpKind::Eq if is_zero(lhs) => Some((rhs, NonZeroBranch::Else)), + BinOpKind::Eq if is_zero(rhs) => Some((lhs, NonZeroBranch::Else)), + _ => None, + } +} + +fn branch_block<'tcx>( + then: &'tcx Expr<'tcx>, + r#else: Option<&'tcx Expr<'tcx>>, + branch: NonZeroBranch, +) -> Option<&'tcx Block<'tcx>> { + match branch { + NonZeroBranch::Then => match then.kind { + ExprKind::Block(block, _) => Some(block), + _ => None, + }, + NonZeroBranch::Else => match r#else?.kind { + ExprKind::Block(block, _) => Some(block), + _ => None, + }, + } +} + +fn is_zero(expr: &Expr<'_>) -> bool { + is_integer_literal(expr, 0) +} + +fn is_unsigned_integer(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + matches!(cx.typeck_results().expr_ty(expr).peel_refs().kind(), ty::Uint(_)) +} diff --git a/clippy_lints/src/manual_take.rs b/clippy_lints/src/manual_take.rs new file mode 100644 index 000000000000..8e74d04c4556 --- /dev/null +++ b/clippy_lints/src/manual_take.rs @@ -0,0 +1,114 @@ +use clippy_config::Conf; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{MEM_TAKE, Msrv}; +use clippy_utils::source::snippet_with_context; +use rustc_ast::LitKind; +use rustc_errors::Applicability; +use rustc_hir::{Block, Expr, ExprKind, StmtKind}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_session::impl_lint_pass; + +declare_clippy_lint! { + /// ### What it does + /// Detects manual re-implementations of `std::mem::take`. + /// + /// ### Why is this bad? + /// Because the function call is shorter and easier to read. + /// + /// ### Known issues + /// Currently the lint only detects cases involving `bool`s. + /// + /// ### Example + /// ```no_run + /// let mut x = true; + /// let _ = if x { + /// x = false; + /// true + /// } else { + /// false + /// }; + /// ``` + /// Use instead: + /// ```no_run + /// let mut x = true; + /// let _ = std::mem::take(&mut x); + /// ``` + #[clippy::version = "1.94.0"] + pub MANUAL_TAKE, + complexity, + "manual `mem::take` implementation" +} +pub struct ManualTake { + msrv: Msrv, +} + +impl ManualTake { + pub fn new(conf: &'static Conf) -> Self { + Self { msrv: conf.msrv } + } +} + +impl_lint_pass!(ManualTake => [MANUAL_TAKE]); + +impl LateLintPass<'_> for ManualTake { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + if let ExprKind::If(cond, then, Some(otherwise)) = expr.kind + && let ExprKind::Path(_) = cond.kind + && let ExprKind::Block( + Block { + stmts: [stmt], + expr: Some(then_expr), + .. + }, + .., + ) = then.kind + && let ExprKind::Block( + Block { + stmts: [], + expr: Some(else_expr), + .. + }, + .., + ) = otherwise.kind + && let StmtKind::Semi(assignment) = stmt.kind + && let ExprKind::Assign(mut_c, possible_false, _) = assignment.kind + && let ExprKind::Path(_) = mut_c.kind + && !expr.span.in_external_macro(cx.sess().source_map()) + && let Some(std_or_core) = clippy_utils::std_or_core(cx) + && self.msrv.meets(cx, MEM_TAKE) + && clippy_utils::SpanlessEq::new(cx).eq_expr(cond, mut_c) + && Some(false) == as_const_bool(possible_false) + && let Some(then_bool) = as_const_bool(then_expr) + && let Some(else_bool) = as_const_bool(else_expr) + && then_bool != else_bool + { + span_lint_and_then( + cx, + MANUAL_TAKE, + expr.span, + "manual implementation of `mem::take`", + |diag| { + let mut app = Applicability::MachineApplicable; + let negate = if then_bool { "" } else { "!" }; + let taken = snippet_with_context(cx, cond.span, expr.span.ctxt(), "_", &mut app).0; + diag.span_suggestion_verbose( + expr.span, + "use", + format!("{negate}{std_or_core}::mem::take(&mut {taken})"), + app, + ); + }, + ); + } + } +} + +fn as_const_bool(e: &Expr<'_>) -> Option { + if let ExprKind::Lit(lit) = e.kind + && let LitKind::Bool(b) = lit.node + { + Some(b) + } else { + None + } +} diff --git a/clippy_lints/src/methods/manual_is_variant_and.rs b/clippy_lints/src/methods/manual_is_variant_and.rs index 8f65858987b9..5ce9d364cdd8 100644 --- a/clippy_lints/src/methods/manual_is_variant_and.rs +++ b/clippy_lints/src/methods/manual_is_variant_and.rs @@ -1,12 +1,13 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::MaybeDef; -use clippy_utils::source::{snippet, snippet_with_applicability}; +use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; use clippy_utils::{get_parent_expr, sym}; use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; +use rustc_hir::def_id::DefId; use rustc_hir::{BinOpKind, Closure, Expr, ExprKind, QPath}; use rustc_lint::LateContext; use rustc_middle::ty; @@ -14,7 +15,37 @@ use rustc_span::{Span, Symbol}; use super::MANUAL_IS_VARIANT_AND; -pub(super) fn check( +#[derive(Clone, Copy, PartialEq)] +enum Flavor { + Option, + Result, +} + +impl Flavor { + fn new(cx: &LateContext<'_>, def_id: DefId) -> Option { + match cx.tcx.get_diagnostic_name(def_id)? { + sym::Option => Some(Self::Option), + sym::Result => Some(Self::Result), + _ => None, + } + } + + const fn diag_sym(self) -> Symbol { + match self { + Self::Option => sym::Option, + Self::Result => sym::Result, + } + } + + const fn positive_variant_name(self) -> Symbol { + match self { + Self::Option => sym::Some, + Self::Result => sym::Ok, + } + } +} + +pub(super) fn check_map_unwrap_or_default( cx: &LateContext<'_>, expr: &Expr<'_>, map_recv: &Expr<'_>, @@ -30,11 +61,13 @@ pub(super) fn check( } // 2. the caller of `map()` is neither `Option` nor `Result` - let is_option = cx.typeck_results().expr_ty(map_recv).is_diag_item(cx, sym::Option); - let is_result = cx.typeck_results().expr_ty(map_recv).is_diag_item(cx, sym::Result); - if !is_option && !is_result { + let Some(flavor) = (cx.typeck_results()) + .expr_ty(map_recv) + .opt_def_id() + .and_then(|did| Flavor::new(cx, did)) + else { return; - } + }; // 3. the caller of `unwrap_or_default` is neither `Option` nor `Result` if !cx.typeck_results().expr_ty(expr).is_bool() { @@ -46,44 +79,23 @@ pub(super) fn check( return; } - let lint_msg = if is_option { - "called `map().unwrap_or_default()` on an `Option` value" - } else { - "called `map().unwrap_or_default()` on a `Result` value" + let lint_span = expr.span.with_lo(map_span.lo()); + let lint_msg = match flavor { + Flavor::Option => "called `map().unwrap_or_default()` on an `Option` value", + Flavor::Result => "called `map().unwrap_or_default()` on a `Result` value", }; - let suggestion = if is_option { "is_some_and" } else { "is_ok_and" }; - span_lint_and_sugg( - cx, - MANUAL_IS_VARIANT_AND, - expr.span.with_lo(map_span.lo()), - lint_msg, - "use", - format!("{}({})", suggestion, snippet(cx, map_arg.span, "..")), - Applicability::MachineApplicable, - ); -} + span_lint_and_then(cx, MANUAL_IS_VARIANT_AND, lint_span, lint_msg, |diag| { + let method = match flavor { + Flavor::Option => "is_some_and", + Flavor::Result => "is_ok_and", + }; -#[derive(Clone, Copy, PartialEq)] -enum Flavor { - Option, - Result, -} + let mut app = Applicability::MachineApplicable; + let map_arg_snippet = snippet_with_applicability(cx, map_arg.span, "_", &mut app); -impl Flavor { - const fn symbol(self) -> Symbol { - match self { - Self::Option => sym::Option, - Self::Result => sym::Result, - } - } - - const fn positive(self) -> Symbol { - match self { - Self::Option => sym::Some, - Self::Result => sym::Ok, - } - } + diag.span_suggestion(lint_span, "use", format!("{method}({map_arg_snippet})"), app); + }); } #[derive(Clone, Copy, PartialEq)] @@ -178,7 +190,7 @@ fn emit_lint<'tcx>( cx, MANUAL_IS_VARIANT_AND, span, - format!("called `.map() {op} {pos}()`", pos = flavor.positive(),), + format!("called `.map() {op} {pos}()`", pos = flavor.positive_variant_name()), "use", format!( "{inversion}{recv}.{method}({body})", @@ -195,24 +207,23 @@ pub(super) fn check_map(cx: &LateContext<'_>, expr: &Expr<'_>) { && op.span.eq_ctxt(expr.span) && let Ok(op) = Op::try_from(op.node) { - // Check `left` and `right` expression in any order, and for `Option` and `Result` + // Check `left` and `right` expression in any order for (expr1, expr2) in [(left, right), (right, left)] { - for flavor in [Flavor::Option, Flavor::Result] { - if let ExprKind::Call(call, [arg]) = expr1.kind - && let ExprKind::Lit(lit) = arg.kind - && let LitKind::Bool(bool_cst) = lit.node - && let ExprKind::Path(QPath::Resolved(_, path)) = call.kind - && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), _) = path.res - && let ty = cx.typeck_results().expr_ty(expr1) - && let ty::Adt(adt, args) = ty.kind() - && cx.tcx.is_diagnostic_item(flavor.symbol(), adt.did()) - && args.type_at(0).is_bool() - && let ExprKind::MethodCall(_, recv, [map_expr], _) = expr2.kind - && cx.typeck_results().expr_ty(recv).is_diag_item(cx, flavor.symbol()) - && let Ok(map_func) = MapFunc::try_from(map_expr) - { - return emit_lint(cx, parent_expr.span, op, flavor, bool_cst, map_func, recv); - } + if let ExprKind::Call(call, [arg]) = expr1.kind + && let ExprKind::Lit(lit) = arg.kind + && let LitKind::Bool(bool_cst) = lit.node + && let ExprKind::Path(QPath::Resolved(_, path)) = call.kind + && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), _) = path.res + && let ExprKind::MethodCall(_, recv, [map_expr], _) = expr2.kind + && let ty = cx.typeck_results().expr_ty(expr1) + && let ty::Adt(adt, args) = ty.kind() + && let Some(flavor) = Flavor::new(cx, adt.did()) + && args.type_at(0).is_bool() + && cx.typeck_results().expr_ty(recv).is_diag_item(cx, flavor.diag_sym()) + && let Ok(map_func) = MapFunc::try_from(map_expr) + { + emit_lint(cx, parent_expr.span, op, flavor, bool_cst, map_func, recv); + return; } } } diff --git a/clippy_lints/src/methods/map_unwrap_or.rs b/clippy_lints/src/methods/map_unwrap_or.rs index 8eb26fb50747..ac2f99180486 100644 --- a/clippy_lints/src/methods/map_unwrap_or.rs +++ b/clippy_lints/src/methods/map_unwrap_or.rs @@ -1,71 +1,210 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::res::MaybeDef; -use clippy_utils::source::snippet; -use clippy_utils::usage::mutated_variables; +use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::ty::is_copy; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir as hir; +use rustc_hir::def::Res; +use rustc_hir::intravisit::{Visitor, walk_expr, walk_path}; +use rustc_hir::{ExprKind, HirId, LangItem, Node, PatKind, Path, QPath}; use rustc_lint::LateContext; -use rustc_span::symbol::sym; +use rustc_middle::hir::nested_filter; +use rustc_span::{Span, sym}; +use std::ops::ControlFlow; use super::MAP_UNWRAP_OR; -/// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s -/// -/// Returns true if the lint was emitted +/// lint use of `map().unwrap_or()` for `Option`s and `Result`s +#[expect(clippy::too_many_arguments)] pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'_>, - recv: &'tcx hir::Expr<'_>, - map_arg: &'tcx hir::Expr<'_>, - unwrap_arg: &'tcx hir::Expr<'_>, + expr: &rustc_hir::Expr<'_>, + recv: &rustc_hir::Expr<'_>, + map_arg: &'tcx rustc_hir::Expr<'_>, + unwrap_recv: &rustc_hir::Expr<'_>, + unwrap_arg: &'tcx rustc_hir::Expr<'_>, + map_span: Span, msrv: Msrv, -) -> bool { - // lint if the caller of `map()` is an `Option` or a `Result`. - let is_option = cx.typeck_results().expr_ty(recv).is_diag_item(cx, sym::Option); - let is_result = cx.typeck_results().expr_ty(recv).is_diag_item(cx, sym::Result); +) { + let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs(); + let recv_ty_kind = match recv_ty.opt_diag_name(cx) { + Some(sym::Option) => sym::Option, + Some(sym::Result) if msrv.meets(cx, msrvs::RESULT_MAP_OR) => sym::Result, + _ => return, + }; - if is_result && !msrv.meets(cx, msrvs::RESULT_MAP_OR_ELSE) { - return false; - } + let unwrap_arg_ty = cx.typeck_results().expr_ty(unwrap_arg); + if !is_copy(cx, unwrap_arg_ty) { + // Replacing `.map().unwrap_or()` with `.map_or(, )` can sometimes lead to + // borrowck errors, see #10579 for one such instance. + // In particular, if `a` causes a move and `f` references that moved binding, then we cannot lint: + // ``` + // let x = vec![1, 2]; + // x.get(0..1).map(|s| s.to_vec()).unwrap_or(x); + // ``` + // This compiles, but changing it to `map_or` will produce a compile error: + // ``` + // let x = vec![1, 2]; + // x.get(0..1).map_or(x, |s| s.to_vec()) + // ^ moving `x` here + // ^^^^^^^^^^^ while it is borrowed here (and later used in the closure) + // ``` + // So, we have to check that `a` is not referenced anywhere (even outside of the `.map` closure!) + // before the call to `unwrap_or`. - if is_option || is_result { - // Don't make a suggestion that may fail to compile due to mutably borrowing - // the same variable twice. - let map_mutated_vars = mutated_variables(recv, cx); - let unwrap_mutated_vars = mutated_variables(unwrap_arg, cx); - if let (Some(map_mutated_vars), Some(unwrap_mutated_vars)) = (map_mutated_vars, unwrap_mutated_vars) { - if map_mutated_vars.intersection(&unwrap_mutated_vars).next().is_some() { - return false; - } - } else { - return false; - } - - // lint message - let msg = if is_option { - "called `map().unwrap_or_else()` on an `Option` value" - } else { - "called `map().unwrap_or_else()` on a `Result` value" + let mut unwrap_visitor = UnwrapVisitor { + cx, + identifiers: FxHashSet::default(), }; - // get snippets for args to map() and unwrap_or_else() - let map_snippet = snippet(cx, map_arg.span, ".."); - let unwrap_snippet = snippet(cx, unwrap_arg.span, ".."); - // lint, with note if both map() and unwrap_or_else() have the same span - if map_arg.span.eq_ctxt(unwrap_arg.span) { - let var_snippet = snippet(cx, recv.span, ".."); - span_lint_and_sugg( - cx, - MAP_UNWRAP_OR, - expr.span, - msg, - "try", - format!("{var_snippet}.map_or_else({unwrap_snippet}, {map_snippet})"), - Applicability::MachineApplicable, - ); - return true; + unwrap_visitor.visit_expr(unwrap_arg); + + let mut reference_visitor = ReferenceVisitor { + cx, + identifiers: unwrap_visitor.identifiers, + unwrap_or_span: unwrap_arg.span, + }; + + let body = cx.tcx.hir_body_owned_by(cx.tcx.hir_enclosing_body_owner(expr.hir_id)); + + // Visit the body, and return if we've found a reference + if reference_visitor.visit_body(body).is_break() { + return; } } - false + if !unwrap_arg.span.eq_ctxt(map_span) { + return; + } + + let mut applicability = Applicability::MachineApplicable; + // get snippet for unwrap_or() + let unwrap_snippet = snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability); + // lint message + + let suggest_kind = if recv_ty_kind == sym::Option + && unwrap_arg + .basic_res() + .ctor_parent(cx) + .is_lang_item(cx, LangItem::OptionNone) + { + SuggestedKind::AndThen + } + // is_some_and is stabilised && `unwrap_or` argument is false; suggest `is_some_and` instead + else if matches!(&unwrap_arg.kind, ExprKind::Lit(lit) + if matches!(lit.node, rustc_ast::LitKind::Bool(false))) + && msrv.meets(cx, msrvs::OPTION_RESULT_IS_VARIANT_AND) + { + SuggestedKind::IsVariantAnd + } else { + SuggestedKind::Other + }; + + let arg = match suggest_kind { + SuggestedKind::AndThen => "None", + SuggestedKind::IsVariantAnd => "false", + SuggestedKind::Other => "", + }; + + let suggest = match (suggest_kind, recv_ty_kind) { + (SuggestedKind::AndThen, _) => "and_then()", + (SuggestedKind::IsVariantAnd, sym::Result) => "is_ok_and()", + (SuggestedKind::IsVariantAnd, sym::Option) => "is_some_and()", + _ => "map_or(, )", + }; + + let msg = format!( + "called `map().unwrap_or({arg})` on {} `{recv_ty_kind}` value", + if recv_ty_kind == sym::Option { "an" } else { "a" } + ); + + span_lint_and_then(cx, MAP_UNWRAP_OR, expr.span, msg, |diag| { + let map_arg_span = map_arg.span; + + let mut suggestion = vec![ + ( + map_span, + String::from(match (suggest_kind, recv_ty_kind) { + (SuggestedKind::AndThen, _) => "and_then", + (SuggestedKind::IsVariantAnd, sym::Result) => "is_ok_and", + (SuggestedKind::IsVariantAnd, sym::Option) => "is_some_and", + (SuggestedKind::Other, _) + if unwrap_arg_ty.peel_refs().is_array() + && cx.typeck_results().expr_ty_adjusted(unwrap_arg).peel_refs().is_slice() => + { + return; + }, + _ => "map_or", + }), + ), + (expr.span.with_lo(unwrap_recv.span.hi()), String::new()), + ]; + + if matches!(suggest_kind, SuggestedKind::Other) { + suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{unwrap_snippet}, "))); + } + + diag.multipart_suggestion(format!("use `{suggest}` instead"), suggestion, applicability); + }); +} + +#[derive(Clone, Copy, PartialEq, Eq)] +enum SuggestedKind { + AndThen, + IsVariantAnd, + Other, +} + +struct UnwrapVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + identifiers: FxHashSet, +} + +impl<'tcx> Visitor<'tcx> for UnwrapVisitor<'_, 'tcx> { + type NestedFilter = nested_filter::All; + + fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) { + if let Res::Local(local_id) = path.res + && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) + && let PatKind::Binding(_, local_id, ..) = pat.kind + { + self.identifiers.insert(local_id); + } + walk_path(self, path); + } + + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.cx.tcx + } +} + +struct ReferenceVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + identifiers: FxHashSet, + unwrap_or_span: Span, +} + +impl<'tcx> Visitor<'tcx> for ReferenceVisitor<'_, 'tcx> { + type NestedFilter = nested_filter::All; + type Result = ControlFlow<()>; + fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) -> ControlFlow<()> { + // If we haven't found a reference yet, check if this references + // one of the locals that was moved in the `unwrap_or` argument. + // We are only interested in exprs that appear before the `unwrap_or` call. + if expr.span < self.unwrap_or_span + && let ExprKind::Path(ref path) = expr.kind + && let QPath::Resolved(_, path) = path + && let Res::Local(local_id) = path.res + && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) + && let PatKind::Binding(_, local_id, ..) = pat.kind + && self.identifiers.contains(&local_id) + { + return ControlFlow::Break(()); + } + walk_expr(self, expr) + } + + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.cx.tcx + } } diff --git a/clippy_lints/src/methods/map_unwrap_or_else.rs b/clippy_lints/src/methods/map_unwrap_or_else.rs new file mode 100644 index 000000000000..8bb532b21635 --- /dev/null +++ b/clippy_lints/src/methods/map_unwrap_or_else.rs @@ -0,0 +1,68 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::res::MaybeDef as _; +use clippy_utils::source::snippet; +use clippy_utils::sym; +use clippy_utils::usage::mutated_variables; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_lint::LateContext; + +use super::MAP_UNWRAP_OR; + +/// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s +/// +/// Is part of the `map_unwrap_or` lint, split into separate files for readability. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'_>, + recv: &'tcx hir::Expr<'_>, + map_arg: &'tcx hir::Expr<'_>, + unwrap_arg: &'tcx hir::Expr<'_>, + msrv: Msrv, +) -> bool { + let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs(); + let recv_ty_kind = match recv_ty.opt_diag_name(cx) { + Some(sym::Option) => sym::Option, + Some(sym::Result) if msrv.meets(cx, msrvs::RESULT_MAP_OR_ELSE) => sym::Result, + _ => return false, + }; + + // Don't make a suggestion that may fail to compile due to mutably borrowing + // the same variable twice. + let Some(map_mutated_vars) = mutated_variables(recv, cx) else { + return false; + }; + let Some(unwrap_mutated_vars) = mutated_variables(unwrap_arg, cx) else { + return false; + }; + if map_mutated_vars.intersection(&unwrap_mutated_vars).next().is_some() { + return false; + } + + // lint message + let msg = if recv_ty_kind == sym::Option { + "called `map().unwrap_or_else()` on an `Option` value" + } else { + "called `map().unwrap_or_else()` on a `Result` value" + }; + // get snippets for args to map() and unwrap_or_else() + let map_snippet = snippet(cx, map_arg.span, ".."); + let unwrap_snippet = snippet(cx, unwrap_arg.span, ".."); + // lint, with note if both map() and unwrap_or_else() have the same span + if map_arg.span.eq_ctxt(unwrap_arg.span) { + let var_snippet = snippet(cx, recv.span, ".."); + span_lint_and_sugg( + cx, + MAP_UNWRAP_OR, + expr.span, + msg, + "try", + format!("{var_snippet}.map_or_else({unwrap_snippet}, {map_snippet})"), + Applicability::MachineApplicable, + ); + return true; + } + + false +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 248a147cfd77..376e93aa7e7d 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -74,6 +74,7 @@ mod map_err_ignore; mod map_flatten; mod map_identity; mod map_unwrap_or; +mod map_unwrap_or_else; mod map_with_unused_argument_over_ranges; mod mut_mutex_lock; mod needless_as_bytes; @@ -89,7 +90,6 @@ mod open_options; mod option_as_ref_cloned; mod option_as_ref_deref; mod option_map_or_none; -mod option_map_unwrap_or; mod or_fun_call; mod or_then_unwrap; mod path_buf_push_overwrite; @@ -3933,7 +3933,8 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usage of `option.map(f).unwrap_or_default()` and `result.map(f).unwrap_or_default()` where f is a function or closure that returns the `bool` type. + /// Checks for usage of `option.map(f).unwrap_or_default()` and `result.map(f).unwrap_or_default()` where `f` is a function or closure that returns the `bool` type. + /// /// Also checks for equality comparisons like `option.map(f) == Some(true)` and `result.map(f) == Ok(true)`. /// /// ### Why is this bad? @@ -5531,10 +5532,10 @@ impl Methods { stable_sort_primitive::check(cx, expr, recv); }, (sym::sort_by, [arg]) => { - unnecessary_sort_by::check(cx, expr, recv, arg, false); + unnecessary_sort_by::check(cx, expr, call_span, arg, false); }, (sym::sort_unstable_by, [arg]) => { - unnecessary_sort_by::check(cx, expr, recv, arg, true); + unnecessary_sort_by::check(cx, expr, call_span, arg, true); }, (sym::split, [arg]) => { str_split::check(cx, expr, recv, arg); @@ -5576,7 +5577,7 @@ impl Methods { unnecessary_fallible_conversions::check_method(cx, expr); }, (sym::to_owned, []) => { - if !suspicious_to_owned::check(cx, expr, recv) { + if !suspicious_to_owned::check(cx, expr, span) { implicit_clone::check(cx, name, expr, recv); } }, @@ -5607,7 +5608,7 @@ impl Methods { manual_saturating_arithmetic::check_unwrap_or(cx, expr, lhs, rhs, u_arg, arith); }, Some((sym::map, m_recv, [m_arg], span, _)) => { - option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span, self.msrv); + map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span, self.msrv); }, Some((then_method @ (sym::then | sym::then_some), t_recv, [t_arg], _, _)) => { obfuscated_if_else::check( @@ -5629,7 +5630,7 @@ impl Methods { manual_saturating_arithmetic::check_sub_unwrap_or_default(cx, expr, lhs, rhs); }, Some((sym::map, m_recv, [arg], span, _)) => { - manual_is_variant_and::check(cx, expr, m_recv, arg, span, self.msrv); + manual_is_variant_and::check_map_unwrap_or_default(cx, expr, m_recv, arg, span, self.msrv); }, Some((then_method @ (sym::then | sym::then_some), t_recv, [t_arg], _, _)) => { obfuscated_if_else::check( @@ -5648,7 +5649,7 @@ impl Methods { (sym::unwrap_or_else, [u_arg]) => { match method_call(recv) { Some((sym::map, recv, [map_arg], _, _)) - if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, self.msrv) => {}, + if map_unwrap_or_else::check(cx, expr, recv, map_arg, u_arg, self.msrv) => {}, Some((then_method @ (sym::then | sym::then_some), t_recv, [t_arg], _, _)) => { obfuscated_if_else::check( cx, diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index 0e2012319147..6bdb40e46b38 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::ops::ControlFlow; use super::NEEDLESS_COLLECT; @@ -16,8 +17,8 @@ use rustc_hir::{ use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, AssocTag, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, Ty}; -use rustc_span::Span; use rustc_span::symbol::Ident; +use rustc_span::{Span, Symbol}; const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed"; @@ -104,16 +105,19 @@ pub(super) fn check<'tcx>( Node::LetStmt(l) => { if let PatKind::Binding(BindingMode::NONE | BindingMode::MUT, id, _, None) = l.pat.kind && let ty = cx.typeck_results().expr_ty(collect_expr) - && matches!( - ty.opt_diag_name(cx), - Some(sym::Vec | sym::VecDeque | sym::BinaryHeap | sym::LinkedList) - ) + && let Some(extra_spec) = ty.opt_diag_name(cx).and_then(ExtraFunctionSpec::new) && let iter_ty = cx.typeck_results().expr_ty(iter_expr) && let Some(block) = get_enclosing_block(cx, l.hir_id) - && let Some(iter_calls) = detect_iter_and_into_iters(block, id, cx, get_captured_ids(cx, iter_ty)) + && let Some((iter_calls, extra_calls)) = + detect_iter_and_into_iters(block, id, cx, get_captured_ids(cx, iter_ty), extra_spec) && let [iter_call] = &*iter_calls { - let mut used_count_visitor = UsedCountVisitor { cx, id, count: 0 }; + let mut used_count_visitor = UsedCountVisitor { + cx, + id, + extra_spec, + count: 0, + }; walk_block(&mut used_count_visitor, block); if used_count_visitor.count > 1 { return; @@ -135,11 +139,24 @@ pub(super) fn check<'tcx>( span, NEEDLESS_COLLECT_MSG, |diag| { - let iter_replacement = - format!("{}{}", Sugg::hir(cx, iter_expr, ".."), iter_call.get_iter_method(cx)); + let iter_snippet = Sugg::hir(cx, iter_expr, ".."); + let mut iter_replacement = iter_snippet.to_string(); + for extra in &extra_calls { + iter_replacement = extra.apply_iter_method(cx, &iter_replacement); + } + iter_replacement.push_str(&iter_call.get_iter_method(cx)); + + let mut remove_suggestions = vec![(l.span, String::new())]; + remove_suggestions.extend( + extra_calls + .iter() + .flat_map(|extra| extra.span().map(|s| (s, String::new()))), + ); + remove_suggestions.push((iter_call.span, iter_replacement)); + diag.multipart_suggestion( iter_call.get_suggestion_text(), - vec![(l.span, String::new()), (iter_call.span, iter_replacement)], + remove_suggestions, Applicability::MaybeIncorrect, ); }, @@ -272,6 +289,7 @@ struct IterFunction { func: IterFunctionKind, span: Span, } + impl IterFunction { fn get_iter_method(&self, cx: &LateContext<'_>) -> String { match &self.func { @@ -288,6 +306,7 @@ impl IterFunction { }, } } + fn get_suggestion_text(&self) -> &'static str { match &self.func { IterFunctionKind::IntoIter(_) => { @@ -305,6 +324,7 @@ impl IterFunction { } } } + enum IterFunctionKind { IntoIter(HirId), Len, @@ -312,16 +332,119 @@ enum IterFunctionKind { Contains(Span), } +struct ExtraFunctionSpan { + /// Span of the function call + func_span: Span, + /// Span of the argument + arg_span: Span, +} + +enum ExtraFunction { + Push { + back: Vec, + front: Vec, + }, + Extend(ExtraFunctionSpan), +} + +impl ExtraFunction { + fn apply_iter_method(&self, cx: &LateContext<'_>, inner: &str) -> String { + match &self { + ExtraFunction::Push { back, front } => { + let back_sugg = back + .iter() + .map(|span| snippet(cx, span.arg_span, "..")) + .intersperse(Cow::Borrowed(", ")) + .collect::(); + let front = front + .iter() + .map(|span| snippet(cx, span.arg_span, "..")) + .intersperse(Cow::Borrowed(", ")) + .collect::(); + match (front.is_empty(), back_sugg.is_empty()) { + (true, true) => inner.to_string(), + (true, false) => format!("{inner}.chain([{back_sugg}])"), + (false, true) => format!("[{front}].into_iter().chain({inner})"), + (false, false) => format!("[{front}].into_iter().chain({inner}).chain([{back_sugg}])"), + } + }, + ExtraFunction::Extend(span) => { + let s = snippet(cx, span.arg_span, ".."); + format!("{inner}.chain({s})") + }, + } + } + + fn span(&self) -> Box + '_> { + match &self { + ExtraFunction::Push { back, front } => Box::new( + back.iter() + .map(|s| s.func_span) + .chain(front.iter().map(|s| s.func_span)), + ), + ExtraFunction::Extend(span) => Box::new(std::iter::once(span.func_span)), + } + } +} + +#[derive(Clone, Copy)] +struct ExtraFunctionPushSpec { + back: Option, + front: Option, +} + +#[derive(Clone, Copy)] +struct ExtraFunctionSpec { + push_symbol: ExtraFunctionPushSpec, + extend_symbol: Option, +} + +impl ExtraFunctionSpec { + fn new(target: Symbol) -> Option { + match target { + sym::Vec => Some(ExtraFunctionSpec { + push_symbol: ExtraFunctionPushSpec { + back: Some(sym::push), + front: None, + }, + extend_symbol: Some(sym::extend), + }), + sym::VecDeque | sym::LinkedList => Some(ExtraFunctionSpec { + push_symbol: ExtraFunctionPushSpec { + back: Some(sym::push_back), + front: Some(sym::push_front), + }, + extend_symbol: Some(sym::extend), + }), + sym::BinaryHeap => Some(ExtraFunctionSpec { + push_symbol: ExtraFunctionPushSpec { + back: None, + front: None, + }, + extend_symbol: None, + }), + _ => None, + } + } + + fn is_extra_function(self, name: Symbol) -> bool { + self.push_symbol.back == Some(name) || self.push_symbol.front == Some(name) || self.extend_symbol == Some(name) + } +} + struct IterFunctionVisitor<'a, 'tcx> { illegal_mutable_capture_ids: HirIdSet, current_mutably_captured_ids: HirIdSet, cx: &'a LateContext<'tcx>, uses: Vec>, + extras: Vec, + extra_spec: ExtraFunctionSpec, hir_id_uses_map: FxHashMap, current_statement_hir_id: Option, seen_other: bool, target: HirId, } + impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> { fn visit_block(&mut self, block: &'tcx Block<'tcx>) { for (expr, hir_id) in block.stmts.iter().filter_map(get_expr_and_hir_id_from_stmt) { @@ -341,6 +464,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> { } } + #[expect(clippy::too_many_lines)] fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { // Check function calls on our collection if let ExprKind::MethodCall(method_name, recv, args, _) = &expr.kind { @@ -384,6 +508,53 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> { func: IterFunctionKind::Contains(args[0].span), span: expr.span, })), + name if let is_push_back = self.extra_spec.push_symbol.back.is_some_and(|sym| name == sym) + && (is_push_back || self.extra_spec.push_symbol.front.is_some_and(|sym| name == sym)) + && self.uses.is_empty() => + { + let span = get_span_of_expr_or_parent_stmt(self.cx, expr); + match self.extras.last_mut() { + Some(ExtraFunction::Push { back, .. }) if is_push_back => { + back.push(ExtraFunctionSpan { + func_span: span, + arg_span: args[0].span, + }); + }, + Some(ExtraFunction::Push { front, .. }) => { + front.push(ExtraFunctionSpan { + func_span: span, + arg_span: args[0].span, + }); + }, + _ if is_push_back => { + self.extras.push(ExtraFunction::Push { + back: vec![ExtraFunctionSpan { + func_span: span, + arg_span: args[0].span, + }], + front: Vec::new(), + }); + }, + _ => { + self.extras.push(ExtraFunction::Push { + back: Vec::new(), + front: vec![ExtraFunctionSpan { + func_span: span, + arg_span: args[0].span, + }], + }); + }, + } + }, + name if self.extra_spec.extend_symbol.is_some_and(|sym| name == sym) + && self.uses.is_empty() => + { + let span = get_span_of_expr_or_parent_stmt(self.cx, expr); + self.extras.push(ExtraFunction::Extend(ExtraFunctionSpan { + func_span: span, + arg_span: args[0].span, + })); + }, _ => { self.seen_other = true; if let Some(hir_id) = self.current_statement_hir_id { @@ -421,6 +592,16 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> { } } +/// If parent of the `expr` is a statement, return the span of the statement, otherwise return the +/// span of the expression. +fn get_span_of_expr_or_parent_stmt<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Span { + if let Node::Stmt(stmt) = cx.tcx.parent_hir_node(expr.hir_id) { + stmt.span + } else { + expr.span + } +} + enum LoopKind<'tcx> { Conditional(&'tcx Expr<'tcx>), Loop, @@ -468,6 +649,7 @@ fn get_expr_and_hir_id_from_stmt<'v>(stmt: &'v Stmt<'v>) -> Option<(&'v Expr<'v> struct UsedCountVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, id: HirId, + extra_spec: ExtraFunctionSpec, count: usize, } @@ -475,11 +657,20 @@ impl<'tcx> Visitor<'tcx> for UsedCountVisitor<'_, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - if expr.res_local_id() == Some(self.id) { - self.count += 1; - } else { + if expr.res_local_id() != Some(self.id) { walk_expr(self, expr); + return; } + + let parent = self.cx.tcx.parent_hir_node(expr.hir_id); + if let Node::Expr(expr) = parent + && let ExprKind::MethodCall(method_name, _, _, _) = &expr.kind + && self.extra_spec.is_extra_function(method_name.ident.name) + { + return; + } + + self.count += 1; } fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { @@ -494,12 +685,15 @@ fn detect_iter_and_into_iters<'tcx: 'a, 'a>( id: HirId, cx: &'a LateContext<'tcx>, captured_ids: HirIdSet, -) -> Option> { + extra_spec: ExtraFunctionSpec, +) -> Option<(Vec, Vec)> { let mut visitor = IterFunctionVisitor { illegal_mutable_capture_ids: captured_ids, current_mutably_captured_ids: HirIdSet::default(), cx, uses: Vec::new(), + extras: Vec::new(), + extra_spec, hir_id_uses_map: FxHashMap::default(), current_statement_hir_id: None, seen_other: false, @@ -509,7 +703,7 @@ fn detect_iter_and_into_iters<'tcx: 'a, 'a>( if visitor.seen_other { None } else { - Some(visitor.uses.into_iter().flatten().collect()) + Some((visitor.uses.into_iter().flatten().collect(), visitor.extras)) } } diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs deleted file mode 100644 index 32a9b4fe7c58..000000000000 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ /dev/null @@ -1,180 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::res::MaybeDef; -use clippy_utils::source::snippet_with_applicability; -use clippy_utils::ty::is_copy; -use rustc_data_structures::fx::FxHashSet; -use rustc_errors::Applicability; -use rustc_hir::def::Res; -use rustc_hir::intravisit::{Visitor, walk_path}; -use rustc_hir::{ExprKind, HirId, Node, PatKind, Path, QPath}; -use rustc_lint::LateContext; -use rustc_middle::hir::nested_filter; -use rustc_span::{Span, sym}; -use std::ops::ControlFlow; - -use super::MAP_UNWRAP_OR; - -/// lint use of `map().unwrap_or()` for `Option`s -#[expect(clippy::too_many_arguments)] -pub(super) fn check<'tcx>( - cx: &LateContext<'tcx>, - expr: &rustc_hir::Expr<'_>, - recv: &rustc_hir::Expr<'_>, - map_arg: &'tcx rustc_hir::Expr<'_>, - unwrap_recv: &rustc_hir::Expr<'_>, - unwrap_arg: &'tcx rustc_hir::Expr<'_>, - map_span: Span, - msrv: Msrv, -) { - // lint if the caller of `map()` is an `Option` - if cx.typeck_results().expr_ty(recv).is_diag_item(cx, sym::Option) { - if !is_copy(cx, cx.typeck_results().expr_ty(unwrap_arg)) { - // Replacing `.map().unwrap_or()` with `.map_or(, )` can sometimes lead to - // borrowck errors, see #10579 for one such instance. - // In particular, if `a` causes a move and `f` references that moved binding, then we cannot lint: - // ``` - // let x = vec![1, 2]; - // x.get(0..1).map(|s| s.to_vec()).unwrap_or(x); - // ``` - // This compiles, but changing it to `map_or` will produce a compile error: - // ``` - // let x = vec![1, 2]; - // x.get(0..1).map_or(x, |s| s.to_vec()) - // ^ moving `x` here - // ^^^^^^^^^^^ while it is borrowed here (and later used in the closure) - // ``` - // So, we have to check that `a` is not referenced anywhere (even outside of the `.map` closure!) - // before the call to `unwrap_or`. - - let mut unwrap_visitor = UnwrapVisitor { - cx, - identifiers: FxHashSet::default(), - }; - unwrap_visitor.visit_expr(unwrap_arg); - - let mut reference_visitor = ReferenceVisitor { - cx, - identifiers: unwrap_visitor.identifiers, - unwrap_or_span: unwrap_arg.span, - }; - - let body = cx.tcx.hir_body_owned_by(cx.tcx.hir_enclosing_body_owner(expr.hir_id)); - - // Visit the body, and return if we've found a reference - if reference_visitor.visit_body(body).is_break() { - return; - } - } - - if !unwrap_arg.span.eq_ctxt(map_span) { - return; - } - - // is_some_and is stabilised && `unwrap_or` argument is false; suggest `is_some_and` instead - let suggest_is_some_and = matches!(&unwrap_arg.kind, ExprKind::Lit(lit) - if matches!(lit.node, rustc_ast::LitKind::Bool(false))) - && msrv.meets(cx, msrvs::OPTION_RESULT_IS_VARIANT_AND); - - let mut applicability = Applicability::MachineApplicable; - // get snippet for unwrap_or() - let unwrap_snippet = snippet_with_applicability(cx, unwrap_arg.span, "..", &mut applicability); - // lint message - // comparing the snippet from source to raw text ("None") below is safe - // because we already have checked the type. - let arg = if unwrap_snippet == "None" { - "None" - } else if suggest_is_some_and { - "false" - } else { - "" - }; - let unwrap_snippet_none = unwrap_snippet == "None"; - let suggest = if unwrap_snippet_none { - "and_then()" - } else if suggest_is_some_and { - "is_some_and()" - } else { - "map_or(, )" - }; - let msg = format!("called `map().unwrap_or({arg})` on an `Option` value"); - - span_lint_and_then(cx, MAP_UNWRAP_OR, expr.span, msg, |diag| { - let map_arg_span = map_arg.span; - - let mut suggestion = vec![ - ( - map_span, - String::from(if unwrap_snippet_none { - "and_then" - } else if suggest_is_some_and { - "is_some_and" - } else { - "map_or" - }), - ), - (expr.span.with_lo(unwrap_recv.span.hi()), String::new()), - ]; - - if !unwrap_snippet_none && !suggest_is_some_and { - suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{unwrap_snippet}, "))); - } - - diag.multipart_suggestion(format!("use `{suggest}` instead"), suggestion, applicability); - }); - } -} - -struct UnwrapVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - identifiers: FxHashSet, -} - -impl<'tcx> Visitor<'tcx> for UnwrapVisitor<'_, 'tcx> { - type NestedFilter = nested_filter::All; - - fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) { - if let Res::Local(local_id) = path.res - && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) - && let PatKind::Binding(_, local_id, ..) = pat.kind - { - self.identifiers.insert(local_id); - } - walk_path(self, path); - } - - fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { - self.cx.tcx - } -} - -struct ReferenceVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - identifiers: FxHashSet, - unwrap_or_span: Span, -} - -impl<'tcx> Visitor<'tcx> for ReferenceVisitor<'_, 'tcx> { - type NestedFilter = nested_filter::All; - type Result = ControlFlow<()>; - fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'_>) -> ControlFlow<()> { - // If we haven't found a reference yet, check if this references - // one of the locals that was moved in the `unwrap_or` argument. - // We are only interested in exprs that appear before the `unwrap_or` call. - if expr.span < self.unwrap_or_span - && let ExprKind::Path(ref path) = expr.kind - && let QPath::Resolved(_, path) = path - && let Res::Local(local_id) = path.res - && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) - && let PatKind::Binding(_, local_id, ..) = pat.kind - && self.identifiers.contains(&local_id) - { - return ControlFlow::Break(()); - } - rustc_hir::intravisit::walk_expr(self, expr) - } - - fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { - self.cx.tcx - } -} diff --git a/clippy_lints/src/methods/suspicious_to_owned.rs b/clippy_lints/src/methods/suspicious_to_owned.rs index bcd1f11931fc..e9a5104eb3b4 100644 --- a/clippy_lints/src/methods/suspicious_to_owned.rs +++ b/clippy_lints/src/methods/suspicious_to_owned.rs @@ -1,15 +1,14 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::MaybeDef; -use clippy_utils::source::snippet_with_context; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; use rustc_middle::ty::print::with_forced_trimmed_paths; -use rustc_span::sym; +use rustc_span::{Span, sym}; use super::SUSPICIOUS_TO_OWNED; -pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) -> bool { +pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_span: Span) -> bool { if cx .typeck_results() .type_dependent_def_id(expr.hir_id) @@ -18,28 +17,22 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) - && let input_type = cx.typeck_results().expr_ty(expr) && input_type.is_diag_item(cx, sym::Cow) { - let mut app = Applicability::MaybeIncorrect; - let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0; + let app = Applicability::MaybeIncorrect; span_lint_and_then( cx, SUSPICIOUS_TO_OWNED, expr.span, with_forced_trimmed_paths!(format!( - "this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned" + "this `to_owned` call clones the `{input_type}` itself and does not cause its contents to become owned" )), |diag| { diag.span_suggestion( - expr.span, - "depending on intent, either make the Cow an Owned variant", - format!("{recv_snip}.into_owned()"), - app, - ); - diag.span_suggestion( - expr.span, - "or clone the Cow itself", - format!("{recv_snip}.clone()"), + method_span, + "depending on intent, either make the `Cow` an `Owned` variant", + "into_owned".to_string(), app, ); + diag.span_suggestion(method_span, "or clone the `Cow` itself", "clone".to_string(), app); }, ); return true; diff --git a/clippy_lints/src/methods/unnecessary_map_or.rs b/clippy_lints/src/methods/unnecessary_map_or.rs index 0c01be4b1875..21e112360aaf 100644 --- a/clippy_lints/src/methods/unnecessary_map_or.rs +++ b/clippy_lints/src/methods/unnecessary_map_or.rs @@ -8,7 +8,7 @@ use clippy_utils::sugg::{Sugg, make_binop}; use clippy_utils::ty::{implements_trait, is_copy}; use clippy_utils::visitors::is_local_used; use clippy_utils::{get_parent_expr, is_from_proc_macro}; -use rustc_ast::LitKind::Bool; +use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, PatKind}; use rustc_lint::LateContext; @@ -48,13 +48,14 @@ pub(super) fn check<'a>( let ExprKind::Lit(def_kind) = def.kind else { return; }; - - let recv_ty = cx.typeck_results().expr_ty_adjusted(recv); - - let Bool(def_bool) = def_kind.node else { + let LitKind::Bool(def_bool) = def_kind.node else { return; }; + let typeck = cx.typeck_results(); + + let recv_ty = typeck.expr_ty_adjusted(recv); + let variant = match recv_ty.opt_diag_name(cx) { Some(sym::Option) => Variant::Some, Some(sym::Result) => Variant::Ok, @@ -63,12 +64,12 @@ pub(super) fn check<'a>( let ext_def_span = def.span.until(map.span); - let (sugg, method, applicability) = if cx.typeck_results().expr_adjustments(recv).is_empty() + let (sugg, method, applicability): (_, Cow<'_, _>, _) = if typeck.expr_adjustments(recv).is_empty() && let ExprKind::Closure(map_closure) = map.kind && let closure_body = cx.tcx.hir_body(map_closure.body) && let closure_body_value = closure_body.value.peel_blocks() && let ExprKind::Binary(op, l, r) = closure_body_value.kind - && let Some(param) = closure_body.params.first() + && let [param] = closure_body.params && let PatKind::Binding(_, hir_id, _, _) = param.pat.kind // checking that map_or is one of the following: // .map_or(false, |x| x == y) @@ -78,14 +79,13 @@ pub(super) fn check<'a>( && ((BinOpKind::Eq == op.node && !def_bool) || (BinOpKind::Ne == op.node && def_bool)) && let non_binding_location = if l.res_local_id() == Some(hir_id) { r } else { l } && switch_to_eager_eval(cx, non_binding_location) - // if its both then that's a strange edge case and + // if it's both then that's a strange edge case and // we can just ignore it, since by default clippy will error on this && (l.res_local_id() == Some(hir_id)) != (r.res_local_id() == Some(hir_id)) && !is_local_used(cx, non_binding_location, hir_id) - && let typeck_results = cx.typeck_results() - && let l_ty = typeck_results.expr_ty(l) - && l_ty == typeck_results.expr_ty(r) - && let Some(partial_eq) = cx.tcx.get_diagnostic_item(sym::PartialEq) + && let l_ty = typeck.expr_ty(l) + && l_ty == typeck.expr_ty(r) + && let Some(partial_eq) = cx.tcx.lang_items().eq_trait() && implements_trait(cx, recv_ty, partial_eq, &[recv_ty.into()]) && is_copy(cx, l_ty) { @@ -97,12 +97,12 @@ pub(super) fn check<'a>( // being converted to `Some(5) == Some(5).then(|| 1)` isn't // the same thing + let mut app = Applicability::MachineApplicable; let inner_non_binding = Sugg::NonParen(Cow::Owned(format!( "{wrap}({})", - Sugg::hir(cx, non_binding_location, "") + Sugg::hir_with_applicability(cx, non_binding_location, "", &mut app) ))); - let mut app = Applicability::MachineApplicable; let binop = make_binop( op.node, &Sugg::hir_with_applicability(cx, recv, "..", &mut app), @@ -126,18 +126,18 @@ pub(super) fn check<'a>( } .into_string(); - (vec![(expr.span, sugg)], "a standard comparison", app) + (vec![(expr.span, sugg)], "a standard comparison".into(), app) } else if !def_bool && msrv.meets(cx, msrvs::OPTION_RESULT_IS_VARIANT_AND) { let suggested_name = variant.method_name(); ( - vec![(method_span, suggested_name.into()), (ext_def_span, String::default())], - suggested_name, + vec![(method_span, suggested_name.into()), (ext_def_span, String::new())], + format!("`{suggested_name}`").into(), Applicability::MachineApplicable, ) } else if def_bool && matches!(variant, Variant::Some) && msrv.meets(cx, msrvs::IS_NONE_OR) { ( - vec![(method_span, "is_none_or".into()), (ext_def_span, String::default())], - "is_none_or", + vec![(method_span, "is_none_or".into()), (ext_def_span, String::new())], + "`is_none_or`".into(), Applicability::MachineApplicable, ) } else { diff --git a/clippy_lints/src/methods/unnecessary_sort_by.rs b/clippy_lints/src/methods/unnecessary_sort_by.rs index 7cc8c79481a0..3f81a6ecd2f8 100644 --- a/clippy_lints/src/methods/unnecessary_sort_by.rs +++ b/clippy_lints/src/methods/unnecessary_sort_by.rs @@ -1,47 +1,51 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; +use clippy_utils::source::snippet_with_applicability; use clippy_utils::std_or_core; use clippy_utils::sugg::Sugg; -use clippy_utils::ty::implements_trait; +use clippy_utils::ty::{implements_trait, is_copy, peel_n_ty_refs}; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_hir::{Closure, Expr, ExprKind, Mutability, Param, Pat, PatKind, Path, PathSegment, QPath}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, GenericArgKind}; -use rustc_span::sym; +use rustc_middle::ty::{self, GenericArgKind, Ty}; use rustc_span::symbol::Ident; +use rustc_span::{Span, sym}; use std::iter; +use std::ops::Not; use super::UNNECESSARY_SORT_BY; enum LintTrigger { - Sort(SortDetection), + Sort, SortByKey(SortByKeyDetection), } -struct SortDetection { - vec_name: String, -} - struct SortByKeyDetection { - vec_name: String, - closure_arg: String, + closure_arg: Span, closure_body: String, reverse: bool, + applicability: Applicability, } /// Detect if the two expressions are mirrored (identical, except one /// contains a and the other replaces it with b) -fn mirrored_exprs(a_expr: &Expr<'_>, a_ident: &Ident, b_expr: &Expr<'_>, b_ident: &Ident) -> bool { - match (&a_expr.kind, &b_expr.kind) { +fn mirrored_exprs( + a_expr: &Expr<'_>, + b_expr: &Expr<'_>, + binding_map: &BindingMap, + binding_source: BindingSource, +) -> bool { + match (a_expr.kind, b_expr.kind) { // Two arrays with mirrored contents - (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => { - iter::zip(*left_exprs, *right_exprs).all(|(left, right)| mirrored_exprs(left, a_ident, right, b_ident)) - }, + (ExprKind::Array(left_exprs), ExprKind::Array(right_exprs)) => iter::zip(left_exprs, right_exprs) + .all(|(left, right)| mirrored_exprs(left, right, binding_map, binding_source)), // The two exprs are function calls. // Check to see that the function itself and its arguments are mirrored (ExprKind::Call(left_expr, left_args), ExprKind::Call(right_expr, right_args)) => { - mirrored_exprs(left_expr, a_ident, right_expr, b_ident) - && iter::zip(*left_args, *right_args).all(|(left, right)| mirrored_exprs(left, a_ident, right, b_ident)) + mirrored_exprs(left_expr, right_expr, binding_map, binding_source) + && iter::zip(left_args, right_args) + .all(|(left, right)| mirrored_exprs(left, right, binding_map, binding_source)) }, // The two exprs are method calls. // Check to see that the function is the same and the arguments and receivers are mirrored @@ -50,116 +54,219 @@ fn mirrored_exprs(a_expr: &Expr<'_>, a_ident: &Ident, b_expr: &Expr<'_>, b_ident ExprKind::MethodCall(right_segment, right_receiver, right_args, _), ) => { left_segment.ident == right_segment.ident - && iter::zip(*left_args, *right_args).all(|(left, right)| mirrored_exprs(left, a_ident, right, b_ident)) - && mirrored_exprs(left_receiver, a_ident, right_receiver, b_ident) + && iter::zip(left_args, right_args) + .all(|(left, right)| mirrored_exprs(left, right, binding_map, binding_source)) + && mirrored_exprs(left_receiver, right_receiver, binding_map, binding_source) }, // Two tuples with mirrored contents - (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => { - iter::zip(*left_exprs, *right_exprs).all(|(left, right)| mirrored_exprs(left, a_ident, right, b_ident)) - }, + (ExprKind::Tup(left_exprs), ExprKind::Tup(right_exprs)) => iter::zip(left_exprs, right_exprs) + .all(|(left, right)| mirrored_exprs(left, right, binding_map, binding_source)), // Two binary ops, which are the same operation and which have mirrored arguments (ExprKind::Binary(left_op, left_left, left_right), ExprKind::Binary(right_op, right_left, right_right)) => { left_op.node == right_op.node - && mirrored_exprs(left_left, a_ident, right_left, b_ident) - && mirrored_exprs(left_right, a_ident, right_right, b_ident) + && mirrored_exprs(left_left, right_left, binding_map, binding_source) + && mirrored_exprs(left_right, right_right, binding_map, binding_source) }, // Two unary ops, which are the same operation and which have the same argument (ExprKind::Unary(left_op, left_expr), ExprKind::Unary(right_op, right_expr)) => { - left_op == right_op && mirrored_exprs(left_expr, a_ident, right_expr, b_ident) + left_op == right_op && mirrored_exprs(left_expr, right_expr, binding_map, binding_source) }, // The two exprs are literals of some kind (ExprKind::Lit(left_lit), ExprKind::Lit(right_lit)) => left_lit.node == right_lit.node, - (ExprKind::Cast(left, _), ExprKind::Cast(right, _)) => mirrored_exprs(left, a_ident, right, b_ident), + (ExprKind::Cast(left, _), ExprKind::Cast(right, _)) => mirrored_exprs(left, right, binding_map, binding_source), (ExprKind::DropTemps(left_block), ExprKind::DropTemps(right_block)) => { - mirrored_exprs(left_block, a_ident, right_block, b_ident) + mirrored_exprs(left_block, right_block, binding_map, binding_source) }, (ExprKind::Field(left_expr, left_ident), ExprKind::Field(right_expr, right_ident)) => { - left_ident.name == right_ident.name && mirrored_exprs(left_expr, a_ident, right_expr, right_ident) + left_ident.name == right_ident.name && mirrored_exprs(left_expr, right_expr, binding_map, binding_source) }, // Two paths: either one is a and the other is b, or they're identical to each other ( ExprKind::Path(QPath::Resolved( _, - Path { + &Path { segments: left_segments, .. }, )), ExprKind::Path(QPath::Resolved( _, - Path { + &Path { segments: right_segments, .. }, )), ) => { - (iter::zip(*left_segments, *right_segments).all(|(left, right)| left.ident == right.ident) - && left_segments - .iter() - .all(|seg| &seg.ident != a_ident && &seg.ident != b_ident)) + (iter::zip(left_segments, right_segments).all(|(left, right)| left.ident == right.ident) + && left_segments.iter().all(|seg| { + !binding_map.contains_key(&BindingKey { + ident: seg.ident, + source: BindingSource::Left, + }) && !binding_map.contains_key(&BindingKey { + ident: seg.ident, + source: BindingSource::Right, + }) + })) || (left_segments.len() == 1 - && &left_segments[0].ident == a_ident && right_segments.len() == 1 - && &right_segments[0].ident == b_ident) + && binding_map + .get(&BindingKey { + ident: left_segments[0].ident, + source: binding_source, + }) + .is_some_and(|value| value.mirrored.ident == right_segments[0].ident)) }, // Matching expressions, but one or both is borrowed ( ExprKind::AddrOf(left_kind, Mutability::Not, left_expr), ExprKind::AddrOf(right_kind, Mutability::Not, right_expr), - ) => left_kind == right_kind && mirrored_exprs(left_expr, a_ident, right_expr, b_ident), - (_, ExprKind::AddrOf(_, Mutability::Not, right_expr)) => mirrored_exprs(a_expr, a_ident, right_expr, b_ident), - (ExprKind::AddrOf(_, Mutability::Not, left_expr), _) => mirrored_exprs(left_expr, a_ident, b_expr, b_ident), + ) => left_kind == right_kind && mirrored_exprs(left_expr, right_expr, binding_map, binding_source), + (_, ExprKind::AddrOf(_, Mutability::Not, right_expr)) => { + mirrored_exprs(a_expr, right_expr, binding_map, binding_source) + }, + (ExprKind::AddrOf(_, Mutability::Not, left_expr), _) => { + mirrored_exprs(left_expr, b_expr, binding_map, binding_source) + }, _ => false, } } -fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) -> Option { +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +enum BindingSource { + Left, + Right, +} + +impl Not for BindingSource { + type Output = BindingSource; + + fn not(self) -> Self::Output { + match self { + BindingSource::Left => BindingSource::Right, + BindingSource::Right => BindingSource::Left, + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +struct BindingKey { + /// The identifier of the binding. + ident: Ident, + /// The source of the binding. + source: BindingSource, +} + +struct BindingValue { + /// The mirrored binding. + mirrored: BindingKey, + /// The number of refs the binding is wrapped in. + n_refs: usize, +} + +/// A map from binding info to the number of refs the binding is wrapped in. +type BindingMap = FxHashMap; +/// Extract the binding pairs, if the two patterns are mirrored. The pats are assumed to be used in +/// closure inputs and thus irrefutable. +fn mapping_of_mirrored_pats(a_pat: &Pat<'_>, b_pat: &Pat<'_>) -> Option { + fn mapping_of_mirrored_pats_inner( + a_pat: &Pat<'_>, + b_pat: &Pat<'_>, + mapping: &mut BindingMap, + n_refs: usize, + ) -> bool { + match (&a_pat.kind, &b_pat.kind) { + (PatKind::Tuple(a_pats, a_dots), PatKind::Tuple(b_pats, b_dots)) => { + a_dots == b_dots + && a_pats.len() == b_pats.len() + && iter::zip(a_pats.iter(), b_pats.iter()) + .all(|(a, b)| mapping_of_mirrored_pats_inner(a, b, mapping, n_refs)) + }, + (PatKind::Binding(_, _, a_ident, _), PatKind::Binding(_, _, b_ident, _)) => { + let a_key = BindingKey { + ident: *a_ident, + source: BindingSource::Left, + }; + let b_key = BindingKey { + ident: *b_ident, + source: BindingSource::Right, + }; + let a_value = BindingValue { + mirrored: b_key, + n_refs, + }; + let b_value = BindingValue { + mirrored: a_key, + n_refs, + }; + mapping.insert(a_key, a_value); + mapping.insert(b_key, b_value); + true + }, + (PatKind::Wild, PatKind::Wild) => true, + (PatKind::TupleStruct(_, a_pats, a_dots), PatKind::TupleStruct(_, b_pats, b_dots)) => { + a_dots == b_dots + && a_pats.len() == b_pats.len() + && iter::zip(a_pats.iter(), b_pats.iter()) + .all(|(a, b)| mapping_of_mirrored_pats_inner(a, b, mapping, n_refs)) + }, + (PatKind::Struct(_, a_fields, a_rest), PatKind::Struct(_, b_fields, b_rest)) => { + a_rest == b_rest + && a_fields.len() == b_fields.len() + && iter::zip(a_fields.iter(), b_fields.iter()).all(|(a_field, b_field)| { + a_field.ident == b_field.ident + && mapping_of_mirrored_pats_inner(a_field.pat, b_field.pat, mapping, n_refs) + }) + }, + (PatKind::Ref(a_inner, _, _), PatKind::Ref(b_inner, _, _)) => { + mapping_of_mirrored_pats_inner(a_inner, b_inner, mapping, n_refs + 1) + }, + (PatKind::Slice(a_elems, None, a_rest), PatKind::Slice(b_elems, None, b_rest)) => { + a_elems.len() == b_elems.len() + && iter::zip(a_elems.iter(), b_elems.iter()) + .all(|(a, b)| mapping_of_mirrored_pats_inner(a, b, mapping, n_refs)) + && a_rest.len() == b_rest.len() + && iter::zip(a_rest.iter(), b_rest.iter()) + .all(|(a, b)| mapping_of_mirrored_pats_inner(a, b, mapping, n_refs)) + }, + _ => false, + } + } + + let mut mapping = FxHashMap::default(); + if mapping_of_mirrored_pats_inner(a_pat, b_pat, &mut mapping, 0) { + return Some(mapping); + } + + None +} + +fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>) -> Option { if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) && let Some(impl_id) = cx.tcx.impl_of_assoc(method_id) && cx.tcx.type_of(impl_id).instantiate_identity().is_slice() && let ExprKind::Closure(&Closure { body, .. }) = arg.kind && let closure_body = cx.tcx.hir_body(body) - && let &[ - Param { - pat: - Pat { - kind: PatKind::Binding(_, _, left_ident, _), - .. - }, - .. - }, - Param { - pat: - Pat { - kind: PatKind::Binding(_, _, right_ident, _), - .. - }, - .. - }, - ] = &closure_body.params + && let &[Param { pat: l_pat, .. }, Param { pat: r_pat, .. }] = closure_body.params + && let Some(binding_map) = mapping_of_mirrored_pats(l_pat, r_pat) && let ExprKind::MethodCall(method_path, left_expr, [right_expr], _) = closure_body.value.kind && method_path.ident.name == sym::cmp - && cx - .ty_based_def(closure_body.value) - .opt_parent(cx) - .is_diag_item(cx, sym::Ord) + && let Some(ord_trait) = cx.tcx.get_diagnostic_item(sym::Ord) + && cx.ty_based_def(closure_body.value).opt_parent(cx).opt_def_id() == Some(ord_trait) { - let (closure_body, closure_arg, reverse) = if mirrored_exprs(left_expr, left_ident, right_expr, right_ident) { - ( - Sugg::hir(cx, left_expr, "..").to_string(), - left_ident.name.to_string(), - false, - ) - } else if mirrored_exprs(left_expr, right_ident, right_expr, left_ident) { - ( - Sugg::hir(cx, left_expr, "..").to_string(), - right_ident.name.to_string(), - true, - ) + let (closure_body, closure_arg, reverse) = + if mirrored_exprs(left_expr, right_expr, &binding_map, BindingSource::Left) { + (left_expr, l_pat.span, false) + } else if mirrored_exprs(left_expr, right_expr, &binding_map, BindingSource::Right) { + (left_expr, r_pat.span, true) + } else { + return None; + }; + + let mut applicability = if reverse { + Applicability::MaybeIncorrect } else { - return None; + Applicability::MachineApplicable }; - let vec_name = Sugg::hir(cx, recv, "..").to_string(); if let ExprKind::Path(QPath::Resolved( _, @@ -167,22 +274,53 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Exp segments: [PathSegment { ident: left_name, .. }], .. }, - )) = &left_expr.kind - && left_name == left_ident - && cx - .tcx - .get_diagnostic_item(sym::Ord) - .is_some_and(|id| implements_trait(cx, cx.typeck_results().expr_ty(left_expr), id, &[])) + )) = left_expr.kind { - return Some(LintTrigger::Sort(SortDetection { vec_name })); + if let PatKind::Binding(_, _, left_ident, _) = l_pat.kind + && *left_name == left_ident + && implements_trait(cx, cx.typeck_results().expr_ty(left_expr), ord_trait, &[]) + { + return Some(LintTrigger::Sort); + } + + let mut left_expr_ty = cx.typeck_results().expr_ty(left_expr); + let left_ident_n_refs = binding_map + .get(&BindingKey { + ident: *left_name, + source: BindingSource::Left, + }) + .map_or(0, |value| value.n_refs); + // Peel off the outer-most ref which is introduced by the closure, if it is not already peeled + // by the pattern + if left_ident_n_refs == 0 { + (left_expr_ty, _) = peel_n_ty_refs(left_expr_ty, 1); + } + if !reverse && is_copy(cx, left_expr_ty) { + let mut closure_body = + snippet_with_applicability(cx, closure_body.span, "_", &mut applicability).to_string(); + if left_ident_n_refs == 0 { + closure_body = format!("*{closure_body}"); + } + return Some(LintTrigger::SortByKey(SortByKeyDetection { + closure_arg, + closure_body, + reverse, + applicability, + })); + } } - if !expr_borrows(cx, left_expr) { + let left_expr_ty = cx.typeck_results().expr_ty(left_expr); + if !expr_borrows(left_expr_ty) + // Don't lint if the closure is accessing non-Copy fields + && (!expr_is_field_access(left_expr) || is_copy(cx, left_expr_ty)) + { + let closure_body = Sugg::hir_with_applicability(cx, closure_body, "_", &mut applicability).to_string(); return Some(LintTrigger::SortByKey(SortByKeyDetection { - vec_name, closure_arg, closure_body, reverse, + applicability, })); } } @@ -190,61 +328,75 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Exp None } -fn expr_borrows(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - let ty = cx.typeck_results().expr_ty(expr); +fn expr_borrows(ty: Ty<'_>) -> bool { matches!(ty.kind(), ty::Ref(..)) || ty.walk().any(|arg| matches!(arg.kind(), GenericArgKind::Lifetime(_))) } +fn expr_is_field_access(expr: &Expr<'_>) -> bool { + match expr.kind { + ExprKind::Field(_, _) => true, + ExprKind::AddrOf(_, Mutability::Not, inner) => expr_is_field_access(inner), + _ => false, + } +} + pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, - recv: &'tcx Expr<'_>, + call_span: Span, arg: &'tcx Expr<'_>, is_unstable: bool, ) { - match detect_lint(cx, expr, recv, arg) { + match detect_lint(cx, expr, arg) { Some(LintTrigger::SortByKey(trigger)) => { let method = if is_unstable { "sort_unstable_by_key" } else { "sort_by_key" }; - span_lint_and_sugg( + let Some(std_or_core) = std_or_core(cx) else { + // To make it this far the crate has to reference diagnostic items defined in core. Either this is + // the `core` crate, there's an `extern crate core` somewhere, or another crate is defining the + // diagnostic items. It's fine to not lint in all those cases even if we might be able to. + return; + }; + span_lint_and_then( cx, UNNECESSARY_SORT_BY, expr.span, format!("consider using `{method}`"), - "try", - format!( - "{}.{}(|{}| {})", - trigger.vec_name, - method, - trigger.closure_arg, - if let Some(std_or_core) = std_or_core(cx) - && trigger.reverse - { - format!("{}::cmp::Reverse({})", std_or_core, trigger.closure_body) + |diag| { + let mut app = trigger.applicability; + let closure_body = if trigger.reverse { + format!("{std_or_core}::cmp::Reverse({})", trigger.closure_body) } else { trigger.closure_body - }, - ), - if trigger.reverse { - Applicability::MaybeIncorrect - } else { - Applicability::MachineApplicable + }; + let closure_arg = snippet_with_applicability(cx, trigger.closure_arg, "_", &mut app); + diag.span_suggestion_verbose( + call_span, + "try", + format!("{method}(|{closure_arg}| {closure_body})"), + app, + ); }, ); }, - Some(LintTrigger::Sort(trigger)) => { + Some(LintTrigger::Sort) => { let method = if is_unstable { "sort_unstable" } else { "sort" }; - span_lint_and_sugg( + span_lint_and_then( cx, UNNECESSARY_SORT_BY, expr.span, format!("consider using `{method}`"), - "try", - format!("{}.{}()", trigger.vec_name, method), - Applicability::MachineApplicable, + |diag| { + diag.span_suggestion_verbose( + call_span, + "try", + format!("{method}()"), + Applicability::MachineApplicable, + ); + }, ); }, None => {}, diff --git a/clippy_lints/src/missing_trait_methods.rs b/clippy_lints/src/missing_trait_methods.rs index 8e9400e9d583..7a791f949943 100644 --- a/clippy_lints/src/missing_trait_methods.rs +++ b/clippy_lints/src/missing_trait_methods.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_lint_allowed; use clippy_utils::macros::span_is_local; +use clippy_utils::source::snippet_opt; use rustc_hir::def_id::DefIdSet; use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -84,7 +85,14 @@ impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods { cx.tcx.def_span(item.owner_id), format!("missing trait method provided by default: `{}`", assoc.name()), |diag| { - diag.span_help(cx.tcx.def_span(assoc.def_id), "implement the method"); + if assoc.def_id.is_local() { + diag.span_help(cx.tcx.def_span(assoc.def_id), "implement the method"); + } else if let Some(snippet) = snippet_opt(cx, of_trait.trait_ref.path.span) { + diag.help(format!( + "implement the missing `{}` method of the `{snippet}` trait", + assoc.name(), + )); + } }, ); } diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 55208ae708b9..d1d0d31ed91a 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -1,9 +1,9 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::higher; use clippy_utils::source::{indent_of, snippet_block, snippet_with_context}; use rustc_ast::Label; use rustc_errors::Applicability; -use rustc_hir::{Block, Expr, ExprKind, LoopSource, StmtKind}; +use rustc_hir::{Block, Expr, ExprKind, HirId, LoopSource, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::declare_lint_pass; use rustc_span::{ExpnKind, Span}; @@ -336,14 +336,9 @@ fn emit_warning(cx: &LateContext<'_>, data: &LintData<'_>, header: &str, typ: Li data.if_expr, ), }; - span_lint_and_help( - cx, - NEEDLESS_CONTINUE, - expr.span, - message, - None, - format!("{header}\n{snip}"), - ); + span_lint_hir_and_then(cx, NEEDLESS_CONTINUE, expr.hir_id, expr.span, message, |diag| { + diag.help(format!("{header}\n{snip}")); + }); } fn suggestion_snippet_for_continue_inside_if(cx: &LateContext<'_>, data: &LintData<'_>) -> String { @@ -424,11 +419,11 @@ fn suggestion_snippet_for_continue_inside_else(cx: &LateContext<'_>, data: &Lint fn check_last_stmt_in_expr(cx: &LateContext<'_>, inner_expr: &Expr<'_>, func: &F) where - F: Fn(Option<&Label>, Span), + F: Fn(HirId, Option<&Label>, Span), { match inner_expr.kind { ExprKind::Continue(continue_label) => { - func(continue_label.label.as_ref(), inner_expr.span); + func(inner_expr.hir_id, continue_label.label.as_ref(), inner_expr.span); }, ExprKind::If(_, then_block, else_block) if let ExprKind::Block(then_block, _) = then_block.kind => { check_last_stmt_in_block(cx, then_block, func); @@ -454,7 +449,7 @@ where fn check_last_stmt_in_block(cx: &LateContext<'_>, b: &Block<'_>, func: &F) where - F: Fn(Option<&Label>, Span), + F: Fn(HirId, Option<&Label>, Span), { if let Some(expr) = b.expr { check_last_stmt_in_expr(cx, expr, func); @@ -470,15 +465,17 @@ where fn check_and_warn(cx: &LateContext<'_>, expr: &Expr<'_>) { with_loop_block(expr, |loop_block, label| { - let p = |continue_label: Option<&Label>, span: Span| { + let p = |continue_hir_id, continue_label: Option<&Label>, span: Span| { if compare_labels(label, continue_label) { - span_lint_and_help( + span_lint_hir_and_then( cx, NEEDLESS_CONTINUE, + continue_hir_id, span, MSG_REDUNDANT_CONTINUE_EXPRESSION, - None, - DROP_CONTINUE_EXPRESSION_MSG, + |diag| { + diag.help(DROP_CONTINUE_EXPRESSION_MSG); + }, ); } }; diff --git a/clippy_lints/src/operators/arithmetic_side_effects.rs b/clippy_lints/src/operators/arithmetic_side_effects.rs index 91a069559f7b..106286d16d18 100644 --- a/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -33,7 +33,10 @@ impl ArithmeticSideEffects { allowed_binary.extend([ ("f32", FxHashSet::from_iter(["f32"])), ("f64", FxHashSet::from_iter(["f64"])), - ("std::string::String", FxHashSet::from_iter(["str"])), + ( + "std::string::String", + FxHashSet::from_iter(["str", "std::string::String"]), + ), ]); for (lhs, rhs) in &conf.arithmetic_side_effects_allowed_binary { allowed_binary.entry(lhs).or_default().insert(rhs); diff --git a/clippy_lints/src/operators/double_comparison.rs b/clippy_lints/src/operators/double_comparison.rs index 71982023779e..a40a724d2da5 100644 --- a/clippy_lints/src/operators/double_comparison.rs +++ b/clippy_lints/src/operators/double_comparison.rs @@ -39,6 +39,18 @@ pub(super) fn check(cx: &LateContext<'_>, op: BinOpKind, lhs: &Expr<'_>, rhs: &E | (BinOpKind::And, BinOpKind::Ge, BinOpKind::Le) => { "==" }, + // x != y && x >= y => x > y + (BinOpKind::And, BinOpKind::Ne, BinOpKind::Ge) + // x >= y && x != y => x > y + | (BinOpKind::And, BinOpKind::Ge, BinOpKind::Ne) => { + ">" + }, + // x != y && x <= y => x < y + (BinOpKind::And, BinOpKind::Ne, BinOpKind::Le) + // x <= y && x != y => x < y + | (BinOpKind::And, BinOpKind::Le, BinOpKind::Ne) => { + "<" + }, _ => return, }; diff --git a/clippy_lints/src/redundant_test_prefix.rs b/clippy_lints/src/redundant_test_prefix.rs index 84276e321657..602093259eae 100644 --- a/clippy_lints/src/redundant_test_prefix.rs +++ b/clippy_lints/src/redundant_test_prefix.rs @@ -47,6 +47,10 @@ declare_clippy_lint! { /// } /// } /// ``` + /// + /// ### Note + /// Clippy can only lint compiled code. For this lint to trigger, you must configure `cargo clippy` + /// to include test compilation, for instance, by using flags such as `--tests` or `--all-targets`. #[clippy::version = "1.88.0"] pub REDUNDANT_TEST_PREFIX, restriction, diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs index fabb21f78b9e..8557e8d18d10 100644 --- a/clippy_lints/src/significant_drop_tightening.rs +++ b/clippy_lints/src/significant_drop_tightening.rs @@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::MaybeResPath; use clippy_utils::source::{indent_of, snippet}; use clippy_utils::{expr_or_init, get_builtin_attr, peel_hir_expr_unary, sym}; +use rustc_ast::BindingMode; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -89,13 +90,14 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { |diag| { match apa.counter { 0 | 1 => {}, - 2 => { + 2 if let Some(last_method_span) = apa.last_method_span => { let indent = " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0)); let init_method = snippet(cx, apa.first_method_span, ".."); - let usage_method = snippet(cx, apa.last_method_span, ".."); - let stmt = if let Some(last_bind_ident) = apa.last_bind_ident { + let usage_method = snippet(cx, last_method_span, ".."); + let stmt = if let Some((binding_mode, last_bind_ident)) = apa.last_bind_ident { format!( - "\n{indent}let {} = {init_method}.{usage_method};", + "\n{indent}let {}{} = {init_method}.{usage_method};", + binding_mode.prefix_str(), snippet(cx, last_bind_ident.span, ".."), ) } else { @@ -310,13 +312,13 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> { }; match self.ap.curr_stmt.kind { hir::StmtKind::Let(local) => { - if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind { - apa.last_bind_ident = Some(ident); + if let hir::PatKind::Binding(binding_mode, _, ident, _) = local.pat.kind { + apa.last_bind_ident = Some((binding_mode, ident)); } if let Some(local_init) = local.init && let hir::ExprKind::MethodCall(_, _, _, span) = local_init.kind { - apa.last_method_span = span; + apa.last_method_span = Some(span); } }, hir::StmtKind::Semi(semi_expr) => { @@ -326,7 +328,7 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> { return; } if let hir::ExprKind::MethodCall(_, _, _, span) = semi_expr.kind { - apa.last_method_span = span; + apa.last_method_span = Some(span); } }, _ => {}, @@ -385,9 +387,9 @@ struct AuxParamsAttr { /// The last visited binding or variable span within a block that had any referenced inner type /// marked with `#[has_significant_drop]`. - last_bind_ident: Option, + last_bind_ident: Option<(BindingMode, Ident)>, /// Similar to `last_bind_span` but encompasses the right-hand method call. - last_method_span: Span, + last_method_span: Option, /// Similar to `last_bind_span` but encompasses the whole contained statement. last_stmt_span: Span, } @@ -403,7 +405,7 @@ impl Default for AuxParamsAttr { first_method_span: DUMMY_SP, first_stmt_span: DUMMY_SP, last_bind_ident: None, - last_method_span: DUMMY_SP, + last_method_span: None, last_stmt_span: DUMMY_SP, } } diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index b25fa0905feb..8524497c387c 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -150,7 +150,9 @@ impl SlowVectorInit { && func.ty_rel_def(cx).is_diag_item(cx, sym::vec_with_capacity) { Some(InitializedSize::Initialized(len_expr)) - } else if matches!(expr.kind, ExprKind::Call(func, []) if func.ty_rel_def(cx).is_diag_item(cx, sym::vec_new)) { + } else if let ExprKind::Call(func, []) = expr.kind + && func.ty_rel_def(cx).is_diag_item(cx, sym::vec_new) + { Some(InitializedSize::Uninitialized) } else { None diff --git a/clippy_lints/src/strlen_on_c_strings.rs b/clippy_lints/src/strlen_on_c_strings.rs index 0d50bd547652..962ab9cce14c 100644 --- a/clippy_lints/src/strlen_on_c_strings.rs +++ b/clippy_lints/src/strlen_on_c_strings.rs @@ -1,4 +1,6 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_config::Conf; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::MaybeDef; use clippy_utils::source::snippet_with_context; use clippy_utils::visitors::is_expr_unsafe; @@ -6,12 +8,12 @@ use clippy_utils::{match_libc_symbol, sym}; use rustc_errors::Applicability; use rustc_hir::{Block, BlockCheckMode, Expr, ExprKind, LangItem, Node, UnsafeSource}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::declare_lint_pass; +use rustc_session::impl_lint_pass; declare_clippy_lint! { /// ### What it does /// Checks for usage of `libc::strlen` on a `CString` or `CStr` value, - /// and suggest calling `as_bytes().len()` or `to_bytes().len()` respectively instead. + /// and suggest calling `count_bytes()` instead. /// /// ### Why is this bad? /// libc::strlen is an unsafe function, which we don't need to call @@ -27,15 +29,25 @@ declare_clippy_lint! { /// ```rust, no_run /// use std::ffi::CString; /// let cstring = CString::new("foo").expect("CString::new failed"); - /// let len = cstring.as_bytes().len(); + /// let len = cstring.count_bytes(); /// ``` #[clippy::version = "1.55.0"] pub STRLEN_ON_C_STRINGS, complexity, - "using `libc::strlen` on a `CString` or `CStr` value, while `as_bytes().len()` or `to_bytes().len()` respectively can be used instead" + "using `libc::strlen` on a `CString` or `CStr` value, while `count_bytes()` can be used instead" } -declare_lint_pass!(StrlenOnCStrings => [STRLEN_ON_C_STRINGS]); +pub struct StrlenOnCStrings { + msrv: Msrv, +} + +impl StrlenOnCStrings { + pub fn new(conf: &Conf) -> Self { + Self { msrv: conf.msrv } + } +} + +impl_lint_pass!(StrlenOnCStrings => [STRLEN_ON_C_STRINGS]); impl<'tcx> LateLintPass<'tcx> for StrlenOnCStrings { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { @@ -47,7 +59,21 @@ impl<'tcx> LateLintPass<'tcx> for StrlenOnCStrings { && let ExprKind::MethodCall(path, self_arg, [], _) = recv.kind && !recv.span.from_expansion() && path.ident.name == sym::as_ptr + && let typeck = cx.typeck_results() + && typeck + .expr_ty_adjusted(self_arg) + .peel_refs() + .is_lang_item(cx, LangItem::CStr) { + let ty = typeck.expr_ty(self_arg).peel_refs(); + let ty_kind = if ty.is_diag_item(cx, sym::cstring_type) { + "`CString` value" + } else if ty.is_lang_item(cx, LangItem::CStr) { + "`CStr` value" + } else { + "type that dereferences to `CStr`" + }; + let ctxt = expr.span.ctxt(); let span = match cx.tcx.parent_hir_node(expr.hir_id) { Node::Block(&Block { @@ -58,25 +84,23 @@ impl<'tcx> LateLintPass<'tcx> for StrlenOnCStrings { _ => expr.span, }; - let ty = cx.typeck_results().expr_ty(self_arg).peel_refs(); - let mut app = Applicability::MachineApplicable; - let val_name = snippet_with_context(cx, self_arg.span, ctxt, "..", &mut app).0; - let method_name = if ty.is_diag_item(cx, sym::cstring_type) { - "as_bytes" - } else if ty.is_lang_item(cx, LangItem::CStr) { - "to_bytes" - } else { - return; - }; - - span_lint_and_sugg( + span_lint_and_then( cx, STRLEN_ON_C_STRINGS, span, - "using `libc::strlen` on a `CString` or `CStr` value", - "try", - format!("{val_name}.{method_name}().len()"), - app, + format!("using `libc::strlen` on a {ty_kind}"), + |diag| { + let mut app = Applicability::MachineApplicable; + let val_name = snippet_with_context(cx, self_arg.span, ctxt, "_", &mut app).0; + + let suggestion = if self.msrv.meets(cx, msrvs::CSTR_COUNT_BYTES) { + format!("{val_name}.count_bytes()") + } else { + format!("{val_name}.to_bytes().len()") + }; + + diag.span_suggestion(span, "use", suggestion, app); + }, ); } } diff --git a/clippy_lints/src/transmute/transmuting_null.rs b/clippy_lints/src/transmute/transmuting_null.rs index 3f435f255d91..4f06d98703f6 100644 --- a/clippy_lints/src/transmute/transmuting_null.rs +++ b/clippy_lints/src/transmute/transmuting_null.rs @@ -42,6 +42,18 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t return true; } + // Catching: + // `std::mem::transmute(std::ptr::without_provenance::(0))` + // `std::mem::transmute(std::ptr::without_provenance_mut::(0))` + if let ExprKind::Call(func1, [arg1]) = arg.kind + && (func1.basic_res().is_diag_item(cx, sym::ptr_without_provenance) + || func1.basic_res().is_diag_item(cx, sym::ptr_without_provenance_mut)) + && is_integer_const(cx, arg1, 0) + { + span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG); + return true; + } + // Catching: // `std::mem::transmute({ 0 as *const u64 })` and similar const blocks if let ExprKind::Block(block, _) = arg.kind diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index 9d27a66a9ab8..1b26b1b32b80 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -115,6 +115,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { && !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, block.hir_id) && !is_unsafe_from_proc_macro(cx, block.span) && !block_has_safety_comment(cx, block.span, self.accept_comment_above_attributes) + && !block_has_inner_safety_comment(cx, block.span) && !block_parents_have_safety_comment( self.accept_comment_above_statement, self.accept_comment_above_attributes, @@ -839,6 +840,23 @@ fn text_has_safety_comment( } } } + // Check for a comment that appears after other code on the same line (e.g., `let x = // SAFETY:`) + // This handles cases in macros where the comment is on the same line as preceding code. + // We only check the first (immediate preceding) line for this pattern. + // Only whitespace is allowed between the comment marker and `SAFETY:`. + if let Some(comment_start) = [line.find("//"), line.find("/*")].into_iter().flatten().min() + && let after_marker = &line[comment_start + 2..] // skip marker + && let trimmed = after_marker.trim_start() // skip whitespace + && trimmed.get(..7).is_some_and(|s| s.eq_ignore_ascii_case("SAFETY:")) + { + let safety_offset = 2 + (after_marker.len() - trimmed.len()); + return HasSafetyComment::Yes( + start_pos + + BytePos(u32::try_from(line_start).unwrap()) + + BytePos(u32::try_from(comment_start + safety_offset).unwrap()), + false, + ); + } // No line comments; look for the start of a block comment. // This will only find them if they are at the start of a line. let (mut line_start, mut line) = (line_start, line); @@ -894,3 +912,20 @@ fn is_const_or_static(node: &Node<'_>) -> bool { }) ) } + +fn block_has_inner_safety_comment(cx: &LateContext<'_>, span: Span) -> bool { + let source_map = cx.sess().source_map(); + if let Ok(src) = source_map.span_to_snippet(span) + && let Some(after_brace) = src + .strip_prefix("unsafe") + .and_then(|s| s.trim_start().strip_prefix('{')) + && let Some(comment) = after_brace + .trim_start() + .strip_prefix("//") + .or_else(|| after_brace.trim_start().strip_prefix("/*")) + { + comment.trim_start().to_ascii_uppercase().starts_with("SAFETY:") + } else { + false + } +} diff --git a/clippy_lints/src/unnested_or_patterns.rs b/clippy_lints/src/unnested_or_patterns.rs index 975dd332ad06..12f8bd50e144 100644 --- a/clippy_lints/src/unnested_or_patterns.rs +++ b/clippy_lints/src/unnested_or_patterns.rs @@ -152,7 +152,12 @@ fn insert_necessary_parens(pat: &mut Pat) { walk_pat(self, pat); let target = match &mut pat.kind { // `i @ a | b`, `box a | b`, and `& mut? a | b`. - Ident(.., Some(p)) | Box(p) | Ref(p, _, _) if matches!(&p.kind, Or(ps) if ps.len() > 1) => p, + Ident(.., Some(p)) | Box(p) | Ref(p, _, _) + if let Or(ps) = &p.kind + && ps.len() > 1 => + { + p + }, // `&(mut x)` Ref(p, Pinnedness::Not, Mutability::Not) if matches!(p.kind, Ident(BindingMode::MUT, ..)) => p, _ => return, diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 423301edfe83..4ce132e9e3ab 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -365,7 +365,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { format!("useless conversion to the same type: `{b}`"), "consider removing `.into_iter()`", sugg, - Applicability::MachineApplicable, // snippet + applicability, ); } } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 8243077cab89..e6fadc783621 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -325,7 +325,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { ConstArgKind::Infer(..) => chain!(self, "let ConstArgKind::Infer(..) = {const_arg}.kind"), ConstArgKind::Error(..) => chain!(self, "let ConstArgKind::Error(..) = {const_arg}.kind"), ConstArgKind::Tup(..) => chain!(self, "let ConstArgKind::Tup(..) = {const_arg}.kind"), - ConstArgKind::Literal(..) => chain!(self, "let ConstArgKind::Literal(..) = {const_arg}.kind") + ConstArgKind::Literal(..) => chain!(self, "let ConstArgKind::Literal(..) = {const_arg}.kind"), } } diff --git a/clippy_lints_internal/src/collapsible_calls.rs b/clippy_lints_internal/src/collapsible_span_lint_calls.rs similarity index 66% rename from clippy_lints_internal/src/collapsible_calls.rs rename to clippy_lints_internal/src/collapsible_span_lint_calls.rs index 7c9e7286925e..b048a1004b0d 100644 --- a/clippy_lints_internal/src/collapsible_calls.rs +++ b/clippy_lints_internal/src/collapsible_span_lint_calls.rs @@ -1,11 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet; -use clippy_utils::{SpanlessEq, is_lint_allowed, peel_blocks_with_stmt}; +use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; +use clippy_utils::{SpanlessEq, is_lint_allowed, peel_blocks_with_stmt, sym}; use rustc_errors::Applicability; use rustc_hir::{Closure, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::Span; +use rustc_span::{Span, SyntaxContext}; use std::borrow::{Borrow, Cow}; @@ -88,33 +88,42 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls { && let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind && let ExprKind::Path(..) = recv.kind { - let and_then_snippets = - get_and_then_snippets(cx, call_cx.span, call_lint.span, call_sp.span, call_msg.span); + let mut app = Applicability::MachineApplicable; + let expr_ctxt = expr.span.ctxt(); + let and_then_snippets = get_and_then_snippets( + cx, + expr_ctxt, + call_cx.span, + call_lint.span, + call_sp.span, + call_msg.span, + &mut app, + ); let mut sle = SpanlessEq::new(cx).deny_side_effects(); - match ps.ident.as_str() { - "span_suggestion" if sle.eq_expr(call_sp, &span_call_args[0]) => { - suggest_suggestion( - cx, - expr, - &and_then_snippets, - &span_suggestion_snippets(cx, span_call_args), - ); + match ps.ident.name { + sym::span_suggestion if sle.eq_expr(call_sp, &span_call_args[0]) => { + let snippets = span_suggestion_snippets(cx, expr_ctxt, span_call_args, &mut app); + suggest_suggestion(cx, expr, &and_then_snippets, &snippets, app); }, - "span_help" if sle.eq_expr(call_sp, &span_call_args[0]) => { - let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#); - suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), true); + sym::span_help if sle.eq_expr(call_sp, &span_call_args[0]) => { + let help_snippet = + snippet_with_context(cx, span_call_args[1].span, expr_ctxt, r#""...""#, &mut app).0; + suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), true, app); }, - "span_note" if sle.eq_expr(call_sp, &span_call_args[0]) => { - let note_snippet = snippet(cx, span_call_args[1].span, r#""...""#); - suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), true); + sym::span_note if sle.eq_expr(call_sp, &span_call_args[0]) => { + let note_snippet = + snippet_with_context(cx, span_call_args[1].span, expr_ctxt, r#""...""#, &mut app).0; + suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), true, app); }, - "help" => { - let help_snippet = snippet(cx, span_call_args[0].span, r#""...""#); - suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), false); + sym::help => { + let help_snippet = + snippet_with_context(cx, span_call_args[0].span, expr_ctxt, r#""...""#, &mut app).0; + suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), false, app); }, - "note" => { - let note_snippet = snippet(cx, span_call_args[0].span, r#""...""#); - suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), false); + sym::note => { + let note_snippet = + snippet_with_context(cx, span_call_args[0].span, expr_ctxt, r#""...""#, &mut app).0; + suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), false, app); }, _ => (), } @@ -122,24 +131,26 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls { } } -struct AndThenSnippets<'a> { - cx: Cow<'a, str>, - lint: Cow<'a, str>, - span: Cow<'a, str>, - msg: Cow<'a, str>, +struct AndThenSnippets { + cx: Cow<'static, str>, + lint: Cow<'static, str>, + span: Cow<'static, str>, + msg: Cow<'static, str>, } fn get_and_then_snippets( cx: &LateContext<'_>, + expr_ctxt: SyntaxContext, cx_span: Span, lint_span: Span, span_span: Span, msg_span: Span, -) -> AndThenSnippets<'static> { - let cx_snippet = snippet(cx, cx_span, "cx"); - let lint_snippet = snippet(cx, lint_span, ".."); - let span_snippet = snippet(cx, span_span, "span"); - let msg_snippet = snippet(cx, msg_span, r#""...""#); + app: &mut Applicability, +) -> AndThenSnippets { + let cx_snippet = snippet_with_applicability(cx, cx_span, "cx", app); + let lint_snippet = snippet_with_applicability(cx, lint_span, "..", app); + let span_snippet = snippet_with_applicability(cx, span_span, "span", app); + let msg_snippet = snippet_with_context(cx, msg_span, expr_ctxt, r#""...""#, app).0; AndThenSnippets { cx: cx_snippet, @@ -149,19 +160,22 @@ fn get_and_then_snippets( } } -struct SpanSuggestionSnippets<'a> { - help: Cow<'a, str>, - sugg: Cow<'a, str>, - applicability: Cow<'a, str>, +struct SpanSuggestionSnippets { + help: Cow<'static, str>, + sugg: Cow<'static, str>, + applicability: Cow<'static, str>, } -fn span_suggestion_snippets<'a, 'hir>( +fn span_suggestion_snippets<'hir>( cx: &LateContext<'_>, + expr_ctxt: SyntaxContext, span_call_args: &'hir [Expr<'hir>], -) -> SpanSuggestionSnippets<'a> { - let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#); - let sugg_snippet = snippet(cx, span_call_args[2].span, ".."); - let applicability_snippet = snippet(cx, span_call_args[3].span, "Applicability::MachineApplicable"); + app: &mut Applicability, +) -> SpanSuggestionSnippets { + let help_snippet = snippet_with_context(cx, span_call_args[1].span, expr_ctxt, r#""...""#, app).0; + let sugg_snippet = snippet_with_context(cx, span_call_args[2].span, expr_ctxt, "..", app).0; + let applicability_snippet = + snippet_with_applicability(cx, span_call_args[3].span, "Applicability::MachineApplicable", app); SpanSuggestionSnippets { help: help_snippet, @@ -173,8 +187,9 @@ fn span_suggestion_snippets<'a, 'hir>( fn suggest_suggestion( cx: &LateContext<'_>, expr: &Expr<'_>, - and_then_snippets: &AndThenSnippets<'_>, - span_suggestion_snippets: &SpanSuggestionSnippets<'_>, + and_then_snippets: &AndThenSnippets, + span_suggestion_snippets: &SpanSuggestionSnippets, + app: Applicability, ) { span_lint_and_sugg( cx, @@ -192,16 +207,17 @@ fn suggest_suggestion( span_suggestion_snippets.sugg, span_suggestion_snippets.applicability ), - Applicability::MachineApplicable, + app, ); } fn suggest_help( cx: &LateContext<'_>, expr: &Expr<'_>, - and_then_snippets: &AndThenSnippets<'_>, + and_then_snippets: &AndThenSnippets, help: &str, with_span: bool, + app: Applicability, ) { let option_span = if with_span { format!("Some({})", and_then_snippets.span) @@ -219,16 +235,17 @@ fn suggest_help( "span_lint_and_help({}, {}, {}, {}, {}, {help})", and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg, &option_span, ), - Applicability::MachineApplicable, + app, ); } fn suggest_note( cx: &LateContext<'_>, expr: &Expr<'_>, - and_then_snippets: &AndThenSnippets<'_>, + and_then_snippets: &AndThenSnippets, note: &str, with_span: bool, + app: Applicability, ) { let note_span = if with_span { format!("Some({})", and_then_snippets.span) @@ -246,6 +263,6 @@ fn suggest_note( "span_lint_and_note({}, {}, {}, {}, {note_span}, {note})", and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg, ), - Applicability::MachineApplicable, + app, ); } diff --git a/clippy_lints_internal/src/lib.rs b/clippy_lints_internal/src/lib.rs index e009f263f11f..502d5cd3f340 100644 --- a/clippy_lints_internal/src/lib.rs +++ b/clippy_lints_internal/src/lib.rs @@ -2,7 +2,7 @@ #![allow( clippy::missing_docs_in_private_items, clippy::must_use_candidate, - clippy::symbol_as_str, + clippy::symbol_as_str )] #![warn( trivial_casts, @@ -29,7 +29,7 @@ extern crate rustc_session; extern crate rustc_span; mod almost_standard_lint_formulation; -mod collapsible_calls; +mod collapsible_span_lint_calls; mod derive_deserialize_allowing_unknown; mod internal_paths; mod lint_without_lint_pass; @@ -46,7 +46,7 @@ use rustc_lint::{Lint, LintStore}; static LINTS: &[&Lint] = &[ almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION, - collapsible_calls::COLLAPSIBLE_SPAN_LINT_CALLS, + collapsible_span_lint_calls::COLLAPSIBLE_SPAN_LINT_CALLS, derive_deserialize_allowing_unknown::DERIVE_DESERIALIZE_ALLOWING_UNKNOWN, lint_without_lint_pass::DEFAULT_LINT, lint_without_lint_pass::INVALID_CLIPPY_VERSION_ATTRIBUTE, @@ -67,7 +67,7 @@ pub fn register_lints(store: &mut LintStore) { store.register_early_pass(|| Box::new(unsorted_clippy_utils_paths::UnsortedClippyUtilsPaths)); store.register_early_pass(|| Box::new(produce_ice::ProduceIce)); - store.register_late_pass(|_| Box::new(collapsible_calls::CollapsibleCalls)); + store.register_late_pass(|_| Box::new(collapsible_span_lint_calls::CollapsibleCalls)); store.register_late_pass(|_| Box::new(derive_deserialize_allowing_unknown::DeriveDeserializeAllowingUnknown)); store.register_late_pass(|_| Box::::default()); store.register_late_pass(|_| Box::::default()); diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index 503d581d6c7f..b61b663d1026 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.94" +version = "0.1.95" edition = "2024" description = "Helpful tools for writing lints, provided as they are used in Clippy" repository = "https://github.com/rust-lang/rust-clippy" diff --git a/clippy_utils/README.md b/clippy_utils/README.md index ecd36b157571..204a66a435ee 100644 --- a/clippy_utils/README.md +++ b/clippy_utils/README.md @@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain: ``` -nightly-2026-01-08 +nightly-2026-01-22 ``` diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index 32f6cb4fd5e9..56490cfc8b65 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -159,7 +159,10 @@ impl LimitStack { } pub fn pop_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: Symbol) { let stack = &mut self.stack; - parse_attrs(sess, attrs, name, |val| debug_assert_eq!(stack.pop(), Some(val))); + parse_attrs(sess, attrs, name, |val| { + let popped = stack.pop(); + debug_assert_eq!(popped, Some(val)); + }); } } diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index c7bb3a064a09..b9f104a79a27 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -505,7 +505,7 @@ impl HirEqInterExpr<'_, '_, '_> { (ExprKind::Block(l, _), ExprKind::Block(r, _)) => self.eq_block(l, r), (ExprKind::Binary(l_op, ll, lr), ExprKind::Binary(r_op, rl, rr)) => { l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) - || swap_binop(l_op.node, ll, lr).is_some_and(|(l_op, ll, lr)| { + || swap_binop(self.inner.cx, l_op.node, ll, lr).is_some_and(|(l_op, ll, lr)| { l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) }) }, @@ -667,7 +667,7 @@ impl HirEqInterExpr<'_, '_, '_> { match (&left.kind, &right.kind) { (ConstArgKind::Tup(l_t), ConstArgKind::Tup(r_t)) => { - l_t.len() == r_t.len() && l_t.iter().zip(*r_t).all(|(l_c, r_c)| self.eq_const_arg(*l_c, *r_c)) + l_t.len() == r_t.len() && l_t.iter().zip(*r_t).all(|(l_c, r_c)| self.eq_const_arg(l_c, r_c)) }, (ConstArgKind::Path(l_p), ConstArgKind::Path(r_p)) => self.eq_qpath(l_p, r_p), (ConstArgKind::Anon(l_an), ConstArgKind::Anon(r_an)) => self.eq_body(l_an.body, r_an.body), @@ -689,9 +689,12 @@ impl HirEqInterExpr<'_, '_, '_> { (ConstArgKind::Literal(kind_l), ConstArgKind::Literal(kind_r)) => kind_l == kind_r, (ConstArgKind::Array(l_arr), ConstArgKind::Array(r_arr)) => { l_arr.elems.len() == r_arr.elems.len() - && l_arr.elems.iter().zip(r_arr.elems.iter()) - .all(|(l_elem, r_elem)| self.eq_const_arg(l_elem, r_elem)) - } + && l_arr + .elems + .iter() + .zip(r_arr.elems.iter()) + .all(|(l_elem, r_elem)| self.eq_const_arg(l_elem, r_elem)) + }, // Use explicit match for now since ConstArg is undergoing flux. ( ConstArgKind::Path(..) @@ -955,26 +958,35 @@ fn reduce_exprkind<'hir>(cx: &LateContext<'_>, kind: &'hir ExprKind<'hir>) -> &' } fn swap_binop<'a>( + cx: &LateContext<'_>, binop: BinOpKind, lhs: &'a Expr<'a>, rhs: &'a Expr<'a>, ) -> Option<(BinOpKind, &'a Expr<'a>, &'a Expr<'a>)> { match binop { - BinOpKind::Add | BinOpKind::Eq | BinOpKind::Ne | BinOpKind::BitAnd | BinOpKind::BitXor | BinOpKind::BitOr => { - Some((binop, rhs, lhs)) - }, + // `==` and `!=`, are commutative + BinOpKind::Eq | BinOpKind::Ne => Some((binop, rhs, lhs)), + // Comparisons can be reversed BinOpKind::Lt => Some((BinOpKind::Gt, rhs, lhs)), BinOpKind::Le => Some((BinOpKind::Ge, rhs, lhs)), BinOpKind::Ge => Some((BinOpKind::Le, rhs, lhs)), BinOpKind::Gt => Some((BinOpKind::Lt, rhs, lhs)), - BinOpKind::Mul // Not always commutative, e.g. with matrices. See issue #5698 - | BinOpKind::Shl - | BinOpKind::Shr - | BinOpKind::Rem - | BinOpKind::Sub - | BinOpKind::Div + // Non-commutative operators + BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Rem | BinOpKind::Sub | BinOpKind::Div => None, + // We know that those operators are commutative for primitive types, + // and we don't assume anything for other types + BinOpKind::Mul + | BinOpKind::Add | BinOpKind::And - | BinOpKind::Or => None, + | BinOpKind::Or + | BinOpKind::BitAnd + | BinOpKind::BitXor + | BinOpKind::BitOr => cx + .typeck_results() + .expr_ty_adjusted(lhs) + .peel_refs() + .is_primitive() + .then_some((binop, rhs, lhs)), } } @@ -1564,7 +1576,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { match &const_arg.kind { ConstArgKind::Tup(tup) => { for arg in *tup { - self.hash_const_arg(*arg); + self.hash_const_arg(arg); } }, ConstArgKind::Path(path) => self.hash_qpath(path), diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 7e3b1ccd224e..6b10f4b51442 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -6,11 +6,7 @@ #![feature(assert_matches)] #![feature(unwrap_infallible)] #![recursion_limit = "512"] -#![allow( - clippy::missing_errors_doc, - clippy::missing_panics_doc, - clippy::must_use_candidate, -)] +#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)] #![warn( trivial_casts, trivial_numeric_casts, @@ -2028,12 +2024,12 @@ pub fn is_expr_temporary_value(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { } pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> { - if !is_no_std_crate(cx) { - Some("std") - } else if !is_no_core_crate(cx) { + if is_no_core_crate(cx) { + None + } else if is_no_std_crate(cx) { Some("core") } else { - None + Some("std") } } diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 4a7fa3472cae..18fab6035f28 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -23,6 +23,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,91,0 { DURATION_FROM_MINUTES_HOURS } 1,88,0 { LET_CHAINS } 1,87,0 { OS_STR_DISPLAY, INT_MIDPOINT, CONST_CHAR_IS_DIGIT, UNSIGNED_IS_MULTIPLE_OF, INTEGER_SIGN_CAST } 1,85,0 { UINT_FLOAT_MIDPOINT, CONST_SIZE_OF_VAL } @@ -31,7 +32,7 @@ msrv_aliases! { 1,82,0 { IS_NONE_OR, REPEAT_N, RAW_REF_OP, SPECIALIZED_TO_STRING_FOR_REFS } 1,81,0 { LINT_REASONS_STABILIZATION, ERROR_IN_CORE, EXPLICIT_SELF_TYPE_ELISION, DURATION_ABS_DIFF } 1,80,0 { BOX_INTO_ITER, LAZY_CELL } - 1,79,0 { CONST_BLOCKS } + 1,79,0 { CONST_BLOCKS, CSTR_COUNT_BYTES } 1,77,0 { C_STR_LITERALS } 1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT } 1,75,0 { OPTION_AS_SLICE } @@ -61,7 +62,7 @@ msrv_aliases! { 1,45,0 { STR_STRIP_PREFIX } 1,43,0 { LOG2_10, LOG10_2, NUMERIC_ASSOCIATED_CONSTANTS } 1,42,0 { MATCHES_MACRO, SLICE_PATTERNS, PTR_SLICE_RAW_PARTS } - 1,41,0 { RE_REBALANCING_COHERENCE, RESULT_MAP_OR_ELSE } + 1,41,0 { RE_REBALANCING_COHERENCE, RESULT_MAP_OR, RESULT_MAP_OR_ELSE } 1,40,0 { MEM_TAKE, NON_EXHAUSTIVE, OPTION_AS_DEREF } 1,38,0 { POINTER_CAST, REM_EUCLID } 1,37,0 { TYPE_ALIAS_ENUM_VARIANTS } @@ -69,12 +70,12 @@ msrv_aliases! { 1,35,0 { OPTION_COPIED, RANGE_CONTAINS } 1,34,0 { TRY_FROM } 1,33,0 { UNDERSCORE_IMPORTS } - 1,32,0 { CONST_IS_POWER_OF_TWO } + 1,32,0 { CONST_IS_POWER_OF_TWO, CONST_DURATION_FROM_NANOS_MICROS_MILLIS_SECS } 1,31,0 { OPTION_REPLACE } 1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES } 1,29,0 { ITER_FLATTEN } 1,28,0 { FROM_BOOL, REPEAT_WITH, SLICE_FROM_REF } - 1,27,0 { ITERATOR_TRY_FOLD, DOUBLE_ENDED_ITERATOR_RFIND } + 1,27,0 { ITERATOR_TRY_FOLD, DOUBLE_ENDED_ITERATOR_RFIND, DURATION_FROM_NANOS_MICROS } 1,26,0 { RANGE_INCLUSIVE, STRING_RETAIN, POINTER_ADD_SUB_METHODS } 1,24,0 { IS_ASCII_DIGIT, PTR_NULL } 1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN } @@ -82,6 +83,7 @@ msrv_aliases! { 1,16,0 { STR_REPEAT, RESULT_UNWRAP_OR_DEFAULT } 1,15,0 { MAYBE_BOUND_IN_WHERE } 1,13,0 { QUESTION_MARK_OPERATOR } + 1,3,0 { DURATION_FROM_MILLIS_SECS } } /// `#[clippy::msrv]` attributes are rarely used outside of Clippy's test suite, as a basic diff --git a/clippy_utils/src/sym.rs b/clippy_utils/src/sym.rs index 94591a7ee30a..5d6f2241c7c0 100644 --- a/clippy_utils/src/sym.rs +++ b/clippy_utils/src/sym.rs @@ -139,6 +139,7 @@ generate! { disallowed_types, drain, dump, + duration_constructors, ends_with, enum_glob_use, enumerate, @@ -163,12 +164,20 @@ generate! { from_be_bytes, from_bytes_with_nul, from_bytes_with_nul_unchecked, + from_days, + from_hours, from_le_bytes, + from_micros, + from_millis, + from_mins, + from_nanos, from_ne_bytes, from_ptr, from_raw, from_raw_parts, + from_secs, from_str_radix, + from_weeks, fs, fuse, futures_util, @@ -179,6 +188,7 @@ generate! { get_unchecked, get_unchecked_mut, has_significant_drop, + help, hidden_glob_reexports, hygiene, ilog, @@ -271,6 +281,8 @@ generate! { powi, product, push, + push_back, + push_front, push_str, read, read_exact, @@ -325,7 +337,10 @@ generate! { sort, sort_by, sort_unstable_by, + span_help, span_lint_and_then, + span_note, + span_suggestion, split, split_at, split_at_checked, diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index c1be4acc7068..2f5f2f7d166f 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -438,6 +438,21 @@ pub fn peel_and_count_ty_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize, Option, n: usize) -> (Ty<'_>, Option) { + let mut mutbl = None; + for _ in 0..n { + if let ty::Ref(_, dest_ty, m) = ty.kind() { + ty = *dest_ty; + mutbl.replace(mutbl.map_or(*m, |mutbl: Mutability| mutbl.min(*m))); + } else { + break; + } + } + (ty, mutbl) +} + /// Checks whether `a` and `b` are same types having same `Const` generic args, but ignores /// lifetimes. /// @@ -815,7 +830,7 @@ impl AdtVariantInfo { .enumerate() .map(|(i, f)| (i, approx_ty_size(cx, f.ty(cx.tcx, subst)))) .collect::>(); - fields_size.sort_by(|(_, a_size), (_, b_size)| a_size.cmp(b_size)); + fields_size.sort_by_key(|(_, a_size)| *a_size); Self { ind: i, @@ -824,7 +839,7 @@ impl AdtVariantInfo { } }) .collect::>(); - variants_size.sort_by(|a, b| b.size.cmp(&a.size)); + variants_size.sort_by_key(|b| std::cmp::Reverse(b.size)); variants_size } } diff --git a/declare_clippy_lint/Cargo.toml b/declare_clippy_lint/Cargo.toml index ee6d6cdbc34e..39831e2b52d6 100644 --- a/declare_clippy_lint/Cargo.toml +++ b/declare_clippy_lint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "declare_clippy_lint" -version = "0.1.94" +version = "0.1.95" edition = "2024" repository = "https://github.com/rust-lang/rust-clippy" license = "MIT OR Apache-2.0" diff --git a/lintcheck/src/input.rs b/lintcheck/src/input.rs index 7dda2b7b25f8..ee3fcaa0a84a 100644 --- a/lintcheck/src/input.rs +++ b/lintcheck/src/input.rs @@ -281,8 +281,7 @@ impl CrateWithSource { CrateSource::Path { path } => { fn is_cache_dir(entry: &DirEntry) -> bool { fs::read(entry.path().join("CACHEDIR.TAG")) - .map(|x| x.starts_with(b"Signature: 8a477f597d28d172789f06886806bc55")) - .unwrap_or(false) + .is_ok_and(|x| x.starts_with(b"Signature: 8a477f597d28d172789f06886806bc55")) } // copy path into the dest_crate_root but skip directories that contain a CACHEDIR.TAG file. diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 0755e1d29c69..c26289c23725 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,6 +1,6 @@ [toolchain] # begin autogenerated nightly -channel = "nightly-2026-01-08" +channel = "nightly-2026-01-22" # end autogenerated nightly components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" diff --git a/src/driver.rs b/src/driver.rs index c9ca6335de6e..7425da70df90 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -30,11 +30,10 @@ use rustc_span::symbol::Symbol; use std::env; use std::fs::read_to_string; +use std::io::Write as _; use std::path::Path; use std::process::exit; -use anstream::println; - /// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If /// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`. fn arg_value<'a>(args: &'a [String], find_arg: &str, pred: impl Fn(&str) -> bool) -> Option<&'a str> { @@ -184,7 +183,9 @@ impl rustc_driver::Callbacks for ClippyCallbacks { } fn display_help() { - println!("{}", help_message()); + if writeln!(&mut anstream::stdout().lock(), "{}", help_message()).is_err() { + exit(rustc_driver::EXIT_FAILURE); + } } const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml"; @@ -251,8 +252,10 @@ pub fn main() { if orig_args.iter().any(|a| a == "--version" || a == "-V") { let version_info = rustc_tools_util::get_version_info!(); - println!("{version_info}"); - exit(0); + match writeln!(&mut anstream::stdout().lock(), "{version_info}") { + Ok(()) => exit(rustc_driver::EXIT_SUCCESS), + Err(_) => exit(rustc_driver::EXIT_FAILURE), + } } // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. diff --git a/src/main.rs b/src/main.rs index 688161c7bfcb..98b888444831 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,19 +4,24 @@ // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] -use std::env; -use std::path::PathBuf; -use std::process::{self, Command}; +extern crate rustc_driver; -use anstream::println; +use std::env; +use std::io::Write as _; +use std::path::PathBuf; +use std::process::{self, Command, exit}; fn show_help() { - println!("{}", help_message()); + if writeln!(&mut anstream::stdout().lock(), "{}", help_message()).is_err() { + exit(rustc_driver::EXIT_FAILURE); + } } fn show_version() { let version_info = rustc_tools_util::get_version_info!(); - println!("{version_info}"); + if writeln!(&mut anstream::stdout().lock(), "{version_info}").is_err() { + exit(rustc_driver::EXIT_FAILURE); + } } pub fn main() { diff --git a/tests/ui-internal/collapsible_span_lint_calls.fixed b/tests/ui-internal/collapsible_span_lint_calls.fixed index 76f68686ee2a..2b646a38b534 100644 --- a/tests/ui-internal/collapsible_span_lint_calls.fixed +++ b/tests/ui-internal/collapsible_span_lint_calls.fixed @@ -50,6 +50,15 @@ impl EarlyLintPass for Pass { span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { db.help(help_msg).help(help_msg); }); + + // Issue #15880 + #[expect(clippy::disallowed_names)] + let foo = "foo"; + span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, format!("try using {foo}"), format!("{foo}.use"), Applicability::MachineApplicable); + span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("try using {foo}")); + span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, format!("try using {foo}")); + span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("required because of {foo}")); + span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, format!("required because of {foo}")); } } diff --git a/tests/ui-internal/collapsible_span_lint_calls.rs b/tests/ui-internal/collapsible_span_lint_calls.rs index 214c8783a669..500552370053 100644 --- a/tests/ui-internal/collapsible_span_lint_calls.rs +++ b/tests/ui-internal/collapsible_span_lint_calls.rs @@ -65,6 +65,35 @@ impl EarlyLintPass for Pass { span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { db.help(help_msg).help(help_msg); }); + + // Issue #15880 + #[expect(clippy::disallowed_names)] + let foo = "foo"; + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls + db.span_suggestion( + expr.span, + format!("try using {foo}"), + format!("{foo}.use"), + Applicability::MachineApplicable, + ); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls + db.span_help(expr.span, format!("try using {foo}")); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls + db.help(format!("try using {foo}")); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls + db.span_note(expr.span, format!("required because of {foo}")); + }); + span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls + db.note(format!("required because of {foo}")); + }); } } diff --git a/tests/ui-internal/collapsible_span_lint_calls.stderr b/tests/ui-internal/collapsible_span_lint_calls.stderr index 9c83538947ca..76b453019270 100644 --- a/tests/ui-internal/collapsible_span_lint_calls.stderr +++ b/tests/ui-internal/collapsible_span_lint_calls.stderr @@ -49,5 +49,53 @@ LL | | db.note(note_msg); LL | | }); | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg)` -error: aborting due to 5 previous errors +error: this call is collapsible + --> tests/ui-internal/collapsible_span_lint_calls.rs:72:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | +LL | | db.span_suggestion( +LL | | expr.span, +... | +LL | | ); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, format!("try using {foo}"), format!("{foo}.use"), Applicability::MachineApplicable)` + +error: this call is collapsible + --> tests/ui-internal/collapsible_span_lint_calls.rs:81:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | +LL | | db.span_help(expr.span, format!("try using {foo}")); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("try using {foo}"))` + +error: this call is collapsible + --> tests/ui-internal/collapsible_span_lint_calls.rs:85:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | +LL | | db.help(format!("try using {foo}")); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, format!("try using {foo}"))` + +error: this call is collapsible + --> tests/ui-internal/collapsible_span_lint_calls.rs:89:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | +LL | | db.span_note(expr.span, format!("required because of {foo}")); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), format!("required because of {foo}"))` + +error: this call is collapsible + --> tests/ui-internal/collapsible_span_lint_calls.rs:93:9 + | +LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | +LL | | db.note(format!("required because of {foo}")); +LL | | }); + | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, format!("required because of {foo}"))` + +error: aborting due to 10 previous errors diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index 61e5af81d827..bcc46adda8a0 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -1,15 +1,39 @@ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:270:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:244:22 + | +LL | let _x = unsafe { 1 }; + | ^^^^^^^^^^^^ +... +LL | t!(); + | ---- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:256:13 + | +LL | unsafe { 1 }; + | ^^^^^^^^^^^^ +... +LL | t!(); + | ---- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:337:19 | LL | /* Safety: */ unsafe {} | ^^^^^^^^^ | = help: consider adding a safety comment on the preceding line - = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:275:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:342:5 | LL | unsafe {} | ^^^^^^^^^ @@ -17,7 +41,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -25,7 +49,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:29 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -33,7 +57,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:48 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -41,7 +65,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:18 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -49,7 +73,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:37 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -57,7 +81,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:293:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:360:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -65,7 +89,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:299:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:366:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -73,7 +97,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:306:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:373:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -81,7 +105,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:311:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:378:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -89,7 +113,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:316:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:383:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -97,7 +121,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:327:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:394:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -105,7 +129,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:334:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:401:13 | LL | unsafe {} | ^^^^^^^^^ @@ -117,7 +141,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:410:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -125,7 +149,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:349:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:416:5 | LL | unsafe { | ^^^^^^^^ @@ -133,7 +157,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:360:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:427:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -141,7 +165,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:365:20 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:432:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +173,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:373:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:440:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +181,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:381:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:448:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +189,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:470:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +201,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +213,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:439:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +221,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +233,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:446:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:513:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +241,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:493:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:560:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +249,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:498:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:565:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +257,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:503:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:570:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,13 +265,13 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: constant has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:508:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:575:5 | LL | const BIG_NUMBER: i32 = 1000000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:507:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:574:8 | LL | // SAFETY: | ^^^^^^^ @@ -255,7 +279,7 @@ LL | // SAFETY: = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:577:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +287,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:518:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:585:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +295,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:528:1 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:595:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +303,7 @@ LL | unsafe impl CrateRoot for () {} = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:543:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:610:5 | LL | / let _ = { LL | | @@ -289,13 +313,13 @@ LL | | }; | |______^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:542:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:609:8 | LL | // SAFETY: this is more than one level away, so it should warn | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:545:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:612:12 | LL | if unsafe { true } { | ^^^^^^^^^^^^^^^ @@ -303,7 +327,7 @@ LL | if unsafe { true } { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:549:23 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:616:23 | LL | let bar = unsafe {}; | ^^^^^^^^^ @@ -311,7 +335,7 @@ LL | let bar = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:638:52 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:705:52 | LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; | ^^^^^^^^^^^^ @@ -319,7 +343,7 @@ LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:647:41 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:714:41 | LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -327,7 +351,7 @@ LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:657:42 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:724:42 | LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; | ^^^^^^^^^^^^ @@ -335,7 +359,7 @@ LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:662:40 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:729:40 | LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -343,136 +367,136 @@ LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: constant has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:701:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:768:5 | LL | const UNIX_EPOCH_JULIAN_DAY: i32 = | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:699:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:766:8 | LL | // SAFETY: fail ONLY if `accept-comment-above-attribute = false` | ^^^^^^^ error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:721:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:788:5 | LL | _ = bar(); | ^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:720:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:787:8 | LL | // SAFETY: unnecessary_safety_comment triggers here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:741:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:808:5 | LL | mod x {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:740:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:807:8 | LL | // SAFETY: ... | ^^^^^^^ error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:746:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:813:5 | LL | mod y {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:744:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:811:8 | LL | // SAFETY: ... | ^^^^^^^ error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:751:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:818:5 | LL | mod z {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:750:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:817:8 | LL | // SAFETY: ... | ^^^^^^^ error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:759:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:826:5 | LL | mod y {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:757:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:824:8 | LL | // SAFETY: ... | ^^^^^^^ error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:774:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:841:9 | LL | let x = 34; | ^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:772:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:839:12 | LL | // SAFETY: ... | ^^^^^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:781:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:848:5 | LL | unsafe fn unsafe_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider changing the `safety` comment for a `# Safety` doc comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:780:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:847:8 | LL | // SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:787:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:854:5 | LL | unsafe fn unsafe_block_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider changing the `safety` comment for a `# Safety` doc comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:785:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:852:8 | LL | SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:791:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:858:5 | LL | fn safe_comment() {} | ^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:790:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:857:8 | LL | // SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:795:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:862:5 | LL | fn safe_doc_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:794:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:861:9 | LL | /// SAFETY: Bla | ^^^^^^^ -error: aborting due to 50 previous errors +error: aborting due to 52 previous errors diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index e252cffea916..0de8ed716bed 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -1,15 +1,39 @@ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:270:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:244:22 + | +LL | let _x = unsafe { 1 }; + | ^^^^^^^^^^^^ +... +LL | t!(); + | ---- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:256:13 + | +LL | unsafe { 1 }; + | ^^^^^^^^^^^^ +... +LL | t!(); + | ---- in this macro invocation + | + = help: consider adding a safety comment on the preceding line + = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:337:19 | LL | /* Safety: */ unsafe {} | ^^^^^^^^^ | = help: consider adding a safety comment on the preceding line - = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:275:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:342:5 | LL | unsafe {} | ^^^^^^^^^ @@ -17,7 +41,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:14 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -25,7 +49,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:29 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:29 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -33,7 +57,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:280:48 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:347:48 | LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; | ^^^^^^^^^^^^^ @@ -41,7 +65,7 @@ LL | let _ = [unsafe { 14 }, unsafe { 15 }, 42, unsafe { 16 }]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:18 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:18 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -49,7 +73,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:287:37 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:354:37 | LL | let _ = (42, unsafe {}, "test", unsafe {}); | ^^^^^^^^^ @@ -57,7 +81,7 @@ LL | let _ = (42, unsafe {}, "test", unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:293:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:360:14 | LL | let _ = *unsafe { &42 }; | ^^^^^^^^^^^^^^ @@ -65,7 +89,7 @@ LL | let _ = *unsafe { &42 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:299:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:366:19 | LL | let _ = match unsafe {} { | ^^^^^^^^^ @@ -73,7 +97,7 @@ LL | let _ = match unsafe {} { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:306:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:373:14 | LL | let _ = &unsafe {}; | ^^^^^^^^^ @@ -81,7 +105,7 @@ LL | let _ = &unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:311:14 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:378:14 | LL | let _ = [unsafe {}; 5]; | ^^^^^^^^^ @@ -89,7 +113,7 @@ LL | let _ = [unsafe {}; 5]; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:316:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:383:13 | LL | let _ = unsafe {}; | ^^^^^^^^^ @@ -97,7 +121,7 @@ LL | let _ = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:327:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:394:8 | LL | t!(unsafe {}); | ^^^^^^^^^ @@ -105,7 +129,7 @@ LL | t!(unsafe {}); = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:334:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:401:13 | LL | unsafe {} | ^^^^^^^^^ @@ -117,7 +141,7 @@ LL | t!(); = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:343:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:410:5 | LL | unsafe {} // SAFETY: | ^^^^^^^^^ @@ -125,7 +149,7 @@ LL | unsafe {} // SAFETY: = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:349:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:416:5 | LL | unsafe { | ^^^^^^^^ @@ -133,7 +157,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:360:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:427:5 | LL | unsafe {}; | ^^^^^^^^^ @@ -141,7 +165,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:365:20 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:432:20 | LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,7 +173,7 @@ LL | println!("{}", unsafe { String::from_utf8_unchecked(vec![]) }); = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:373:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:440:5 | LL | unsafe impl A for () {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +181,7 @@ LL | unsafe impl A for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:381:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:448:9 | LL | unsafe impl B for (u32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +189,7 @@ LL | unsafe impl B for (u32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:403:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:470:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +201,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -189,7 +213,7 @@ LL | no_safety_comment!(()); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:439:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:5 | LL | unsafe impl T for (i32) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +221,7 @@ LL | unsafe impl T for (i32) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:429:13 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +233,7 @@ LL | no_safety_comment!(u32); = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:446:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:513:5 | LL | unsafe impl T for (bool) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +241,7 @@ LL | unsafe impl T for (bool) {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:493:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:560:5 | LL | unsafe impl NoComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +249,7 @@ LL | unsafe impl NoComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:498:19 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:565:19 | LL | /* SAFETY: */ unsafe impl InlineComment for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +257,7 @@ LL | /* SAFETY: */ unsafe impl InlineComment for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:503:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:570:5 | LL | unsafe impl TrailingComment for () {} // SAFETY: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,13 +265,13 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: = help: consider adding a safety comment on the preceding line error: constant has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:508:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:575:5 | LL | const BIG_NUMBER: i32 = 1000000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:507:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:574:8 | LL | // SAFETY: | ^^^^^^^ @@ -255,7 +279,7 @@ LL | // SAFETY: = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:510:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:577:5 | LL | unsafe impl Interference for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +287,7 @@ LL | unsafe impl Interference for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:518:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:585:5 | LL | unsafe impl ImplInFn for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -271,7 +295,7 @@ LL | unsafe impl ImplInFn for () {} = help: consider adding a safety comment on the preceding line error: unsafe impl missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:528:1 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:595:1 | LL | unsafe impl CrateRoot for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +303,7 @@ LL | unsafe impl CrateRoot for () {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:539:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:606:9 | LL | unsafe {}; | ^^^^^^^^^ @@ -287,7 +311,7 @@ LL | unsafe {}; = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:543:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:610:5 | LL | / let _ = { LL | | @@ -297,13 +321,13 @@ LL | | }; | |______^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:542:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:609:8 | LL | // SAFETY: this is more than one level away, so it should warn | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:545:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:612:12 | LL | if unsafe { true } { | ^^^^^^^^^^^^^^^ @@ -311,7 +335,7 @@ LL | if unsafe { true } { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:549:23 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:616:23 | LL | let bar = unsafe {}; | ^^^^^^^^^ @@ -319,7 +343,7 @@ LL | let bar = unsafe {}; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:568:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:635:9 | LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -327,7 +351,7 @@ LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:573:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:640:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -335,7 +359,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:578:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:645:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -343,7 +367,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:585:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:652:5 | LL | unsafe {} | ^^^^^^^^^ @@ -351,7 +375,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:590:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:657:5 | LL | unsafe { | ^^^^^^^^ @@ -359,7 +383,7 @@ LL | unsafe { = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:598:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:665:9 | LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -367,7 +391,7 @@ LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:604:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:671:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -375,7 +399,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:611:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:678:9 | LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -383,7 +407,7 @@ LL | unsafe { a_const_function_with_a_very_long_name_to_break_the_line() = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:617:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:684:5 | LL | unsafe {} | ^^^^^^^^^ @@ -391,7 +415,7 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:638:52 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:705:52 | LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; | ^^^^^^^^^^^^ @@ -399,7 +423,7 @@ LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:647:41 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:714:41 | LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -407,7 +431,7 @@ LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:657:42 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:724:42 | LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; | ^^^^^^^^^^^^ @@ -415,7 +439,7 @@ LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:662:40 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:729:40 | LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; | ^^^^^^^^^^^^ @@ -423,7 +447,7 @@ LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:673:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:740:9 | LL | unsafe { here_is_another_variable_with_long_name }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -431,7 +455,7 @@ LL | unsafe { here_is_another_variable_with_long_name }; = help: consider adding a safety comment on the preceding line error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:702:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:769:9 | LL | unsafe { Date::__from_ordinal_date_unchecked(1970, 1) }.into_julian_day_just_make_this_line_longer(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -439,19 +463,19 @@ LL | unsafe { Date::__from_ordinal_date_unchecked(1970, 1) }.into_julian = help: consider adding a safety comment on the preceding line error: statement has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:721:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:788:5 | LL | _ = bar(); | ^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:720:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:787:8 | LL | // SAFETY: unnecessary_safety_comment triggers here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:735:12 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:802:12 | LL | return unsafe { h() }; | ^^^^^^^^^^^^^^ @@ -459,31 +483,31 @@ LL | return unsafe { h() }; = help: consider adding a safety comment on the preceding line error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:741:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:808:5 | LL | mod x {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:740:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:807:8 | LL | // SAFETY: ... | ^^^^^^^ error: module has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:751:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:818:5 | LL | mod z {} | ^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:750:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:817:8 | LL | // SAFETY: ... | ^^^^^^^ error: unsafe block missing a safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:766:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:833:9 | LL | unsafe {} | ^^^^^^^^^ @@ -491,52 +515,52 @@ LL | unsafe {} = help: consider adding a safety comment on the preceding line error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:781:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:848:5 | LL | unsafe fn unsafe_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider changing the `safety` comment for a `# Safety` doc comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:780:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:847:8 | LL | // SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:787:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:854:5 | LL | unsafe fn unsafe_block_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider changing the `safety` comment for a `# Safety` doc comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:785:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:852:8 | LL | SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:791:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:858:5 | LL | fn safe_comment() {} | ^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:790:8 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:857:8 | LL | // SAFETY: Bla | ^^^^^^^ error: function has unnecessary safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:795:5 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:862:5 | LL | fn safe_doc_comment() {} | ^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider removing the safety comment - --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:794:9 + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:861:9 | LL | /// SAFETY: Bla | ^^^^^^^ -error: aborting due to 60 previous errors +error: aborting due to 62 previous errors diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index db9e81cf10a1..8032c388ccfe 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -201,6 +201,66 @@ fn comment_macro_def() { t!(); } +fn comment_macro_def_with_let() { + macro_rules! t { + () => { + let _x = + // SAFETY: here be exactly one dragon + unsafe { 1 }; + }; + } + + t!(); +} + +#[rustfmt::skip] +fn comment_macro_def_with_let_same_line() { + macro_rules! t { + () => { + let _x =// SAFETY: same line comment + unsafe { 1 }; + }; + } + + t!(); +} + +fn inner_comment_macro_def_with_let() { + macro_rules! t { + () => { + let _x = unsafe { + // SAFETY: inside the block + 1 + }; + }; + } + + t!(); +} + +fn no_comment_macro_def_with_let() { + macro_rules! t { + () => { + let _x = unsafe { 1 }; + //~^ undocumented_unsafe_blocks + }; + } + + t!(); +} + +fn prefixed_safety_comment_macro_def_with_let() { + macro_rules! t { + () => { + let _x =// not a SAFETY: comment, should lint + unsafe { 1 }; + //~^ undocumented_unsafe_blocks + }; + } + + t!(); +} + fn non_ascii_comment() { // ॐ᧻໒ SaFeTy: ௵∰ unsafe {}; @@ -263,6 +323,13 @@ fn in_closure(x: *const u32) { let _ = || unsafe { *x }; } +fn inner_block_comment_block_style(x: *const u32) { + let _ = unsafe { + /* SAFETY: block comment inside */ + *x + }; +} + // Invalid comments #[rustfmt::skip] diff --git a/tests/ui/arithmetic_side_effects.rs b/tests/ui/arithmetic_side_effects.rs index b7ed596d811e..87397a549bf4 100644 --- a/tests/ui/arithmetic_side_effects.rs +++ b/tests/ui/arithmetic_side_effects.rs @@ -174,7 +174,6 @@ pub fn hard_coded_allowed() { let _ = Saturating(0u32) + Saturating(0u32); let _ = String::new() + ""; let _ = String::new() + &String::new(); - //~^ arithmetic_side_effects let _ = Wrapping(0u32) + Wrapping(0u32); let saturating: Saturating = Saturating(0u32); diff --git a/tests/ui/arithmetic_side_effects.stderr b/tests/ui/arithmetic_side_effects.stderr index 22742a82601a..2767a051786e 100644 --- a/tests/ui/arithmetic_side_effects.stderr +++ b/tests/ui/arithmetic_side_effects.stderr @@ -14,784 +14,778 @@ LL | let _ = 1f128 + 1f128; | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:176:13 - | -LL | let _ = String::new() + &String::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:312:5 + --> tests/ui/arithmetic_side_effects.rs:311:5 | LL | _n += 1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:314:5 + --> tests/ui/arithmetic_side_effects.rs:313:5 | LL | _n += &1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:316:5 + --> tests/ui/arithmetic_side_effects.rs:315:5 | LL | _n -= 1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:318:5 + --> tests/ui/arithmetic_side_effects.rs:317:5 | LL | _n -= &1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:320:5 + --> tests/ui/arithmetic_side_effects.rs:319:5 | LL | _n /= 0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:322:5 + --> tests/ui/arithmetic_side_effects.rs:321:5 | LL | _n /= &0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:324:5 + --> tests/ui/arithmetic_side_effects.rs:323:5 | LL | _n %= 0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:326:5 + --> tests/ui/arithmetic_side_effects.rs:325:5 | LL | _n %= &0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:328:5 + --> tests/ui/arithmetic_side_effects.rs:327:5 | LL | _n *= 2; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:330:5 + --> tests/ui/arithmetic_side_effects.rs:329:5 | LL | _n *= &2; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:332:5 + --> tests/ui/arithmetic_side_effects.rs:331:5 | LL | _n += -1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:334:5 + --> tests/ui/arithmetic_side_effects.rs:333:5 | LL | _n += &-1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:336:5 + --> tests/ui/arithmetic_side_effects.rs:335:5 | LL | _n -= -1; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:338:5 + --> tests/ui/arithmetic_side_effects.rs:337:5 | LL | _n -= &-1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:340:5 + --> tests/ui/arithmetic_side_effects.rs:339:5 | LL | _n /= -0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:342:5 + --> tests/ui/arithmetic_side_effects.rs:341:5 | LL | _n /= &-0; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:344:5 + --> tests/ui/arithmetic_side_effects.rs:343:5 | LL | _n %= -0; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:346:5 + --> tests/ui/arithmetic_side_effects.rs:345:5 | LL | _n %= &-0; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:348:5 + --> tests/ui/arithmetic_side_effects.rs:347:5 | LL | _n *= -2; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:350:5 + --> tests/ui/arithmetic_side_effects.rs:349:5 | LL | _n *= &-2; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:352:5 + --> tests/ui/arithmetic_side_effects.rs:351:5 | LL | _custom += Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:354:5 + --> tests/ui/arithmetic_side_effects.rs:353:5 | LL | _custom += &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:356:5 + --> tests/ui/arithmetic_side_effects.rs:355:5 | LL | _custom -= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:358:5 + --> tests/ui/arithmetic_side_effects.rs:357:5 | LL | _custom -= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:360:5 + --> tests/ui/arithmetic_side_effects.rs:359:5 | LL | _custom /= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:362:5 + --> tests/ui/arithmetic_side_effects.rs:361:5 | LL | _custom /= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:364:5 + --> tests/ui/arithmetic_side_effects.rs:363:5 | LL | _custom %= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:366:5 + --> tests/ui/arithmetic_side_effects.rs:365:5 | LL | _custom %= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:368:5 + --> tests/ui/arithmetic_side_effects.rs:367:5 | LL | _custom *= Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:370:5 + --> tests/ui/arithmetic_side_effects.rs:369:5 | LL | _custom *= &Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:372:5 + --> tests/ui/arithmetic_side_effects.rs:371:5 | LL | _custom >>= Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:374:5 + --> tests/ui/arithmetic_side_effects.rs:373:5 | LL | _custom >>= &Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:376:5 + --> tests/ui/arithmetic_side_effects.rs:375:5 | LL | _custom <<= Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:378:5 + --> tests/ui/arithmetic_side_effects.rs:377:5 | LL | _custom <<= &Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:380:5 + --> tests/ui/arithmetic_side_effects.rs:379:5 | LL | _custom += -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:382:5 + --> tests/ui/arithmetic_side_effects.rs:381:5 | LL | _custom += &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:384:5 + --> tests/ui/arithmetic_side_effects.rs:383:5 | LL | _custom -= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:386:5 + --> tests/ui/arithmetic_side_effects.rs:385:5 | LL | _custom -= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:388:5 + --> tests/ui/arithmetic_side_effects.rs:387:5 | LL | _custom /= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:390:5 + --> tests/ui/arithmetic_side_effects.rs:389:5 | LL | _custom /= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:392:5 + --> tests/ui/arithmetic_side_effects.rs:391:5 | LL | _custom %= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:394:5 + --> tests/ui/arithmetic_side_effects.rs:393:5 | LL | _custom %= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:396:5 + --> tests/ui/arithmetic_side_effects.rs:395:5 | LL | _custom *= -Custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:398:5 + --> tests/ui/arithmetic_side_effects.rs:397:5 | LL | _custom *= &-Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:400:5 + --> tests/ui/arithmetic_side_effects.rs:399:5 | LL | _custom >>= -Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:402:5 + --> tests/ui/arithmetic_side_effects.rs:401:5 | LL | _custom >>= &-Custom; | ^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:404:5 + --> tests/ui/arithmetic_side_effects.rs:403:5 | LL | _custom <<= -Custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:406:5 + --> tests/ui/arithmetic_side_effects.rs:405:5 | LL | _custom <<= &-Custom; | ^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:410:10 + --> tests/ui/arithmetic_side_effects.rs:409:10 | LL | _n = _n + 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:412:10 + --> tests/ui/arithmetic_side_effects.rs:411:10 | LL | _n = _n + &1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:414:10 + --> tests/ui/arithmetic_side_effects.rs:413:10 | LL | _n = 1 + _n; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:416:10 + --> tests/ui/arithmetic_side_effects.rs:415:10 | LL | _n = &1 + _n; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:418:10 + --> tests/ui/arithmetic_side_effects.rs:417:10 | LL | _n = _n - 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:420:10 + --> tests/ui/arithmetic_side_effects.rs:419:10 | LL | _n = _n - &1; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:422:10 + --> tests/ui/arithmetic_side_effects.rs:421:10 | LL | _n = 1 - _n; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:424:10 + --> tests/ui/arithmetic_side_effects.rs:423:10 | LL | _n = &1 - _n; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:426:10 + --> tests/ui/arithmetic_side_effects.rs:425:10 | LL | _n = _n / 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:428:10 + --> tests/ui/arithmetic_side_effects.rs:427:10 | LL | _n = _n / &0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:430:10 + --> tests/ui/arithmetic_side_effects.rs:429:10 | LL | _n = _n % 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:432:10 + --> tests/ui/arithmetic_side_effects.rs:431:10 | LL | _n = _n % &0; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:434:10 + --> tests/ui/arithmetic_side_effects.rs:433:10 | LL | _n = _n * 2; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:436:10 + --> tests/ui/arithmetic_side_effects.rs:435:10 | LL | _n = _n * &2; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:438:10 + --> tests/ui/arithmetic_side_effects.rs:437:10 | LL | _n = 2 * _n; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:440:10 + --> tests/ui/arithmetic_side_effects.rs:439:10 | LL | _n = &2 * _n; | ^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:442:10 + --> tests/ui/arithmetic_side_effects.rs:441:10 | LL | _n = 23 + &85; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:444:10 + --> tests/ui/arithmetic_side_effects.rs:443:10 | LL | _n = &23 + 85; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:446:10 + --> tests/ui/arithmetic_side_effects.rs:445:10 | LL | _n = &23 + &85; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:448:15 + --> tests/ui/arithmetic_side_effects.rs:447:15 | LL | _custom = _custom + _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:450:15 + --> tests/ui/arithmetic_side_effects.rs:449:15 | LL | _custom = _custom + &_custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:452:15 + --> tests/ui/arithmetic_side_effects.rs:451:15 | LL | _custom = Custom + _custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:454:15 + --> tests/ui/arithmetic_side_effects.rs:453:15 | LL | _custom = &Custom + _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:456:15 + --> tests/ui/arithmetic_side_effects.rs:455:15 | LL | _custom = _custom - Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:458:15 + --> tests/ui/arithmetic_side_effects.rs:457:15 | LL | _custom = _custom - &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:460:15 + --> tests/ui/arithmetic_side_effects.rs:459:15 | LL | _custom = Custom - _custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:462:15 + --> tests/ui/arithmetic_side_effects.rs:461:15 | LL | _custom = &Custom - _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:464:15 + --> tests/ui/arithmetic_side_effects.rs:463:15 | LL | _custom = _custom / Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:466:15 + --> tests/ui/arithmetic_side_effects.rs:465:15 | LL | _custom = _custom / &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:468:15 + --> tests/ui/arithmetic_side_effects.rs:467:15 | LL | _custom = _custom % Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:470:15 + --> tests/ui/arithmetic_side_effects.rs:469:15 | LL | _custom = _custom % &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:472:15 + --> tests/ui/arithmetic_side_effects.rs:471:15 | LL | _custom = _custom * Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:474:15 + --> tests/ui/arithmetic_side_effects.rs:473:15 | LL | _custom = _custom * &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:476:15 + --> tests/ui/arithmetic_side_effects.rs:475:15 | LL | _custom = Custom * _custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:478:15 + --> tests/ui/arithmetic_side_effects.rs:477:15 | LL | _custom = &Custom * _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:480:15 + --> tests/ui/arithmetic_side_effects.rs:479:15 | LL | _custom = Custom + &Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:482:15 + --> tests/ui/arithmetic_side_effects.rs:481:15 | LL | _custom = &Custom + Custom; | ^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:484:15 + --> tests/ui/arithmetic_side_effects.rs:483:15 | LL | _custom = &Custom + &Custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:486:15 + --> tests/ui/arithmetic_side_effects.rs:485:15 | LL | _custom = _custom >> _custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:488:15 + --> tests/ui/arithmetic_side_effects.rs:487:15 | LL | _custom = _custom >> &_custom; | ^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:490:15 + --> tests/ui/arithmetic_side_effects.rs:489:15 | LL | _custom = Custom << _custom; | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:492:15 + --> tests/ui/arithmetic_side_effects.rs:491:15 | LL | _custom = &Custom << _custom; | ^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:496:23 + --> tests/ui/arithmetic_side_effects.rs:495:23 | LL | _n.saturating_div(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:498:21 + --> tests/ui/arithmetic_side_effects.rs:497:21 | LL | _n.wrapping_div(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:500:21 + --> tests/ui/arithmetic_side_effects.rs:499:21 | LL | _n.wrapping_rem(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:502:28 + --> tests/ui/arithmetic_side_effects.rs:501:28 | LL | _n.wrapping_rem_euclid(0); | ^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:505:23 + --> tests/ui/arithmetic_side_effects.rs:504:23 | LL | _n.saturating_div(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:507:21 + --> tests/ui/arithmetic_side_effects.rs:506:21 | LL | _n.wrapping_div(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:509:21 + --> tests/ui/arithmetic_side_effects.rs:508:21 | LL | _n.wrapping_rem(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:511:28 + --> tests/ui/arithmetic_side_effects.rs:510:28 | LL | _n.wrapping_rem_euclid(_n); | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:514:23 + --> tests/ui/arithmetic_side_effects.rs:513:23 | LL | _n.saturating_div(*Box::new(_n)); | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:518:10 + --> tests/ui/arithmetic_side_effects.rs:517:10 | LL | _n = -_n; | ^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:520:10 + --> tests/ui/arithmetic_side_effects.rs:519:10 | LL | _n = -&_n; | ^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:522:15 + --> tests/ui/arithmetic_side_effects.rs:521:15 | LL | _custom = -_custom; | ^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:524:15 + --> tests/ui/arithmetic_side_effects.rs:523:15 | LL | _custom = -&_custom; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:526:9 + --> tests/ui/arithmetic_side_effects.rs:525:9 | LL | _ = -*Box::new(_n); | ^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:536:5 + --> tests/ui/arithmetic_side_effects.rs:535:5 | LL | 1 + i; | ^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:538:5 + --> tests/ui/arithmetic_side_effects.rs:537:5 | LL | i * 2; | ^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:540:5 + --> tests/ui/arithmetic_side_effects.rs:539:5 | LL | 1 % i / 2; | ^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:542:5 + --> tests/ui/arithmetic_side_effects.rs:541:5 | LL | i - 2 + 2 - i; | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:544:5 + --> tests/ui/arithmetic_side_effects.rs:543:5 | LL | -i; | ^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:556:5 + --> tests/ui/arithmetic_side_effects.rs:555:5 | LL | i += 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:558:5 + --> tests/ui/arithmetic_side_effects.rs:557:5 | LL | i -= 1; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:560:5 + --> tests/ui/arithmetic_side_effects.rs:559:5 | LL | i *= 2; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:563:5 + --> tests/ui/arithmetic_side_effects.rs:562:5 | LL | i /= 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:566:5 + --> tests/ui/arithmetic_side_effects.rs:565:5 | LL | i /= var1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:568:5 + --> tests/ui/arithmetic_side_effects.rs:567:5 | LL | i /= var2; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:571:5 + --> tests/ui/arithmetic_side_effects.rs:570:5 | LL | i %= 0; | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:574:5 + --> tests/ui/arithmetic_side_effects.rs:573:5 | LL | i %= var1; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:576:5 + --> tests/ui/arithmetic_side_effects.rs:575:5 | LL | i %= var2; | ^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:587:5 + --> tests/ui/arithmetic_side_effects.rs:586:5 | LL | 10 / a | ^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:642:9 + --> tests/ui/arithmetic_side_effects.rs:641:9 | LL | x / maybe_zero | ^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:647:9 + --> tests/ui/arithmetic_side_effects.rs:646:9 | LL | x % maybe_zero | ^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:659:5 + --> tests/ui/arithmetic_side_effects.rs:658:5 | LL | one.add_assign(1); | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:664:5 + --> tests/ui/arithmetic_side_effects.rs:663:5 | LL | one.sub_assign(1); | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:685:5 + --> tests/ui/arithmetic_side_effects.rs:684:5 | LL | one.add(&one); | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:687:5 + --> tests/ui/arithmetic_side_effects.rs:686:5 | LL | Box::new(one).add(one); | ^^^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:696:13 + --> tests/ui/arithmetic_side_effects.rs:695:13 | LL | let _ = u128::MAX + u128::from(1u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:713:13 + --> tests/ui/arithmetic_side_effects.rs:712:13 | LL | let _ = u128::MAX * u128::from(1u8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:736:33 + --> tests/ui/arithmetic_side_effects.rs:735:33 | LL | let _ = Duration::from_secs(86400 * Foo::from(1)); | ^^^^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:742:33 + --> tests/ui/arithmetic_side_effects.rs:741:33 | LL | let _ = Duration::from_secs(86400 * shift(1)); | ^^^^^^^^^^^^^^^^ -error: aborting due to 132 previous errors +error: aborting due to 131 previous errors diff --git a/tests/ui/cognitive_complexity.rs b/tests/ui/cognitive_complexity.rs index 8080c6775e0b..3945028f8271 100644 --- a/tests/ui/cognitive_complexity.rs +++ b/tests/ui/cognitive_complexity.rs @@ -472,3 +472,28 @@ mod issue14422 { return; } } + +#[clippy::cognitive_complexity = "1"] +mod attribute_stacking { + fn bad() { + //~^ cognitive_complexity + if true { + println!("a"); + } + } + + #[clippy::cognitive_complexity = "2"] + fn ok() { + if true { + println!("a"); + } + } + + // should revert to cognitive_complexity = "1" + fn bad_again() { + //~^ cognitive_complexity + if true { + println!("a"); + } + } +} diff --git a/tests/ui/cognitive_complexity.stderr b/tests/ui/cognitive_complexity.stderr index 67ef4e5655bd..e5f54a37229d 100644 --- a/tests/ui/cognitive_complexity.stderr +++ b/tests/ui/cognitive_complexity.stderr @@ -176,5 +176,21 @@ LL | fn bar() { | = help: you could split it up into multiple smaller functions -error: aborting due to 22 previous errors +error: the function has a cognitive complexity of (2/1) + --> tests/ui/cognitive_complexity.rs:478:8 + | +LL | fn bad() { + | ^^^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of (2/1) + --> tests/ui/cognitive_complexity.rs:493:8 + | +LL | fn bad_again() { + | ^^^^^^^^^ + | + = help: you could split it up into multiple smaller functions + +error: aborting due to 24 previous errors diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.rs b/tests/ui/crate_level_checks/entrypoint_recursion.rs index 3ded902e36b1..84147d8e9c16 100644 --- a/tests/ui/crate_level_checks/entrypoint_recursion.rs +++ b/tests/ui/crate_level_checks/entrypoint_recursion.rs @@ -1,12 +1,11 @@ -//@check-pass //@ignore-target: apple - #![feature(rustc_attrs)] - #[warn(clippy::main_recursion)] #[allow(unconditional_recursion)] #[rustc_main] fn a() { - println!("Hello, World!"); a(); + //~^ main_recursion } + +fn main() {} diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.stderr b/tests/ui/crate_level_checks/entrypoint_recursion.stderr new file mode 100644 index 000000000000..d9f50d2dfc4b --- /dev/null +++ b/tests/ui/crate_level_checks/entrypoint_recursion.stderr @@ -0,0 +1,12 @@ +error: recursing into entrypoint `a` + --> tests/ui/crate_level_checks/entrypoint_recursion.rs:7:5 + | +LL | a(); + | ^ + | + = help: consider using another function for this recursion + = note: `-D clippy::main-recursion` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::main_recursion)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/crate_level_checks/no_std_main_recursion.rs b/tests/ui/crate_level_checks/no_std_main_recursion.rs new file mode 100644 index 000000000000..74763d67dd78 --- /dev/null +++ b/tests/ui/crate_level_checks/no_std_main_recursion.rs @@ -0,0 +1,13 @@ +//@check-pass +//@compile-flags: -Cpanic=abort +#![no_std] +#[warn(clippy::main_recursion)] +#[allow(unconditional_recursion)] +fn main() { + main(); +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/tests/ui/double_comparison.fixed b/tests/ui/double_comparison.fixed index 0680eb35ef97..29047b8a31cb 100644 --- a/tests/ui/double_comparison.fixed +++ b/tests/ui/double_comparison.fixed @@ -35,4 +35,20 @@ fn main() { //~^ double_comparisons // do something } + if x < y { + //~^ double_comparisons + // do something + } + if x < y { + //~^ double_comparisons + // do something + } + if x > y { + //~^ double_comparisons + // do something + } + if x > y { + //~^ double_comparisons + // do something + } } diff --git a/tests/ui/double_comparison.rs b/tests/ui/double_comparison.rs index 18ab7d2c4254..13edb2a996a1 100644 --- a/tests/ui/double_comparison.rs +++ b/tests/ui/double_comparison.rs @@ -35,4 +35,20 @@ fn main() { //~^ double_comparisons // do something } + if x != y && x <= y { + //~^ double_comparisons + // do something + } + if x <= y && x != y { + //~^ double_comparisons + // do something + } + if x != y && x >= y { + //~^ double_comparisons + // do something + } + if x >= y && x != y { + //~^ double_comparisons + // do something + } } diff --git a/tests/ui/double_comparison.stderr b/tests/ui/double_comparison.stderr index 984614c203eb..be7eba611cb0 100644 --- a/tests/ui/double_comparison.stderr +++ b/tests/ui/double_comparison.stderr @@ -49,5 +49,29 @@ error: this binary expression can be simplified LL | if x >= y && x <= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` -error: aborting due to 8 previous errors +error: this binary expression can be simplified + --> tests/ui/double_comparison.rs:38:8 + | +LL | if x != y && x <= y { + | ^^^^^^^^^^^^^^^^ help: try: `x < y` + +error: this binary expression can be simplified + --> tests/ui/double_comparison.rs:42:8 + | +LL | if x <= y && x != y { + | ^^^^^^^^^^^^^^^^ help: try: `x < y` + +error: this binary expression can be simplified + --> tests/ui/double_comparison.rs:46:8 + | +LL | if x != y && x >= y { + | ^^^^^^^^^^^^^^^^ help: try: `x > y` + +error: this binary expression can be simplified + --> tests/ui/double_comparison.rs:50:8 + | +LL | if x >= y && x != y { + | ^^^^^^^^^^^^^^^^ help: try: `x > y` + +error: aborting due to 12 previous errors diff --git a/tests/ui/duration_suboptimal_units.fixed b/tests/ui/duration_suboptimal_units.fixed new file mode 100644 index 000000000000..98c4b6e965ba --- /dev/null +++ b/tests/ui/duration_suboptimal_units.fixed @@ -0,0 +1,91 @@ +//@aux-build:proc_macros.rs +#![warn(clippy::duration_suboptimal_units)] + +use std::time::Duration; + +const SIXTY: u64 = 60; + +macro_rules! mac { + (slow_rythm) => { + 3600 + }; + (duration) => { + Duration::from_mins(5) + //~^ duration_suboptimal_units + }; + (arg => $e:expr) => { + Duration::from_secs($e) + }; +} + +fn main() { + let dur = Duration::from_secs(0); + let dur = Duration::from_secs(42); + let dur = Duration::from_hours(3); + + let dur = Duration::from_mins(1); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(3); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(10); + //~^ duration_suboptimal_units + let dur = Duration::from_hours(24); + //~^ duration_suboptimal_units + let dur = Duration::from_secs(5); + //~^ duration_suboptimal_units + let dur = Duration::from_hours(13); + //~^ duration_suboptimal_units + + // Constants are intentionally not resolved, as we don't want to recommend a literal value over + // using constants. + let dur = Duration::from_secs(SIXTY); + // Technically it would be nice to use Duration::from_mins(SIXTY) here, but that is a follow-up + let dur = Duration::from_secs(SIXTY * 60); + + const { + let dur = Duration::from_secs(0); + let dur = Duration::from_secs(5); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(3); + //~^ duration_suboptimal_units + let dur = Duration::from_hours(24); + //~^ duration_suboptimal_units + + let dur = Duration::from_secs(SIXTY); + } + + // Qualified Durations must be kept + std::time::Duration::from_mins(1); + //~^ duration_suboptimal_units + + // We lint in normal macros + assert_eq!(Duration::from_hours(1), Duration::from_mins(6)); + //~^ duration_suboptimal_units + + // We lint in normal macros (marker is in macro itself) + let dur = mac!(duration); + + // We don't lint in macros if duration comes from outside + let dur = mac!(arg => 3600); + + // We don't lint in external macros + let dur = proc_macros::external! { Duration::from_secs(3_600) }; + + // We don't lint values coming from macros + let dur = Duration::from_secs(mac!(slow_rythm)); +} + +mod my_duration { + struct Duration {} + + impl Duration { + pub const fn from_secs(_secs: u64) -> Self { + Self {} + } + } + + fn test() { + // Only suggest the change for std::time::Duration, not for other Duration structs + let dur = Duration::from_secs(60); + } +} diff --git a/tests/ui/duration_suboptimal_units.rs b/tests/ui/duration_suboptimal_units.rs new file mode 100644 index 000000000000..c4f33a9f92e0 --- /dev/null +++ b/tests/ui/duration_suboptimal_units.rs @@ -0,0 +1,91 @@ +//@aux-build:proc_macros.rs +#![warn(clippy::duration_suboptimal_units)] + +use std::time::Duration; + +const SIXTY: u64 = 60; + +macro_rules! mac { + (slow_rythm) => { + 3600 + }; + (duration) => { + Duration::from_secs(300) + //~^ duration_suboptimal_units + }; + (arg => $e:expr) => { + Duration::from_secs($e) + }; +} + +fn main() { + let dur = Duration::from_secs(0); + let dur = Duration::from_secs(42); + let dur = Duration::from_hours(3); + + let dur = Duration::from_secs(60); + //~^ duration_suboptimal_units + let dur = Duration::from_secs(180); + //~^ duration_suboptimal_units + let dur = Duration::from_secs(10 * 60); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(24 * 60); + //~^ duration_suboptimal_units + let dur = Duration::from_millis(5_000); + //~^ duration_suboptimal_units + let dur = Duration::from_nanos(13 * 60 * 60 * 1_000 * 1_000 * 1_000); + //~^ duration_suboptimal_units + + // Constants are intentionally not resolved, as we don't want to recommend a literal value over + // using constants. + let dur = Duration::from_secs(SIXTY); + // Technically it would be nice to use Duration::from_mins(SIXTY) here, but that is a follow-up + let dur = Duration::from_secs(SIXTY * 60); + + const { + let dur = Duration::from_secs(0); + let dur = Duration::from_millis(5_000); + //~^ duration_suboptimal_units + let dur = Duration::from_secs(180); + //~^ duration_suboptimal_units + let dur = Duration::from_mins(24 * 60); + //~^ duration_suboptimal_units + + let dur = Duration::from_secs(SIXTY); + } + + // Qualified Durations must be kept + std::time::Duration::from_secs(60); + //~^ duration_suboptimal_units + + // We lint in normal macros + assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6)); + //~^ duration_suboptimal_units + + // We lint in normal macros (marker is in macro itself) + let dur = mac!(duration); + + // We don't lint in macros if duration comes from outside + let dur = mac!(arg => 3600); + + // We don't lint in external macros + let dur = proc_macros::external! { Duration::from_secs(3_600) }; + + // We don't lint values coming from macros + let dur = Duration::from_secs(mac!(slow_rythm)); +} + +mod my_duration { + struct Duration {} + + impl Duration { + pub const fn from_secs(_secs: u64) -> Self { + Self {} + } + } + + fn test() { + // Only suggest the change for std::time::Duration, not for other Duration structs + let dur = Duration::from_secs(60); + } +} diff --git a/tests/ui/duration_suboptimal_units.stderr b/tests/ui/duration_suboptimal_units.stderr new file mode 100644 index 000000000000..f129dbade8dc --- /dev/null +++ b/tests/ui/duration_suboptimal_units.stderr @@ -0,0 +1,152 @@ +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:26:15 + | +LL | let dur = Duration::from_secs(60); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::duration-suboptimal-units` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::duration_suboptimal_units)]` +help: try using from_mins + | +LL - let dur = Duration::from_secs(60); +LL + let dur = Duration::from_mins(1); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:28:15 + | +LL | let dur = Duration::from_secs(180); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_mins + | +LL - let dur = Duration::from_secs(180); +LL + let dur = Duration::from_mins(3); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:30:15 + | +LL | let dur = Duration::from_secs(10 * 60); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_mins + | +LL - let dur = Duration::from_secs(10 * 60); +LL + let dur = Duration::from_mins(10); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:32:15 + | +LL | let dur = Duration::from_mins(24 * 60); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - let dur = Duration::from_mins(24 * 60); +LL + let dur = Duration::from_hours(24); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:34:15 + | +LL | let dur = Duration::from_millis(5_000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_secs + | +LL - let dur = Duration::from_millis(5_000); +LL + let dur = Duration::from_secs(5); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:36:15 + | +LL | let dur = Duration::from_nanos(13 * 60 * 60 * 1_000 * 1_000 * 1_000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - let dur = Duration::from_nanos(13 * 60 * 60 * 1_000 * 1_000 * 1_000); +LL + let dur = Duration::from_hours(13); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:47:19 + | +LL | let dur = Duration::from_millis(5_000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_secs + | +LL - let dur = Duration::from_millis(5_000); +LL + let dur = Duration::from_secs(5); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:49:19 + | +LL | let dur = Duration::from_secs(180); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_mins + | +LL - let dur = Duration::from_secs(180); +LL + let dur = Duration::from_mins(3); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:51:19 + | +LL | let dur = Duration::from_mins(24 * 60); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - let dur = Duration::from_mins(24 * 60); +LL + let dur = Duration::from_hours(24); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:58:5 + | +LL | std::time::Duration::from_secs(60); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_mins + | +LL - std::time::Duration::from_secs(60); +LL + std::time::Duration::from_mins(1); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:62:16 + | +LL | assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_hours + | +LL - assert_eq!(Duration::from_secs(3_600), Duration::from_mins(6)); +LL + assert_eq!(Duration::from_hours(1), Duration::from_mins(6)); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units.rs:13:9 + | +LL | Duration::from_secs(300) + | ^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | let dur = mac!(duration); + | -------------- in this macro invocation + | + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: try using from_mins + | +LL - Duration::from_secs(300) +LL + Duration::from_mins(5) + | + +error: aborting due to 12 previous errors + diff --git a/tests/ui/duration_suboptimal_units_days_weeks.fixed b/tests/ui/duration_suboptimal_units_days_weeks.fixed new file mode 100644 index 000000000000..b0abcbb7bf03 --- /dev/null +++ b/tests/ui/duration_suboptimal_units_days_weeks.fixed @@ -0,0 +1,17 @@ +#![warn(clippy::duration_suboptimal_units)] +// The duration_constructors feature enables `Duration::from_days` and `Duration::from_weeks`, so we +// should suggest them +#![feature(duration_constructors)] + +use std::time::Duration; + +fn main() { + let dur = Duration::from_mins(1); + //~^ duration_suboptimal_units + + let dur = Duration::from_days(1); + //~^ duration_suboptimal_units + + let dur = Duration::from_weeks(13); + //~^ duration_suboptimal_units +} diff --git a/tests/ui/duration_suboptimal_units_days_weeks.rs b/tests/ui/duration_suboptimal_units_days_weeks.rs new file mode 100644 index 000000000000..663476905c0f --- /dev/null +++ b/tests/ui/duration_suboptimal_units_days_weeks.rs @@ -0,0 +1,17 @@ +#![warn(clippy::duration_suboptimal_units)] +// The duration_constructors feature enables `Duration::from_days` and `Duration::from_weeks`, so we +// should suggest them +#![feature(duration_constructors)] + +use std::time::Duration; + +fn main() { + let dur = Duration::from_secs(60); + //~^ duration_suboptimal_units + + let dur = Duration::from_hours(24); + //~^ duration_suboptimal_units + + let dur = Duration::from_nanos(13 * 7 * 24 * 60 * 60 * 1_000 * 1_000 * 1_000); + //~^ duration_suboptimal_units +} diff --git a/tests/ui/duration_suboptimal_units_days_weeks.stderr b/tests/ui/duration_suboptimal_units_days_weeks.stderr new file mode 100644 index 000000000000..98325358bfa6 --- /dev/null +++ b/tests/ui/duration_suboptimal_units_days_weeks.stderr @@ -0,0 +1,40 @@ +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units_days_weeks.rs:9:15 + | +LL | let dur = Duration::from_secs(60); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::duration-suboptimal-units` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::duration_suboptimal_units)]` +help: try using from_mins + | +LL - let dur = Duration::from_secs(60); +LL + let dur = Duration::from_mins(1); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units_days_weeks.rs:12:15 + | +LL | let dur = Duration::from_hours(24); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_days + | +LL - let dur = Duration::from_hours(24); +LL + let dur = Duration::from_days(1); + | + +error: constructing a `Duration` using a smaller unit when a larger unit would be more readable + --> tests/ui/duration_suboptimal_units_days_weeks.rs:15:15 + | +LL | let dur = Duration::from_nanos(13 * 7 * 24 * 60 * 60 * 1_000 * 1_000 * 1_000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try using from_weeks + | +LL - let dur = Duration::from_nanos(13 * 7 * 24 * 60 * 60 * 1_000 * 1_000 * 1_000); +LL + let dur = Duration::from_weeks(13); + | + +error: aborting due to 3 previous errors + diff --git a/tests/ui/extra_unused_lifetimes.rs b/tests/ui/extra_unused_lifetimes.rs index 5fdcd5a7e078..677523489599 100644 --- a/tests/ui/extra_unused_lifetimes.rs +++ b/tests/ui/extra_unused_lifetimes.rs @@ -1,4 +1,5 @@ //@aux-build:proc_macro_derive.rs +//@aux-build:proc_macros.rs #![allow( unused, @@ -11,6 +12,7 @@ #[macro_use] extern crate proc_macro_derive; +extern crate proc_macros; fn empty() {} @@ -148,4 +150,34 @@ mod issue_13578 { impl<'a, T: 'a> Foo for Option where &'a T: Foo {} } +// no lint on proc macro generated code +mod proc_macro_generated { + use proc_macros::external; + + // no lint on external macro (extra unused lifetimes in impl block) + external! { + struct ExternalImplStruct; + + impl<'a> ExternalImplStruct { + fn foo() {} + } + } + + // no lint on external macro (extra unused lifetimes in method) + external! { + struct ExternalMethodStruct; + + impl ExternalMethodStruct { + fn bar<'a>(&self) {} + } + } + + // no lint on external macro (extra unused lifetimes in trait method) + external! { + trait ExternalUnusedLifetimeTrait { + fn unused_lt<'a>(x: u8) {} + } + } +} + fn main() {} diff --git a/tests/ui/extra_unused_lifetimes.stderr b/tests/ui/extra_unused_lifetimes.stderr index 0cecbbe80f76..d748376d476c 100644 --- a/tests/ui/extra_unused_lifetimes.stderr +++ b/tests/ui/extra_unused_lifetimes.stderr @@ -1,5 +1,5 @@ error: this lifetime isn't used in the function definition - --> tests/ui/extra_unused_lifetimes.rs:19:14 + --> tests/ui/extra_unused_lifetimes.rs:21:14 | LL | fn unused_lt<'a>(x: u8) {} | ^^ @@ -8,37 +8,37 @@ LL | fn unused_lt<'a>(x: u8) {} = help: to override `-D warnings` add `#[allow(clippy::extra_unused_lifetimes)]` error: this lifetime isn't used in the function definition - --> tests/ui/extra_unused_lifetimes.rs:47:10 + --> tests/ui/extra_unused_lifetimes.rs:49:10 | LL | fn x<'a>(&self) {} | ^^ error: this lifetime isn't used in the function definition - --> tests/ui/extra_unused_lifetimes.rs:74:22 + --> tests/ui/extra_unused_lifetimes.rs:76:22 | LL | fn unused_lt<'a>(x: u8) {} | ^^ error: this lifetime isn't used in the impl - --> tests/ui/extra_unused_lifetimes.rs:86:10 + --> tests/ui/extra_unused_lifetimes.rs:88:10 | LL | impl<'a> std::ops::AddAssign<&Scalar> for &mut Scalar { | ^^ error: this lifetime isn't used in the impl - --> tests/ui/extra_unused_lifetimes.rs:93:10 + --> tests/ui/extra_unused_lifetimes.rs:95:10 | LL | impl<'b> Scalar { | ^^ error: this lifetime isn't used in the function definition - --> tests/ui/extra_unused_lifetimes.rs:95:26 + --> tests/ui/extra_unused_lifetimes.rs:97:26 | LL | pub fn something<'c>() -> Self { | ^^ error: this lifetime isn't used in the impl - --> tests/ui/extra_unused_lifetimes.rs:125:10 + --> tests/ui/extra_unused_lifetimes.rs:127:10 | LL | impl<'a, T: Source + ?Sized + 'a> Source for Box { | ^^ diff --git a/tests/ui/if_same_then_else.rs b/tests/ui/if_same_then_else.rs index 6d2e63e7299a..6e0e2c5ea720 100644 --- a/tests/ui/if_same_then_else.rs +++ b/tests/ui/if_same_then_else.rs @@ -11,6 +11,8 @@ unreachable_code )] +use std::ops::*; + struct Foo { bar: u8, } @@ -133,18 +135,6 @@ fn func() { fn f(val: &[u8]) {} -mod issue_5698 { - fn mul_not_always_commutative(x: i32, y: i32) -> i32 { - if x == 42 { - x * y - } else if x == 21 { - y * x - } else { - 0 - } - } -} - mod issue_8836 { fn do_not_lint() { if true { @@ -245,3 +235,73 @@ mod issue_11213 { } fn main() {} + +fn issue16416(x: bool, a: T, b: T) +where + T: Add + Sub + Mul + Div + Rem + BitAnd + BitOr + BitXor + PartialEq + Eq + PartialOrd + Ord + Shr + Shl + Copy, +{ + // Non-guaranteed-commutative operators + _ = if x { a * b } else { b * a }; + _ = if x { a + b } else { b + a }; + _ = if x { a - b } else { b - a }; + _ = if x { a / b } else { b / a }; + _ = if x { a % b } else { b % a }; + _ = if x { a << b } else { b << a }; + _ = if x { a >> b } else { b >> a }; + _ = if x { a & b } else { b & a }; + _ = if x { a ^ b } else { b ^ a }; + _ = if x { a | b } else { b | a }; + + // Guaranteed commutative operators + //~v if_same_then_else + _ = if x { a == b } else { b == a }; + //~v if_same_then_else + _ = if x { a != b } else { b != a }; + + // Symetric operators + //~v if_same_then_else + _ = if x { a < b } else { b > a }; + //~v if_same_then_else + _ = if x { a <= b } else { b >= a }; + //~v if_same_then_else + _ = if x { a > b } else { b < a }; + //~v if_same_then_else + _ = if x { a >= b } else { b <= a }; +} + +fn issue16416_prim(x: bool, a: u32, b: u32) { + // Non-commutative operators + _ = if x { a - b } else { b - a }; + _ = if x { a / b } else { b / a }; + _ = if x { a % b } else { b % a }; + _ = if x { a << b } else { b << a }; + _ = if x { a >> b } else { b >> a }; + + // Commutative operators on primitive types + //~v if_same_then_else + _ = if x { a * b } else { b * a }; + //~v if_same_then_else + _ = if x { a + b } else { b + a }; + //~v if_same_then_else + _ = if x { a & b } else { b & a }; + //~v if_same_then_else + _ = if x { a ^ b } else { b ^ a }; + //~v if_same_then_else + _ = if x { a | b } else { b | a }; + + // Always commutative operators + //~v if_same_then_else + _ = if x { a == b } else { b == a }; + //~v if_same_then_else + _ = if x { a != b } else { b != a }; + + // Symetric operators + //~v if_same_then_else + _ = if x { a < b } else { b > a }; + //~v if_same_then_else + _ = if x { a <= b } else { b >= a }; + //~v if_same_then_else + _ = if x { a > b } else { b < a }; + //~v if_same_then_else + _ = if x { a >= b } else { b <= a }; +} diff --git a/tests/ui/if_same_then_else.stderr b/tests/ui/if_same_then_else.stderr index b76da3fb1cb5..57396a566941 100644 --- a/tests/ui/if_same_then_else.stderr +++ b/tests/ui/if_same_then_else.stderr @@ -1,5 +1,5 @@ error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:23:13 + --> tests/ui/if_same_then_else.rs:25:13 | LL | if true { | _____________^ @@ -12,7 +12,7 @@ LL | | } else { | |_____^ | note: same as this - --> tests/ui/if_same_then_else.rs:31:12 + --> tests/ui/if_same_then_else.rs:33:12 | LL | } else { | ____________^ @@ -27,43 +27,43 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::if_same_then_else)]` error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:67:21 + --> tests/ui/if_same_then_else.rs:69:21 | LL | let _ = if true { 0.0 } else { 0.0 }; | ^^^^^^^ | note: same as this - --> tests/ui/if_same_then_else.rs:67:34 + --> tests/ui/if_same_then_else.rs:69:34 | LL | let _ = if true { 0.0 } else { 0.0 }; | ^^^^^^^ error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:70:21 + --> tests/ui/if_same_then_else.rs:72:21 | LL | let _ = if true { -0.0 } else { -0.0 }; | ^^^^^^^^ | note: same as this - --> tests/ui/if_same_then_else.rs:70:35 + --> tests/ui/if_same_then_else.rs:72:35 | LL | let _ = if true { -0.0 } else { -0.0 }; | ^^^^^^^^ error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:82:21 + --> tests/ui/if_same_then_else.rs:84:21 | LL | let _ = if true { 42 } else { 42 }; | ^^^^^^ | note: same as this - --> tests/ui/if_same_then_else.rs:82:33 + --> tests/ui/if_same_then_else.rs:84:33 | LL | let _ = if true { 42 } else { 42 }; | ^^^^^^ error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:85:13 + --> tests/ui/if_same_then_else.rs:87:13 | LL | if true { | _____________^ @@ -76,7 +76,7 @@ LL | | } else { | |_____^ | note: same as this - --> tests/ui/if_same_then_else.rs:92:12 + --> tests/ui/if_same_then_else.rs:94:12 | LL | } else { | ____________^ @@ -89,7 +89,7 @@ LL | | } | |_____^ error: this `if` has identical blocks - --> tests/ui/if_same_then_else.rs:238:14 + --> tests/ui/if_same_then_else.rs:228:14 | LL | if x { | ______________^ @@ -98,7 +98,7 @@ LL | | } else { | |_________^ | note: same as this - --> tests/ui/if_same_then_else.rs:240:16 + --> tests/ui/if_same_then_else.rs:230:16 | LL | } else { | ________________^ @@ -106,5 +106,209 @@ LL | | 0_u8.is_power_of_two() LL | | } | |_________^ -error: aborting due to 6 previous errors +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:257:14 + | +LL | _ = if x { a == b } else { b == a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:257:30 + | +LL | _ = if x { a == b } else { b == a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:259:14 + | +LL | _ = if x { a != b } else { b != a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:259:30 + | +LL | _ = if x { a != b } else { b != a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:263:14 + | +LL | _ = if x { a < b } else { b > a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:263:29 + | +LL | _ = if x { a < b } else { b > a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:265:14 + | +LL | _ = if x { a <= b } else { b >= a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:265:30 + | +LL | _ = if x { a <= b } else { b >= a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:267:14 + | +LL | _ = if x { a > b } else { b < a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:267:29 + | +LL | _ = if x { a > b } else { b < a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:269:14 + | +LL | _ = if x { a >= b } else { b <= a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:269:30 + | +LL | _ = if x { a >= b } else { b <= a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:282:14 + | +LL | _ = if x { a * b } else { b * a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:282:29 + | +LL | _ = if x { a * b } else { b * a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:284:14 + | +LL | _ = if x { a + b } else { b + a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:284:29 + | +LL | _ = if x { a + b } else { b + a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:286:14 + | +LL | _ = if x { a & b } else { b & a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:286:29 + | +LL | _ = if x { a & b } else { b & a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:288:14 + | +LL | _ = if x { a ^ b } else { b ^ a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:288:29 + | +LL | _ = if x { a ^ b } else { b ^ a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:290:14 + | +LL | _ = if x { a | b } else { b | a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:290:29 + | +LL | _ = if x { a | b } else { b | a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:294:14 + | +LL | _ = if x { a == b } else { b == a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:294:30 + | +LL | _ = if x { a == b } else { b == a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:296:14 + | +LL | _ = if x { a != b } else { b != a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:296:30 + | +LL | _ = if x { a != b } else { b != a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:300:14 + | +LL | _ = if x { a < b } else { b > a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:300:29 + | +LL | _ = if x { a < b } else { b > a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:302:14 + | +LL | _ = if x { a <= b } else { b >= a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:302:30 + | +LL | _ = if x { a <= b } else { b >= a }; + | ^^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:304:14 + | +LL | _ = if x { a > b } else { b < a }; + | ^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:304:29 + | +LL | _ = if x { a > b } else { b < a }; + | ^^^^^^^^^ + +error: this `if` has identical blocks + --> tests/ui/if_same_then_else.rs:306:14 + | +LL | _ = if x { a >= b } else { b <= a }; + | ^^^^^^^^^^ + | +note: same as this + --> tests/ui/if_same_then_else.rs:306:30 + | +LL | _ = if x { a >= b } else { b <= a }; + | ^^^^^^^^^^ + +error: aborting due to 23 previous errors diff --git a/tests/ui/int_plus_one.fixed b/tests/ui/int_plus_one.fixed index a1aba6bf7f64..cdd19515e9a7 100644 --- a/tests/ui/int_plus_one.fixed +++ b/tests/ui/int_plus_one.fixed @@ -4,15 +4,15 @@ fn main() { let x = 1i32; let y = 0i32; - let _ = x > y; - //~^ int_plus_one - let _ = y < x; - //~^ int_plus_one + let _ = x > y; //~ int_plus_one + let _ = x > y; //~ int_plus_one + let _ = y < x; //~ int_plus_one + let _ = y < x; //~ int_plus_one - let _ = x > y; - //~^ int_plus_one - let _ = y < x; - //~^ int_plus_one + let _ = x > y; //~ int_plus_one + let _ = x > y; //~ int_plus_one + let _ = y < x; //~ int_plus_one + let _ = y < x; //~ int_plus_one let _ = x > y; // should be ok let _ = y < x; // should be ok diff --git a/tests/ui/int_plus_one.rs b/tests/ui/int_plus_one.rs index f804fc9047de..8d7d2e8982d8 100644 --- a/tests/ui/int_plus_one.rs +++ b/tests/ui/int_plus_one.rs @@ -4,15 +4,15 @@ fn main() { let x = 1i32; let y = 0i32; - let _ = x >= y + 1; - //~^ int_plus_one - let _ = y + 1 <= x; - //~^ int_plus_one + let _ = x >= y + 1; //~ int_plus_one + let _ = x >= 1 + y; //~ int_plus_one + let _ = y + 1 <= x; //~ int_plus_one + let _ = 1 + y <= x; //~ int_plus_one - let _ = x - 1 >= y; - //~^ int_plus_one - let _ = y <= x - 1; - //~^ int_plus_one + let _ = x - 1 >= y; //~ int_plus_one + let _ = -1 + x >= y; //~ int_plus_one + let _ = y <= x - 1; //~ int_plus_one + let _ = y <= -1 + x; //~ int_plus_one let _ = x > y; // should be ok let _ = y < x; // should be ok diff --git a/tests/ui/int_plus_one.stderr b/tests/ui/int_plus_one.stderr index 052706028141..8bdff5680bdc 100644 --- a/tests/ui/int_plus_one.stderr +++ b/tests/ui/int_plus_one.stderr @@ -7,23 +7,47 @@ LL | let _ = x >= y + 1; = note: `-D clippy::int-plus-one` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::int_plus_one)]` +error: unnecessary `>= y + 1` or `x - 1 >=` + --> tests/ui/int_plus_one.rs:8:13 + | +LL | let _ = x >= 1 + y; + | ^^^^^^^^^^ help: change it to: `x > y` + error: unnecessary `>= y + 1` or `x - 1 >=` --> tests/ui/int_plus_one.rs:9:13 | LL | let _ = y + 1 <= x; | ^^^^^^^^^^ help: change it to: `y < x` +error: unnecessary `>= y + 1` or `x - 1 >=` + --> tests/ui/int_plus_one.rs:10:13 + | +LL | let _ = 1 + y <= x; + | ^^^^^^^^^^ help: change it to: `y < x` + error: unnecessary `>= y + 1` or `x - 1 >=` --> tests/ui/int_plus_one.rs:12:13 | LL | let _ = x - 1 >= y; | ^^^^^^^^^^ help: change it to: `x > y` +error: unnecessary `>= y + 1` or `x - 1 >=` + --> tests/ui/int_plus_one.rs:13:13 + | +LL | let _ = -1 + x >= y; + | ^^^^^^^^^^^ help: change it to: `x > y` + error: unnecessary `>= y + 1` or `x - 1 >=` --> tests/ui/int_plus_one.rs:14:13 | LL | let _ = y <= x - 1; | ^^^^^^^^^^ help: change it to: `y < x` -error: aborting due to 4 previous errors +error: unnecessary `>= y + 1` or `x - 1 >=` + --> tests/ui/int_plus_one.rs:15:13 + | +LL | let _ = y <= -1 + x; + | ^^^^^^^^^^^ help: change it to: `y < x` + +error: aborting due to 8 previous errors diff --git a/tests/ui/manual_checked_ops.rs b/tests/ui/manual_checked_ops.rs new file mode 100644 index 000000000000..93630faa1086 --- /dev/null +++ b/tests/ui/manual_checked_ops.rs @@ -0,0 +1,72 @@ +#![warn(clippy::manual_checked_ops)] + +fn main() { + let mut a = 10u32; + let mut b = 5u32; + + // Should trigger lint + if b != 0 { + //~^ manual_checked_ops + let _result = a / b; + let _another = (a + 1) / b; + } + + // Should trigger lint (compound assignment) + if b != 0 { + //~^ manual_checked_ops + a /= b; + } + + if b > 0 { + //~^ manual_checked_ops + let _result = a / b; + } + + if b == 0 { + //~^ manual_checked_ops + println!("zero"); + } else { + let _result = a / b; + } + + // Should NOT trigger (already using checked_div) + if let Some(result) = b.checked_div(a) { + println!("{result}"); + } + + // Should NOT trigger (signed integers are not linted) + let c = -5i32; + if c != 0 { + let _result = 10 / c; + } + + // Should NOT trigger (side effects in divisor) + if counter() > 0 { + let _ = 32 / counter(); + } + + // Should NOT trigger (divisor used before division) + if b > 0 { + use_value(b); + let _ = a / b; + } + + // Should NOT trigger (divisor may change during evaluation) + if b > 0 { + g(inc_and_return_value(&mut b), a / b); + } +} + +fn counter() -> u32 { + println!("counter"); + 1 +} + +fn use_value(_v: u32) {} + +fn inc_and_return_value(x: &mut u32) -> u32 { + *x += 1; + *x +} + +fn g(_lhs: u32, _rhs: u32) {} diff --git a/tests/ui/manual_checked_ops.stderr b/tests/ui/manual_checked_ops.stderr new file mode 100644 index 000000000000..311f319bad14 --- /dev/null +++ b/tests/ui/manual_checked_ops.stderr @@ -0,0 +1,50 @@ +error: manual checked division + --> tests/ui/manual_checked_ops.rs:8:8 + | +LL | if b != 0 { + | ^^^^^^ check performed here +LL | +LL | let _result = a / b; + | ----- division performed here +LL | let _another = (a + 1) / b; + | ----------- ... and here + | + = help: consider using `checked_div` + = note: `-D clippy::manual-checked-ops` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_checked_ops)]` + +error: manual checked division + --> tests/ui/manual_checked_ops.rs:15:8 + | +LL | if b != 0 { + | ^^^^^^ check performed here +LL | +LL | a /= b; + | ------ division performed here + | + = help: consider using `checked_div` + +error: manual checked division + --> tests/ui/manual_checked_ops.rs:20:8 + | +LL | if b > 0 { + | ^^^^^ check performed here +LL | +LL | let _result = a / b; + | ----- division performed here + | + = help: consider using `checked_div` + +error: manual checked division + --> tests/ui/manual_checked_ops.rs:25:8 + | +LL | if b == 0 { + | ^^^^^^ check performed here +... +LL | let _result = a / b; + | ----- division performed here + | + = help: consider using `checked_div` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/manual_take.fixed b/tests/ui/manual_take.fixed new file mode 100644 index 000000000000..5891bd49c81c --- /dev/null +++ b/tests/ui/manual_take.fixed @@ -0,0 +1,57 @@ +#![warn(clippy::manual_take)] + +fn main() { + msrv_1_39(); + msrv_1_40(); + let mut x = true; + let mut y = false; + + let _lint_negated = !std::mem::take(&mut x); + + let _ = if x { + y = false; + true + } else { + false + }; + + let _ = if x { + x = true; + true + } else { + false + }; + + let _ = if x { + x = false; + y = true; + false + } else { + true + }; + + let _ = if x { + x = false; + false + } else { + y = true; + true + }; +} + +#[clippy::msrv = "1.39.0"] +fn msrv_1_39() -> bool { + let mut x = true; + if x { + x = false; + true + } else { + false + } +} + +#[clippy::msrv = "1.40.0"] +fn msrv_1_40() -> bool { + let mut x = true; + std::mem::take(&mut x) +} diff --git a/tests/ui/manual_take.rs b/tests/ui/manual_take.rs new file mode 100644 index 000000000000..89903fcb2416 --- /dev/null +++ b/tests/ui/manual_take.rs @@ -0,0 +1,69 @@ +#![warn(clippy::manual_take)] + +fn main() { + msrv_1_39(); + msrv_1_40(); + let mut x = true; + let mut y = false; + + let _lint_negated = if x { + //~^ manual_take + x = false; + false + } else { + true + }; + + let _ = if x { + y = false; + true + } else { + false + }; + + let _ = if x { + x = true; + true + } else { + false + }; + + let _ = if x { + x = false; + y = true; + false + } else { + true + }; + + let _ = if x { + x = false; + false + } else { + y = true; + true + }; +} + +#[clippy::msrv = "1.39.0"] +fn msrv_1_39() -> bool { + let mut x = true; + if x { + x = false; + true + } else { + false + } +} + +#[clippy::msrv = "1.40.0"] +fn msrv_1_40() -> bool { + let mut x = true; + if x { + //~^ manual_take + x = false; + true + } else { + false + } +} diff --git a/tests/ui/manual_take.stderr b/tests/ui/manual_take.stderr new file mode 100644 index 000000000000..69ba7778a275 --- /dev/null +++ b/tests/ui/manual_take.stderr @@ -0,0 +1,53 @@ +error: manual implementation of `mem::take` + --> tests/ui/manual_take.rs:9:25 + | +LL | let _lint_negated = if x { + | _________________________^ +LL | | +LL | | x = false; +LL | | false +LL | | } else { +LL | | true +LL | | }; + | |_____^ + | + = note: `-D clippy::manual-take` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_take)]` +help: use + | +LL - let _lint_negated = if x { +LL - +LL - x = false; +LL - false +LL - } else { +LL - true +LL - }; +LL + let _lint_negated = !std::mem::take(&mut x); + | + +error: manual implementation of `mem::take` + --> tests/ui/manual_take.rs:62:5 + | +LL | / if x { +LL | | +LL | | x = false; +LL | | true +LL | | } else { +LL | | false +LL | | } + | |_____^ + | +help: use + | +LL - if x { +LL - +LL - x = false; +LL - true +LL - } else { +LL - false +LL - } +LL + std::mem::take(&mut x) + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/manual_take_nocore.rs b/tests/ui/manual_take_nocore.rs new file mode 100644 index 000000000000..ef4f23395028 --- /dev/null +++ b/tests/ui/manual_take_nocore.rs @@ -0,0 +1,37 @@ +//@ check-pass +#![feature(no_core, lang_items)] +#![no_core] +#![allow(clippy::missing_safety_doc)] +#![warn(clippy::manual_take)] + +#[link(name = "c")] +unsafe extern "C" {} + +#[lang = "pointee_sized"] +pub trait PointeeSized {} + +#[lang = "meta_sized"] +pub trait MetaSized: PointeeSized {} + +#[lang = "sized"] +pub trait Sized: MetaSized {} +#[lang = "copy"] +pub trait Copy {} +#[lang = "freeze"] +pub unsafe trait Freeze {} + +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + 0 +} + +fn main() { + let mut x = true; + // this should not lint because we don't have std nor core + let _manual_take = if x { + x = false; + true + } else { + false + }; +} diff --git a/tests/ui/manual_take_nostd.fixed b/tests/ui/manual_take_nostd.fixed new file mode 100644 index 000000000000..123c5a91998c --- /dev/null +++ b/tests/ui/manual_take_nostd.fixed @@ -0,0 +1,10 @@ +#![no_std] +#![warn(clippy::manual_take)] + +pub fn manual_mem_take_should_reference_core() { + let mut x = true; + + let _lint_negated = !core::mem::take(&mut x); + + let _lint = core::mem::take(&mut x); +} diff --git a/tests/ui/manual_take_nostd.rs b/tests/ui/manual_take_nostd.rs new file mode 100644 index 000000000000..0df352477b74 --- /dev/null +++ b/tests/ui/manual_take_nostd.rs @@ -0,0 +1,22 @@ +#![no_std] +#![warn(clippy::manual_take)] + +pub fn manual_mem_take_should_reference_core() { + let mut x = true; + + let _lint_negated = if x { + //~^ manual_take + x = false; + false + } else { + true + }; + + let _lint = if x { + //~^ manual_take + x = false; + true + } else { + false + }; +} diff --git a/tests/ui/manual_take_nostd.stderr b/tests/ui/manual_take_nostd.stderr new file mode 100644 index 000000000000..71a5066e4db3 --- /dev/null +++ b/tests/ui/manual_take_nostd.stderr @@ -0,0 +1,54 @@ +error: manual implementation of `mem::take` + --> tests/ui/manual_take_nostd.rs:7:25 + | +LL | let _lint_negated = if x { + | _________________________^ +LL | | +LL | | x = false; +LL | | false +LL | | } else { +LL | | true +LL | | }; + | |_____^ + | + = note: `-D clippy::manual-take` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_take)]` +help: use + | +LL - let _lint_negated = if x { +LL - +LL - x = false; +LL - false +LL - } else { +LL - true +LL - }; +LL + let _lint_negated = !core::mem::take(&mut x); + | + +error: manual implementation of `mem::take` + --> tests/ui/manual_take_nostd.rs:15:17 + | +LL | let _lint = if x { + | _________________^ +LL | | +LL | | x = false; +LL | | true +LL | | } else { +LL | | false +LL | | }; + | |_____^ + | +help: use + | +LL - let _lint = if x { +LL - +LL - x = false; +LL - true +LL - } else { +LL - false +LL - }; +LL + let _lint = core::mem::take(&mut x); + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/map_unwrap_or.rs b/tests/ui/map_unwrap_or.rs index fba81cb493cd..dccacd7df8af 100644 --- a/tests/ui/map_unwrap_or.rs +++ b/tests/ui/map_unwrap_or.rs @@ -156,3 +156,11 @@ mod issue_10579 { println!("{y:?}"); } } + +fn issue15752() { + struct Foo<'a>(&'a [u32]); + + let x = Some(Foo(&[1, 2, 3])); + x.map(|y| y.0).unwrap_or(&[]); + //~^ map_unwrap_or +} diff --git a/tests/ui/map_unwrap_or.stderr b/tests/ui/map_unwrap_or.stderr index df0207c420e6..bd9e0eeb0bda 100644 --- a/tests/ui/map_unwrap_or.stderr +++ b/tests/ui/map_unwrap_or.stderr @@ -232,5 +232,11 @@ LL - let _ = opt.map(|x| x > 5).unwrap_or(false); LL + let _ = opt.is_some_and(|x| x > 5); | -error: aborting due to 15 previous errors +error: called `map().unwrap_or()` on an `Option` value + --> tests/ui/map_unwrap_or.rs:164:5 + | +LL | x.map(|y| y.0).unwrap_or(&[]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 16 previous errors diff --git a/tests/ui/map_unwrap_or_fixable.fixed b/tests/ui/map_unwrap_or_fixable.fixed index 90f3cf8bab04..dca2536132d7 100644 --- a/tests/ui/map_unwrap_or_fixable.fixed +++ b/tests/ui/map_unwrap_or_fixable.fixed @@ -1,6 +1,11 @@ //@aux-build:option_helpers.rs #![warn(clippy::map_unwrap_or)] +#![allow( + clippy::unnecessary_lazy_evaluations, + clippy::manual_is_variant_and, + clippy::unnecessary_map_or +)] #[macro_use] extern crate option_helpers; @@ -51,3 +56,37 @@ fn main() { option_methods(); result_methods(); } + +fn issue15714() { + let o: Option = Some(3); + let r: Result = Ok(3); + println!("{}", o.map_or(3, |y| y + 1)); + //~^ map_unwrap_or + println!("{}", o.map_or_else(|| 3, |y| y + 1)); + //~^ map_unwrap_or + println!("{}", r.map_or(3, |y| y + 1)); + //~^ map_unwrap_or + println!("{}", r.map_or_else(|()| 3, |y| y + 1)); + //~^ map_unwrap_or + + println!("{}", r.is_ok_and(|y| y == 1)); + //~^ map_unwrap_or +} + +fn issue15713() { + let x = &Some(3); + println!("{}", x.map_or(3, |y| y + 1)); + //~^ map_unwrap_or + + let x: &Result = &Ok(3); + println!("{}", x.map_or(3, |y| y + 1)); + //~^ map_unwrap_or + + let x = &Some(3); + println!("{}", x.map_or_else(|| 3, |y| y + 1)); + //~^ map_unwrap_or + + let x: &Result = &Ok(3); + println!("{}", x.map_or_else(|_| 3, |y| y + 1)); + //~^ map_unwrap_or +} diff --git a/tests/ui/map_unwrap_or_fixable.rs b/tests/ui/map_unwrap_or_fixable.rs index 1078c7a3cf34..c60cb082ae3c 100644 --- a/tests/ui/map_unwrap_or_fixable.rs +++ b/tests/ui/map_unwrap_or_fixable.rs @@ -1,6 +1,11 @@ //@aux-build:option_helpers.rs #![warn(clippy::map_unwrap_or)] +#![allow( + clippy::unnecessary_lazy_evaluations, + clippy::manual_is_variant_and, + clippy::unnecessary_map_or +)] #[macro_use] extern crate option_helpers; @@ -57,3 +62,37 @@ fn main() { option_methods(); result_methods(); } + +fn issue15714() { + let o: Option = Some(3); + let r: Result = Ok(3); + println!("{}", o.map(|y| y + 1).unwrap_or(3)); + //~^ map_unwrap_or + println!("{}", o.map(|y| y + 1).unwrap_or_else(|| 3)); + //~^ map_unwrap_or + println!("{}", r.map(|y| y + 1).unwrap_or(3)); + //~^ map_unwrap_or + println!("{}", r.map(|y| y + 1).unwrap_or_else(|()| 3)); + //~^ map_unwrap_or + + println!("{}", r.map(|y| y == 1).unwrap_or(false)); + //~^ map_unwrap_or +} + +fn issue15713() { + let x = &Some(3); + println!("{}", x.map(|y| y + 1).unwrap_or(3)); + //~^ map_unwrap_or + + let x: &Result = &Ok(3); + println!("{}", x.map(|y| y + 1).unwrap_or(3)); + //~^ map_unwrap_or + + let x = &Some(3); + println!("{}", x.map(|y| y + 1).unwrap_or_else(|| 3)); + //~^ map_unwrap_or + + let x: &Result = &Ok(3); + println!("{}", x.map(|y| y + 1).unwrap_or_else(|_| 3)); + //~^ map_unwrap_or +} diff --git a/tests/ui/map_unwrap_or_fixable.stderr b/tests/ui/map_unwrap_or_fixable.stderr index 99e660f8dbd1..33a865d6769c 100644 --- a/tests/ui/map_unwrap_or_fixable.stderr +++ b/tests/ui/map_unwrap_or_fixable.stderr @@ -1,5 +1,5 @@ error: called `map().unwrap_or_else()` on an `Option` value - --> tests/ui/map_unwrap_or_fixable.rs:16:13 + --> tests/ui/map_unwrap_or_fixable.rs:21:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -11,7 +11,7 @@ LL | | .unwrap_or_else(|| 0); = help: to override `-D warnings` add `#[allow(clippy::map_unwrap_or)]` error: called `map().unwrap_or_else()` on a `Result` value - --> tests/ui/map_unwrap_or_fixable.rs:47:13 + --> tests/ui/map_unwrap_or_fixable.rs:52:13 | LL | let _ = res.map(|x| x + 1) | _____________^ @@ -19,5 +19,89 @@ LL | let _ = res.map(|x| x + 1) LL | | .unwrap_or_else(|_e| 0); | |_______________________________^ help: try: `res.map_or_else(|_e| 0, |x| x + 1)` -error: aborting due to 2 previous errors +error: called `map().unwrap_or()` on an `Option` value + --> tests/ui/map_unwrap_or_fixable.rs:69:20 + | +LL | println!("{}", o.map(|y| y + 1).unwrap_or(3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `map_or(, )` instead + | +LL - println!("{}", o.map(|y| y + 1).unwrap_or(3)); +LL + println!("{}", o.map_or(3, |y| y + 1)); + | + +error: called `map().unwrap_or_else()` on an `Option` value + --> tests/ui/map_unwrap_or_fixable.rs:71:20 + | +LL | println!("{}", o.map(|y| y + 1).unwrap_or_else(|| 3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `o.map_or_else(|| 3, |y| y + 1)` + +error: called `map().unwrap_or()` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:73:20 + | +LL | println!("{}", r.map(|y| y + 1).unwrap_or(3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `map_or(, )` instead + | +LL - println!("{}", r.map(|y| y + 1).unwrap_or(3)); +LL + println!("{}", r.map_or(3, |y| y + 1)); + | + +error: called `map().unwrap_or_else()` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:75:20 + | +LL | println!("{}", r.map(|y| y + 1).unwrap_or_else(|()| 3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `r.map_or_else(|()| 3, |y| y + 1)` + +error: called `map().unwrap_or(false)` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:78:20 + | +LL | println!("{}", r.map(|y| y == 1).unwrap_or(false)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `is_ok_and()` instead + | +LL - println!("{}", r.map(|y| y == 1).unwrap_or(false)); +LL + println!("{}", r.is_ok_and(|y| y == 1)); + | + +error: called `map().unwrap_or()` on an `Option` value + --> tests/ui/map_unwrap_or_fixable.rs:84:20 + | +LL | println!("{}", x.map(|y| y + 1).unwrap_or(3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `map_or(, )` instead + | +LL - println!("{}", x.map(|y| y + 1).unwrap_or(3)); +LL + println!("{}", x.map_or(3, |y| y + 1)); + | + +error: called `map().unwrap_or()` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:88:20 + | +LL | println!("{}", x.map(|y| y + 1).unwrap_or(3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `map_or(, )` instead + | +LL - println!("{}", x.map(|y| y + 1).unwrap_or(3)); +LL + println!("{}", x.map_or(3, |y| y + 1)); + | + +error: called `map().unwrap_or_else()` on an `Option` value + --> tests/ui/map_unwrap_or_fixable.rs:92:20 + | +LL | println!("{}", x.map(|y| y + 1).unwrap_or_else(|| 3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.map_or_else(|| 3, |y| y + 1)` + +error: called `map().unwrap_or_else()` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:96:20 + | +LL | println!("{}", x.map(|y| y + 1).unwrap_or_else(|_| 3)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.map_or_else(|_| 3, |y| y + 1)` + +error: aborting due to 11 previous errors diff --git a/tests/ui/missing_trait_methods.rs b/tests/ui/missing_trait_methods.rs index 7af186ba3322..67070a299951 100644 --- a/tests/ui/missing_trait_methods.rs +++ b/tests/ui/missing_trait_methods.rs @@ -62,3 +62,10 @@ impl MissingMultiple for Partial {} //~| missing_trait_methods fn main() {} + +//~v missing_trait_methods +impl PartialEq for Partial { + fn eq(&self, other: &Partial) -> bool { + todo!() + } +} diff --git a/tests/ui/missing_trait_methods.stderr b/tests/ui/missing_trait_methods.stderr index d9fb8951ab3d..e5155ad587cb 100644 --- a/tests/ui/missing_trait_methods.stderr +++ b/tests/ui/missing_trait_methods.stderr @@ -60,5 +60,13 @@ help: implement the method LL | fn three() {} | ^^^^^^^^^^ -error: aborting due to 5 previous errors +error: missing trait method provided by default: `ne` + --> tests/ui/missing_trait_methods.rs:67:1 + | +LL | impl PartialEq for Partial { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: implement the missing `ne` method of the `PartialEq` trait + +error: aborting due to 6 previous errors diff --git a/tests/ui/needless_collect.fixed b/tests/ui/needless_collect.fixed index 99027e79b664..2d59c1d42b05 100644 --- a/tests/ui/needless_collect.fixed +++ b/tests/ui/needless_collect.fixed @@ -219,3 +219,79 @@ fn issue16270() { // Do not lint, `..` implements `Index` but is not `usize` _ = &(1..3).collect::>()[..]; } + +#[warn(clippy::needless_collect)] +mod collect_push_then_iter { + use std::collections::{BinaryHeap, LinkedList, VecDeque}; + + fn vec_push(iter: impl Iterator) -> Vec { + + //~^ needless_collect + + iter.chain([1]).map(|x| x + 1).collect() + } + + fn vec_push_no_iter(iter: impl Iterator) { + let mut v = iter.collect::>(); + v.push(1); + } + + fn vec_push_multiple(iter: impl Iterator) -> Vec { + + //~^ needless_collect + + + iter.chain([1, 2]).map(|x| x + 1).collect() + } + + fn linked_list_push(iter: impl Iterator) -> LinkedList { + + //~^ needless_collect + + iter.chain([1]).map(|x| x + 1).collect() + } + + fn binary_heap_push(iter: impl Iterator) -> BinaryHeap { + let mut v = iter.collect::>(); + v.push(1); + v.into_iter().map(|x| x + 1).collect() + } + + fn vec_push_mixed(iter: impl Iterator) -> bool { + let mut v = iter.collect::>(); + let ok = v.contains(&1); + v.push(1); + ok + } + + fn linked_list_extend(iter: impl Iterator, s: Vec) -> LinkedList { + + //~^ needless_collect + + iter.chain(s).map(|x| x + 1).collect() + } + + fn deque_push_front(iter: impl Iterator) -> VecDeque { + + //~^ needless_collect + + + [1, 2].into_iter().chain(iter).map(|x| x + 1).collect() + } + + fn linked_list_push_front_mixed( + iter: impl Iterator, + iter2: impl Iterator, + ) -> LinkedList { + + //~^ needless_collect + + + + + + + + [5].into_iter().chain([1, 3].into_iter().chain(iter).chain([2]).chain(iter2)).chain([4, 6]).map(|x| x + 1).collect() + } +} diff --git a/tests/ui/needless_collect.rs b/tests/ui/needless_collect.rs index 683cc49c9af3..346cddd88e70 100644 --- a/tests/ui/needless_collect.rs +++ b/tests/ui/needless_collect.rs @@ -219,3 +219,79 @@ fn issue16270() { // Do not lint, `..` implements `Index` but is not `usize` _ = &(1..3).collect::>()[..]; } + +#[warn(clippy::needless_collect)] +mod collect_push_then_iter { + use std::collections::{BinaryHeap, LinkedList, VecDeque}; + + fn vec_push(iter: impl Iterator) -> Vec { + let mut v = iter.collect::>(); + //~^ needless_collect + v.push(1); + v.into_iter().map(|x| x + 1).collect() + } + + fn vec_push_no_iter(iter: impl Iterator) { + let mut v = iter.collect::>(); + v.push(1); + } + + fn vec_push_multiple(iter: impl Iterator) -> Vec { + let mut v = iter.collect::>(); + //~^ needless_collect + v.push(1); + v.push(2); + v.into_iter().map(|x| x + 1).collect() + } + + fn linked_list_push(iter: impl Iterator) -> LinkedList { + let mut v = iter.collect::>(); + //~^ needless_collect + v.push_back(1); + v.into_iter().map(|x| x + 1).collect() + } + + fn binary_heap_push(iter: impl Iterator) -> BinaryHeap { + let mut v = iter.collect::>(); + v.push(1); + v.into_iter().map(|x| x + 1).collect() + } + + fn vec_push_mixed(iter: impl Iterator) -> bool { + let mut v = iter.collect::>(); + let ok = v.contains(&1); + v.push(1); + ok + } + + fn linked_list_extend(iter: impl Iterator, s: Vec) -> LinkedList { + let mut ll = iter.collect::>(); + //~^ needless_collect + ll.extend(s); + ll.into_iter().map(|x| x + 1).collect() + } + + fn deque_push_front(iter: impl Iterator) -> VecDeque { + let mut v = iter.collect::>(); + //~^ needless_collect + v.push_front(1); + v.push_front(2); + v.into_iter().map(|x| x + 1).collect() + } + + fn linked_list_push_front_mixed( + iter: impl Iterator, + iter2: impl Iterator, + ) -> LinkedList { + let mut v = iter.collect::>(); + //~^ needless_collect + v.push_front(1); + v.push_back(2); + v.push_front(3); + v.extend(iter2); + v.push_back(4); + v.push_front(5); + v.push_back(6); + v.into_iter().map(|x| x + 1).collect() + } +} diff --git a/tests/ui/needless_collect.stderr b/tests/ui/needless_collect.stderr index c77674dc55d4..b10312224c8e 100644 --- a/tests/ui/needless_collect.stderr +++ b/tests/ui/needless_collect.stderr @@ -121,5 +121,115 @@ error: avoid using `collect()` when not needed LL | baz((0..10), (), ('a'..='z').collect::>()) | ^^^^^^^^^^^^^^^^^^^^ help: remove this call -error: aborting due to 20 previous errors +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:228:26 + | +LL | let mut v = iter.collect::>(); + | ^^^^^^^ +... +LL | v.into_iter().map(|x| x + 1).collect() + | ------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ iter.chain([1]).map(|x| x + 1).collect() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:240:26 + | +LL | let mut v = iter.collect::>(); + | ^^^^^^^ +... +LL | v.into_iter().map(|x| x + 1).collect() + | ------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ +LL ~ iter.chain([1, 2]).map(|x| x + 1).collect() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:248:26 + | +LL | let mut v = iter.collect::>(); + | ^^^^^^^ +... +LL | v.into_iter().map(|x| x + 1).collect() + | ------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ iter.chain([1]).map(|x| x + 1).collect() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:268:27 + | +LL | let mut ll = iter.collect::>(); + | ^^^^^^^ +... +LL | ll.into_iter().map(|x| x + 1).collect() + | -------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ iter.chain(s).map(|x| x + 1).collect() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:275:26 + | +LL | let mut v = iter.collect::>(); + | ^^^^^^^ +... +LL | v.into_iter().map(|x| x + 1).collect() + | ------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ +LL ~ [1, 2].into_iter().chain(iter).map(|x| x + 1).collect() + | + +error: avoid using `collect()` when not needed + --> tests/ui/needless_collect.rs:286:26 + | +LL | let mut v = iter.collect::>(); + | ^^^^^^^ +... +LL | v.into_iter().map(|x| x + 1).collect() + | ------------- the iterator could be used here instead + | +help: use the original Iterator instead of collecting it and then producing a new one + | +LL ~ +LL | +LL ~ +LL ~ +LL ~ +LL ~ +LL ~ +LL ~ +LL ~ +LL ~ [5].into_iter().chain([1, 3].into_iter().chain(iter).chain([2]).chain(iter2)).chain([4, 6]).map(|x| x + 1).collect() + | + +error: aborting due to 26 previous errors diff --git a/tests/ui/needless_continue.rs b/tests/ui/needless_continue.rs index 88b7905e7fa8..3275dddf1a0f 100644 --- a/tests/ui/needless_continue.rs +++ b/tests/ui/needless_continue.rs @@ -342,3 +342,38 @@ fn issue15548() { } } } + +fn issue16256() { + fn some_condition() -> bool { + true + } + fn another_condition() -> bool { + true + } + + for _ in 0..5 { + if some_condition() { + // ... + continue; + } + + if another_condition() { + // ... + // "this `continue` expression is redundant" is posted on + // the `continue` node. + #[expect(clippy::needless_continue)] + continue; + } + } + + for _ in 0..5 { + // "This `else` block is redundant" is posted on the + // `else` node. + #[expect(clippy::needless_continue)] + if some_condition() { + // ... + } else { + continue; + } + } +} diff --git a/tests/ui/needless_lifetimes.fixed b/tests/ui/needless_lifetimes.fixed index 15ca409c95bd..90a07454b4d7 100644 --- a/tests/ui/needless_lifetimes.fixed +++ b/tests/ui/needless_lifetimes.fixed @@ -470,13 +470,36 @@ mod in_macro { } } - // no lint on external macro + // no lint on external macro (standalone function) external! { fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 { unimplemented!() } } + // no lint on external macro (method in impl block) + external! { + struct ExternalStruct; + + impl ExternalStruct { + fn needless_lifetime_method<'a>(x: &'a u8) -> &'a u8 { + unimplemented!() + } + } + } + + // no lint on external macro (trait method) + external! { + trait ExternalTrait { + fn needless_lifetime_trait_method<'a>(x: &'a u8) -> &'a u8; + } + } + + // no lint on external macro (extra unused lifetimes in function) + external! { + fn extra_unused_lifetime<'a>(x: u8) {} + } + inline! { fn f<$'a>(arg: &$'a str) -> &$'a str { arg diff --git a/tests/ui/needless_lifetimes.rs b/tests/ui/needless_lifetimes.rs index af9649d72987..6df38897f42d 100644 --- a/tests/ui/needless_lifetimes.rs +++ b/tests/ui/needless_lifetimes.rs @@ -470,13 +470,36 @@ mod in_macro { } } - // no lint on external macro + // no lint on external macro (standalone function) external! { fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 { unimplemented!() } } + // no lint on external macro (method in impl block) + external! { + struct ExternalStruct; + + impl ExternalStruct { + fn needless_lifetime_method<'a>(x: &'a u8) -> &'a u8 { + unimplemented!() + } + } + } + + // no lint on external macro (trait method) + external! { + trait ExternalTrait { + fn needless_lifetime_trait_method<'a>(x: &'a u8) -> &'a u8; + } + } + + // no lint on external macro (extra unused lifetimes in function) + external! { + fn extra_unused_lifetime<'a>(x: u8) {} + } + inline! { fn f<$'a>(arg: &$'a str) -> &$'a str { arg diff --git a/tests/ui/significant_drop_tightening.fixed b/tests/ui/significant_drop_tightening.fixed index 3d416056226c..559c1bb94570 100644 --- a/tests/ui/significant_drop_tightening.fixed +++ b/tests/ui/significant_drop_tightening.fixed @@ -146,3 +146,39 @@ pub fn unnecessary_contention_with_single_owned_results() { pub fn do_heavy_computation_that_takes_time(_: T) {} fn main() {} + +fn issue15574() { + use std::io::{BufRead, Read, stdin}; + use std::process; + + println!("Hello, what's your name?"); + + let mut stdin = stdin().lock().take(40); + //~^ significant_drop_tightening + let mut buffer = String::with_capacity(10); + + + //~^ significant_drop_tightening + if stdin.read_line(&mut buffer).is_err() { + eprintln!("An error has occured while reading."); + return; + } + drop(stdin); + println!("Our string has a capacity of {}", buffer.capacity()); + println!("Hello {}!", buffer); +} + +fn issue16343() { + fn get_items(x: &()) -> Vec<()> { + vec![*x] + } + + let storage = Mutex::new(()); + let lock = storage.lock().unwrap(); + //~^ significant_drop_tightening + let items = get_items(&lock); + drop(lock); + for item in items { + println!("item {:?}", item); + } +} diff --git a/tests/ui/significant_drop_tightening.rs b/tests/ui/significant_drop_tightening.rs index d9c4ad543593..dff36baf383d 100644 --- a/tests/ui/significant_drop_tightening.rs +++ b/tests/ui/significant_drop_tightening.rs @@ -142,3 +142,36 @@ pub fn unnecessary_contention_with_single_owned_results() { pub fn do_heavy_computation_that_takes_time(_: T) {} fn main() {} + +fn issue15574() { + use std::io::{BufRead, Read, stdin}; + use std::process; + + println!("Hello, what's your name?"); + let stdin = stdin().lock(); + //~^ significant_drop_tightening + let mut buffer = String::with_capacity(10); + + let mut stdin = stdin.take(40); + //~^ significant_drop_tightening + if stdin.read_line(&mut buffer).is_err() { + eprintln!("An error has occured while reading."); + return; + } + println!("Our string has a capacity of {}", buffer.capacity()); + println!("Hello {}!", buffer); +} + +fn issue16343() { + fn get_items(x: &()) -> Vec<()> { + vec![*x] + } + + let storage = Mutex::new(()); + let lock = storage.lock().unwrap(); + //~^ significant_drop_tightening + let items = get_items(&lock); + for item in items { + println!("item {:?}", item); + } +} diff --git a/tests/ui/significant_drop_tightening.stderr b/tests/ui/significant_drop_tightening.stderr index 25cd9da73a10..785bee4970ec 100644 --- a/tests/ui/significant_drop_tightening.stderr +++ b/tests/ui/significant_drop_tightening.stderr @@ -83,5 +83,74 @@ LL | LL ~ | -error: aborting due to 4 previous errors +error: temporary with significant `Drop` can be early dropped + --> tests/ui/significant_drop_tightening.rs:151:9 + | +LL | fn issue15574() { + | _________________- +LL | | use std::io::{BufRead, Read, stdin}; +LL | | use std::process; +... | +LL | | let stdin = stdin().lock(); + | | ^^^^^ +... | +LL | | println!("Hello {}!", buffer); +LL | | } + | |_- temporary `stdin` is currently being dropped at the end of its contained scope + | + = note: this might lead to unnecessary resource contention +help: merge the temporary construction with its single usage + | +LL ~ +LL + let mut stdin = stdin().lock().take(40); +LL | +LL | let mut buffer = String::with_capacity(10); +LL | +LL ~ + | + +error: temporary with significant `Drop` can be early dropped + --> tests/ui/significant_drop_tightening.rs:155:13 + | +LL | fn issue15574() { + | _________________- +LL | | use std::io::{BufRead, Read, stdin}; +LL | | use std::process; +... | +LL | | let mut stdin = stdin.take(40); + | | ^^^^^ +... | +LL | | println!("Hello {}!", buffer); +LL | | } + | |_- temporary `stdin` is currently being dropped at the end of its contained scope + | + = note: this might lead to unnecessary resource contention +help: drop the temporary after the end of its last usage + | +LL ~ } +LL + drop(stdin); + | + +error: temporary with significant `Drop` can be early dropped + --> tests/ui/significant_drop_tightening.rs:171:9 + | +LL | fn issue16343() { + | _________________- +LL | | fn get_items(x: &()) -> Vec<()> { +LL | | vec![*x] +... | +LL | | let lock = storage.lock().unwrap(); + | | ^^^^ +... | +LL | | } + | |_- temporary `lock` is currently being dropped at the end of its contained scope + | + = note: this might lead to unnecessary resource contention +help: drop the temporary after the end of its last usage + | +LL ~ let items = get_items(&lock); +LL + drop(lock); + | + +error: aborting due to 7 previous errors diff --git a/tests/ui/strlen_on_c_strings.fixed b/tests/ui/strlen_on_c_strings.fixed index 17c1b541f77c..6604da70874d 100644 --- a/tests/ui/strlen_on_c_strings.fixed +++ b/tests/ui/strlen_on_c_strings.fixed @@ -1,37 +1,68 @@ #![warn(clippy::strlen_on_c_strings)] -#![allow(dead_code, clippy::manual_c_str_literals)] +#![allow(clippy::manual_c_str_literals, clippy::boxed_local)] -#[allow(unused)] use libc::strlen; use std::ffi::{CStr, CString}; fn main() { // CString let cstring = CString::new("foo").expect("CString::new failed"); - let _ = cstring.as_bytes().len(); - //~^ strlen_on_c_strings + let _ = cstring.count_bytes(); + //~^ ERROR: using `libc::strlen` on a `CString` value // CStr let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); - let _ = cstr.to_bytes().len(); - //~^ strlen_on_c_strings + let _ = cstr.count_bytes(); + //~^ ERROR: using `libc::strlen` on a `CStr` value - let _ = cstr.to_bytes().len(); - //~^ strlen_on_c_strings + let _ = cstr.count_bytes(); + //~^ ERROR: using `libc::strlen` on a `CStr` value let pcstr: *const &CStr = &cstr; - let _ = unsafe { (*pcstr).to_bytes().len() }; - //~^ strlen_on_c_strings + let _ = unsafe { (*pcstr).count_bytes() }; + //~^ ERROR: using `libc::strlen` on a `CStr` value unsafe fn unsafe_identity(x: T) -> T { x } - let _ = unsafe { unsafe_identity(cstr).to_bytes().len() }; - //~^ strlen_on_c_strings - let _ = unsafe { unsafe_identity(cstr) }.to_bytes().len(); - //~^ strlen_on_c_strings + let _ = unsafe { unsafe_identity(cstr).count_bytes() }; + //~^ ERROR: using `libc::strlen` on a `CStr` value + let _ = unsafe { unsafe_identity(cstr) }.count_bytes(); + //~^ ERROR: using `libc::strlen` on a `CStr` value let f: unsafe fn(_) -> _ = unsafe_identity; - let _ = unsafe { f(cstr).to_bytes().len() }; + let _ = unsafe { f(cstr).count_bytes() }; + //~^ ERROR: using `libc::strlen` on a `CStr` value +} + +// make sure we lint types that _adjust_ to `CStr` +fn adjusted(box_cstring: Box, box_cstr: Box, arc_cstring: std::sync::Arc) { + let _ = box_cstring.count_bytes(); + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` + let _ = box_cstr.count_bytes(); + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` + let _ = arc_cstring.count_bytes(); + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` +} + +#[clippy::msrv = "1.78"] +fn msrv_1_78() { + let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + let _ = cstr.to_bytes().len(); + //~^ strlen_on_c_strings + + let cstring = CString::new("foo").expect("CString::new failed"); + let _ = cstring.to_bytes().len(); + //~^ strlen_on_c_strings +} + +#[clippy::msrv = "1.79"] +fn msrv_1_79() { + let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + let _ = cstr.count_bytes(); + //~^ strlen_on_c_strings + + let cstring = CString::new("foo").expect("CString::new failed"); + let _ = cstring.count_bytes(); //~^ strlen_on_c_strings } diff --git a/tests/ui/strlen_on_c_strings.rs b/tests/ui/strlen_on_c_strings.rs index c641422f5df4..11fbdf585064 100644 --- a/tests/ui/strlen_on_c_strings.rs +++ b/tests/ui/strlen_on_c_strings.rs @@ -1,7 +1,6 @@ #![warn(clippy::strlen_on_c_strings)] -#![allow(dead_code, clippy::manual_c_str_literals)] +#![allow(clippy::manual_c_str_literals, clippy::boxed_local)] -#[allow(unused)] use libc::strlen; use std::ffi::{CStr, CString}; @@ -9,29 +8,61 @@ fn main() { // CString let cstring = CString::new("foo").expect("CString::new failed"); let _ = unsafe { libc::strlen(cstring.as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CString` value // CStr let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); let _ = unsafe { libc::strlen(cstr.as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CStr` value let _ = unsafe { strlen(cstr.as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CStr` value let pcstr: *const &CStr = &cstr; let _ = unsafe { strlen((*pcstr).as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CStr` value unsafe fn unsafe_identity(x: T) -> T { x } let _ = unsafe { strlen(unsafe_identity(cstr).as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CStr` value let _ = unsafe { strlen(unsafe { unsafe_identity(cstr) }.as_ptr()) }; - //~^ strlen_on_c_strings + //~^ ERROR: using `libc::strlen` on a `CStr` value let f: unsafe fn(_) -> _ = unsafe_identity; let _ = unsafe { strlen(f(cstr).as_ptr()) }; + //~^ ERROR: using `libc::strlen` on a `CStr` value +} + +// make sure we lint types that _adjust_ to `CStr` +fn adjusted(box_cstring: Box, box_cstr: Box, arc_cstring: std::sync::Arc) { + let _ = unsafe { libc::strlen(box_cstring.as_ptr()) }; + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` + let _ = unsafe { libc::strlen(box_cstr.as_ptr()) }; + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` + let _ = unsafe { libc::strlen(arc_cstring.as_ptr()) }; + //~^ ERROR: using `libc::strlen` on a type that dereferences to `CStr` +} + +#[clippy::msrv = "1.78"] +fn msrv_1_78() { + let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + let _ = unsafe { libc::strlen(cstr.as_ptr()) }; + //~^ strlen_on_c_strings + + let cstring = CString::new("foo").expect("CString::new failed"); + let _ = unsafe { libc::strlen(cstring.as_ptr()) }; + //~^ strlen_on_c_strings +} + +#[clippy::msrv = "1.79"] +fn msrv_1_79() { + let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); + let _ = unsafe { libc::strlen(cstr.as_ptr()) }; + //~^ strlen_on_c_strings + + let cstring = CString::new("foo").expect("CString::new failed"); + let _ = unsafe { libc::strlen(cstring.as_ptr()) }; //~^ strlen_on_c_strings } diff --git a/tests/ui/strlen_on_c_strings.stderr b/tests/ui/strlen_on_c_strings.stderr index 84a93b99ee33..1f1b5ccdb0ef 100644 --- a/tests/ui/strlen_on_c_strings.stderr +++ b/tests/ui/strlen_on_c_strings.stderr @@ -1,47 +1,89 @@ -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:11:13 +error: using `libc::strlen` on a `CString` value + --> tests/ui/strlen_on_c_strings.rs:10:13 | LL | let _ = unsafe { libc::strlen(cstring.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstring.as_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstring.count_bytes()` | = note: `-D clippy::strlen-on-c-strings` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::strlen_on_c_strings)]` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:16:13 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:15:13 | LL | let _ = unsafe { libc::strlen(cstr.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstr.to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstr.count_bytes()` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:19:13 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:18:13 | LL | let _ = unsafe { strlen(cstr.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstr.to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstr.count_bytes()` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:23:22 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:22:22 | LL | let _ = unsafe { strlen((*pcstr).as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*pcstr).to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `(*pcstr).count_bytes()` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:29:22 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:28:22 | LL | let _ = unsafe { strlen(unsafe_identity(cstr).as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unsafe_identity(cstr).to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `unsafe_identity(cstr).count_bytes()` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:31:13 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:30:13 | LL | let _ = unsafe { strlen(unsafe { unsafe_identity(cstr) }.as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unsafe { unsafe_identity(cstr) }.to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `unsafe { unsafe_identity(cstr) }.count_bytes()` -error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:35:22 +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:34:22 | LL | let _ = unsafe { strlen(f(cstr).as_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `f(cstr).to_bytes().len()` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `f(cstr).count_bytes()` -error: aborting due to 7 previous errors +error: using `libc::strlen` on a type that dereferences to `CStr` + --> tests/ui/strlen_on_c_strings.rs:40:13 + | +LL | let _ = unsafe { libc::strlen(box_cstring.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `box_cstring.count_bytes()` + +error: using `libc::strlen` on a type that dereferences to `CStr` + --> tests/ui/strlen_on_c_strings.rs:42:13 + | +LL | let _ = unsafe { libc::strlen(box_cstr.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `box_cstr.count_bytes()` + +error: using `libc::strlen` on a type that dereferences to `CStr` + --> tests/ui/strlen_on_c_strings.rs:44:13 + | +LL | let _ = unsafe { libc::strlen(arc_cstring.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `arc_cstring.count_bytes()` + +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:51:13 + | +LL | let _ = unsafe { libc::strlen(cstr.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstr.to_bytes().len()` + +error: using `libc::strlen` on a `CString` value + --> tests/ui/strlen_on_c_strings.rs:55:13 + | +LL | let _ = unsafe { libc::strlen(cstring.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstring.to_bytes().len()` + +error: using `libc::strlen` on a `CStr` value + --> tests/ui/strlen_on_c_strings.rs:62:13 + | +LL | let _ = unsafe { libc::strlen(cstr.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstr.count_bytes()` + +error: using `libc::strlen` on a `CString` value + --> tests/ui/strlen_on_c_strings.rs:66:13 + | +LL | let _ = unsafe { libc::strlen(cstring.as_ptr()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `cstring.count_bytes()` + +error: aborting due to 14 previous errors diff --git a/tests/ui/suspicious_to_owned.1.fixed b/tests/ui/suspicious_to_owned.1.fixed new file mode 100644 index 000000000000..6fd536a38ed1 --- /dev/null +++ b/tests/ui/suspicious_to_owned.1.fixed @@ -0,0 +1,73 @@ +#![warn(clippy::suspicious_to_owned)] +#![warn(clippy::implicit_clone)] +#![allow(clippy::redundant_clone)] +use std::borrow::Cow; +use std::ffi::{CStr, c_char}; + +fn main() { + let moo = "Moooo"; + let c_moo = b"Moooo\0"; + let c_moo_ptr = c_moo.as_ptr() as *const c_char; + let moos = ['M', 'o', 'o']; + let moos_vec = moos.to_vec(); + + // we expect this to be linted + let cow = Cow::Borrowed(moo); + let _ = cow.into_owned(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(moo); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(moo); + let _ = cow.clone(); + + // we expect this to be linted + let cow = Cow::Borrowed(&moos); + let _ = cow.into_owned(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(&moos); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(&moos); + let _ = cow.clone(); + + // we expect this to be linted + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.into_owned(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.clone(); + + // we expect this to be linted + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.into_owned(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.clone(); + + // we expect no lints for these + let _ = moo.to_owned(); + let _ = c_moo.to_owned(); + let _ = moos.to_owned(); + + // we expect implicit_clone lints for these + let _ = String::from(moo).clone(); + //~^ implicit_clone + + let _ = moos_vec.clone(); + //~^ implicit_clone +} diff --git a/tests/ui/suspicious_to_owned.2.fixed b/tests/ui/suspicious_to_owned.2.fixed new file mode 100644 index 000000000000..841adf8ea274 --- /dev/null +++ b/tests/ui/suspicious_to_owned.2.fixed @@ -0,0 +1,73 @@ +#![warn(clippy::suspicious_to_owned)] +#![warn(clippy::implicit_clone)] +#![allow(clippy::redundant_clone)] +use std::borrow::Cow; +use std::ffi::{CStr, c_char}; + +fn main() { + let moo = "Moooo"; + let c_moo = b"Moooo\0"; + let c_moo_ptr = c_moo.as_ptr() as *const c_char; + let moos = ['M', 'o', 'o']; + let moos_vec = moos.to_vec(); + + // we expect this to be linted + let cow = Cow::Borrowed(moo); + let _ = cow.clone(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(moo); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(moo); + let _ = cow.clone(); + + // we expect this to be linted + let cow = Cow::Borrowed(&moos); + let _ = cow.clone(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(&moos); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(&moos); + let _ = cow.clone(); + + // we expect this to be linted + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.clone(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = Cow::Borrowed(&moos_vec); + let _ = cow.clone(); + + // we expect this to be linted + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.clone(); + //~^ suspicious_to_owned + + // we expect no lints for this + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.into_owned(); + // we expect no lints for this + let cow = unsafe { CStr::from_ptr(c_moo_ptr) }.to_string_lossy(); + let _ = cow.clone(); + + // we expect no lints for these + let _ = moo.to_owned(); + let _ = c_moo.to_owned(); + let _ = moos.to_owned(); + + // we expect implicit_clone lints for these + let _ = String::from(moo).clone(); + //~^ implicit_clone + + let _ = moos_vec.clone(); + //~^ implicit_clone +} diff --git a/tests/ui/suspicious_to_owned.rs b/tests/ui/suspicious_to_owned.rs index 2eec05ccaf4c..f59b3fd6ed0c 100644 --- a/tests/ui/suspicious_to_owned.rs +++ b/tests/ui/suspicious_to_owned.rs @@ -1,4 +1,3 @@ -//@no-rustfix: overlapping suggestions #![warn(clippy::suspicious_to_owned)] #![warn(clippy::implicit_clone)] #![allow(clippy::redundant_clone)] diff --git a/tests/ui/suspicious_to_owned.stderr b/tests/ui/suspicious_to_owned.stderr index f90bea5fb8ff..5fda1ed1cc9c 100644 --- a/tests/ui/suspicious_to_owned.stderr +++ b/tests/ui/suspicious_to_owned.stderr @@ -1,71 +1,71 @@ -error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned - --> tests/ui/suspicious_to_owned.rs:17:13 +error: this `to_owned` call clones the `Cow<'_, str>` itself and does not cause its contents to become owned + --> tests/ui/suspicious_to_owned.rs:16:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ | = note: `-D clippy::suspicious-to-owned` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::suspicious_to_owned)]` -help: depending on intent, either make the Cow an Owned variant +help: depending on intent, either make the `Cow` an `Owned` variant | LL | let _ = cow.into_owned(); | ++ -help: or clone the Cow itself +help: or clone the `Cow` itself | LL - let _ = cow.to_owned(); LL + let _ = cow.clone(); | -error: this `to_owned` call clones the Cow<'_, [char; 3]> itself and does not cause the Cow<'_, [char; 3]> contents to become owned - --> tests/ui/suspicious_to_owned.rs:29:13 +error: this `to_owned` call clones the `Cow<'_, [char; 3]>` itself and does not cause its contents to become owned + --> tests/ui/suspicious_to_owned.rs:28:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ | -help: depending on intent, either make the Cow an Owned variant +help: depending on intent, either make the `Cow` an `Owned` variant | LL | let _ = cow.into_owned(); | ++ -help: or clone the Cow itself +help: or clone the `Cow` itself | LL - let _ = cow.to_owned(); LL + let _ = cow.clone(); | -error: this `to_owned` call clones the Cow<'_, Vec> itself and does not cause the Cow<'_, Vec> contents to become owned - --> tests/ui/suspicious_to_owned.rs:41:13 +error: this `to_owned` call clones the `Cow<'_, Vec>` itself and does not cause its contents to become owned + --> tests/ui/suspicious_to_owned.rs:40:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ | -help: depending on intent, either make the Cow an Owned variant +help: depending on intent, either make the `Cow` an `Owned` variant | LL | let _ = cow.into_owned(); | ++ -help: or clone the Cow itself +help: or clone the `Cow` itself | LL - let _ = cow.to_owned(); LL + let _ = cow.clone(); | -error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned - --> tests/ui/suspicious_to_owned.rs:53:13 +error: this `to_owned` call clones the `Cow<'_, str>` itself and does not cause its contents to become owned + --> tests/ui/suspicious_to_owned.rs:52:13 | LL | let _ = cow.to_owned(); | ^^^^^^^^^^^^^^ | -help: depending on intent, either make the Cow an Owned variant +help: depending on intent, either make the `Cow` an `Owned` variant | LL | let _ = cow.into_owned(); | ++ -help: or clone the Cow itself +help: or clone the `Cow` itself | LL - let _ = cow.to_owned(); LL + let _ = cow.clone(); | error: implicitly cloning a `String` by calling `to_owned` on its dereferenced type - --> tests/ui/suspicious_to_owned.rs:69:13 + --> tests/ui/suspicious_to_owned.rs:68:13 | LL | let _ = String::from(moo).to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `String::from(moo).clone()` @@ -74,7 +74,7 @@ LL | let _ = String::from(moo).to_owned(); = help: to override `-D warnings` add `#[allow(clippy::implicit_clone)]` error: implicitly cloning a `Vec` by calling `to_owned` on its dereferenced type - --> tests/ui/suspicious_to_owned.rs:72:13 + --> tests/ui/suspicious_to_owned.rs:71:13 | LL | let _ = moos_vec.to_owned(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `moos_vec.clone()` diff --git a/tests/ui/transmuting_null.rs b/tests/ui/transmuting_null.rs index 00aa35dff803..efa4c5cfdc2d 100644 --- a/tests/ui/transmuting_null.rs +++ b/tests/ui/transmuting_null.rs @@ -47,9 +47,20 @@ fn transumute_single_expr_blocks() { } } +fn transmute_pointer_creators() { + unsafe { + let _: &u64 = std::mem::transmute(std::ptr::without_provenance::(0)); + //~^ transmuting_null + + let _: &u64 = std::mem::transmute(std::ptr::without_provenance_mut::(0)); + //~^ transmuting_null + } +} + fn main() { one_liners(); transmute_const(); transmute_const_int(); transumute_single_expr_blocks(); + transmute_pointer_creators(); } diff --git a/tests/ui/transmuting_null.stderr b/tests/ui/transmuting_null.stderr index e1de391813bd..3c6c28f31d0d 100644 --- a/tests/ui/transmuting_null.stderr +++ b/tests/ui/transmuting_null.stderr @@ -37,5 +37,17 @@ error: transmuting a known null pointer into a reference LL | let _: &u64 = std::mem::transmute(const { u64::MIN as *const u64 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: transmuting a known null pointer into a reference + --> tests/ui/transmuting_null.rs:52:23 + | +LL | let _: &u64 = std::mem::transmute(std::ptr::without_provenance::(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: transmuting a known null pointer into a reference + --> tests/ui/transmuting_null.rs:55:23 + | +LL | let _: &u64 = std::mem::transmute(std::ptr::without_provenance_mut::(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors diff --git a/tests/ui/unnecessary_map_or.fixed b/tests/ui/unnecessary_map_or.fixed index 10552431d65d..52c114339292 100644 --- a/tests/ui/unnecessary_map_or.fixed +++ b/tests/ui/unnecessary_map_or.fixed @@ -70,7 +70,7 @@ fn main() { let _ = r.is_ok_and(|x| x == 7); //~^ unnecessary_map_or - // lint constructs that are not comparaisons as well + // lint constructs that are not comparisons as well let func = |_x| true; let r: Result = Ok(3); let _ = r.is_ok_and(func); diff --git a/tests/ui/unnecessary_map_or.rs b/tests/ui/unnecessary_map_or.rs index 4b406ec2998b..dd2e1a569469 100644 --- a/tests/ui/unnecessary_map_or.rs +++ b/tests/ui/unnecessary_map_or.rs @@ -74,7 +74,7 @@ fn main() { let _ = r.map_or(false, |x| x == 7); //~^ unnecessary_map_or - // lint constructs that are not comparaisons as well + // lint constructs that are not comparisons as well let func = |_x| true; let r: Result = Ok(3); let _ = r.map_or(false, func); diff --git a/tests/ui/unnecessary_map_or.stderr b/tests/ui/unnecessary_map_or.stderr index b8a22346c378..d11e7179f921 100644 --- a/tests/ui/unnecessary_map_or.stderr +++ b/tests/ui/unnecessary_map_or.stderr @@ -56,7 +56,7 @@ LL | | 6 >= 5 LL | | }); | |______^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(5).map_or(false, |n| { LL + let _ = Some(5).is_some_and(|n| { @@ -68,7 +68,7 @@ error: this `map_or` can be simplified LL | let _ = Some(vec![5]).map_or(false, |n| n == [5]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(vec![5]).map_or(false, |n| n == [5]); LL + let _ = Some(vec![5]).is_some_and(|n| n == [5]); @@ -80,7 +80,7 @@ error: this `map_or` can be simplified LL | let _ = Some(vec![1]).map_or(false, |n| vec![2] == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(vec![1]).map_or(false, |n| vec![2] == n); LL + let _ = Some(vec![1]).is_some_and(|n| vec![2] == n); @@ -92,7 +92,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(false, |n| n == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(5).map_or(false, |n| n == n); LL + let _ = Some(5).is_some_and(|n| n == n); @@ -104,7 +104,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 }); LL + let _ = Some(5).is_some_and(|n| n == if 2 > 1 { n } else { 0 }); @@ -116,7 +116,7 @@ error: this `map_or` can be simplified LL | let _ = Ok::, i32>(vec![5]).map_or(false, |n| n == [5]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_ok_and instead +help: use `is_ok_and` instead | LL - let _ = Ok::, i32>(vec![5]).map_or(false, |n| n == [5]); LL + let _ = Ok::, i32>(vec![5]).is_ok_and(|n| n == [5]); @@ -152,7 +152,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(true, |n| n == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - let _ = Some(5).map_or(true, |n| n == 5); LL + let _ = Some(5).is_none_or(|n| n == 5); @@ -164,7 +164,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(true, |n| 5 == n); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - let _ = Some(5).map_or(true, |n| 5 == n); LL + let _ = Some(5).is_none_or(|n| 5 == n); @@ -212,7 +212,7 @@ error: this `map_or` can be simplified LL | let _ = r.map_or(false, |x| x == 7); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_ok_and instead +help: use `is_ok_and` instead | LL - let _ = r.map_or(false, |x| x == 7); LL + let _ = r.is_ok_and(|x| x == 7); @@ -224,7 +224,7 @@ error: this `map_or` can be simplified LL | let _ = r.map_or(false, func); | ^^^^^^^^^^^^^^^^^^^^^ | -help: use is_ok_and instead +help: use `is_ok_and` instead | LL - let _ = r.map_or(false, func); LL + let _ = r.is_ok_and(func); @@ -236,7 +236,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(false, func); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let _ = Some(5).map_or(false, func); LL + let _ = Some(5).is_some_and(func); @@ -248,7 +248,7 @@ error: this `map_or` can be simplified LL | let _ = Some(5).map_or(true, func); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - let _ = Some(5).map_or(true, func); LL + let _ = Some(5).is_none_or(func); @@ -272,7 +272,7 @@ error: this `map_or` can be simplified LL | o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) LL + o.is_none_or(|n| n > 5) || (o as &Option).map_or(true, |n| n < 5) @@ -284,7 +284,7 @@ error: this `map_or` can be simplified LL | o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - o.map_or(true, |n| n > 5) || (o as &Option).map_or(true, |n| n < 5) LL + o.map_or(true, |n| n > 5) || (o as &Option).is_none_or(|n| n < 5) @@ -296,7 +296,7 @@ error: this `map_or` can be simplified LL | o.map_or(true, |n| n > 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - o.map_or(true, |n| n > 5) LL + o.is_none_or(|n| n > 5) @@ -308,7 +308,7 @@ error: this `map_or` can be simplified LL | let x = a.map_or(false, |a| a == *s); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - let x = a.map_or(false, |a| a == *s); LL + let x = a.is_some_and(|a| a == *s); @@ -320,7 +320,7 @@ error: this `map_or` can be simplified LL | let y = b.map_or(true, |b| b == *s); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_none_or instead +help: use `is_none_or` instead | LL - let y = b.map_or(true, |b| b == *s); LL + let y = b.is_none_or(|b| b == *s); @@ -356,7 +356,7 @@ error: this `map_or` can be simplified LL | _ = s.lock().unwrap().map_or(false, |s| s == "foo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - _ = s.lock().unwrap().map_or(false, |s| s == "foo"); LL + _ = s.lock().unwrap().is_some_and(|s| s == "foo"); @@ -368,7 +368,7 @@ error: this `map_or` can be simplified LL | _ = s.map_or(false, |s| s == "foo"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: use is_some_and instead +help: use `is_some_and` instead | LL - _ = s.map_or(false, |s| s == "foo"); LL + _ = s.is_some_and(|s| s == "foo"); diff --git a/tests/ui/unnecessary_sort_by.fixed b/tests/ui/unnecessary_sort_by.fixed index 5255ab173efb..6870470e74c5 100644 --- a/tests/ui/unnecessary_sort_by.fixed +++ b/tests/ui/unnecessary_sort_by.fixed @@ -111,3 +111,65 @@ fn main() { issue_5754::test(); issue_6001::test(); } + +fn issue16405() { + let mut v: Vec<(i32, &str)> = vec![(1, "foo"), (2, "bar")]; + + v.sort_by_key(|a| a.0); + //~^ unnecessary_sort_by + + struct Item { + key: i32, + value: String, + } + + let mut items = vec![ + Item { + key: 2, + value: "b".to_string(), + }, + Item { + key: 1, + value: "a".to_string(), + }, + ]; + items.sort_by_key(|item1| item1.key); + //~^ unnecessary_sort_by + + items.sort_by(|item1, item2| item1.value.cmp(&item2.value)); + + items.sort_by_key(|item1| item1.value.clone()); + //~^ unnecessary_sort_by +} + +fn issue16348() { + let mut v: Vec<(i32, &str)> = vec![(1, "foo"), (2, "bar")]; + v.sort_by_key(|(_, s1)| *s1); + //~^ unnecessary_sort_by + + struct Foo { + bar: i32, + } + let mut v: Vec = vec![Foo { bar: 1 }, Foo { bar: 2 }]; + v.sort_by_key(|Foo { bar: b1 }| *b1); + //~^ unnecessary_sort_by + + struct Baz(i32); + let mut v: Vec = vec![Baz(1), Baz(2)]; + v.sort_by_key(|Baz(b1)| *b1); + //~^ unnecessary_sort_by + + v.sort_by_key(|&Baz(b1)| b1); + //~^ unnecessary_sort_by + + let mut v: Vec<&i32> = vec![&1, &2]; + v.sort_by_key(|&&b1| b1); + //~^ unnecessary_sort_by + + let mut v: Vec<[i32; 2]> = vec![[1, 2], [3, 4]]; + v.sort_by_key(|[a1, b1]| *a1); + //~^ unnecessary_sort_by + + v.sort_by_key(|[a1, b1]| a1 - b1); + //~^ unnecessary_sort_by +} diff --git a/tests/ui/unnecessary_sort_by.rs b/tests/ui/unnecessary_sort_by.rs index 65db7ca3f137..d95306176817 100644 --- a/tests/ui/unnecessary_sort_by.rs +++ b/tests/ui/unnecessary_sort_by.rs @@ -111,3 +111,65 @@ fn main() { issue_5754::test(); issue_6001::test(); } + +fn issue16405() { + let mut v: Vec<(i32, &str)> = vec![(1, "foo"), (2, "bar")]; + + v.sort_by(|a, b| a.0.cmp(&b.0)); + //~^ unnecessary_sort_by + + struct Item { + key: i32, + value: String, + } + + let mut items = vec![ + Item { + key: 2, + value: "b".to_string(), + }, + Item { + key: 1, + value: "a".to_string(), + }, + ]; + items.sort_by(|item1, item2| item1.key.cmp(&item2.key)); + //~^ unnecessary_sort_by + + items.sort_by(|item1, item2| item1.value.cmp(&item2.value)); + + items.sort_by(|item1, item2| item1.value.clone().cmp(&item2.value.clone())); + //~^ unnecessary_sort_by +} + +fn issue16348() { + let mut v: Vec<(i32, &str)> = vec![(1, "foo"), (2, "bar")]; + v.sort_by(|(_, s1), (_, s2)| s1.cmp(s2)); + //~^ unnecessary_sort_by + + struct Foo { + bar: i32, + } + let mut v: Vec = vec![Foo { bar: 1 }, Foo { bar: 2 }]; + v.sort_by(|Foo { bar: b1 }, Foo { bar: b2 }| b1.cmp(b2)); + //~^ unnecessary_sort_by + + struct Baz(i32); + let mut v: Vec = vec![Baz(1), Baz(2)]; + v.sort_by(|Baz(b1), Baz(b2)| b1.cmp(b2)); + //~^ unnecessary_sort_by + + v.sort_by(|&Baz(b1), &Baz(b2)| b1.cmp(&b2)); + //~^ unnecessary_sort_by + + let mut v: Vec<&i32> = vec![&1, &2]; + v.sort_by(|&&b1, &&b2| b1.cmp(&b2)); + //~^ unnecessary_sort_by + + let mut v: Vec<[i32; 2]> = vec![[1, 2], [3, 4]]; + v.sort_by(|[a1, b1], [a2, b2]| a1.cmp(a2)); + //~^ unnecessary_sort_by + + v.sort_by(|[a1, b1], [a2, b2]| (a1 - b1).cmp(&(a2 - b2))); + //~^ unnecessary_sort_by +} diff --git a/tests/ui/unnecessary_sort_by.stderr b/tests/ui/unnecessary_sort_by.stderr index a066554037fe..cc545d604ff3 100644 --- a/tests/ui/unnecessary_sort_by.stderr +++ b/tests/ui/unnecessary_sort_by.stderr @@ -2,76 +2,267 @@ error: consider using `sort` --> tests/ui/unnecessary_sort_by.rs:12:5 | LL | vec.sort_by(|a, b| a.cmp(b)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_sort_by)]` +help: try + | +LL - vec.sort_by(|a, b| a.cmp(b)); +LL + vec.sort(); + | error: consider using `sort_unstable` --> tests/ui/unnecessary_sort_by.rs:14:5 | LL | vec.sort_unstable_by(|a, b| a.cmp(b)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_unstable_by(|a, b| a.cmp(b)); +LL + vec.sort_unstable(); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by.rs:16:5 | LL | vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (a + 5).abs())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); +LL + vec.sort_by_key(|a| (a + 5).abs()); + | error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:18:5 | LL | vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| id(-a))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b))); +LL + vec.sort_unstable_by_key(|a| id(-a)); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by.rs:22:5 | LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|b| std::cmp::Reverse((b + 5).abs()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); +LL + vec.sort_by_key(|b| std::cmp::Reverse((b + 5).abs())); + | error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:24:5 | LL | vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|b| std::cmp::Reverse(id(-b)))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a))); +LL + vec.sort_unstable_by_key(|b| std::cmp::Reverse(id(-b))); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by.rs:35:5 | LL | vec.sort_by(|a, b| (***a).abs().cmp(&(***b).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (***a).abs())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_by(|a, b| (***a).abs().cmp(&(***b).abs())); +LL + vec.sort_by_key(|a| (***a).abs()); + | error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:37:5 | LL | vec.sort_unstable_by(|a, b| (***a).abs().cmp(&(***b).abs())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| (***a).abs())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_unstable_by(|a, b| (***a).abs().cmp(&(***b).abs())); +LL + vec.sort_unstable_by_key(|a| (***a).abs()); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by.rs:97:9 | LL | args.sort_by(|a, b| a.name().cmp(&b.name())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|a| a.name())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - args.sort_by(|a, b| a.name().cmp(&b.name())); +LL + args.sort_by_key(|a| a.name()); + | error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:99:9 | LL | args.sort_unstable_by(|a, b| a.name().cmp(&b.name())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_unstable_by_key(|a| a.name())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - args.sort_unstable_by(|a, b| a.name().cmp(&b.name())); +LL + args.sort_unstable_by_key(|a| a.name()); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by.rs:102:9 | LL | args.sort_by(|a, b| b.name().cmp(&a.name())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|b| std::cmp::Reverse(b.name()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - args.sort_by(|a, b| b.name().cmp(&a.name())); +LL + args.sort_by_key(|b| std::cmp::Reverse(b.name())); + | error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:104:9 | LL | args.sort_unstable_by(|a, b| b.name().cmp(&a.name())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_unstable_by_key(|b| std::cmp::Reverse(b.name()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - args.sort_unstable_by(|a, b| b.name().cmp(&a.name())); +LL + args.sort_unstable_by_key(|b| std::cmp::Reverse(b.name())); + | -error: aborting due to 12 previous errors +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:118:5 + | +LL | v.sort_by(|a, b| a.0.cmp(&b.0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|a, b| a.0.cmp(&b.0)); +LL + v.sort_by_key(|a| a.0); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:136:5 + | +LL | items.sort_by(|item1, item2| item1.key.cmp(&item2.key)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - items.sort_by(|item1, item2| item1.key.cmp(&item2.key)); +LL + items.sort_by_key(|item1| item1.key); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:141:5 + | +LL | items.sort_by(|item1, item2| item1.value.clone().cmp(&item2.value.clone())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - items.sort_by(|item1, item2| item1.value.clone().cmp(&item2.value.clone())); +LL + items.sort_by_key(|item1| item1.value.clone()); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:147:5 + | +LL | v.sort_by(|(_, s1), (_, s2)| s1.cmp(s2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|(_, s1), (_, s2)| s1.cmp(s2)); +LL + v.sort_by_key(|(_, s1)| *s1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:154:5 + | +LL | v.sort_by(|Foo { bar: b1 }, Foo { bar: b2 }| b1.cmp(b2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|Foo { bar: b1 }, Foo { bar: b2 }| b1.cmp(b2)); +LL + v.sort_by_key(|Foo { bar: b1 }| *b1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:159:5 + | +LL | v.sort_by(|Baz(b1), Baz(b2)| b1.cmp(b2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|Baz(b1), Baz(b2)| b1.cmp(b2)); +LL + v.sort_by_key(|Baz(b1)| *b1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:162:5 + | +LL | v.sort_by(|&Baz(b1), &Baz(b2)| b1.cmp(&b2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|&Baz(b1), &Baz(b2)| b1.cmp(&b2)); +LL + v.sort_by_key(|&Baz(b1)| b1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:166:5 + | +LL | v.sort_by(|&&b1, &&b2| b1.cmp(&b2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|&&b1, &&b2| b1.cmp(&b2)); +LL + v.sort_by_key(|&&b1| b1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:170:5 + | +LL | v.sort_by(|[a1, b1], [a2, b2]| a1.cmp(a2)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|[a1, b1], [a2, b2]| a1.cmp(a2)); +LL + v.sort_by_key(|[a1, b1]| *a1); + | + +error: consider using `sort_by_key` + --> tests/ui/unnecessary_sort_by.rs:173:5 + | +LL | v.sort_by(|[a1, b1], [a2, b2]| (a1 - b1).cmp(&(a2 - b2))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - v.sort_by(|[a1, b1], [a2, b2]| (a1 - b1).cmp(&(a2 - b2))); +LL + v.sort_by_key(|[a1, b1]| a1 - b1); + | + +error: aborting due to 22 previous errors diff --git a/tests/ui/unnecessary_sort_by_no_core.rs b/tests/ui/unnecessary_sort_by_no_core.rs new file mode 100644 index 000000000000..cb0da6339cb3 --- /dev/null +++ b/tests/ui/unnecessary_sort_by_no_core.rs @@ -0,0 +1,26 @@ +//@check-pass +#![feature(no_core)] +#![no_std] +#![no_core] +extern crate alloc; +extern crate core as mycore; +use alloc::vec; +use alloc::vec::Vec; +use mycore::cmp::Ord as _; + +fn issue_11524() -> Vec { + let mut vec = vec![1, 2, 3]; + + // We could lint and suggest `vec.sort_by_key(|a| a + 1);`, but we don't bother to -- see the + // comment in the lint at line 194 + vec.sort_by(|a, b| (a + 1).cmp(&(b + 1))); + vec +} + +fn issue_11524_2() -> Vec { + let mut vec = vec![1, 2, 3]; + + // Should not lint, as even `vec.sort_by_key(|b| core::cmp::Reverse(b + 1));` would not compile + vec.sort_by(|a, b| (b + 1).cmp(&(a + 1))); + vec +} diff --git a/tests/ui/unnecessary_sort_by_no_std.stderr b/tests/ui/unnecessary_sort_by_no_std.stderr index de3ef4123514..b4dd6a6dbdc5 100644 --- a/tests/ui/unnecessary_sort_by_no_std.stderr +++ b/tests/ui/unnecessary_sort_by_no_std.stderr @@ -2,16 +2,27 @@ error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by_no_std.rs:10:5 | LL | vec.sort_by(|a, b| (a + 1).cmp(&(b + 1))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| a + 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_sort_by)]` +help: try + | +LL - vec.sort_by(|a, b| (a + 1).cmp(&(b + 1))); +LL + vec.sort_by_key(|a| a + 1); + | error: consider using `sort_by_key` --> tests/ui/unnecessary_sort_by_no_std.rs:19:5 | LL | vec.sort_by(|a, b| (b + 1).cmp(&(a + 1))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|b| core::cmp::Reverse(b + 1))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - vec.sort_by(|a, b| (b + 1).cmp(&(a + 1))); +LL + vec.sort_by_key(|b| core::cmp::Reverse(b + 1)); + | error: aborting due to 2 previous errors diff --git a/tests/ui/while_let_loop.rs b/tests/ui/while_let_loop.rs index f28c504742fd..b5a362669ce2 100644 --- a/tests/ui/while_let_loop.rs +++ b/tests/ui/while_let_loop.rs @@ -253,3 +253,24 @@ fn let_assign() { } } } + +fn issue16378() { + // This does not lint today because of the extra statement(s) + // before the `break`. + // TODO: When the `break` statement/expr in the `let`/`else` is the + // only way to leave the loop, the lint could trigger and move + // the statements preceeding the `break` after the loop, as in: + // ```rust + // while let Some(x) = std::hint::black_box(None::) { + // println!("x = {x}"); + // } + // println!("fail"); + // ``` + loop { + let Some(x) = std::hint::black_box(None::) else { + println!("fail"); + break; + }; + println!("x = {x}"); + } +} From e86cfa0577af318b408fc786fa2fcac0a9961371 Mon Sep 17 00:00:00 2001 From: KaiTomotake Date: Thu, 22 Jan 2026 11:57:45 +0900 Subject: [PATCH 096/978] add foregin type tests add tests/ui/rfcs/rfc-1861-extern-types/comparison.rs --- .../rfcs/rfc-1861-extern-types/comparison.rs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/ui/rfcs/rfc-1861-extern-types/comparison.rs diff --git a/tests/ui/rfcs/rfc-1861-extern-types/comparison.rs b/tests/ui/rfcs/rfc-1861-extern-types/comparison.rs new file mode 100644 index 000000000000..6504fd64f64d --- /dev/null +++ b/tests/ui/rfcs/rfc-1861-extern-types/comparison.rs @@ -0,0 +1,35 @@ +// Foreign type tests not covering all operations +//@ only-nightly +//@ build-pass + +#![feature(extern_types)] + +#![allow(ambiguous_wide_pointer_comparisons)] + +extern "C" { + type ForeignType; +} + +#[repr(C)] +struct Example { + field: ForeignType, +} + +fn main() { + // pointer comparison + let a = std::ptr::null::(); + let b = std::ptr::null::(); + + assert!(a == b); + + // field address computation + let p = std::ptr::null::(); + unsafe { + let _ = &(*p).field; + } + + // pointer casts involving extern types + let raw = std::ptr::null::<()>(); + let ext = raw as *const ForeignType; + let _ = ext as *const (); +} From 1ebafc50427639355278cbd1bf83977f8589f451 Mon Sep 17 00:00:00 2001 From: "Matheus L. P." Date: Thu, 22 Jan 2026 16:32:35 -0600 Subject: [PATCH 097/978] fix(manual_let_else): add trailing comma when necessary Adds a trailing comma to struct patterns ending with `..`. Fixes rust-lang#16433 --- clippy_lints/src/manual_let_else.rs | 2 +- tests/ui/manual_let_else_match.fixed | 15 ++++++++++++++- tests/ui/manual_let_else_match.rs | 19 ++++++++++++++++++- tests/ui/manual_let_else_match.stderr | 12 +++++++++++- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/manual_let_else.rs b/clippy_lints/src/manual_let_else.rs index 38ee4ce104a5..cb3cc999c936 100644 --- a/clippy_lints/src/manual_let_else.rs +++ b/clippy_lints/src/manual_let_else.rs @@ -301,7 +301,7 @@ fn replace_in_pattern( .collect::>(); let fields_string = fields.join(", "); - let dot_dot_str = if dot_dot.is_some() { " .." } else { "" }; + let dot_dot_str = if dot_dot.is_some() { ", .." } else { "" }; let (sn_pth, _) = snippet_with_context(cx, path.span(), span.ctxt(), "", app); return format!("{sn_pth} {{ {fields_string}{dot_dot_str} }}"); }, diff --git a/tests/ui/manual_let_else_match.fixed b/tests/ui/manual_let_else_match.fixed index 15f604aec292..9cdf394e9ee4 100644 --- a/tests/ui/manual_let_else_match.fixed +++ b/tests/ui/manual_let_else_match.fixed @@ -1,4 +1,4 @@ -#![allow(unused_braces, unused_variables, dead_code)] +#![allow(unused_braces, unused_variables, dead_code, irrefutable_let_patterns)] #![allow( clippy::collapsible_else_if, clippy::let_unit_value, @@ -182,3 +182,16 @@ fn issue9939b() { let Some(Issue9939b { earthquake: erosion, hurricane: _x }) = issue else { unreachable!("can't happen") }; assert!(erosion); } + +mod issue16433 { + // https://github.com/rust-lang/rust-clippy/issues/16433 + struct A { + a: u32, + b: u32, + } + + fn foo() { + let a = A { a: 1, b: 1 }; + let A { a: first_arg, .. } = a else { return }; + } +} diff --git a/tests/ui/manual_let_else_match.rs b/tests/ui/manual_let_else_match.rs index 44a044b142bd..b1a20551e584 100644 --- a/tests/ui/manual_let_else_match.rs +++ b/tests/ui/manual_let_else_match.rs @@ -1,4 +1,4 @@ -#![allow(unused_braces, unused_variables, dead_code)] +#![allow(unused_braces, unused_variables, dead_code, irrefutable_let_patterns)] #![allow( clippy::collapsible_else_if, clippy::let_unit_value, @@ -250,3 +250,20 @@ fn issue9939b() { }; assert!(erosion); } + +mod issue16433 { + // https://github.com/rust-lang/rust-clippy/issues/16433 + struct A { + a: u32, + b: u32, + } + + fn foo() { + let a = A { a: 1, b: 1 }; + let first_arg = match a { + //~^ manual_let_else + A { a, .. } => a, + _ => return, + }; + } +} diff --git a/tests/ui/manual_let_else_match.stderr b/tests/ui/manual_let_else_match.stderr index ed6117ebffb7..6bbfb0e84d95 100644 --- a/tests/ui/manual_let_else_match.stderr +++ b/tests/ui/manual_let_else_match.stderr @@ -171,5 +171,15 @@ LL | | None => unreachable!("can't happen"), LL | | }; | |______^ help: consider writing: `let Some(Issue9939b { earthquake: erosion, hurricane: _x }) = issue else { unreachable!("can't happen") };` -error: aborting due to 17 previous errors +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else_match.rs:263:9 + | +LL | / let first_arg = match a { +LL | | +LL | | A { a, .. } => a, +LL | | _ => return, +LL | | }; + | |__________^ help: consider writing: `let A { a: first_arg, .. } = a else { return };` + +error: aborting due to 18 previous errors From 6710b7f1dfce4911e6dcfacf1ff621d8c0a72498 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 23 Jan 2026 11:24:01 +0200 Subject: [PATCH 098/978] coercions.md: add date-check marker r? @BoxyUwU --- src/doc/rustc-dev-guide/src/hir-typeck/coercions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc-dev-guide/src/hir-typeck/coercions.md b/src/doc/rustc-dev-guide/src/hir-typeck/coercions.md index 158ac0885d32..c63c64f5f945 100644 --- a/src/doc/rustc-dev-guide/src/hir-typeck/coercions.md +++ b/src/doc/rustc-dev-guide/src/hir-typeck/coercions.md @@ -1,4 +1,5 @@ # Coercions + Coercions are implicit operations which transform a value into a different type. A coercion *site* is a position where a coercion is able to be implicitly performed. There are two kinds of coercion sites: - one-to-one From 3157c0b674d90ced9fd6b5c8e8654b0c1a31bf5b Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Fri, 16 Jan 2026 23:02:25 +0100 Subject: [PATCH 099/978] reduce suggestion diff Now, only `call_span` is replaced, so the receiver is not a part of the diff. This also removes the need to create a snippet for the receiver. --- clippy_lints/src/methods/mod.rs | 2 +- clippy_lints/src/methods/str_split.rs | 31 +++++++---- tests/ui/str_split.stderr | 79 +++++++++++++++++++++++---- 3 files changed, 89 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 659a704a1ecb..36f69159e847 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -5538,7 +5538,7 @@ impl Methods { unnecessary_sort_by::check(cx, expr, recv, arg, true); }, (sym::split, [arg]) => { - str_split::check(cx, expr, recv, arg); + str_split::check(cx, expr, recv, call_span, arg); }, (sym::splitn | sym::rsplitn, [count_arg, pat_arg]) => { if let Some(Constant::Int(count)) = ConstEvalCtxt::new(cx).eval(count_arg) { diff --git a/clippy_lints/src/methods/str_split.rs b/clippy_lints/src/methods/str_split.rs index 9644b2c774b5..8641f7c0abec 100644 --- a/clippy_lints/src/methods/str_split.rs +++ b/clippy_lints/src/methods/str_split.rs @@ -1,20 +1,26 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_with_context; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sym; use clippy_utils::visitors::is_const_evaluatable; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; +use rustc_span::Span; use super::STR_SPLIT_AT_NEWLINE; -pub(super) fn check<'a>(cx: &LateContext<'a>, expr: &'_ Expr<'_>, split_recv: &'a Expr<'_>, split_arg: &'_ Expr<'_>) { +pub(super) fn check<'a>( + cx: &LateContext<'a>, + expr: &'_ Expr<'_>, + split_recv: &'a Expr<'_>, + split_span: Span, + split_arg: &'_ Expr<'_>, +) { // We're looking for `A.trim().split(B)`, where the adjusted type of `A` is `&str` (e.g. an // expression returning `String`), and `B` is a `Pattern` that hard-codes a newline (either `"\n"` // or `"\r\n"`). There are a lot of ways to specify a pattern, and this lint only checks the most // basic ones: a `'\n'`, `"\n"`, and `"\r\n"`. - if let ExprKind::MethodCall(trim_method_name, trim_recv, [], _) = split_recv.kind + if let ExprKind::MethodCall(trim_method_name, trim_recv, [], trim_span) = split_recv.kind && trim_method_name.ident.name == sym::trim && cx.typeck_results().expr_ty_adjusted(trim_recv).peel_refs().is_str() && !is_const_evaluatable(cx, trim_recv) @@ -24,18 +30,19 @@ pub(super) fn check<'a>(cx: &LateContext<'a>, expr: &'_ Expr<'_>, split_recv: &' LitKind::Char('\n') | LitKind::Str(sym::LF | sym::CRLF, _) ) { - let mut app = Applicability::MaybeIncorrect; - span_lint_and_sugg( + span_lint_and_then( cx, STR_SPLIT_AT_NEWLINE, expr.span, "using `str.trim().split()` with hard-coded newlines", - "use `str.lines()` instead", - format!( - "{}.lines()", - snippet_with_context(cx, trim_recv.span, expr.span.ctxt(), "..", &mut app).0 - ), - app, + |diag| { + diag.span_suggestion_verbose( + trim_span.to(split_span), // combine the call spans of the two methods + "use `str.lines()` instead", + "lines()", + Applicability::MaybeIncorrect, + ); + }, ); } } diff --git a/tests/ui/str_split.stderr b/tests/ui/str_split.stderr index 40202c8ac47a..1ab755008e56 100644 --- a/tests/ui/str_split.stderr +++ b/tests/ui/str_split.stderr @@ -2,64 +2,123 @@ error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:58:13 | LL | let _ = s1.trim().split('\n'); - | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()` + | ^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::str-split-at-newline` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::str_split_at_newline)]` +help: use `str.lines()` instead + | +LL - let _ = s1.trim().split('\n'); +LL + let _ = s1.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:61:13 | LL | let _ = s1.trim().split("\n"); - | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s1.trim().split("\n"); +LL + let _ = s1.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:63:13 | LL | let _ = s1.trim().split("\r\n"); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s1.trim().split("\r\n"); +LL + let _ = s1.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:67:13 | LL | let _ = s2.trim().split('\n'); - | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s2.trim().split('\n'); +LL + let _ = s2.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:70:13 | LL | let _ = s2.trim().split("\n"); - | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s2.trim().split("\n"); +LL + let _ = s2.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:72:13 | LL | let _ = s2.trim().split("\r\n"); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s2.trim().split("\r\n"); +LL + let _ = s2.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:77:13 | LL | let _ = s3.trim().split('\n'); - | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s3.trim().split('\n'); +LL + let _ = s3.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:80:13 | LL | let _ = s3.trim().split("\n"); - | ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s3.trim().split("\n"); +LL + let _ = s3.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:82:13 | LL | let _ = s3.trim().split("\r\n"); - | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = s3.trim().split("\r\n"); +LL + let _ = s3.lines(); + | error: using `str.trim().split()` with hard-coded newlines --> tests/ui/str_split.rs:86:13 | LL | let _ = make_str!(s1).trim().split('\n'); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `make_str!(s1).lines()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `str.lines()` instead + | +LL - let _ = make_str!(s1).trim().split('\n'); +LL + let _ = make_str!(s1).lines(); + | error: aborting due to 10 previous errors From 7ecd7cd582d9cc7a8ab23b36301c6cd5ddcf54c7 Mon Sep 17 00:00:00 2001 From: Redddy Date: Fri, 23 Jan 2026 22:20:50 +0900 Subject: [PATCH 100/978] Fix typo Co-authored-by: Yuki Okushi --- src/doc/rustc-dev-guide/src/walkthrough.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/walkthrough.md b/src/doc/rustc-dev-guide/src/walkthrough.md index 0522e9d444a9..4bfff17b5fdd 100644 --- a/src/doc/rustc-dev-guide/src/walkthrough.md +++ b/src/doc/rustc-dev-guide/src/walkthrough.md @@ -161,12 +161,12 @@ Here is the tracking issue on for our [`?` macro feature][tracking]. ## Experimental RFC (eRFC) -An eRFC is a variant of the RFC process used for complex features wherethe high-level need +An eRFC is a variant of the RFC process used for complex features where the high-level need is clear, but the design space is too large to settle on a detailed specification upfront. Instead of providing a final design, an eRFC outlines a high-level strategy to authorize a period of active experimentation. This allows the team to implement the feature behind a feature gate and gather practical data, which then informs a subsequent formal RFC for stabilization. -While this process was used for major features like coroutines ([see RFC2033][rfc2033]), +While this process was used for major features like coroutines ([see RFC 2033][rfc2033]), the explicit "eRFC" label is rarely used today. The project now generally prefers approving a standard RFC for an initial version and iterating on it through the nightly channel before final stabilization. From 36c0fb5a2dbb8b33407d814585e610d05d555030 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 23 Jan 2026 15:57:18 +0100 Subject: [PATCH 101/978] Add new `byte_value` and `char_value` methods to `proc_macro::Literal` --- library/proc_macro/src/lib.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index a005f743ddfa..2a75c4489095 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -54,7 +54,9 @@ use std::{error, fmt}; pub use diagnostic::{Diagnostic, Level, MultiSpan}; #[unstable(feature = "proc_macro_value", issue = "136652")] pub use rustc_literal_escaper::EscapeError; -use rustc_literal_escaper::{MixedUnit, unescape_byte_str, unescape_c_str, unescape_str}; +use rustc_literal_escaper::{ + MixedUnit, unescape_byte, unescape_byte_str, unescape_c_str, unescape_char, unescape_str, +}; #[unstable(feature = "proc_macro_totokens", issue = "130977")] pub use to_tokens::ToTokens; @@ -1443,6 +1445,28 @@ impl Literal { }) } + /// Returns the unescaped char value if the current literal is a char. + #[unstable(feature = "proc_macro_value", issue = "136652")] + pub fn byte_value(&self) -> Result { + self.0.symbol.with(|symbol| match self.0.kind { + bridge::LitKind::Char => { + unescape_byte(symbol).map_err(ConversionErrorKind::FailedToUnescape) + } + _ => Err(ConversionErrorKind::InvalidLiteralKind), + }) + } + + /// Returns the unescaped char value if the current literal is a char. + #[unstable(feature = "proc_macro_value", issue = "136652")] + pub fn char_value(&self) -> Result { + self.0.symbol.with(|symbol| match self.0.kind { + bridge::LitKind::Char => { + unescape_char(symbol).map_err(ConversionErrorKind::FailedToUnescape) + } + _ => Err(ConversionErrorKind::InvalidLiteralKind), + }) + } + /// Returns the unescaped string value if the current literal is a string or a string literal. #[unstable(feature = "proc_macro_value", issue = "136652")] pub fn str_value(&self) -> Result { From 33b77c8886ebc14cea9965eabd724265c2955266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 23 Jan 2026 17:53:48 +0100 Subject: [PATCH 102/978] Pass on the `feedable` query modifier to macros --- compiler/rustc_macros/src/query.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 1ad9bbc3b4b3..b13361b3e6a5 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -373,6 +373,7 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { no_hash, anon, eval_always, + feedable, depth_limit, separate_provide_extern, return_result_from_ensure_ok, From 6d36c8a5fc4dd9ad3a4cf95ca31ecdc7f06bafc1 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Thu, 25 Dec 2025 10:51:54 +0000 Subject: [PATCH 103/978] Return ExitCode from rustc_driver::main This makes rustc simply return an exit code from main rather than calling `std::process::exit` with an exit code. This means that drops run normally and the process exits cleanly. Also instead of hard coding success and failure codes this uses `ExitCode::SUCCESS` and `ExitCode::FAILURE`, which in turn effectively uses `libc::EXIT_SUCCESS` and `libc::EXIT_FAILURE` (via std). These are `0` and `1` respectively for all currently supported host platforms so it doesn't actually change the exit code. --- compiler/rustc/src/main.rs | 4 +++- compiler/rustc_driver_impl/src/lib.rs | 12 ++++++------ src/librustdoc/lib.rs | 9 ++++----- src/tools/clippy/src/driver.rs | 26 ++++++++++++++------------ src/tools/rustdoc/main.rs | 4 +++- tests/ui-fulldeps/obtain-borrowck.rs | 8 ++++---- 6 files changed, 34 insertions(+), 29 deletions(-) diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index 89c61cdf00a5..30d64b05cfde 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -3,6 +3,8 @@ // Several crates are depended upon but unused so that they are present in the sysroot #![expect(unused_crate_dependencies)] +use std::process::ExitCode; + // A note about jemalloc: rustc uses jemalloc when built for CI and // distribution. The obvious way to do this is with the `#[global_allocator]` // mechanism. However, for complicated reasons (see @@ -38,6 +40,6 @@ #[cfg(feature = "jemalloc")] use tikv_jemalloc_sys as _; -fn main() { +fn main() -> ExitCode { rustc_driver::main() } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 38ee87601614..9ecb85548f22 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -20,7 +20,7 @@ use std::fs::{self, File}; use std::io::{self, IsTerminal, Read, Write}; use std::panic::{self, PanicHookInfo}; use std::path::{Path, PathBuf}; -use std::process::{self, Command, Stdio}; +use std::process::{Command, ExitCode, Stdio, Termination}; use std::sync::OnceLock; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Instant; @@ -1382,10 +1382,10 @@ fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> { /// Variant of `catch_fatal_errors` for the `interface::Result` return type /// that also computes the exit code. -pub fn catch_with_exit_code(f: impl FnOnce()) -> i32 { +pub fn catch_with_exit_code(f: impl FnOnce() -> T) -> ExitCode { match catch_fatal_errors(f) { - Ok(()) => EXIT_SUCCESS, - _ => EXIT_FAILURE, + Ok(status) => status.report(), + _ => ExitCode::FAILURE, } } @@ -1670,7 +1670,7 @@ pub fn install_ctrlc_handler() { .expect("Unable to install ctrlc handler"); } -pub fn main() -> ! { +pub fn main() -> ExitCode { let start_time = Instant::now(); let start_rss = get_resident_set_size(); @@ -1690,5 +1690,5 @@ pub fn main() -> ! { print_time_passes_entry("total", start_time.elapsed(), start_rss, end_rss, format); } - process::exit(exit_code) + exit_code } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 137319ae0c06..21ac851e5486 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -71,7 +71,7 @@ extern crate tikv_jemalloc_sys as _; use std::env::{self, VarError}; use std::io::{self, IsTerminal}; use std::path::Path; -use std::process; +use std::process::ExitCode; use rustc_errors::DiagCtxtHandle; use rustc_hir::def_id::LOCAL_CRATE; @@ -126,7 +126,7 @@ mod visit; mod visit_ast; mod visit_lib; -pub fn main() { +pub fn main() -> ExitCode { let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); rustc_driver::install_ice_hook( @@ -164,11 +164,10 @@ pub fn main() { Err(error) => early_dcx.early_fatal(error.to_string()), } - let exit_code = rustc_driver::catch_with_exit_code(|| { + rustc_driver::catch_with_exit_code(|| { let at_args = rustc_driver::args::raw_args(&early_dcx); main_args(&mut early_dcx, &at_args); - }); - process::exit(exit_code); + }) } fn init_logging(early_dcx: &EarlyDiagCtxt) { diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 7425da70df90..cf06f43e8d4a 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -32,7 +32,7 @@ use std::env; use std::fs::read_to_string; use std::io::Write as _; use std::path::Path; -use std::process::exit; +use std::process::ExitCode; /// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If /// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`. @@ -182,15 +182,17 @@ impl rustc_driver::Callbacks for ClippyCallbacks { } } -fn display_help() { +fn display_help() -> ExitCode { if writeln!(&mut anstream::stdout().lock(), "{}", help_message()).is_err() { - exit(rustc_driver::EXIT_FAILURE); + ExitCode::FAILURE + } else { + ExitCode::SUCCESS } } const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml"; -pub fn main() { +pub fn main() -> ExitCode { let early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); rustc_driver::init_rustc_env_logger(&early_dcx); @@ -203,7 +205,7 @@ pub fn main() { dcx.handle().note(format!("Clippy version: {version_info}")); }); - exit(rustc_driver::catch_with_exit_code(move || { + rustc_driver::catch_with_exit_code(move || { let mut orig_args = rustc_driver::args::raw_args(&early_dcx); let has_sysroot_arg = |args: &mut [String]| -> bool { @@ -246,15 +248,15 @@ pub fn main() { pass_sysroot_env_if_given(&mut args, sys_root_env); rustc_driver::run_compiler(&args, &mut DefaultCallbacks); - return; + return ExitCode::SUCCESS; } if orig_args.iter().any(|a| a == "--version" || a == "-V") { let version_info = rustc_tools_util::get_version_info!(); - match writeln!(&mut anstream::stdout().lock(), "{version_info}") { - Ok(()) => exit(rustc_driver::EXIT_SUCCESS), - Err(_) => exit(rustc_driver::EXIT_FAILURE), + return match writeln!(&mut anstream::stdout().lock(), "{version_info}") { + Ok(()) => ExitCode::SUCCESS, + Err(_) => ExitCode::FAILURE, } } @@ -268,8 +270,7 @@ pub fn main() { } if !wrapper_mode && (orig_args.iter().any(|a| a == "--help" || a == "-h") || orig_args.len() == 1) { - display_help(); - exit(0); + return display_help(); } let mut args: Vec = orig_args.clone(); @@ -311,7 +312,8 @@ pub fn main() { } else { rustc_driver::run_compiler(&args, &mut RustcCallbacks { clippy_args_var }); } - })) + ExitCode::SUCCESS + }) } #[must_use] diff --git a/src/tools/rustdoc/main.rs b/src/tools/rustdoc/main.rs index d4099cafe5df..a35bcf9f547c 100644 --- a/src/tools/rustdoc/main.rs +++ b/src/tools/rustdoc/main.rs @@ -1,6 +1,8 @@ // We need this feature as it changes `dylib` linking behavior and allows us to link to `rustc_driver`. #![feature(rustc_private)] -fn main() { +use std::process::ExitCode; + +fn main() -> ExitCode { rustdoc::main() } diff --git a/tests/ui-fulldeps/obtain-borrowck.rs b/tests/ui-fulldeps/obtain-borrowck.rs index a562d0ccd3df..603eadad25b7 100644 --- a/tests/ui-fulldeps/obtain-borrowck.rs +++ b/tests/ui-fulldeps/obtain-borrowck.rs @@ -28,6 +28,7 @@ extern crate rustc_session; use std::cell::RefCell; use std::collections::HashMap; +use std::process::ExitCode; use std::thread_local; use rustc_borrowck::consumers::{self, BodyWithBorrowckFacts, ConsumerOptions}; @@ -42,16 +43,15 @@ use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_session::Session; -fn main() { - let exit_code = rustc_driver::catch_with_exit_code(move || { +fn main() -> ExitCode { + rustc_driver::catch_with_exit_code(move || { let mut rustc_args: Vec<_> = std::env::args().collect(); // We must pass -Zpolonius so that the borrowck information is computed. rustc_args.push("-Zpolonius".to_owned()); let mut callbacks = CompilerCalls::default(); // Call the Rust compiler with our callbacks. rustc_driver::run_compiler(&rustc_args, &mut callbacks); - }); - std::process::exit(exit_code); + }) } #[derive(Default)] From 4e4651b0457166674cff7dcf25410a3a9a95e811 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Thu, 25 Dec 2025 10:51:54 +0000 Subject: [PATCH 104/978] Return ExitCode from rustc_driver::main This makes rustc simply return an exit code from main rather than calling `std::process::exit` with an exit code. This means that drops run normally and the process exits cleanly. Also instead of hard coding success and failure codes this uses `ExitCode::SUCCESS` and `ExitCode::FAILURE`, which in turn effectively uses `libc::EXIT_SUCCESS` and `libc::EXIT_FAILURE` (via std). These are `0` and `1` respectively for all currently supported host platforms so it doesn't actually change the exit code. --- src/driver.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index 7425da70df90..cf06f43e8d4a 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -32,7 +32,7 @@ use std::env; use std::fs::read_to_string; use std::io::Write as _; use std::path::Path; -use std::process::exit; +use std::process::ExitCode; /// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If /// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`. @@ -182,15 +182,17 @@ impl rustc_driver::Callbacks for ClippyCallbacks { } } -fn display_help() { +fn display_help() -> ExitCode { if writeln!(&mut anstream::stdout().lock(), "{}", help_message()).is_err() { - exit(rustc_driver::EXIT_FAILURE); + ExitCode::FAILURE + } else { + ExitCode::SUCCESS } } const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml"; -pub fn main() { +pub fn main() -> ExitCode { let early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); rustc_driver::init_rustc_env_logger(&early_dcx); @@ -203,7 +205,7 @@ pub fn main() { dcx.handle().note(format!("Clippy version: {version_info}")); }); - exit(rustc_driver::catch_with_exit_code(move || { + rustc_driver::catch_with_exit_code(move || { let mut orig_args = rustc_driver::args::raw_args(&early_dcx); let has_sysroot_arg = |args: &mut [String]| -> bool { @@ -246,15 +248,15 @@ pub fn main() { pass_sysroot_env_if_given(&mut args, sys_root_env); rustc_driver::run_compiler(&args, &mut DefaultCallbacks); - return; + return ExitCode::SUCCESS; } if orig_args.iter().any(|a| a == "--version" || a == "-V") { let version_info = rustc_tools_util::get_version_info!(); - match writeln!(&mut anstream::stdout().lock(), "{version_info}") { - Ok(()) => exit(rustc_driver::EXIT_SUCCESS), - Err(_) => exit(rustc_driver::EXIT_FAILURE), + return match writeln!(&mut anstream::stdout().lock(), "{version_info}") { + Ok(()) => ExitCode::SUCCESS, + Err(_) => ExitCode::FAILURE, } } @@ -268,8 +270,7 @@ pub fn main() { } if !wrapper_mode && (orig_args.iter().any(|a| a == "--help" || a == "-h") || orig_args.len() == 1) { - display_help(); - exit(0); + return display_help(); } let mut args: Vec = orig_args.clone(); @@ -311,7 +312,8 @@ pub fn main() { } else { rustc_driver::run_compiler(&args, &mut RustcCallbacks { clippy_args_var }); } - })) + ExitCode::SUCCESS + }) } #[must_use] From 0c432af701682603f7e2863e339fb4222563ab6d Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 26 Dec 2025 18:44:02 +0000 Subject: [PATCH 105/978] Use ExitCode when returning from main in miri --- src/tools/miri/src/bin/miri.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 48f8e146a190..aa5e5d708da9 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -39,6 +39,7 @@ mod log; use std::env; use std::num::{NonZero, NonZeroI32}; use std::ops::Range; +use std::process::ExitCode; use std::rc::Rc; use std::str::FromStr; use std::sync::Once; @@ -404,7 +405,11 @@ fn run_compiler_and_exit( // Invoke compiler, catch any unwinding panics and handle return code. let exit_code = rustc_driver::catch_with_exit_code(move || rustc_driver::run_compiler(args, callbacks)); - exit(exit_code) + exit(if exit_code == ExitCode::SUCCESS { + rustc_driver::EXIT_SUCCESS + } else { + rustc_driver::EXIT_FAILURE + }) } /// Parses a comma separated list of `T` from the given string: @@ -434,7 +439,7 @@ fn parse_range(val: &str) -> Result, &'static str> { Ok(from..to) } -fn main() { +fn main() -> ExitCode { let early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); // Snapshot a copy of the environment before `rustc` starts messing with it. @@ -449,9 +454,7 @@ fn main() { if crate_kind == "host" { // For host crates like proc macros and build scripts, we are an entirely normal rustc. // These eventually produce actual binaries and never run in Miri. - match rustc_driver::main() { - // Empty match proves this function will never return. - } + return rustc_driver::main(); } else if crate_kind != "target" { panic!("invalid `MIRI_BE_RUSTC` value: {crate_kind:?}") }; From b0f680cfa496045e82596344710710ecaefd0ba9 Mon Sep 17 00:00:00 2001 From: Juho Kahala <57393910+quaternic@users.noreply.github.com> Date: Sat, 24 Jan 2026 02:05:22 +0200 Subject: [PATCH 106/978] Set `codegen-units=1` for benchmarks This should remove some of the nondeterminism in benchmark results observed in rust-lang/compiler-builtins#935. --- library/compiler-builtins/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/compiler-builtins/Cargo.toml b/library/compiler-builtins/Cargo.toml index 8501f4e630b5..d0eaa16393cd 100644 --- a/library/compiler-builtins/Cargo.toml +++ b/library/compiler-builtins/Cargo.toml @@ -51,6 +51,7 @@ codegen-units = 1 lto = "fat" [profile.bench] +codegen-units = 1 # Required for gungraun debug = true strip = false From a88826bb755b3b8ebc44ccf4d4a75d5d669d236f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 24 Jan 2026 00:05:58 +0000 Subject: [PATCH 107/978] chore: release libm v0.2.16 Co-authored-by: Trevor Gross --- library/compiler-builtins/libm/CHANGELOG.md | 16 ++++++++++++++++ library/compiler-builtins/libm/Cargo.toml | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/library/compiler-builtins/libm/CHANGELOG.md b/library/compiler-builtins/libm/CHANGELOG.md index 33fec06aa237..037f79ef3ef1 100644 --- a/library/compiler-builtins/libm/CHANGELOG.md +++ b/library/compiler-builtins/libm/CHANGELOG.md @@ -8,6 +8,22 @@ and this project adheres to ## [Unreleased] +## [0.2.16](https://github.com/rust-lang/compiler-builtins/compare/libm-v0.2.15...libm-v0.2.16) - 2025-12-07 + +### Fixed + +- Fix an incorrect result for `fminimum` and `fmaximum` with the input (-0, NaN) +- Fix a typo in `libm::Libm::roundeven` +- Fix the `expm1f` overflow threshold +- Change `CmpResult` to use a pointer-sized return type +- Compare against `CARGO_CFG_TARGET_FAMILY` in a multi-valued fashion +- Implement `exp` and its variants for i586 with inline assembly +- Implement `floor` and `ceil` in assembly on `i586` + +### Other + +- Significantly optimize `fmod` worst case performance ([#1002](https://github.com/rust-lang/compiler-builtins/pull/1002)) + ## [0.2.15](https://github.com/rust-lang/compiler-builtins/compare/libm-v0.2.14...libm-v0.2.15) - 2025-05-06 ### Other diff --git a/library/compiler-builtins/libm/Cargo.toml b/library/compiler-builtins/libm/Cargo.toml index 5b5ca34fd2c9..4d8b9bf827ad 100644 --- a/library/compiler-builtins/libm/Cargo.toml +++ b/library/compiler-builtins/libm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libm" -version = "0.2.15" +version = "0.2.16" authors = [ "Alex Crichton ", "Amanieu d'Antras ", From c0c6e2166d586d8b4b99afd3005725d9aa15f9ea Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Thu, 22 Jan 2026 20:22:06 -0800 Subject: [PATCH 108/978] make generic test invariant of function order --- tests/codegen-llvm/autodiff/generic.rs | 43 +++++++++++++++++--------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/tests/codegen-llvm/autodiff/generic.rs b/tests/codegen-llvm/autodiff/generic.rs index 6f56460a2b6d..b31468c91c9c 100644 --- a/tests/codegen-llvm/autodiff/generic.rs +++ b/tests/codegen-llvm/autodiff/generic.rs @@ -1,6 +1,14 @@ //@ compile-flags: -Zautodiff=Enable -Zautodiff=NoPostopt -C opt-level=3 -Clto=fat //@ no-prefer-dynamic //@ needs-enzyme +//@ revisions: F32 F64 Main + +// Here we verify that the function `square` can be differentiated over f64. +// This is interesting to test, since the user never calls `square` with f64, so on it's own rustc +// would have no reason to monomorphize it that way. However, Enzyme needs the f64 version of +// `square` in order to be able to differentiate it, so we have logic to enforce the +// monomorphization. Here, we test this logic. + #![feature(autodiff)] use std::autodiff::autodiff_reverse; @@ -12,32 +20,37 @@ fn square + Copy>(x: &T) -> T { } // Ensure that `d_square::` code is generated -// -// CHECK: ; generic::square -// CHECK-NEXT: ; Function Attrs: {{.*}} -// CHECK-NEXT: define internal {{.*}} float -// CHECK-NEXT: start: -// CHECK-NOT: ret -// CHECK: fmul float + +// F32-LABEL: ; generic::square:: +// F32-NEXT: ; Function Attrs: {{.*}} +// F32-NEXT: define internal {{.*}} float +// F32-NEXT: start: +// F32-NOT: ret +// F32: fmul float // Ensure that `d_square::` code is generated even if `square::` was never called -// -// CHECK: ; generic::square -// CHECK-NEXT: ; Function Attrs: -// CHECK-NEXT: define internal {{.*}} double -// CHECK-NEXT: start: -// CHECK-NOT: ret -// CHECK: fmul double + +// F64-LABEL: ; generic::d_square:: +// F64-NEXT: ; Function Attrs: {{.*}} +// F64-NEXT: define internal {{.*}} void +// F64-NEXT: start: +// F64-NEXT: {{(tail )?}}call {{(fastcc )?}}void @diffe_{{.*}}(double {{.*}}, ptr {{.*}}) +// F64-NEXT: ret void + +// Main-LABEL: ; generic::main +// Main: ; call generic::square:: +// Main: ; call generic::d_square:: fn main() { let xf32: f32 = std::hint::black_box(3.0); let xf64: f64 = std::hint::black_box(3.0); + let seed: f64 = std::hint::black_box(1.0); let outputf32 = square::(&xf32); assert_eq!(9.0, outputf32); let mut df_dxf64: f64 = std::hint::black_box(0.0); - let output_f64 = d_square::(&xf64, &mut df_dxf64, 1.0); + let output_f64 = d_square::(&xf64, &mut df_dxf64, seed); assert_eq!(6.0, df_dxf64); } From d7877615b41be6bccfad2e6858b9abc7e1834f6e Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Fri, 23 Jan 2026 20:37:58 -0800 Subject: [PATCH 109/978] Update test after new mangling scheme, make test more robust --- tests/codegen-llvm/autodiff/identical_fnc.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/codegen-llvm/autodiff/identical_fnc.rs b/tests/codegen-llvm/autodiff/identical_fnc.rs index 1c18e7acc4b6..a8b186c302ea 100644 --- a/tests/codegen-llvm/autodiff/identical_fnc.rs +++ b/tests/codegen-llvm/autodiff/identical_fnc.rs @@ -8,7 +8,7 @@ // merged placeholder function anymore, and compilation would fail. We prevent this by disabling // LLVM's merge_function pass before AD. Here we implicetely test that our solution keeps working. // We also explicetly test that we keep running merge_function after AD, by checking for two -// identical function calls in the LLVM-IR, while having two different calls in the Rust code. +// identical function calls in the LLVM-IR, despite having two different calls in the Rust code. #![feature(autodiff)] use std::autodiff::autodiff_reverse; @@ -27,14 +27,14 @@ fn square2(x: &f64) -> f64 { // CHECK:; identical_fnc::main // CHECK-NEXT:; Function Attrs: -// CHECK-NEXT:define internal void @_ZN13identical_fnc4main17h6009e4f751bf9407E() +// CHECK-NEXT:define internal void // CHECK-NEXT:start: // CHECK-NOT:br // CHECK-NOT:ret // CHECK:; call identical_fnc::d_square -// CHECK-NEXT:call fastcc void @_ZN13identical_fnc8d_square[[HASH:.+]](double %x.val, ptr noalias noundef align 8 dereferenceable(8) %dx1) +// CHECK-NEXT:call fastcc void @[[HASH:.+]](double %x.val, ptr noalias noundef align 8 dereferenceable(8) %dx1) // CHECK:; call identical_fnc::d_square -// CHECK-NEXT:call fastcc void @_ZN13identical_fnc8d_square[[HASH]](double %x.val, ptr noalias noundef align 8 dereferenceable(8) %dx2) +// CHECK-NEXT:call fastcc void @[[HASH]](double %x.val, ptr noalias noundef align 8 dereferenceable(8) %dx2) fn main() { let x = std::hint::black_box(3.0); From f5cdd5d86e1269cba321033e51e6dcd8c513b240 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Fri, 23 Jan 2026 15:00:11 -0600 Subject: [PATCH 110/978] Update hexagon target linker configurations * hexagon-unknown-qurt: Use hexagon-clang from Hexagon SDK instead of rust-lld * hexagon-unknown-linux-musl: Use hexagon-unknown-linux-musl-clang from the open source toolchain instead of rust-lld. * hexagon-unknown-none-elf: Keep rust-lld but fix the linker flavor. rust-lld is appropriate for a baremetal target but for traditional programs that depend on libc, using clang's driver makes the most sense. --- .../targets/hexagon_unknown_linux_musl.rs | 6 ++--- .../spec/targets/hexagon_unknown_none_elf.rs | 5 +++- .../src/spec/targets/hexagon_unknown_qurt.rs | 4 ++-- .../hexagon-unknown-linux-musl.md | 23 +++++++++++-------- .../platform-support/hexagon-unknown-qurt.md | 13 +++++++---- 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs index 82811cda00ce..92c477f53f8f 100644 --- a/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs @@ -1,4 +1,4 @@ -use crate::spec::{Arch, Cc, LinkerFlavor, Target, TargetMetadata, base}; +use crate::spec::{Arch, Cc, LinkerFlavor, Lld, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); @@ -8,8 +8,8 @@ pub(crate) fn target() -> Target { base.features = "-small-data,+hvx-length128b".into(); base.has_rpath = true; - base.linker = Some("rust-lld".into()); - base.linker_flavor = LinkerFlavor::Unix(Cc::Yes); + base.linker = Some("hexagon-unknown-linux-musl-clang".into()); + base.linker_flavor = LinkerFlavor::Gnu(Cc::Yes, Lld::No); base.c_enum_min_bits = Some(8); diff --git a/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs index 55ec3697a15e..3809057e255c 100644 --- a/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs @@ -1,4 +1,6 @@ -use crate::spec::{Arch, PanicStrategy, Target, TargetMetadata, TargetOptions}; +use crate::spec::{ + Arch, Cc, LinkerFlavor, Lld, PanicStrategy, Target, TargetMetadata, TargetOptions, +}; pub(crate) fn target() -> Target { Target { @@ -28,6 +30,7 @@ pub(crate) fn target() -> Target { emit_debug_gdb_scripts: false, c_enum_min_bits: Some(8), linker: Some("rust-lld".into()), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), ..Default::default() }, } diff --git a/compiler/rustc_target/src/spec/targets/hexagon_unknown_qurt.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_qurt.rs index 746e0cb11dcb..dcc92b4bdcc4 100644 --- a/compiler/rustc_target/src/spec/targets/hexagon_unknown_qurt.rs +++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_qurt.rs @@ -24,8 +24,8 @@ pub(crate) fn target() -> Target { os: Os::Qurt, vendor: "unknown".into(), cpu: "hexagonv69".into(), - linker: Some("rust-lld".into()), - linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("hexagon-clang".into()), + linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No), exe_suffix: ".elf".into(), dynamic_linking: true, executables: true, diff --git a/src/doc/rustc/src/platform-support/hexagon-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/hexagon-unknown-linux-musl.md index d74dd843eb25..eefe82133906 100644 --- a/src/doc/rustc/src/platform-support/hexagon-unknown-linux-musl.md +++ b/src/doc/rustc/src/platform-support/hexagon-unknown-linux-musl.md @@ -36,14 +36,19 @@ Also included in that toolchain is the C library that can be used when creating dynamically linked executables. ```text -# /opt/clang+llvm-18.1.0-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/bin/qemu-hexagon -L /opt/clang+llvm-18.1.0-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/target/hexagon-unknown-linux-musl/usr/ ./hello +# /opt/clang+llvm-VERSION-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/bin/qemu-hexagon -L /opt/clang+llvm-VERSION-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/target/hexagon-unknown-linux-musl/usr/ ./hello ``` ## Linking -This target selects `rust-lld` by default. Another option to use is -[eld](https://github.com/qualcomm/eld), which is also provided with -the opensource hexagon toolchain and the Hexagon SDK. +This target uses `hexagon-unknown-linux-musl-clang` as the default linker. +The linker is available from [the opensource hexagon toolchain](https://github.com/quic/toolchain_for_hexagon/releases) +at paths like `/opt/clang+llvm-21.1.8-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/bin/hexagon-unknown-linux-musl-clang`. + +Alternative linkers include: +- [eld](https://github.com/qualcomm/eld), which is provided with + the opensource hexagon toolchain and the Hexagon SDK +- `rust-lld` can be used by specifying `-C linker=rust-lld` ## Building the target Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this @@ -63,9 +68,9 @@ cxx = "hexagon-unknown-linux-musl-clang++" linker = "hexagon-unknown-linux-musl-clang" ar = "hexagon-unknown-linux-musl-ar" ranlib = "hexagon-unknown-linux-musl-ranlib" -musl-root = "/opt/clang+llvm-18.1.0-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/target/hexagon-unknown-linux-musl/usr" +musl-root = "/opt/clang+llvm-VERSION-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/target/hexagon-unknown-linux-musl/usr" llvm-libunwind = 'in-tree' -qemu-rootfs = "/opt/clang+llvm-18.1.0-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/target/hexagon-unknown-linux-musl/usr" +qemu-rootfs = "/opt/clang+llvm-VERSION-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/target/hexagon-unknown-linux-musl/usr" ``` @@ -88,7 +93,7 @@ target = "hexagon-unknown-linux-musl" [target.hexagon-unknown-linux-musl] linker = "hexagon-unknown-linux-musl-clang" ar = "hexagon-unknown-linux-musl-ar" -runner = "qemu-hexagon -L /opt/clang+llvm-18.1.0-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/target/hexagon-unknown-linux-musl/usr" +runner = "qemu-hexagon -L /opt/clang+llvm-VERSION-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/target/hexagon-unknown-linux-musl/usr" ``` Edit the "runner" in `.cargo/config` to point to the path to your toolchain's @@ -96,13 +101,13 @@ C library. ```text ... -runner = "qemu-hexagon -L /path/to/my/inst/clang+llvm-18.1.0-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/target/hexagon-unknown-linux-musl/usr" +runner = "qemu-hexagon -L /path/to/my/inst/clang+llvm-VERSION-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/target/hexagon-unknown-linux-musl/usr" ... ``` Build/run your rust program with `qemu-hexagon` in your `PATH`: ```text -export PATH=/path/to/my/inst/clang+llvm-18.1.0-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/bin/:$PATH +export PATH=/path/to/my/inst/clang+llvm-VERSION-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/bin/:$PATH cargo run -Zbuild-std -Zbuild-std-features=llvm-libunwind ``` diff --git a/src/doc/rustc/src/platform-support/hexagon-unknown-qurt.md b/src/doc/rustc/src/platform-support/hexagon-unknown-qurt.md index 7928804d0954..d33a90bf188c 100644 --- a/src/doc/rustc/src/platform-support/hexagon-unknown-qurt.md +++ b/src/doc/rustc/src/platform-support/hexagon-unknown-qurt.md @@ -33,10 +33,15 @@ required for building programs for this target. ## Linking -This target selects `rust-lld` by default. Another option to use is -[eld](https://github.com/qualcomm/eld), which is also provided with -[the opensource hexagon toolchain](https://github.com/quic/toolchain_for_hexagon) -and the Hexagon SDK. +This target uses `hexagon-clang` from the Hexagon SDK as the default linker. +The linker is available at paths like +`/opt/Hexagon_SDK/6.4.0.2/tools/HEXAGON_Tools/19.0.04/Tools/bin/hexagon-clang`. + +Alternative linkers include: +- [eld](https://github.com/qualcomm/eld), which is provided with both + [the opensource hexagon toolchain](https://github.com/quic/toolchain_for_hexagon) + and the Hexagon SDK +- `rust-lld` can be used by specifying `-C linker=rust-lld` ## Building the target From 7bcc8a705383710fe8ae1105799d4e1cb852f0e0 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Fri, 23 Jan 2026 21:54:04 -0800 Subject: [PATCH 111/978] update abi handling test --- tests/codegen-llvm/autodiff/abi_handling.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/codegen-llvm/autodiff/abi_handling.rs b/tests/codegen-llvm/autodiff/abi_handling.rs index 5c8126898a8d..a8bc482fc293 100644 --- a/tests/codegen-llvm/autodiff/abi_handling.rs +++ b/tests/codegen-llvm/autodiff/abi_handling.rs @@ -38,14 +38,14 @@ fn square(x: f32) -> f32 { // CHECK-LABEL: ; abi_handling::df1 // CHECK-NEXT: Function Attrs // debug-NEXT: define internal { float, float } -// debug-SAME: (ptr align 4 %x, ptr align 4 %bx_0) +// debug-SAME: (ptr {{.*}}%x, ptr {{.*}}%bx_0) // release-NEXT: define internal fastcc float // release-SAME: (float %x.0.val, float %x.4.val) // CHECK-LABEL: ; abi_handling::f1 // CHECK-NEXT: Function Attrs // debug-NEXT: define internal float -// debug-SAME: (ptr align 4 %x) +// debug-SAME: (ptr {{.*}}%x) // release-NEXT: define internal fastcc noundef float // release-SAME: (float %x.0.val, float %x.4.val) #[autodiff_forward(df1, Dual, Dual)] @@ -58,7 +58,7 @@ fn f1(x: &[f32; 2]) -> f32 { // CHECK-NEXT: Function Attrs // debug-NEXT: define internal { float, float } // debug-SAME: (ptr %f, float %x, float %dret) -// release-NEXT: define internal fastcc float +// release-NEXT: define internal fastcc noundef float // release-SAME: (float noundef %x) // CHECK-LABEL: ; abi_handling::f2 @@ -77,13 +77,13 @@ fn f2(f: fn(f32) -> f32, x: f32) -> f32 { // CHECK-NEXT: Function Attrs // debug-NEXT: define internal { float, float } // debug-SAME: (ptr align 4 %x, ptr align 4 %bx_0, ptr align 4 %y, ptr align 4 %by_0) -// release-NEXT: define internal fastcc { float, float } +// release-NEXT: define internal fastcc float // release-SAME: (float %x.0.val) // CHECK-LABEL: ; abi_handling::f3 // CHECK-NEXT: Function Attrs // debug-NEXT: define internal float -// debug-SAME: (ptr align 4 %x, ptr align 4 %y) +// debug-SAME: (ptr {{.*}}%x, ptr {{.*}}%y) // release-NEXT: define internal fastcc noundef float // release-SAME: (float %x.0.val) #[autodiff_forward(df3, Dual, Dual, Dual)] @@ -160,7 +160,7 @@ fn f6(i: NestedInput) -> f32 { // CHECK-LABEL: ; abi_handling::f7 // CHECK-NEXT: Function Attrs // debug-NEXT: define internal float -// debug-SAME: (ptr align 4 %x.0, ptr align 4 %x.1) +// debug-SAME: (ptr {{.*}}%x.0, ptr {{.*}}%x.1) // release-NEXT: define internal fastcc noundef float // release-SAME: (float %x.0.0.val, float %x.1.0.val) #[autodiff_forward(df7, Dual, Dual)] From b6d567c12cb16a0c02928dfea0db24523ddb9c5f Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Fri, 23 Jan 2026 23:18:52 -0800 Subject: [PATCH 112/978] Shorten the autodiff batching test, to make it more reliable --- tests/codegen-llvm/autodiff/batched.rs | 83 +++++--------------------- 1 file changed, 16 insertions(+), 67 deletions(-) diff --git a/tests/codegen-llvm/autodiff/batched.rs b/tests/codegen-llvm/autodiff/batched.rs index 0ff6134bc07d..5a723ff04183 100644 --- a/tests/codegen-llvm/autodiff/batched.rs +++ b/tests/codegen-llvm/autodiff/batched.rs @@ -1,13 +1,11 @@ //@ compile-flags: -Zautodiff=Enable,NoTT,NoPostopt -C opt-level=3 -Clto=fat //@ no-prefer-dynamic //@ needs-enzyme -// -// In Enzyme, we test against a large range of LLVM versions (5+) and don't have overly many -// breakages. One benefit is that we match the IR generated by Enzyme only after running it -// through LLVM's O3 pipeline, which will remove most of the noise. -// However, our integration test could also be affected by changes in how rustc lowers MIR into -// LLVM-IR, which could cause additional noise and thus breakages. If that's the case, we should -// reduce this test to only match the first lines and the ret instructions. + +// This test combines two features of Enzyme, automatic differentiation and batching. As such, it is +// especially prone to breakages. I reduced it therefore to a minimal check matches argument/return +// types. Based on the original batching author, implementing the batching feature over MLIR instead +// of LLVM should give significantly more reliable performance. #![feature(autodiff)] @@ -22,69 +20,20 @@ fn square(x: &f32) -> f32 { x * x } +// The base ("scalar") case d_square3, without batching. +// CHECK: define internal fastcc float @fwddiffesquare(float %x.0.val, float %"x'.0.val") +// CHECK: %0 = fadd fast float %"x'.0.val", %"x'.0.val" +// CHECK-NEXT: %1 = fmul fast float %0, %x.0.val +// CHECK-NEXT: ret float %1 +// CHECK-NEXT: } + // d_square2 -// CHECK: define internal [4 x float] @fwddiffe4square(ptr noalias noundef readonly align 4 captures(none) dereferenceable(4) %x, [4 x ptr] %"x'") -// CHECK-NEXT: start: -// CHECK-NEXT: %0 = extractvalue [4 x ptr] %"x'", 0 -// CHECK-NEXT: %"_2'ipl" = load float, ptr %0, align 4 -// CHECK-NEXT: %1 = extractvalue [4 x ptr] %"x'", 1 -// CHECK-NEXT: %"_2'ipl1" = load float, ptr %1, align 4 -// CHECK-NEXT: %2 = extractvalue [4 x ptr] %"x'", 2 -// CHECK-NEXT: %"_2'ipl2" = load float, ptr %2, align 4 -// CHECK-NEXT: %3 = extractvalue [4 x ptr] %"x'", 3 -// CHECK-NEXT: %"_2'ipl3" = load float, ptr %3, align 4 -// CHECK-NEXT: %_2 = load float, ptr %x, align 4 -// CHECK-NEXT: %4 = fmul fast float %"_2'ipl", %_2 -// CHECK-NEXT: %5 = fmul fast float %"_2'ipl1", %_2 -// CHECK-NEXT: %6 = fmul fast float %"_2'ipl2", %_2 -// CHECK-NEXT: %7 = fmul fast float %"_2'ipl3", %_2 -// CHECK-NEXT: %8 = fmul fast float %"_2'ipl", %_2 -// CHECK-NEXT: %9 = fmul fast float %"_2'ipl1", %_2 -// CHECK-NEXT: %10 = fmul fast float %"_2'ipl2", %_2 -// CHECK-NEXT: %11 = fmul fast float %"_2'ipl3", %_2 -// CHECK-NEXT: %12 = fadd fast float %4, %8 -// CHECK-NEXT: %13 = insertvalue [4 x float] undef, float %12, 0 -// CHECK-NEXT: %14 = fadd fast float %5, %9 -// CHECK-NEXT: %15 = insertvalue [4 x float] %13, float %14, 1 -// CHECK-NEXT: %16 = fadd fast float %6, %10 -// CHECK-NEXT: %17 = insertvalue [4 x float] %15, float %16, 2 -// CHECK-NEXT: %18 = fadd fast float %7, %11 -// CHECK-NEXT: %19 = insertvalue [4 x float] %17, float %18, 3 -// CHECK-NEXT: ret [4 x float] %19 +// CHECK: define internal fastcc [4 x float] @fwddiffe4square(float %x.0.val, [4 x ptr] %"x'") +// CHECK: ret [4 x float] // CHECK-NEXT: } -// d_square3, the extra float is the original return value (x * x) -// CHECK: define internal { float, [4 x float] } @fwddiffe4square.1(ptr noalias noundef readonly align 4 captures(none) dereferenceable(4) %x, [4 x ptr] %"x'") -// CHECK-NEXT: start: -// CHECK-NEXT: %0 = extractvalue [4 x ptr] %"x'", 0 -// CHECK-NEXT: %"_2'ipl" = load float, ptr %0, align 4 -// CHECK-NEXT: %1 = extractvalue [4 x ptr] %"x'", 1 -// CHECK-NEXT: %"_2'ipl1" = load float, ptr %1, align 4 -// CHECK-NEXT: %2 = extractvalue [4 x ptr] %"x'", 2 -// CHECK-NEXT: %"_2'ipl2" = load float, ptr %2, align 4 -// CHECK-NEXT: %3 = extractvalue [4 x ptr] %"x'", 3 -// CHECK-NEXT: %"_2'ipl3" = load float, ptr %3, align 4 -// CHECK-NEXT: %_2 = load float, ptr %x, align 4 -// CHECK-NEXT: %_0 = fmul float %_2, %_2 -// CHECK-NEXT: %4 = fmul fast float %"_2'ipl", %_2 -// CHECK-NEXT: %5 = fmul fast float %"_2'ipl1", %_2 -// CHECK-NEXT: %6 = fmul fast float %"_2'ipl2", %_2 -// CHECK-NEXT: %7 = fmul fast float %"_2'ipl3", %_2 -// CHECK-NEXT: %8 = fmul fast float %"_2'ipl", %_2 -// CHECK-NEXT: %9 = fmul fast float %"_2'ipl1", %_2 -// CHECK-NEXT: %10 = fmul fast float %"_2'ipl2", %_2 -// CHECK-NEXT: %11 = fmul fast float %"_2'ipl3", %_2 -// CHECK-NEXT: %12 = fadd fast float %4, %8 -// CHECK-NEXT: %13 = insertvalue [4 x float] undef, float %12, 0 -// CHECK-NEXT: %14 = fadd fast float %5, %9 -// CHECK-NEXT: %15 = insertvalue [4 x float] %13, float %14, 1 -// CHECK-NEXT: %16 = fadd fast float %6, %10 -// CHECK-NEXT: %17 = insertvalue [4 x float] %15, float %16, 2 -// CHECK-NEXT: %18 = fadd fast float %7, %11 -// CHECK-NEXT: %19 = insertvalue [4 x float] %17, float %18, 3 -// CHECK-NEXT: %20 = insertvalue { float, [4 x float] } undef, float %_0, 0 -// CHECK-NEXT: %21 = insertvalue { float, [4 x float] } %20, [4 x float] %19, 1 -// CHECK-NEXT: ret { float, [4 x float] } %21 +// CHECK: define internal fastcc { float, [4 x float] } @fwddiffe4square.{{.*}}(float %x.0.val, [4 x ptr] %"x'") +// CHECK: ret { float, [4 x float] } // CHECK-NEXT: } fn main() { From fcbb046ced6d4f93fffa724430a2feb3db0de08a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 24 Jan 2026 00:47:39 +0100 Subject: [PATCH 113/978] Add a marker to tell users that there are hidden (deprecated) items in the search results --- src/librustdoc/html/static/css/rustdoc.css | 11 ++++++++++- src/librustdoc/html/static/js/search.js | 12 +++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 486ca9b22539..b62d6b15cf36 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -341,7 +341,8 @@ summary.hideme, .rustdoc-breadcrumbs, .search-switcher, /* This selector is for the items listed in the "all items" page. */ -ul.all-items { +ul.all-items, +.deprecated-count { font-family: "Fira Sans", Arial, NanumBarunGothic, sans-serif; } @@ -2652,6 +2653,14 @@ However, it's not needed with smaller screen width because the doc/code block is display: none; } +.deprecated-count { + display: none; +} +.hide-deprecated-items .deprecated-count:not(:empty) { + display: block; + margin: 10px 0; +} + /* WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY If you update this line, then you also need to update the line with the same warning diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 9961c1447ec2..55ff48846dcb 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -158,6 +158,7 @@ const REGEX_INVALID_TYPE_FILTER = /[^a-z]/ui; const MAX_RESULTS = 200; const NO_TYPE_FILTER = -1; +const DEPRECATED_COUNT_SELECTOR = "deprecated-count"; /** * The [edit distance] is a metric for measuring the difference between two strings. @@ -4904,7 +4905,12 @@ async function addTab(results, query, display, finishedCallback, isTypeSearch) { let output = document.createElement("ul"); output.className = "search-results " + extraClass; + const deprecatedCountElem = document.createElement("span"); + deprecatedCountElem.className = DEPRECATED_COUNT_SELECTOR; + output.appendChild(deprecatedCountElem); + let count = 0; + let deprecatedCount = 0; /** @type {Promise[]} */ const descList = []; @@ -4922,6 +4928,10 @@ async function addTab(results, query, display, finishedCallback, isTypeSearch) { link.className = "result-" + type; if (obj.item.deprecated) { link.className += " deprecated"; + deprecatedCount += 1; + const plural = deprecatedCount > 1 ? "s" : ""; + deprecatedCountElem.innerText = + `${deprecatedCount} deprecated item${plural} hidden by setting`; } link.href = obj.href; @@ -5411,7 +5421,7 @@ function registerSearchEvents() { const active = document.activeElement; if (active) { const previous = active.previousElementSibling; - if (previous) { + if (previous && previous.className !== DEPRECATED_COUNT_SELECTOR) { // @ts-expect-error previous.focus(); } else { From 0e240d32325bdb491f8894b4dc1e720ec756c4f7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 24 Jan 2026 00:48:37 +0100 Subject: [PATCH 114/978] Add GUI regression test for the display and content of the "hidden deprecated item marker" --- tests/rustdoc-gui/setting-hide-deprecated.goml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tests/rustdoc-gui/setting-hide-deprecated.goml b/tests/rustdoc-gui/setting-hide-deprecated.goml index 6dc5a6bff175..0fefe00f9457 100644 --- a/tests/rustdoc-gui/setting-hide-deprecated.goml +++ b/tests/rustdoc-gui/setting-hide-deprecated.goml @@ -69,7 +69,7 @@ wait-for-css: ("details" + |deprecated_class|, {"display": "block"}, ALL) // And now we check with the search results. call-function: ("perform-search", {"query": "deprecated::depr"}) -// There should at least 7 results. +// There should be at least 7 results. store-count: ("#results ul.search-results.active > a", nb_search_results) assert: |nb_search_results| >= 7 // There should be at least 5 deprecated items. @@ -77,6 +77,12 @@ store-count: ("#results ul.search-results.active > a" + |deprecated_class|, nb_d assert: |nb_search_results| >= 5 // Deprecated items should all be displayed. assert-css: ("#results ul.search-results.active > a" + |deprecated_class|, {"display": "grid"}, ALL) +// The "X deprecated items hidden by setting" element should not be displayed. +assert-text: ( + "#results ul.search-results.active .deprecated-count", + "5 deprecated items hidden by setting", +) +assert-css: ("#results ul.search-results.active .deprecated-count", {"display": "none"}) // We enable the "hide deprecated items" setting. call-function: ("open-settings-menu", {}) click: "#hide-deprecated-items" @@ -86,11 +92,16 @@ wait-for-css: ( {"display": "none"}, ALL, ) +// The "X deprecated items hidden by setting" element should be displayed. +assert-css: ("#results ul.search-results.active .deprecated-count", {"display": "block"}) // Finally we check that the future deprecated item doesn't have the deprecated class in the search -// and therefore isn't impact by the setting. -call-function: ("perform-search", {"query": "deprecated::future_deprecated"}) +// and therefore isn't impacted by the setting. +call-function: ("perform-search", {"query": '"future_deprecated_fn"'}) assert-text: ( "#results ul.search-results.active > a:not(" + |deprecated_class| + ") .path", " lib2::deprecated::NonDeprecatedStruct::future_deprecated_fn", ) +// The "X deprecated items hidden by setting" element should now be empty, and therefore not displayed. +assert-text: ("#results ul.search-results.active .deprecated-count", "") +assert-css: ("#results ul.search-results.active .deprecated-count", {"display": "none"}) From 0cb56dc92ca0f716a6e1512ce93ff5223bb191c9 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Tue, 13 Jan 2026 16:52:02 +0200 Subject: [PATCH 115/978] abi: add a rust-preserve-none calling convention This is the conceptual opposite of the rust-cold calling convention and is particularly useful in combination with the new `explicit_tail_calls` feature. For relatively tight loops implemented with tail calling (`become`) each of the function with the regular calling convention is still responsible for restoring the initial value of the preserved registers. So it is not unusual to end up with a situation where each step in the tail call loop is spilling and reloading registers, along the lines of: foo: push r12 ; do things pop r12 jmp next_step This adds up quickly, especially when most of the clobberable registers are already used to pass arguments or other uses. I was thinking of making the name of this ABI a little less LLVM-derived and more like a conceptual inverse of `rust-cold`, but could not come with a great name (`rust-cold` is itself not a great name: cold in what context? from which perspective? is it supposed to mean that the function is rarely called?) --- src/abi.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/abi.rs b/src/abi.rs index cc2c9fca94df..56ed7c01ed20 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -243,6 +243,8 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { pub fn conv_to_fn_attribute<'gcc>(conv: CanonAbi, arch: &Arch) -> Option> { let attribute = match conv { CanonAbi::C | CanonAbi::Rust => return None, + // gcc/gccjit does not have anything for this. + CanonAbi::RustPreserveNone => return None, CanonAbi::RustCold => FnAttribute::Cold, // Functions with this calling convention can only be called from assembly, but it is // possible to declare an `extern "custom"` block, so the backend still needs a calling From 58156c5cab242898ab0130b7a428b7e14bf3a066 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 24 Jan 2026 11:45:53 -0500 Subject: [PATCH 116/978] Fix segfault related to __builtin_unreachable with inline asm --- src/asm.rs | 4 +--- tests/run/unreachable-function.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 tests/run/unreachable-function.rs diff --git a/src/asm.rs b/src/asm.rs index ceb3dd3ffedf..319f3d327873 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -575,9 +575,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } if dest.is_none() && options.contains(InlineAsmOptions::NORETURN) { let builtin_unreachable = self.context.get_builtin_function("__builtin_unreachable"); - let builtin_unreachable: RValue<'gcc> = - unsafe { std::mem::transmute(builtin_unreachable) }; - self.call(self.type_void(), None, None, builtin_unreachable, &[], None, None); + self.llbb().add_eval(None, self.context.new_call(None, builtin_unreachable, &[])); } // Write results to outputs. diff --git a/tests/run/unreachable-function.rs b/tests/run/unreachable-function.rs new file mode 100644 index 000000000000..0a975487dd78 --- /dev/null +++ b/tests/run/unreachable-function.rs @@ -0,0 +1,27 @@ +// Compiler: +// +// Run-time: +// status: 0 + +use std::arch::asm; + +fn exit_syscall(status: i32) -> ! { + #[cfg(target_arch = "x86_64")] + unsafe { + asm!( + "syscall", + in("rax") 60, + in("rdi") status, + options(noreturn) + ); + } + + #[cfg(not(target_arch = "x86_64"))] + std::process::exit(status); +} + +fn main() { + // Used to crash with rustc_codegen_gcc. + exit_syscall(0); + std::process::exit(1); +} From 2bae85ec5221b6276d82a63adcdb15f11a9ea131 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sat, 24 Jan 2026 11:06:07 -0800 Subject: [PATCH 117/978] Remove `derive(Copy)` on `ArrayWindows` The derived `T: Copy` constraint is not appropriate for an iterator by reference, but we generally do not want `Copy` on iterators anyway. --- library/core/src/slice/iter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index a289b0d6df40..03c503f169c8 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2175,7 +2175,7 @@ unsafe impl Sync for ChunksExactMut<'_, T> where T: Sync {} /// /// [`array_windows`]: slice::array_windows /// [slices]: slice -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] #[stable(feature = "array_windows", since = "1.94.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ArrayWindows<'a, T: 'a, const N: usize> { From 90521553e6fd9bb952fb0f064f7fa022d85d0493 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sat, 24 Jan 2026 11:08:25 -0800 Subject: [PATCH 118/978] Manually `impl Clone for ArrayWindows` This implementation doesn't need the derived `T: Clone`. --- library/core/src/slice/iter.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 03c503f169c8..af63ffa9b0bf 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2175,7 +2175,7 @@ unsafe impl Sync for ChunksExactMut<'_, T> where T: Sync {} /// /// [`array_windows`]: slice::array_windows /// [slices]: slice -#[derive(Debug, Clone)] +#[derive(Debug)] #[stable(feature = "array_windows", since = "1.94.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ArrayWindows<'a, T: 'a, const N: usize> { @@ -2189,6 +2189,14 @@ impl<'a, T: 'a, const N: usize> ArrayWindows<'a, T, N> { } } +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[stable(feature = "array_windows", since = "1.94.0")] +impl Clone for ArrayWindows<'_, T, N> { + fn clone(&self) -> Self { + Self { v: self.v } + } +} + #[stable(feature = "array_windows", since = "1.94.0")] impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> { type Item = &'a [T; N]; From 08cd2ac33db7d2d9c16ebb1dbbe407c399799abc Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sat, 24 Jan 2026 11:10:40 -0800 Subject: [PATCH 119/978] `impl FusedIterator for ArrayWindows` --- library/core/src/slice/iter.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index af63ffa9b0bf..6e881b1e8b74 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2260,6 +2260,9 @@ impl ExactSizeIterator for ArrayWindows<'_, T, N> { } } +#[stable(feature = "array_windows", since = "1.94.0")] +impl FusedIterator for ArrayWindows<'_, T, N> {} + /// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a /// time), starting at the end of the slice. /// From 8f7d556c75be80449be60795085f081615c49227 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sat, 24 Jan 2026 11:13:51 -0800 Subject: [PATCH 120/978] `impl TrustedLen for ArrayWindows` --- library/core/src/slice/iter.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 6e881b1e8b74..c5dffcf7e8f7 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2260,6 +2260,9 @@ impl ExactSizeIterator for ArrayWindows<'_, T, N> { } } +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ArrayWindows<'_, T, N> {} + #[stable(feature = "array_windows", since = "1.94.0")] impl FusedIterator for ArrayWindows<'_, T, N> {} From 129d552d3faa0756af4478d0c243888c6c5a1feb Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sat, 24 Jan 2026 11:19:34 -0800 Subject: [PATCH 121/978] `impl TrustedRandomAccess for ArrayWindows` --- library/core/src/slice/iter.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index c5dffcf7e8f7..ac096afb38af 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -2232,6 +2232,14 @@ impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> { fn last(self) -> Option { self.v.last_chunk() } + + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { + // SAFETY: since the caller guarantees that `idx` is in bounds, + // which means that `idx` cannot overflow an `isize`, and the + // "slice" created by `cast_array` is a subslice of `self.v` + // thus is guaranteed to be valid for the lifetime `'a` of `self.v`. + unsafe { &*self.v.as_ptr().add(idx).cast_array() } + } } #[stable(feature = "array_windows", since = "1.94.0")] @@ -2266,6 +2274,16 @@ unsafe impl TrustedLen for ArrayWindows<'_, T, N> {} #[stable(feature = "array_windows", since = "1.94.0")] impl FusedIterator for ArrayWindows<'_, T, N> {} +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccess for ArrayWindows<'_, T, N> {} + +#[doc(hidden)] +#[unstable(feature = "trusted_random_access", issue = "none")] +unsafe impl TrustedRandomAccessNoCoerce for ArrayWindows<'_, T, N> { + const MAY_HAVE_SIDE_EFFECT: bool = false; +} + /// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a /// time), starting at the end of the slice. /// From e4d146e0c315328f53edd1140e74a4ba84e6689a Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Sat, 24 Jan 2026 21:19:56 +0000 Subject: [PATCH 122/978] fix: `doc_markdown` add PowerShell to whitelist --- book/src/lint_configuration.md | 2 +- clippy_config/src/conf.rs | 2 +- tests/ui/doc/doc-fixable.fixed | 2 +- tests/ui/doc/doc-fixable.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index f81dd421f59b..68ef93d7cbf9 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -575,7 +575,7 @@ default configuration of Clippy. By default, any configuration will replace the * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. -**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "MHz", "GHz", "THz", "AccessKit", "CoAP", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "InfiniBand", "RoCE", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "PowerPC", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "NixOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` +**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "MHz", "GHz", "THz", "AccessKit", "CoAP", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "InfiniBand", "RoCE", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "PowerPC", "PowerShell", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "NixOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` --- **Affected lints:** diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 849d9a613d80..2e7ef3a8b020 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -35,7 +35,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "IPv4", "IPv6", "InfiniBand", "RoCE", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", - "PowerPC", "WebAssembly", + "PowerPC", "PowerShell", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", diff --git a/tests/ui/doc/doc-fixable.fixed b/tests/ui/doc/doc-fixable.fixed index 46695dc929ab..58d8b8b33ade 100644 --- a/tests/ui/doc/doc-fixable.fixed +++ b/tests/ui/doc/doc-fixable.fixed @@ -75,7 +75,7 @@ fn test_units() { /// IPv4 IPv6 /// InfiniBand RoCE /// ClojureScript CoffeeScript JavaScript PostScript PureScript TypeScript -/// PowerPC WebAssembly +/// PowerPC PowerShell WebAssembly /// NaN NaNs /// OAuth GraphQL /// OCaml diff --git a/tests/ui/doc/doc-fixable.rs b/tests/ui/doc/doc-fixable.rs index 4082fa5b56f4..0b1237f716fa 100644 --- a/tests/ui/doc/doc-fixable.rs +++ b/tests/ui/doc/doc-fixable.rs @@ -75,7 +75,7 @@ fn test_units() { /// IPv4 IPv6 /// InfiniBand RoCE /// ClojureScript CoffeeScript JavaScript PostScript PureScript TypeScript -/// PowerPC WebAssembly +/// PowerPC PowerShell WebAssembly /// NaN NaNs /// OAuth GraphQL /// OCaml From cc299873b9cbc16392d3b19bdb64d059ef41d4f0 Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Sat, 24 Jan 2026 21:29:16 +0000 Subject: [PATCH 123/978] fix: `test_attr_in_doctest` FP on `test_harness` --- clippy_lints/src/doc/mod.rs | 10 ++++++++-- tests/ui/test_attr_in_doctest.rs | 8 ++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index ecf7acbd7ce6..e7a984694831 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -1016,6 +1016,7 @@ struct CodeTags { no_run: bool, ignore: bool, compile_fail: bool, + test_harness: bool, rust: bool, } @@ -1026,6 +1027,7 @@ impl Default for CodeTags { no_run: false, ignore: false, compile_fail: false, + test_harness: false, rust: true, } @@ -1059,7 +1061,11 @@ impl CodeTags { tags.compile_fail = true; seen_rust_tags = !seen_other_tags || seen_rust_tags; }, - "test_harness" | "standalone_crate" => { + "test_harness" => { + tags.test_harness = true; + seen_rust_tags = !seen_other_tags || seen_rust_tags; + }, + "standalone_crate" => { seen_rust_tags = !seen_other_tags || seen_rust_tags; }, _ if item.starts_with("ignore-") => seen_rust_tags = true, @@ -1295,7 +1301,7 @@ fn check_doc<'a, Events: Iterator, Range Date: Sun, 25 Jan 2026 00:14:20 +0000 Subject: [PATCH 124/978] Enhance `question_mark` to cover `else if` --- clippy_lints/src/question_mark.rs | 8 ++++++-- tests/ui/question_mark.fixed | 9 +++++++++ tests/ui/question_mark.rs | 14 ++++++++++++++ tests/ui/question_mark.stderr | 14 +++++++++++++- 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index e5fb3c0fa431..5517b7f260ea 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -474,7 +474,6 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: if_else, .. }) = higher::IfLet::hir(cx, expr) - && !is_else_clause(cx.tcx, expr) && let PatKind::TupleStruct(ref path1, [field], ddpos) = let_pat.kind && ddpos.as_opt_usize().is_none() && let PatKind::Binding(BindingMode(by_ref, _), bind_id, ident, None) = field.kind @@ -509,10 +508,15 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: ByRef::Yes(_, Mutability::Not) => ".as_ref()", ByRef::No => "", }; - let sugg = format!( + + let mut sugg = format!( "{receiver_str}{method_call_str}?{}", if requires_semi { ";" } else { "" } ); + if is_else_clause(cx.tcx, expr) { + sugg = format!("{{ {sugg} }}"); + } + span_lint_and_sugg( cx, QUESTION_MARK, diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed index b8072932c4ea..102517d34c61 100644 --- a/tests/ui/question_mark.fixed +++ b/tests/ui/question_mark.fixed @@ -515,3 +515,12 @@ fn wrongly_unmangled_macros() -> Option { test_expr!(42)?; test_expr!(42) } + +fn issue16429(b: i32) -> Option { + let a = Some(5); + let _ = if b == 1 { + b + } else { a? }; + + Some(0) +} diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index b320dcd4b0bc..cfea1277fe76 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -635,3 +635,17 @@ fn wrongly_unmangled_macros() -> Option { } test_expr!(42) } + +fn issue16429(b: i32) -> Option { + let a = Some(5); + let _ = if b == 1 { + b + } else if let Some(x) = a { + //~^ question_mark + x + } else { + return None; + }; + + Some(0) +} diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr index d645c8830adc..c243f12de040 100644 --- a/tests/ui/question_mark.stderr +++ b/tests/ui/question_mark.stderr @@ -350,5 +350,17 @@ LL | | return None; LL | | } | |_____^ help: replace it with: `test_expr!(42)?;` -error: aborting due to 37 previous errors +error: this block may be rewritten with the `?` operator + --> tests/ui/question_mark.rs:643:12 + | +LL | } else if let Some(x) = a { + | ____________^ +LL | | +LL | | x +LL | | } else { +LL | | return None; +LL | | }; + | |_____^ help: replace it with: `{ a? }` + +error: aborting due to 38 previous errors From 8416c544ee6e26d628ece03391c4f661e2289727 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Sun, 25 Jan 2026 15:02:11 +0000 Subject: [PATCH 125/978] Also ignore cases with comments in `let_and_return` --- clippy_lints/src/returns/let_and_return.rs | 2 +- tests/ui/let_and_return.edition2021.fixed | 8 ++++++++ tests/ui/let_and_return.edition2024.fixed | 8 ++++++++ tests/ui/let_and_return.rs | 8 ++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/returns/let_and_return.rs b/clippy_lints/src/returns/let_and_return.rs index 0a00981e15be..b19935959c4d 100644 --- a/clippy_lints/src/returns/let_and_return.rs +++ b/clippy_lints/src/returns/let_and_return.rs @@ -27,7 +27,7 @@ pub(super) fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>) && !initexpr.span.in_external_macro(cx.sess().source_map()) && !retexpr.span.in_external_macro(cx.sess().source_map()) && !local.span.from_expansion() - && !span_contains_non_whitespace(cx, stmt.span.between(retexpr.span), true) + && !span_contains_non_whitespace(cx, stmt.span.between(retexpr.span), false) { span_lint_hir_and_then( cx, diff --git a/tests/ui/let_and_return.edition2021.fixed b/tests/ui/let_and_return.edition2021.fixed index e89e4476bf82..6ca0febc2b8d 100644 --- a/tests/ui/let_and_return.edition2021.fixed +++ b/tests/ui/let_and_return.edition2021.fixed @@ -271,4 +271,12 @@ fn issue15987() -> i32 { r } +fn has_comment() -> Vec { + let v = Vec::new(); + + // TODO: stuff + + v +} + fn main() {} diff --git a/tests/ui/let_and_return.edition2024.fixed b/tests/ui/let_and_return.edition2024.fixed index d2c76673ca03..0fce22936ae6 100644 --- a/tests/ui/let_and_return.edition2024.fixed +++ b/tests/ui/let_and_return.edition2024.fixed @@ -271,4 +271,12 @@ fn issue15987() -> i32 { r } +fn has_comment() -> Vec { + let v = Vec::new(); + + // TODO: stuff + + v +} + fn main() {} diff --git a/tests/ui/let_and_return.rs b/tests/ui/let_and_return.rs index 1af5f8ba5c16..301f153ca8b1 100644 --- a/tests/ui/let_and_return.rs +++ b/tests/ui/let_and_return.rs @@ -271,4 +271,12 @@ fn issue15987() -> i32 { r } +fn has_comment() -> Vec { + let v = Vec::new(); + + // TODO: stuff + + v +} + fn main() {} From 163a4b4caf059f662f0eec6d49ec153939560a40 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Mon, 6 Oct 2025 12:19:50 +0000 Subject: [PATCH 126/978] From: cleanup --- library/core/src/convert/num.rs | 87 ++++++++++++++------------------- 1 file changed, 38 insertions(+), 49 deletions(-) diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index c69026c5c9f3..75c94af30000 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -39,62 +39,51 @@ impl_float_to_int!(f32 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i12 impl_float_to_int!(f64 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); impl_float_to_int!(f128 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); -// Conversion traits for primitive integer and float types -// Conversions T -> T are covered by a blanket impl and therefore excluded -// Some conversions from and to usize/isize are not implemented due to portability concerns -macro_rules! impl_from { - (bool => $Int:ty $(,)?) => { - impl_from!( - bool => $Int, - #[stable(feature = "from_bool", since = "1.28.0")], - concat!( - "Converts a [`bool`] to [`", stringify!($Int), "`] losslessly.\n", - "The resulting value is `0` for `false` and `1` for `true` values.\n", - "\n", - "# Examples\n", - "\n", - "```\n", - "assert_eq!(", stringify!($Int), "::from(true), 1);\n", - "assert_eq!(", stringify!($Int), "::from(false), 0);\n", - "```\n", - ), - ); - }; - ($Small:ty => $Large:ty, #[$attr:meta] $(,)?) => { - impl_from!( - $Small => $Large, - #[$attr], - concat!("Converts [`", stringify!($Small), "`] to [`", stringify!($Large), "`] losslessly."), - ); - }; - ($Small:ty => $Large:ty, #[$attr:meta], $doc:expr $(,)?) => { - #[$attr] +/// Implement `From` for integers +macro_rules! impl_from_bool { + ($($int:ty)*) => {$( + #[stable(feature = "from_bool", since = "1.28.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] - impl const From<$Small> for $Large { - // Rustdocs on the impl block show a "[+] show undocumented items" toggle. - // Rustdocs on functions do not. - #[doc = $doc] + impl const From for $int { + /// Converts from [`bool`] to + #[doc = concat!("[`", stringify!($int), "`]")] + /// , by turning `false` into `0` and `true` into `1`. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(", stringify!($int), "::from(false), 0);")] + /// + #[doc = concat!("assert_eq!(", stringify!($int), "::from(true), 1);")] + /// ``` #[inline(always)] - fn from(small: $Small) -> Self { - small as Self + fn from(b: bool) -> Self { + b as Self } } - }; + )*} } // boolean -> integer -impl_from!(bool => u8); -impl_from!(bool => u16); -impl_from!(bool => u32); -impl_from!(bool => u64); -impl_from!(bool => u128); -impl_from!(bool => usize); -impl_from!(bool => i8); -impl_from!(bool => i16); -impl_from!(bool => i32); -impl_from!(bool => i64); -impl_from!(bool => i128); -impl_from!(bool => isize); +impl_from_bool!(u8 u16 u32 u64 u128 usize); +impl_from_bool!(i8 i16 i32 i64 i128 isize); + +/// Implement `From<$small>` for `$large` +macro_rules! impl_from { + ($small:ty => $large:ty, #[$attr:meta]) => { + #[$attr] + #[rustc_const_unstable(feature = "const_convert", issue = "143773")] + impl const From<$small> for $large { + #[doc = concat!("Converts from [`", stringify!($small), "`] to [`", stringify!($large), "`] losslessly.")] + #[inline(always)] + fn from(small: $small) -> Self { + debug_assert!(<$large>::MIN as i128 <= <$small>::MIN as i128); + debug_assert!(<$small>::MAX as u128 <= <$large>::MAX as u128); + small as Self + } + } + } +} // unsigned integer -> unsigned integer impl_from!(u8 => u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")]); From f12288ec263233265ea19b5e8147f4b87837d514 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Mon, 6 Oct 2025 16:27:02 +0000 Subject: [PATCH 127/978] TryFrom for bool --- library/core/src/convert/num.rs | 36 +++++++++++++++++++ tests/ui/try-trait/bad-interconversion.stderr | 2 +- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 75c94af30000..6e82e3356410 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -327,12 +327,48 @@ macro_rules! impl_try_from_both_bounded { )*} } +/// Implement `TryFrom` for `bool` +macro_rules! impl_try_from_integer_for_bool { + ($($int:ty)+) => {$( + #[stable(feature = "try_from", since = "1.34.0")] + #[rustc_const_unstable(feature = "const_convert", issue = "143773")] + impl const TryFrom<$int> for bool { + type Error = TryFromIntError; + + /// Tries to create a bool from an integer type. + /// Returns an error if the integer is not 0 or 1. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("assert_eq!(0_", stringify!($int), ".try_into(), Ok(false));")] + /// + #[doc = concat!("assert_eq!(1_", stringify!($int), ".try_into(), Ok(true));")] + /// + #[doc = concat!("assert!(<", stringify!($int), " as TryInto>::try_into(2).is_err());")] + /// ``` + #[inline] + fn try_from(i: $int) -> Result { + match i { + 0 => Ok(false), + 1 => Ok(true), + _ => Err(TryFromIntError(())), + } + } + } + )*} +} + macro_rules! rev { ($mac:ident, $source:ty => $($target:ty),+) => {$( $mac!($target => $source); )*} } +// integer -> bool +impl_try_from_integer_for_bool!(u128 u64 u32 u16 u8); +impl_try_from_integer_for_bool!(i128 i64 i32 i16 i8); + // unsigned integer -> unsigned integer impl_try_from_upper_bounded!(u16 => u8); impl_try_from_upper_bounded!(u32 => u8, u16); diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr index f8c0deba99ba..a566800da53e 100644 --- a/tests/ui/try-trait/bad-interconversion.stderr +++ b/tests/ui/try-trait/bad-interconversion.stderr @@ -22,7 +22,7 @@ help: the following other types implement trait `From` ::: $SRC_DIR/core/src/ascii/ascii_char.rs:LL:COL | = note: in this macro invocation - = note: this error originates in the macro `impl_from` which comes from the expansion of the macro `into_int_impl` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `impl_from_bool` which comes from the expansion of the macro `into_int_impl` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` --> $DIR/bad-interconversion.rs:9:12 From 4a6c0dea8bb523515e11a0af9a9dd234a68405bf Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 25 Jan 2026 18:38:20 +0100 Subject: [PATCH 128/978] rhs of short-circuit expression doesn't always run --- clippy_lints/src/loops/never_loop.rs | 4 ++++ tests/ui/never_loop.rs | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/clippy_lints/src/loops/never_loop.rs b/clippy_lints/src/loops/never_loop.rs index e7b9b1cd3881..231388e7379a 100644 --- a/clippy_lints/src/loops/never_loop.rs +++ b/clippy_lints/src/loops/never_loop.rs @@ -6,6 +6,7 @@ use clippy_utils::macros::root_macro_call_first_node; use clippy_utils::source::{snippet, snippet_with_context}; use clippy_utils::visitors::{Descend, for_each_expr_without_closures}; use clippy_utils::{contains_return, sym}; +use rustc_ast::BinOpKind; use rustc_errors::Applicability; use rustc_hir::{ Block, Closure, Destination, Expr, ExprKind, HirId, InlineAsm, InlineAsmOperand, Node, Pat, Stmt, StmtKind, @@ -305,6 +306,9 @@ fn never_loop_expr<'tcx>( } }, ExprKind::Call(e, es) => never_loop_expr_all(cx, once(e).chain(es.iter()), local_labels, main_loop_id), + ExprKind::Binary(op, e1, _) if matches!(op.node, BinOpKind::And | BinOpKind::Or) => { + never_loop_expr(cx, e1, local_labels, main_loop_id) + }, ExprKind::Binary(_, e1, e2) | ExprKind::Assign(e1, e2, _) | ExprKind::AssignOp(_, e1, e2) diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index 9769ee0c3a37..52470c6ee81b 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -546,3 +546,13 @@ fn issue15673() { return; } } + +#[expect(clippy::diverging_sub_expression, clippy::short_circuit_statement)] +fn issue16462() { + let mut n = 10; + loop { + println!("{n}"); + n -= 1; + n >= 0 || break; + } +} From 81acbae770748d42f5d368cf156e21fd786fa7f5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 Jan 2026 21:02:34 +0100 Subject: [PATCH 129/978] Add missing intrinsic translation for `llvm.sqrt.f32` --- src/intrinsic/llvm.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 72fc72d118b7..10183c5ee526 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1062,6 +1062,12 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.xgetbv" => "__builtin_ia32_xgetbv", // NOTE: this doc specifies the equivalent GCC builtins: http://huonw.github.io/llvmint/llvmint/x86/index.html "llvm.sqrt.v2f64" => "__builtin_ia32_sqrtpd", + "llvm.sqrt.f32" => { + let gcc_name = "__builtin_sqrtf"; + let func = cx.context.get_builtin_function(gcc_name); + cx.functions.borrow_mut().insert(gcc_name.to_string(), func); + return func; + } "llvm.x86.avx512.pmul.dq.512" => "__builtin_ia32_pmuldq512_mask", "llvm.x86.avx512.pmulu.dq.512" => "__builtin_ia32_pmuludq512_mask", "llvm.x86.avx512.max.ps.512" => "__builtin_ia32_maxps512_mask", From d3df4bdba52b27d5bdace45b796177c891000f01 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 Jan 2026 21:02:55 +0100 Subject: [PATCH 130/978] Add regression test for --- tests/run/call-llvm-intrinsics.rs | 38 +++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/run/call-llvm-intrinsics.rs diff --git a/tests/run/call-llvm-intrinsics.rs b/tests/run/call-llvm-intrinsics.rs new file mode 100644 index 000000000000..86e041c3a2fb --- /dev/null +++ b/tests/run/call-llvm-intrinsics.rs @@ -0,0 +1,38 @@ +// Compiler: +// +// Run-time: +// status: 0 + +// FIXME: Remove this test once rustc's `./tests/codegen/riscv-abi/call-llvm-intrinsics.rs` +// stops ignoring GCC backend. + +#![feature(link_llvm_intrinsics)] +#![allow(internal_features)] + +struct A; + +impl Drop for A { + fn drop(&mut self) { + println!("A"); + } +} + +extern "C" { + #[link_name = "llvm.sqrt.f32"] + fn sqrt(x: f32) -> f32; +} + +pub fn do_call() { + let _a = A; + + unsafe { + // Ensure that we `call` LLVM intrinsics instead of trying to `invoke` them + // CHECK: store float 4.000000e+00, float* %{{.}}, align 4 + // CHECK: call float @llvm.sqrt.f32(float %{{.}} + sqrt(4.0); + } +} + +fn main() { + do_call(); +} From 46483e6a4672188b8434c0c7e5f144552505229d Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Sun, 25 Jan 2026 16:45:46 -0500 Subject: [PATCH 131/978] Add a new subsection for contributors --- src/doc/rustc-dev-guide/src/SUMMARY.md | 1 + .../src/offload/contributing.md | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/doc/rustc-dev-guide/src/offload/contributing.md diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index daaaef42d909..3f863ebf4c6d 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -106,6 +106,7 @@ - [GPU offload internals](./offload/internals.md) - [Installation](./offload/installation.md) - [Usage](./offload/usage.md) + - [Contributing](./offload/contributing.md) - [Autodiff internals](./autodiff/internals.md) - [Installation](./autodiff/installation.md) - [How to debug](./autodiff/debugging.md) diff --git a/src/doc/rustc-dev-guide/src/offload/contributing.md b/src/doc/rustc-dev-guide/src/offload/contributing.md new file mode 100644 index 000000000000..f3a1ed2150a1 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/offload/contributing.md @@ -0,0 +1,32 @@ +# Contributing + +Contributions are always welcome. This project is experimental, so the documentation and code are likely incomplete. Please ask on [Zulip](https://rust-lang.zulipchat.com/#narrow/channel/422870-t-compiler.2Fgpgpu-backend) (preferred) or the Rust Community Discord for help if you get stuck or if our documentation is unclear. + +We generally try to automate as much of the compilation process as possible for users. However, as a contributor it might sometimes be easier to directly rewrite and compile the LLVM-IR modules (.ll) to quickly iterate on changes, without needing to repeatedly recompile rustc. For people familiar with LLVM we therefore have the shell script below. Only when you are then happy with the IR changes you can work on updating rustc to generate the new, desired output. + +```sh +set -e +# set -e to avoid continuing on errors, which would likely use stale artifacts +# inputs: +# lib.ll (host code) + host.out (device) + +# You only need to run the first three commands once to generate lib.ll and host.out from your rust code. + +# RUSTFLAGS="-Ctarget-cpu=gfx90a --emit=llvm-bc,llvm-ir -Zoffload=Device -Csave-temps -Zunstable-options" cargo +offload build -Zunstable-options -v --target amdgcn-amd-amdhsa -Zbuild-std=core -r +# +# RUSTFLAGS="--emit=llvm-bc,llvm-ir -Csave-temps -Zoffload=Host=/absolute/path/to/project/target/amdgcn-amd-amdhsa/release/deps/host.out -Zunstable-options" cargo +offload build -r +# +# cp target/release/deps/.ll lib.ll + +opt lib.ll -o lib.bc + +"clang-21" "-cc1" "-triple" "x86_64-unknown-linux-gnu" "-S" "-save-temps=cwd" "-disable-free" "-clear-ast-before-backend" "-main-file-name" "lib.rs" "-mrelocation-model" "pic" "-pic-level" "2" "-pic-is-pie" "-mframe-pointer=all" "-fmath-errno" "-ffp-contract=on" "-fno-rounding-math" "-mconstructor-aliases" "-funwind-tables=2" "-target-cpu" "x86-64" "-tune-cpu" "generic" "-resource-dir" "//rust/build/x86_64-unknown-linux-gnu/llvm/lib/clang/21" "-ferror-limit" "19" "-fopenmp" "-fopenmp-offload-mandatory" "-fgnuc-version=4.2.1" "-fskip-odr-check-in-gmf" "-fembed-offload-object=host.out" "-fopenmp-targets=amdgcn-amd-amdhsa" "-faddrsig" "-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o" "host.s" "-x" "ir" "lib.bc" + +"clang-21" "-cc1as" "-triple" "x86_64-unknown-linux-gnu" "-filetype" "obj" "-main-file-name" "lib.rs" "-target-cpu" "x86-64" "-mrelocation-model" "pic" "-o" "host.o" "host.s" + +"//rust/build/x86_64-unknown-linux-gnu/llvm/bin/clang-linker-wrapper" "--should-extract=gfx90a" "--device-compiler=amdgcn-amd-amdhsa=-g" "--device-compiler=amdgcn-amd-amdhsa=-save-temps=cwd" "--device-linker=amdgcn-amd-amdhsa=-lompdevice" "--host-triple=x86_64-unknown-linux-gnu" "--save-temps" "--linker-path=//rust/build/x86_64-unknown-linux-gnu/lld/bin/ld.lld" "--hash-style=gnu" "--eh-frame-hdr" "-m" "elf_x86_64" "-pie" "-dynamic-linker" "/lib64/ld-linux-x86-64.so.2" "-o" "a.out" "/lib/../lib64/Scrt1.o" "/lib/../lib64/crti.o" "/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12/crtbeginS.o" "-L//rust/build/x86_64-unknown-linux-gnu/llvm/bin/../lib/x86_64-unknown-linux-gnu" "-L//rust/build/x86_64-unknown-linux-gnu/llvm/lib/clang/21/lib/x86_64-unknown-linux-gnu" "-L/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" "-L/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12/../../../../lib64" "-L/lib/../lib64" "-L/usr/lib64" "-L/lib" "-L/usr/lib" "host.o" "-lstdc++" "-lm" "-lomp" "-lomptarget" "-L//rust/build/x86_64-unknown-linux-gnu/llvm/lib" "-lgcc_s" "-lgcc" "-lpthread" "-lc" "-lgcc_s" "-lgcc" "/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12/crtendS.o" "/lib/../lib64/crtn.o" + +LIBOMPTARGET_INFO=-1 OFFLOAD_TRACK_ALLOCATION_TRACES=true ./a.out +``` + +Please update the `` placeholders on the `clang-linker-wrapper` invocation. You will likely also need to adjust the library paths. See the linked usage section for details: [usage](usage.md#compile-instructions) From 0b28b1320209cf2c7254a5d4f6de77fd84bbf4b2 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 25 Jan 2026 22:57:18 +0100 Subject: [PATCH 132/978] Add info about unused_attributes --- src/doc/rustc-dev-guide/src/tests/ui.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index 8e3c4c133a3c..b7cf446c4a57 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -636,6 +636,7 @@ By default, test suites under UI test mode (`tests/ui`, `tests/ui-fulldeps`, but not `tests/rustdoc-ui`) will specify - `-A unused` +- `-W unused_attributes` (since these tend to be interesting for ui tests) - `-A internal_features` If: From 02d9865f9ecf81f12b38e6fc261888f2eae2c7aa Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Sat, 17 Jan 2026 20:47:47 +0000 Subject: [PATCH 133/978] Enhance `manual_is_variant_and` to cover manual `is_none_or` --- .../src/methods/manual_is_variant_and.rs | 66 ++++++++++++++++++- clippy_lints/src/methods/mod.rs | 3 + tests/ui/manual_is_variant_and.fixed | 19 ++++++ tests/ui/manual_is_variant_and.rs | 19 ++++++ tests/ui/manual_is_variant_and.stderr | 14 +++- 5 files changed, 118 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/methods/manual_is_variant_and.rs b/clippy_lints/src/methods/manual_is_variant_and.rs index 5ce9d364cdd8..d877b0a62291 100644 --- a/clippy_lints/src/methods/manual_is_variant_and.rs +++ b/clippy_lints/src/methods/manual_is_variant_and.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::MaybeDef; -use clippy_utils::source::snippet_with_applicability; +use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::Sugg; -use clippy_utils::{get_parent_expr, sym}; +use clippy_utils::{SpanlessEq, get_parent_expr, sym}; use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; @@ -228,3 +228,65 @@ pub(super) fn check_map(cx: &LateContext<'_>, expr: &Expr<'_>) { } } } + +pub(super) fn check_or<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + lhs: &'tcx Expr<'tcx>, + rhs: &'tcx Expr<'tcx>, + msrv: Msrv, +) { + let (some_recv, some_arg) = if let ( + ExprKind::MethodCall(none_path, none_recv, [], _), + ExprKind::MethodCall(some_path, some_recv, [some_arg], _), + ) + | ( + ExprKind::MethodCall(some_path, some_recv, [some_arg], _), + ExprKind::MethodCall(none_path, none_recv, [], _), + ) = (lhs.kind, rhs.kind) + && none_path.ident.name == sym::is_none + && some_path.ident.name == sym::is_some_and + && cx + .typeck_results() + .expr_ty_adjusted(none_recv) + .peel_refs() + .is_diag_item(cx, sym::Option) + && cx + .typeck_results() + .expr_ty_adjusted(some_recv) + .peel_refs() + .is_diag_item(cx, sym::Option) + && SpanlessEq::new(cx).eq_expr(none_recv, some_recv) + { + (some_recv, some_arg) + } else { + return; + }; + + if !msrv.meets(cx, msrvs::IS_NONE_OR) { + return; + } + + let Ok(map_func) = MapFunc::try_from(some_arg) else { + return; + }; + + span_lint_and_then( + cx, + MANUAL_IS_VARIANT_AND, + expr.span, + "manual implementation of `Option::is_none_or`", + |diag| { + let mut app = Applicability::MachineApplicable; + let (recv_snip, _) = snippet_with_context(cx, some_recv.span, expr.span.ctxt(), "_", &mut app); + let map_func_snip = map_func.sugg(cx, false, &mut app); + + diag.span_suggestion( + expr.span, + "use", + format!("{recv_snip}.is_none_or({map_func_snip})"), + app, + ); + }, + ); +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 659a704a1ecb..08a472a5d4c4 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4978,6 +4978,9 @@ impl<'tcx> LateLintPass<'tcx> for Methods { }; lint_binary_expr_with_method_call(cx, &mut info); }, + ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Or => { + manual_is_variant_and::check_or(cx, expr, lhs, rhs, self.msrv); + }, _ => (), } } diff --git a/tests/ui/manual_is_variant_and.fixed b/tests/ui/manual_is_variant_and.fixed index 65a9cfa6e64c..884bef6af5f9 100644 --- a/tests/ui/manual_is_variant_and.fixed +++ b/tests/ui/manual_is_variant_and.fixed @@ -226,3 +226,22 @@ mod with_func { assert_eq!(a1, a2); } } + +fn issue16419() { + let then_fn = |s: &str| s.len() > 3; + let opt: Option<&str> = Some("test"); + let _ = opt.is_none_or(then_fn); + //~^ manual_is_variant_and + + let _ = opt.is_none_or(then_fn); + //~^ manual_is_variant_and +} + +#[clippy::msrv = "1.75.0"] +fn issue16419_msrv() { + let then_fn = |s: &str| s.len() > 3; + let opt: Option<&str> = Some("test"); + let _ = opt.is_none() || opt.is_some_and(then_fn); + + let _ = opt.is_some_and(then_fn) || opt.is_none(); +} diff --git a/tests/ui/manual_is_variant_and.rs b/tests/ui/manual_is_variant_and.rs index 85b45d654a7d..53aca94ea370 100644 --- a/tests/ui/manual_is_variant_and.rs +++ b/tests/ui/manual_is_variant_and.rs @@ -235,3 +235,22 @@ mod with_func { assert_eq!(a1, a2); } } + +fn issue16419() { + let then_fn = |s: &str| s.len() > 3; + let opt: Option<&str> = Some("test"); + let _ = opt.is_none() || opt.is_some_and(then_fn); + //~^ manual_is_variant_and + + let _ = opt.is_some_and(then_fn) || opt.is_none(); + //~^ manual_is_variant_and +} + +#[clippy::msrv = "1.75.0"] +fn issue16419_msrv() { + let then_fn = |s: &str| s.len() > 3; + let opt: Option<&str> = Some("test"); + let _ = opt.is_none() || opt.is_some_and(then_fn); + + let _ = opt.is_some_and(then_fn) || opt.is_none(); +} diff --git a/tests/ui/manual_is_variant_and.stderr b/tests/ui/manual_is_variant_and.stderr index da36b5a07d21..56c3b80c0aa5 100644 --- a/tests/ui/manual_is_variant_and.stderr +++ b/tests/ui/manual_is_variant_and.stderr @@ -222,5 +222,17 @@ error: called `.map() != Ok()` LL | let a1 = b.map(iad) != Ok(false); | ^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!b.is_ok_and(|x| !iad(x))` -error: aborting due to 31 previous errors +error: manual implementation of `Option::is_none_or` + --> tests/ui/manual_is_variant_and.rs:242:13 + | +LL | let _ = opt.is_none() || opt.is_some_and(then_fn); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `opt.is_none_or(then_fn)` + +error: manual implementation of `Option::is_none_or` + --> tests/ui/manual_is_variant_and.rs:245:13 + | +LL | let _ = opt.is_some_and(then_fn) || opt.is_none(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `opt.is_none_or(then_fn)` + +error: aborting due to 33 previous errors From 3a33ab0595044615affae9d11ba45df98e5c0dee Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 24 Jan 2026 15:05:36 -0800 Subject: [PATCH 134/978] GVN: Elide more intermediate transmutes --- compiler/rustc_mir_transform/src/gvn.rs | 61 ++++++-- ...n.DataflowConstProp.32bit.panic-abort.diff | 8 +- ....DataflowConstProp.32bit.panic-unwind.diff | 8 +- ...n.DataflowConstProp.64bit.panic-abort.diff | 8 +- ....DataflowConstProp.64bit.panic-unwind.diff | 8 +- ...oxed_slice.main.GVN.32bit.panic-abort.diff | 13 +- ...xed_slice.main.GVN.32bit.panic-unwind.diff | 13 +- ...oxed_slice.main.GVN.64bit.panic-abort.diff | 13 +- ...xed_slice.main.GVN.64bit.panic-unwind.diff | 13 +- .../gvn.fn_pointers.GVN.panic-abort.diff | 18 +-- .../gvn.fn_pointers.GVN.panic-unwind.diff | 18 +-- tests/mir-opt/gvn.rs | 20 ++- ..._then_transmute_again.GVN.panic-abort.diff | 148 +++++++++++++----- ...then_transmute_again.GVN.panic-unwind.diff | 148 +++++++++++++----- .../gvn_ptr_eq_with_constant.main.GVN.diff | 6 +- 15 files changed, 328 insertions(+), 175 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 820998eed100..476ae059649a 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1591,10 +1591,12 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { (Transmute, PtrToPtr) if self.pointers_have_same_metadata(from, to) => { Some(Transmute) } - // If would be legal to always do this, but we don't want to hide information + // It would be legal to always do this, but we don't want to hide information // from the backend that it'd otherwise be able to use for optimizations. (Transmute, Transmute) - if !self.type_may_have_niche_of_interest_to_backend(from) => + if !self.transmute_may_have_niche_of_interest_to_backend( + inner_from, from, to, + ) => { Some(Transmute) } @@ -1642,24 +1644,65 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { } } - /// Returns `false` if we know for sure that this type has no interesting niche, - /// and thus we can skip transmuting through it without worrying. + /// Returns `false` if we're confident that the middle type doesn't have an + /// interesting niche so we can skip that step when transmuting. /// /// The backend will emit `assume`s when transmuting between types with niches, /// so we want to preserve `i32 -> char -> u32` so that that data is around, /// but it's fine to skip whole-range-is-value steps like `A -> u32 -> B`. - fn type_may_have_niche_of_interest_to_backend(&self, ty: Ty<'tcx>) -> bool { - let Ok(layout) = self.ecx.layout_of(ty) else { + fn transmute_may_have_niche_of_interest_to_backend( + &self, + from_ty: Ty<'tcx>, + middle_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, + ) -> bool { + let Ok(middle_layout) = self.ecx.layout_of(middle_ty) else { // If it's too generic or something, then assume it might be interesting later. return true; }; - if layout.uninhabited { + if middle_layout.uninhabited { return true; } - match layout.backend_repr { - BackendRepr::Scalar(a) => !a.is_always_valid(&self.ecx), + match middle_layout.backend_repr { + BackendRepr::Scalar(mid) => { + if mid.is_always_valid(&self.ecx) { + // With no niche it's never interesting, so don't bother + // looking at the layout of the other two types. + false + } else if let Ok(from_layout) = self.ecx.layout_of(from_ty) + && !from_layout.uninhabited + && from_layout.size == middle_layout.size + && let BackendRepr::Scalar(from_a) = from_layout.backend_repr + && let mid_range = mid.valid_range(&self.ecx) + && let from_range = from_a.valid_range(&self.ecx) + && mid_range.contains_range(from_range, middle_layout.size) + { + // The `from_range` is a (non-strict) subset of `mid_range` + // such as if we're doing `bool` -> `ascii::Char` -> `_`, + // where `from_range: 0..=1` and `mid_range: 0..=127`, + // and thus the middle doesn't tell us anything we don't + // already know from the initial type. + false + } else if let Ok(to_layout) = self.ecx.layout_of(to_ty) + && !to_layout.uninhabited + && to_layout.size == middle_layout.size + && let BackendRepr::Scalar(to_a) = to_layout.backend_repr + && let mid_range = mid.valid_range(&self.ecx) + && let to_range = to_a.valid_range(&self.ecx) + && mid_range.contains_range(to_range, middle_layout.size) + { + // The `to_range` is a (non-strict) subset of `mid_range` + // such as if we're doing `_` -> `ascii::Char` -> `bool`, + // where `mid_range: 0..=127` and `to_range: 0..=1`, + // and thus the middle doesn't tell us anything we don't + // already know from the final type. + false + } else { + true + } + } BackendRepr::ScalarPair(a, b) => { !a.is_always_valid(&self.ecx) || !b.is_always_valid(&self.ecx) } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff index 7a60070b7074..5a3342a45cd3 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -16,12 +16,11 @@ scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { - let mut _6: std::num::NonZero; scope 6 { scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let _6: *const [bool; 0]; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -45,11 +44,8 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); - _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); - StorageLive(_7); - _7 = const {0x1 as *const [bool; 0]}; + _6 = const {0x1 as *const [bool; 0]}; _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; - StorageDead(_7); StorageDead(_6); _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff index d13d0d962a69..2d1b05e6e987 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -16,12 +16,11 @@ scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { - let mut _6: std::num::NonZero; scope 6 { scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let _6: *const [bool; 0]; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -45,11 +44,8 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); - _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); - StorageLive(_7); - _7 = const {0x1 as *const [bool; 0]}; + _6 = const {0x1 as *const [bool; 0]}; _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; - StorageDead(_7); StorageDead(_6); _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff index 8701e879e959..695a06e29d3d 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -16,12 +16,11 @@ scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { - let mut _6: std::num::NonZero; scope 6 { scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let _6: *const [bool; 0]; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -45,11 +44,8 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); - _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); - StorageLive(_7); - _7 = const {0x1 as *const [bool; 0]}; + _6 = const {0x1 as *const [bool; 0]}; _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; - StorageDead(_7); StorageDead(_6); _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff index ac1c8d627baa..17714feb1432 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -16,12 +16,11 @@ scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { - let mut _6: std::num::NonZero; scope 6 { scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let _6: *const [bool; 0]; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -45,11 +44,8 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); - _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); - StorageLive(_7); - _7 = const {0x1 as *const [bool; 0]}; + _6 = const {0x1 as *const [bool; 0]}; _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; - StorageDead(_7); StorageDead(_6); _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff index 0205d0cc3d16..7d66d3129115 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff @@ -16,12 +16,11 @@ scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { - let mut _6: std::num::NonZero; scope 6 { scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let _6: *const [bool; 0]; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -45,14 +44,10 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); -- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero (Transmute); -+ _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); - StorageLive(_7); -- _7 = copy _6 as *const [bool; 0] (Transmute); -- _5 = NonNull::<[bool; 0]> { pointer: copy _7 }; -+ _7 = const {0x1 as *const [bool; 0]}; +- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute); +- _5 = NonNull::<[bool; 0]> { pointer: copy _6 }; ++ _6 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; - StorageDead(_7); StorageDead(_6); - _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; + _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff index f6babe35b5a0..cc00bd300a3c 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff @@ -16,12 +16,11 @@ scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { - let mut _6: std::num::NonZero; scope 6 { scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let _6: *const [bool; 0]; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -45,14 +44,10 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); -- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero (Transmute); -+ _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); - StorageLive(_7); -- _7 = copy _6 as *const [bool; 0] (Transmute); -- _5 = NonNull::<[bool; 0]> { pointer: copy _7 }; -+ _7 = const {0x1 as *const [bool; 0]}; +- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute); +- _5 = NonNull::<[bool; 0]> { pointer: copy _6 }; ++ _6 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; - StorageDead(_7); StorageDead(_6); - _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; + _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff index 204e59415c6b..9380cdd6ccb4 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff @@ -16,12 +16,11 @@ scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { - let mut _6: std::num::NonZero; scope 6 { scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let _6: *const [bool; 0]; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -45,14 +44,10 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); -- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero (Transmute); -+ _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); - StorageLive(_7); -- _7 = copy _6 as *const [bool; 0] (Transmute); -- _5 = NonNull::<[bool; 0]> { pointer: copy _7 }; -+ _7 = const {0x1 as *const [bool; 0]}; +- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute); +- _5 = NonNull::<[bool; 0]> { pointer: copy _6 }; ++ _6 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; - StorageDead(_7); StorageDead(_6); - _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; + _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff index 0cf3f43c0464..bea564376274 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff @@ -16,12 +16,11 @@ scope 4 (inlined std::ptr::Unique::<[bool; 0]>::dangling) { let mut _5: std::ptr::NonNull<[bool; 0]>; scope 5 (inlined NonNull::<[bool; 0]>::dangling) { - let mut _6: std::num::NonZero; scope 6 { scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let _6: *const [bool; 0]; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -45,14 +44,10 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); -- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero (Transmute); -+ _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); - StorageLive(_7); -- _7 = copy _6 as *const [bool; 0] (Transmute); -- _5 = NonNull::<[bool; 0]> { pointer: copy _7 }; -+ _7 = const {0x1 as *const [bool; 0]}; +- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute); +- _5 = NonNull::<[bool; 0]> { pointer: copy _6 }; ++ _6 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; - StorageDead(_7); StorageDead(_6); - _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; + _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff index 90920dd0be8f..a29d3331f380 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:617:19: 617:21}; + let mut _9: {closure@$DIR/gvn.rs:618:19: 618:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:617:19: 617:21}; + let mut _13: {closure@$DIR/gvn.rs:618:19: 618:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:617:19: 617:21}; + let _7: {closure@$DIR/gvn.rs:618:19: 618:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:617:19: 617:21}; +- _7 = {closure@$DIR/gvn.rs:618:19: 618:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; + nop; StorageLive(_9); - _9 = copy _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = copy _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff index 0aca8e508f5c..b716fcd4e74b 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:617:19: 617:21}; + let mut _9: {closure@$DIR/gvn.rs:618:19: 618:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:617:19: 617:21}; + let mut _13: {closure@$DIR/gvn.rs:618:19: 618:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:617:19: 617:21}; + let _7: {closure@$DIR/gvn.rs:618:19: 618:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:617:19: 617:21}; +- _7 = {closure@$DIR/gvn.rs:618:19: 618:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; + nop; StorageLive(_9); - _9 = copy _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = copy _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:617:19: 617:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 3c3241fefe22..837e8ac4d9e3 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -9,6 +9,7 @@ #![feature(freeze)] #![allow(ambiguous_wide_pointer_comparisons)] #![allow(unconditional_panic)] +#![allow(unnecessary_transmutes)] #![allow(unused)] use std::intrinsics::mir::*; @@ -985,7 +986,14 @@ unsafe fn aggregate_struct_then_transmute(id: u16, thin: *const u8) { opaque(std::intrinsics::transmute::<_, *const u8>(j)); } -unsafe fn transmute_then_transmute_again(a: u32, c: char) { +#[repr(u8)] +enum ZeroOneTwo { + Zero, + One, + Two, +} + +unsafe fn transmute_then_transmute_again(a: u32, c: char, b: bool, d: u8) { // CHECK: [[TEMP1:_[0-9]+]] = copy _1 as char (Transmute); // CHECK: [[TEMP2:_[0-9]+]] = copy [[TEMP1]] as i32 (Transmute); // CHECK: opaque::(move [[TEMP2]]) @@ -996,6 +1004,16 @@ unsafe fn transmute_then_transmute_again(a: u32, c: char) { // CHECK: opaque::(move [[TEMP]]) let x = std::intrinsics::transmute::(c); opaque(std::intrinsics::transmute::(x)); + + // CHECK: [[TEMP:_[0-9]+]] = copy _3 as u8 (Transmute); + // CHECK: opaque::(move [[TEMP]]) + let x = std::intrinsics::transmute::(b); + opaque(std::intrinsics::transmute::(x)); + + // CHECK: [[TEMP:_[0-9]+]] = copy _4 as bool (Transmute); + // CHECK: opaque::(move [[TEMP]]) + let x = std::intrinsics::transmute::(d); + opaque(std::intrinsics::transmute::(x)); } // Transmuting can skip a pointer cast so long as it wasn't a fat-to-thin cast. diff --git a/tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-abort.diff b/tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-abort.diff index 962fecd2586e..caed065536e3 100644 --- a/tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-abort.diff @@ -1,71 +1,135 @@ - // MIR for `transmute_then_transmute_again` before GVN + // MIR for `transmute_then_transmute_again` after GVN - fn transmute_then_transmute_again(_1: u32, _2: char) -> () { + fn transmute_then_transmute_again(_1: u32, _2: char, _3: bool, _4: u8) -> () { debug a => _1; debug c => _2; + debug b => _3; + debug d => _4; let mut _0: (); - let _3: char; - let mut _4: u32; - let _5: (); - let mut _6: i32; - let mut _7: char; + let _5: char; + let mut _6: u32; + let _7: (); + let mut _8: i32; let mut _9: char; - let _10: (); - let mut _11: i32; - let mut _12: u32; + let mut _11: char; + let _12: (); + let mut _13: i32; + let mut _14: u32; + let mut _16: bool; + let _17: (); + let mut _18: u8; + let mut _19: ZeroOneTwo; + let mut _21: u8; + let _22: (); + let mut _23: bool; + let mut _24: ZeroOneTwo; scope 1 { - debug x => _3; - let _8: u32; + debug x => _5; + let _10: u32; scope 2 { - debug x => _8; + debug x => _10; + let _15: ZeroOneTwo; + scope 3 { + debug x => _15; + let _20: ZeroOneTwo; + scope 4 { + debug x => _20; + } + } } } bb0: { -- StorageLive(_3); +- StorageLive(_5); + nop; - StorageLive(_4); - _4 = copy _1; -- _3 = move _4 as char (Transmute); -+ _3 = copy _1 as char (Transmute); - StorageDead(_4); - StorageLive(_5); StorageLive(_6); + _6 = copy _1; +- _5 = move _6 as char (Transmute); ++ _5 = copy _1 as char (Transmute); + StorageDead(_6); StorageLive(_7); - _7 = copy _3; -- _6 = move _7 as i32 (Transmute); -+ _6 = copy _3 as i32 (Transmute); - StorageDead(_7); - _5 = opaque::(move _6) -> [return: bb1, unwind unreachable]; + StorageLive(_8); + StorageLive(_9); + _9 = copy _5; +- _8 = move _9 as i32 (Transmute); ++ _8 = copy _5 as i32 (Transmute); + StorageDead(_9); + _7 = opaque::(move _8) -> [return: bb1, unwind unreachable]; } bb1: { - StorageDead(_6); - StorageDead(_5); -- StorageLive(_8); + StorageDead(_8); + StorageDead(_7); +- StorageLive(_10); + nop; - StorageLive(_9); - _9 = copy _2; -- _8 = move _9 as u32 (Transmute); -+ _8 = copy _2 as u32 (Transmute); - StorageDead(_9); - StorageLive(_10); StorageLive(_11); + _11 = copy _2; +- _10 = move _11 as u32 (Transmute); ++ _10 = copy _2 as u32 (Transmute); + StorageDead(_11); StorageLive(_12); - _12 = copy _8; -- _11 = move _12 as i32 (Transmute); -+ _11 = copy _2 as i32 (Transmute); - StorageDead(_12); - _10 = opaque::(move _11) -> [return: bb2, unwind unreachable]; + StorageLive(_13); + StorageLive(_14); + _14 = copy _10; +- _13 = move _14 as i32 (Transmute); ++ _13 = copy _2 as i32 (Transmute); + StorageDead(_14); + _12 = opaque::(move _13) -> [return: bb2, unwind unreachable]; } bb2: { - StorageDead(_11); - StorageDead(_10); + StorageDead(_13); + StorageDead(_12); +- StorageLive(_15); ++ nop; + StorageLive(_16); + _16 = copy _3; +- _15 = move _16 as ZeroOneTwo (Transmute); ++ _15 = copy _3 as ZeroOneTwo (Transmute); + StorageDead(_16); + StorageLive(_17); + StorageLive(_18); + StorageLive(_19); +- _19 = move _15; +- _18 = move _19 as u8 (Transmute); ++ _19 = copy _15; ++ _18 = copy _3 as u8 (Transmute); + StorageDead(_19); + _17 = opaque::(move _18) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_18); + StorageDead(_17); +- StorageLive(_20); ++ nop; + StorageLive(_21); + _21 = copy _4; +- _20 = move _21 as ZeroOneTwo (Transmute); ++ _20 = copy _4 as ZeroOneTwo (Transmute); + StorageDead(_21); + StorageLive(_22); + StorageLive(_23); + StorageLive(_24); +- _24 = move _20; +- _23 = move _24 as bool (Transmute); ++ _24 = copy _20; ++ _23 = copy _4 as bool (Transmute); + StorageDead(_24); + _22 = opaque::(move _23) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_23); + StorageDead(_22); _0 = const (); -- StorageDead(_8); -- StorageDead(_3); +- StorageDead(_20); +- StorageDead(_15); +- StorageDead(_10); +- StorageDead(_5); ++ nop; ++ nop; + nop; + nop; return; diff --git a/tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-unwind.diff b/tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-unwind.diff index e32397c1aed0..3b25dd362cd5 100644 --- a/tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.transmute_then_transmute_again.GVN.panic-unwind.diff @@ -1,71 +1,135 @@ - // MIR for `transmute_then_transmute_again` before GVN + // MIR for `transmute_then_transmute_again` after GVN - fn transmute_then_transmute_again(_1: u32, _2: char) -> () { + fn transmute_then_transmute_again(_1: u32, _2: char, _3: bool, _4: u8) -> () { debug a => _1; debug c => _2; + debug b => _3; + debug d => _4; let mut _0: (); - let _3: char; - let mut _4: u32; - let _5: (); - let mut _6: i32; - let mut _7: char; + let _5: char; + let mut _6: u32; + let _7: (); + let mut _8: i32; let mut _9: char; - let _10: (); - let mut _11: i32; - let mut _12: u32; + let mut _11: char; + let _12: (); + let mut _13: i32; + let mut _14: u32; + let mut _16: bool; + let _17: (); + let mut _18: u8; + let mut _19: ZeroOneTwo; + let mut _21: u8; + let _22: (); + let mut _23: bool; + let mut _24: ZeroOneTwo; scope 1 { - debug x => _3; - let _8: u32; + debug x => _5; + let _10: u32; scope 2 { - debug x => _8; + debug x => _10; + let _15: ZeroOneTwo; + scope 3 { + debug x => _15; + let _20: ZeroOneTwo; + scope 4 { + debug x => _20; + } + } } } bb0: { -- StorageLive(_3); +- StorageLive(_5); + nop; - StorageLive(_4); - _4 = copy _1; -- _3 = move _4 as char (Transmute); -+ _3 = copy _1 as char (Transmute); - StorageDead(_4); - StorageLive(_5); StorageLive(_6); + _6 = copy _1; +- _5 = move _6 as char (Transmute); ++ _5 = copy _1 as char (Transmute); + StorageDead(_6); StorageLive(_7); - _7 = copy _3; -- _6 = move _7 as i32 (Transmute); -+ _6 = copy _3 as i32 (Transmute); - StorageDead(_7); - _5 = opaque::(move _6) -> [return: bb1, unwind continue]; + StorageLive(_8); + StorageLive(_9); + _9 = copy _5; +- _8 = move _9 as i32 (Transmute); ++ _8 = copy _5 as i32 (Transmute); + StorageDead(_9); + _7 = opaque::(move _8) -> [return: bb1, unwind continue]; } bb1: { - StorageDead(_6); - StorageDead(_5); -- StorageLive(_8); + StorageDead(_8); + StorageDead(_7); +- StorageLive(_10); + nop; - StorageLive(_9); - _9 = copy _2; -- _8 = move _9 as u32 (Transmute); -+ _8 = copy _2 as u32 (Transmute); - StorageDead(_9); - StorageLive(_10); StorageLive(_11); + _11 = copy _2; +- _10 = move _11 as u32 (Transmute); ++ _10 = copy _2 as u32 (Transmute); + StorageDead(_11); StorageLive(_12); - _12 = copy _8; -- _11 = move _12 as i32 (Transmute); -+ _11 = copy _2 as i32 (Transmute); - StorageDead(_12); - _10 = opaque::(move _11) -> [return: bb2, unwind continue]; + StorageLive(_13); + StorageLive(_14); + _14 = copy _10; +- _13 = move _14 as i32 (Transmute); ++ _13 = copy _2 as i32 (Transmute); + StorageDead(_14); + _12 = opaque::(move _13) -> [return: bb2, unwind continue]; } bb2: { - StorageDead(_11); - StorageDead(_10); + StorageDead(_13); + StorageDead(_12); +- StorageLive(_15); ++ nop; + StorageLive(_16); + _16 = copy _3; +- _15 = move _16 as ZeroOneTwo (Transmute); ++ _15 = copy _3 as ZeroOneTwo (Transmute); + StorageDead(_16); + StorageLive(_17); + StorageLive(_18); + StorageLive(_19); +- _19 = move _15; +- _18 = move _19 as u8 (Transmute); ++ _19 = copy _15; ++ _18 = copy _3 as u8 (Transmute); + StorageDead(_19); + _17 = opaque::(move _18) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageDead(_18); + StorageDead(_17); +- StorageLive(_20); ++ nop; + StorageLive(_21); + _21 = copy _4; +- _20 = move _21 as ZeroOneTwo (Transmute); ++ _20 = copy _4 as ZeroOneTwo (Transmute); + StorageDead(_21); + StorageLive(_22); + StorageLive(_23); + StorageLive(_24); +- _24 = move _20; +- _23 = move _24 as bool (Transmute); ++ _24 = copy _20; ++ _23 = copy _4 as bool (Transmute); + StorageDead(_24); + _22 = opaque::(move _23) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_23); + StorageDead(_22); _0 = const (); -- StorageDead(_8); -- StorageDead(_3); +- StorageDead(_20); +- StorageDead(_15); +- StorageDead(_10); +- StorageDead(_5); ++ nop; ++ nop; + nop; + nop; return; diff --git a/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff b/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff index f56af33ea603..74bbdeb8f744 100644 --- a/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff +++ b/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff @@ -7,7 +7,7 @@ let mut _2: *mut u8; scope 1 (inlined dangling_mut::) { scope 2 (inlined NonNull::::dangling) { - let mut _3: std::num::NonZero; + let _3: std::ptr::Alignment; scope 3 { scope 5 (inlined std::ptr::Alignment::as_nonzero) { } @@ -40,9 +40,9 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); -- _3 = const std::ptr::Alignment::of::::{constant#0} as std::num::NonZero (Transmute); +- _3 = const std::ptr::Alignment::of::::{constant#0}; - _2 = copy _3 as *mut u8 (Transmute); -+ _3 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); ++ _3 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); + _2 = const {0x1 as *mut u8}; StorageDead(_3); StorageLive(_4); From 929e2809734a1b3df4428912d9c8a36ac2546225 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 25 Jan 2026 17:05:09 -0800 Subject: [PATCH 135/978] Update `ptr::Alignment` to go through transmuting --- library/core/src/ptr/alignment.rs | 5 +++- ...ace.PreCodegen.after.32bit.panic-abort.mir | 24 +++++++++---------- ...ce.PreCodegen.after.32bit.panic-unwind.mir | 24 +++++++++---------- ...ace.PreCodegen.after.64bit.panic-abort.mir | 24 +++++++++---------- ...ce.PreCodegen.after.64bit.panic-unwind.mir | 24 +++++++++---------- tests/mir-opt/pre-codegen/drop_boxed_slice.rs | 5 ++-- 6 files changed, 54 insertions(+), 52 deletions(-) diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 42c95e6c9cd2..c3187c9a5c2b 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -166,7 +166,10 @@ impl Alignment { #[unstable(feature = "ptr_alignment_type", issue = "102070")] #[inline] pub const fn as_usize(self) -> usize { - self.0 as usize + // Going through `as_nonzero` helps this be more clearly the inverse of + // `new_unchecked`, letting MIR optimizations fold it away. + + self.as_nonzero().get() } /// Returns the alignment as a [NonZero]<[usize]>. diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir index 6ffadd4c51db..0adc66951e78 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-abort.mir @@ -8,9 +8,8 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { let _2: std::ptr::NonNull<[T]>; let mut _3: *mut [T]; let mut _4: *const [T]; - let _11: (); + let _10: (); scope 3 { - let _8: std::ptr::alignment::AlignmentEnum; scope 4 { scope 17 (inlined Layout::size) { } @@ -27,17 +26,21 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { scope 23 (inlined ::deallocate) { scope 24 (inlined std::alloc::Global::deallocate_impl) { scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - let mut _9: *mut u8; + let mut _8: *mut u8; scope 26 (inlined Layout::size) { } scope 27 (inlined NonNull::::as_ptr) { } scope 28 (inlined std::alloc::dealloc) { - let mut _10: usize; + let mut _9: usize; scope 29 (inlined Layout::size) { } scope 30 (inlined Layout::align) { scope 31 (inlined std::ptr::Alignment::as_usize) { + scope 32 (inlined std::ptr::Alignment::as_nonzero) { + } + scope 33 (inlined NonZero::::get) { + } } } } @@ -82,7 +85,6 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { StorageLive(_4); _3 = copy _2 as *mut [T] (Transmute); _4 = copy _2 as *const [T] (Transmute); - StorageLive(_7); _5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; } @@ -91,23 +93,21 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _6 = const ::ALIGN; _7 = copy _6 as std::ptr::Alignment (Transmute); StorageDead(_6); - _8 = copy (_7.0: std::ptr::alignment::AlignmentEnum); - StorageDead(_7); StorageDead(_4); switchInt(copy _5) -> [0: bb4, otherwise: bb2]; } bb2: { + StorageLive(_8); + _8 = copy _3 as *mut u8 (PtrToPtr); StorageLive(_9); - _9 = copy _3 as *mut u8 (PtrToPtr); - StorageLive(_10); - _10 = discriminant(_8); - _11 = alloc::alloc::__rust_dealloc(move _9, move _5, move _10) -> [return: bb3, unwind unreachable]; + _9 = copy _7 as usize (Transmute); + _10 = alloc::alloc::__rust_dealloc(move _8, move _5, move _9) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_10); StorageDead(_9); + StorageDead(_8); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir index 6ffadd4c51db..0adc66951e78 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.32bit.panic-unwind.mir @@ -8,9 +8,8 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { let _2: std::ptr::NonNull<[T]>; let mut _3: *mut [T]; let mut _4: *const [T]; - let _11: (); + let _10: (); scope 3 { - let _8: std::ptr::alignment::AlignmentEnum; scope 4 { scope 17 (inlined Layout::size) { } @@ -27,17 +26,21 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { scope 23 (inlined ::deallocate) { scope 24 (inlined std::alloc::Global::deallocate_impl) { scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - let mut _9: *mut u8; + let mut _8: *mut u8; scope 26 (inlined Layout::size) { } scope 27 (inlined NonNull::::as_ptr) { } scope 28 (inlined std::alloc::dealloc) { - let mut _10: usize; + let mut _9: usize; scope 29 (inlined Layout::size) { } scope 30 (inlined Layout::align) { scope 31 (inlined std::ptr::Alignment::as_usize) { + scope 32 (inlined std::ptr::Alignment::as_nonzero) { + } + scope 33 (inlined NonZero::::get) { + } } } } @@ -82,7 +85,6 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { StorageLive(_4); _3 = copy _2 as *mut [T] (Transmute); _4 = copy _2 as *const [T] (Transmute); - StorageLive(_7); _5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; } @@ -91,23 +93,21 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _6 = const ::ALIGN; _7 = copy _6 as std::ptr::Alignment (Transmute); StorageDead(_6); - _8 = copy (_7.0: std::ptr::alignment::AlignmentEnum); - StorageDead(_7); StorageDead(_4); switchInt(copy _5) -> [0: bb4, otherwise: bb2]; } bb2: { + StorageLive(_8); + _8 = copy _3 as *mut u8 (PtrToPtr); StorageLive(_9); - _9 = copy _3 as *mut u8 (PtrToPtr); - StorageLive(_10); - _10 = discriminant(_8); - _11 = alloc::alloc::__rust_dealloc(move _9, move _5, move _10) -> [return: bb3, unwind unreachable]; + _9 = copy _7 as usize (Transmute); + _10 = alloc::alloc::__rust_dealloc(move _8, move _5, move _9) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_10); StorageDead(_9); + StorageDead(_8); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir index 6ffadd4c51db..0adc66951e78 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-abort.mir @@ -8,9 +8,8 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { let _2: std::ptr::NonNull<[T]>; let mut _3: *mut [T]; let mut _4: *const [T]; - let _11: (); + let _10: (); scope 3 { - let _8: std::ptr::alignment::AlignmentEnum; scope 4 { scope 17 (inlined Layout::size) { } @@ -27,17 +26,21 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { scope 23 (inlined ::deallocate) { scope 24 (inlined std::alloc::Global::deallocate_impl) { scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - let mut _9: *mut u8; + let mut _8: *mut u8; scope 26 (inlined Layout::size) { } scope 27 (inlined NonNull::::as_ptr) { } scope 28 (inlined std::alloc::dealloc) { - let mut _10: usize; + let mut _9: usize; scope 29 (inlined Layout::size) { } scope 30 (inlined Layout::align) { scope 31 (inlined std::ptr::Alignment::as_usize) { + scope 32 (inlined std::ptr::Alignment::as_nonzero) { + } + scope 33 (inlined NonZero::::get) { + } } } } @@ -82,7 +85,6 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { StorageLive(_4); _3 = copy _2 as *mut [T] (Transmute); _4 = copy _2 as *const [T] (Transmute); - StorageLive(_7); _5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; } @@ -91,23 +93,21 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _6 = const ::ALIGN; _7 = copy _6 as std::ptr::Alignment (Transmute); StorageDead(_6); - _8 = copy (_7.0: std::ptr::alignment::AlignmentEnum); - StorageDead(_7); StorageDead(_4); switchInt(copy _5) -> [0: bb4, otherwise: bb2]; } bb2: { + StorageLive(_8); + _8 = copy _3 as *mut u8 (PtrToPtr); StorageLive(_9); - _9 = copy _3 as *mut u8 (PtrToPtr); - StorageLive(_10); - _10 = discriminant(_8); - _11 = alloc::alloc::__rust_dealloc(move _9, move _5, move _10) -> [return: bb3, unwind unreachable]; + _9 = copy _7 as usize (Transmute); + _10 = alloc::alloc::__rust_dealloc(move _8, move _5, move _9) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_10); StorageDead(_9); + StorageDead(_8); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir index 6ffadd4c51db..0adc66951e78 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.generic_in_place.PreCodegen.after.64bit.panic-unwind.mir @@ -8,9 +8,8 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { let _2: std::ptr::NonNull<[T]>; let mut _3: *mut [T]; let mut _4: *const [T]; - let _11: (); + let _10: (); scope 3 { - let _8: std::ptr::alignment::AlignmentEnum; scope 4 { scope 17 (inlined Layout::size) { } @@ -27,17 +26,21 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { scope 23 (inlined ::deallocate) { scope 24 (inlined std::alloc::Global::deallocate_impl) { scope 25 (inlined std::alloc::Global::deallocate_impl_runtime) { - let mut _9: *mut u8; + let mut _8: *mut u8; scope 26 (inlined Layout::size) { } scope 27 (inlined NonNull::::as_ptr) { } scope 28 (inlined std::alloc::dealloc) { - let mut _10: usize; + let mut _9: usize; scope 29 (inlined Layout::size) { } scope 30 (inlined Layout::align) { scope 31 (inlined std::ptr::Alignment::as_usize) { + scope 32 (inlined std::ptr::Alignment::as_nonzero) { + } + scope 33 (inlined NonZero::::get) { + } } } } @@ -82,7 +85,6 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { StorageLive(_4); _3 = copy _2 as *mut [T] (Transmute); _4 = copy _2 as *const [T] (Transmute); - StorageLive(_7); _5 = std::intrinsics::size_of_val::<[T]>(move _4) -> [return: bb1, unwind unreachable]; } @@ -91,23 +93,21 @@ fn generic_in_place(_1: *mut Box<[T]>) -> () { _6 = const ::ALIGN; _7 = copy _6 as std::ptr::Alignment (Transmute); StorageDead(_6); - _8 = copy (_7.0: std::ptr::alignment::AlignmentEnum); - StorageDead(_7); StorageDead(_4); switchInt(copy _5) -> [0: bb4, otherwise: bb2]; } bb2: { + StorageLive(_8); + _8 = copy _3 as *mut u8 (PtrToPtr); StorageLive(_9); - _9 = copy _3 as *mut u8 (PtrToPtr); - StorageLive(_10); - _10 = discriminant(_8); - _11 = alloc::alloc::__rust_dealloc(move _9, move _5, move _10) -> [return: bb3, unwind unreachable]; + _9 = copy _7 as usize (Transmute); + _10 = alloc::alloc::__rust_dealloc(move _8, move _5, move _9) -> [return: bb3, unwind unreachable]; } bb3: { - StorageDead(_10); StorageDead(_9); + StorageDead(_8); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/drop_boxed_slice.rs b/tests/mir-opt/pre-codegen/drop_boxed_slice.rs index dddcffdd4843..cad7251421eb 100644 --- a/tests/mir-opt/pre-codegen/drop_boxed_slice.rs +++ b/tests/mir-opt/pre-codegen/drop_boxed_slice.rs @@ -11,8 +11,7 @@ pub unsafe fn generic_in_place(ptr: *mut Box<[T]>) { // CHECK: [[SIZE:_.+]] = std::intrinsics::size_of_val::<[T]> // CHECK: [[ALIGN:_.+]] = const ::ALIGN; // CHECK: [[B:_.+]] = copy [[ALIGN]] as std::ptr::Alignment (Transmute); - // CHECK: [[C:_.+]] = copy ([[B]].0: std::ptr::alignment::AlignmentEnum); - // CHECK: [[D:_.+]] = discriminant([[C]]); - // CHECK: = alloc::alloc::__rust_dealloc({{.+}}, move [[SIZE]], move [[D]]) -> + // CHECK: [[C:_.+]] = copy [[B]] as usize (Transmute); + // CHECK: = alloc::alloc::__rust_dealloc({{.+}}, move [[SIZE]], move [[C]]) -> std::ptr::drop_in_place(ptr) } From 9288c208a2ee5ef34dbaad65d3a4aca65d1d62d8 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 25 Jan 2026 16:35:34 -0800 Subject: [PATCH 136/978] Adjust `Alignment` to emphasize that we don't look at its field --- library/core/src/ptr/alignment.rs | 9 +++++++-- ...hout_updating_operand.test.GVN.32bit.panic-abort.diff | 8 ++++---- ...hout_updating_operand.test.GVN.64bit.panic-abort.diff | 8 ++++---- tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff | 2 +- ...rint_invalid_constant.main.GVN.32bit.panic-abort.diff | 6 +++--- ...int_invalid_constant.main.GVN.32bit.panic-unwind.diff | 6 +++--- ...rint_invalid_constant.main.GVN.64bit.panic-abort.diff | 6 +++--- ...int_invalid_constant.main.GVN.64bit.panic-unwind.diff | 6 +++--- 8 files changed, 28 insertions(+), 23 deletions(-) diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index c3187c9a5c2b..7c34b026e14b 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -13,7 +13,12 @@ use crate::{cmp, fmt, hash, mem, num}; #[unstable(feature = "ptr_alignment_type", issue = "102070")] #[derive(Copy, Clone, PartialEq, Eq)] #[repr(transparent)] -pub struct Alignment(AlignmentEnum); +pub struct Alignment { + // This field is never used directly (nor is the enum), + // as it's just there to convey the validity invariant. + // (Hopefully it'll eventually be a pattern type instead.) + _inner_repr_trick: AlignmentEnum, +} // Alignment is `repr(usize)`, but via extra steps. const _: () = assert!(size_of::() == size_of::()); @@ -37,7 +42,7 @@ impl Alignment { /// assert_eq!(Alignment::MIN.as_usize(), 1); /// ``` #[unstable(feature = "ptr_alignment_type", issue = "102070")] - pub const MIN: Self = Self(AlignmentEnum::_Align1Shl0); + pub const MIN: Self = Self::new(1).unwrap(); /// Returns the alignment for a type. /// diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff index 2e428b778504..cde4d281f687 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff @@ -111,7 +111,7 @@ bb3: { - _22 = handle_alloc_error(move _18) -> unwind unreachable; -+ _22 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable; ++ _22 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}) -> unwind unreachable; } bb4: { @@ -190,12 +190,12 @@ StorageLive(_24); - _24 = copy _17 as std::ptr::Alignment (Transmute); - _18 = Layout { size: copy _16, align: move _24 }; -+ _24 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); -+ _18 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}; ++ _24 = const std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }}; ++ _18 = const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}; StorageDead(_24); StorageLive(_19); - _19 = std::alloc::Global::alloc_impl_runtime(copy _18, const false) -> [return: bb7, unwind unreachable]; -+ _19 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable]; ++ _19 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}, const false) -> [return: bb7, unwind unreachable]; } bb7: { diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff index 4531720ee501..ea5622eb9a2f 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff @@ -111,7 +111,7 @@ bb3: { - _22 = handle_alloc_error(move _18) -> unwind unreachable; -+ _22 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable; ++ _22 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}) -> unwind unreachable; } bb4: { @@ -190,12 +190,12 @@ StorageLive(_24); - _24 = copy _17 as std::ptr::Alignment (Transmute); - _18 = Layout { size: copy _16, align: move _24 }; -+ _24 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); -+ _18 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}; ++ _24 = const std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }}; ++ _18 = const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}; StorageDead(_24); StorageLive(_19); - _19 = std::alloc::Global::alloc_impl_runtime(copy _18, const false) -> [return: bb7, unwind unreachable]; -+ _19 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable]; ++ _19 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}, const false) -> [return: bb7, unwind unreachable]; } bb7: { diff --git a/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff b/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff index 74bbdeb8f744..9e543699da70 100644 --- a/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff +++ b/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff @@ -42,7 +42,7 @@ StorageLive(_3); - _3 = const std::ptr::Alignment::of::::{constant#0}; - _2 = copy _3 as *mut u8 (Transmute); -+ _3 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); ++ _3 = const std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }}; + _2 = const {0x1 as *mut u8}; StorageDead(_3); StorageLive(_4); diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff index d0fda06c115c..b48e6fc56f43 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff @@ -63,7 +63,7 @@ bb3: { - _1 = move ((_2 as Some).0: std::alloc::Layout); -+ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; ++ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment {{ _inner_repr_trick: Scalar(0x00000000): std::ptr::alignment::AlignmentEnum }} }}; StorageDead(_8); StorageDead(_2); StorageLive(_3); @@ -73,8 +73,8 @@ StorageLive(_7); - _7 = copy _1; - _6 = std::alloc::Global::alloc_impl_runtime(move _7, const false) -> [return: bb4, unwind unreachable]; -+ _7 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable]; ++ _7 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment {{ _inner_repr_trick: Scalar(0x00000000): std::ptr::alignment::AlignmentEnum }} }}; ++ _6 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment {{ _inner_repr_trick: Scalar(0x00000000): std::ptr::alignment::AlignmentEnum }} }}, const false) -> [return: bb4, unwind unreachable]; } bb4: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff index 485ff902a7b9..d0e59c06ff99 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff @@ -64,7 +64,7 @@ bb4: { - _1 = move ((_2 as Some).0: std::alloc::Layout); -+ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; ++ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment {{ _inner_repr_trick: Scalar(0x00000000): std::ptr::alignment::AlignmentEnum }} }}; StorageDead(_8); StorageDead(_2); StorageLive(_3); @@ -74,8 +74,8 @@ StorageLive(_7); - _7 = copy _1; - _6 = std::alloc::Global::alloc_impl_runtime(move _7, const false) -> [return: bb5, unwind continue]; -+ _7 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue]; ++ _7 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment {{ _inner_repr_trick: Scalar(0x00000000): std::ptr::alignment::AlignmentEnum }} }}; ++ _6 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment {{ _inner_repr_trick: Scalar(0x00000000): std::ptr::alignment::AlignmentEnum }} }}, const false) -> [return: bb5, unwind continue]; } bb5: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff index b45a0f4a9bdd..18fc4ac0d87f 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff @@ -63,7 +63,7 @@ bb3: { - _1 = move ((_2 as Some).0: std::alloc::Layout); -+ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; ++ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment {{ _inner_repr_trick: Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum }} }}; StorageDead(_8); StorageDead(_2); StorageLive(_3); @@ -73,8 +73,8 @@ StorageLive(_7); - _7 = copy _1; - _6 = std::alloc::Global::alloc_impl_runtime(move _7, const false) -> [return: bb4, unwind unreachable]; -+ _7 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable]; ++ _7 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment {{ _inner_repr_trick: Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum }} }}; ++ _6 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment {{ _inner_repr_trick: Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum }} }}, const false) -> [return: bb4, unwind unreachable]; } bb4: { diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff index beee899dafe6..c109fe735e89 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff @@ -64,7 +64,7 @@ bb4: { - _1 = move ((_2 as Some).0: std::alloc::Layout); -+ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; ++ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment {{ _inner_repr_trick: Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum }} }}; StorageDead(_8); StorageDead(_2); StorageLive(_3); @@ -74,8 +74,8 @@ StorageLive(_7); - _7 = copy _1; - _6 = std::alloc::Global::alloc_impl_runtime(move _7, const false) -> [return: bb5, unwind continue]; -+ _7 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue]; ++ _7 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment {{ _inner_repr_trick: Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum }} }}; ++ _6 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment {{ _inner_repr_trick: Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum }} }}, const false) -> [return: bb5, unwind continue]; } bb5: { From 79549a053d0fff919a1e51c20e2fd7328e5a9ad0 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Mon, 26 Jan 2026 04:35:30 +0000 Subject: [PATCH 137/978] Prepare for merging from rust-lang/rust This updates the rust-version file to 873d4682c7d285540b8f28bfe637006cef8918a6. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index d6e02b0dd2b2..ccc0b55d4dc5 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -5c49c4f7c8393c861b849441d27f5d40e0f1e33b +873d4682c7d285540b8f28bfe637006cef8918a6 From 8ff928ed4d4fe1eb74c6ce42a5e4387db49394ff Mon Sep 17 00:00:00 2001 From: Jamie Hill-Daniel Date: Mon, 26 Jan 2026 10:30:54 +0000 Subject: [PATCH 138/978] Fix lockfile update script --- src/tools/update-lockfile.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/update-lockfile.sh b/src/tools/update-lockfile.sh index a968d83d8152..123481b6b681 100755 --- a/src/tools/update-lockfile.sh +++ b/src/tools/update-lockfile.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # Updates the workspaces in `.`, `library` and `src/tools/rustbook` # Logs are written to `cargo_update.log` @@ -6,13 +6,13 @@ set -euo pipefail -echo -e "\ncompiler & tools dependencies:" > cargo_update.log +printf "\ncompiler & tools dependencies:" > cargo_update.log # Remove first line that always just says "Updating crates.io index" cargo update 2>&1 | sed '/crates.io index/d' | \ tee -a cargo_update.log -echo -e "\nlibrary dependencies:" >> cargo_update.log +printf "\nlibrary dependencies:" >> cargo_update.log cargo update --manifest-path library/Cargo.toml 2>&1 | sed '/crates.io index/d' | \ tee -a cargo_update.log -echo -e "\nrustbook dependencies:" >> cargo_update.log +printf "\nrustbook dependencies:" >> cargo_update.log cargo update --manifest-path src/tools/rustbook/Cargo.toml 2>&1 | sed '/crates.io index/d' | \ tee -a cargo_update.log From 8a24ab39125813688fd0d4ed14f928ff26cf0269 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Mon, 26 Jan 2026 11:34:15 +0000 Subject: [PATCH 139/978] Prepare for merging from rust-lang/rust This updates the rust-version file to 0462e8f7e51f20692b02d68efee68bb28a6f4457. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index ccc0b55d4dc5..c8a3b401a6e1 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -873d4682c7d285540b8f28bfe637006cef8918a6 +0462e8f7e51f20692b02d68efee68bb28a6f4457 From c7788af89ac962245d8c3eeb30f7f4562fd70d2a Mon Sep 17 00:00:00 2001 From: Antonio Souza Date: Sun, 25 Jan 2026 20:51:30 -0500 Subject: [PATCH 140/978] Fix contrast ratio for Since element in rustodoc dark theme Signed-off-by: Antonio Souza --- src/librustdoc/html/static/css/noscript.css | 2 +- src/librustdoc/html/static/css/rustdoc.css | 2 +- tests/rustdoc-gui/headings.goml | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css index 6f44854b6914..363cec3116a9 100644 --- a/src/librustdoc/html/static/css/noscript.css +++ b/src/librustdoc/html/static/css/noscript.css @@ -163,7 +163,7 @@ nav.sub { --headings-border-bottom-color: #d2d2d2; --border-color: #e0e0e0; --button-background-color: #f0f0f0; - --right-side-color: grey; + --right-side-color: #d0d0d0; --code-attribute-color: #999; --toggles-color: #999; --toggle-filter: invert(100%); diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 6c34d31cc918..59ea478ee91e 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -3286,7 +3286,7 @@ by default. --headings-border-bottom-color: #d2d2d2; --border-color: #e0e0e0; --button-background-color: #f0f0f0; - --right-side-color: grey; + --right-side-color: #d0d0d0; --code-attribute-color: #999; --toggles-color: #999; --toggle-filter: invert(100%); diff --git a/tests/rustdoc-gui/headings.goml b/tests/rustdoc-gui/headings.goml index 94d80a3e3df5..391234b78ebd 100644 --- a/tests/rustdoc-gui/headings.goml +++ b/tests/rustdoc-gui/headings.goml @@ -221,14 +221,14 @@ call-function: ( define-function: ( "check-since-color", - [theme], + [theme, color], block { call-function: ("switch-theme", {"theme": |theme|}) - assert-css: (".since", {"color": "#808080"}, ALL) + assert-css: (".since", {"color": |color|}, ALL) }, ) go-to: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html" -call-function: ("check-since-color", {"theme": "ayu"}) -call-function: ("check-since-color", {"theme": "dark"}) -call-function: ("check-since-color", {"theme": "light"}) +call-function: ("check-since-color", {"theme": "ayu", "color": "#808080"}) +call-function: ("check-since-color", {"theme": "dark", "color": "#d0d0d0"}) +call-function: ("check-since-color", {"theme": "light", "color": "#808080"}) From 76b6623267dc944fd61e06741327f74ee4820a21 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 23 Jan 2026 11:06:57 +0000 Subject: [PATCH 141/978] target: fix destabilising target-spec-json --- compiler/rustc_target/src/spec/mod.rs | 3 +++ tests/run-make/rust-lld-custom-target/rmake.rs | 6 +++++- tests/run-make/rustdoc-target-spec-json-path/rmake.rs | 8 +++++++- tests/run-make/target-specs/rmake.rs | 9 ++++++++- tests/ui/check-cfg/values-target-json.rs | 3 ++- 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index ef475630d494..164db15d24e0 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -3352,6 +3352,9 @@ impl Target { Err(format!("could not find specification for target {target_tuple:?}")) } + TargetTuple::TargetJson { ref contents, .. } if !unstable_options => { + Err("custom targets are unstable and require `-Zunstable-options`".to_string()) + } TargetTuple::TargetJson { ref contents, .. } => Target::from_json(contents), } } diff --git a/tests/run-make/rust-lld-custom-target/rmake.rs b/tests/run-make/rust-lld-custom-target/rmake.rs index 90ba424ffe94..d281d820f47b 100644 --- a/tests/run-make/rust-lld-custom-target/rmake.rs +++ b/tests/run-make/rust-lld-custom-target/rmake.rs @@ -15,7 +15,11 @@ fn main() { // Compile to a custom target spec with rust-lld enabled by default. We'll check that by asking // the linker to display its version number with a link-arg. assert_rustc_uses_lld( - rustc().crate_type("cdylib").target("custom-target.json").input("lib.rs"), + rustc() + .crate_type("cdylib") + .target("custom-target.json") + .arg("-Zunstable-options") + .input("lib.rs"), ); // But it can also be disabled via linker features. diff --git a/tests/run-make/rustdoc-target-spec-json-path/rmake.rs b/tests/run-make/rustdoc-target-spec-json-path/rmake.rs index d43aa9b90ac7..8660556564f1 100644 --- a/tests/run-make/rustdoc-target-spec-json-path/rmake.rs +++ b/tests/run-make/rustdoc-target-spec-json-path/rmake.rs @@ -5,8 +5,14 @@ use run_make_support::{cwd, rustc, rustdoc}; fn main() { let out_dir = "rustdoc-target-spec-json-path"; - rustc().crate_type("lib").input("dummy_core.rs").target("target.json").run(); + rustc() + .arg("-Zunstable-options") + .crate_type("lib") + .input("dummy_core.rs") + .target("target.json") + .run(); rustdoc() + .arg("-Zunstable-options") .input("my_crate.rs") .out_dir(out_dir) .library_search_path(cwd()) diff --git a/tests/run-make/target-specs/rmake.rs b/tests/run-make/target-specs/rmake.rs index 69292af5fd69..6c88f3164e9e 100644 --- a/tests/run-make/target-specs/rmake.rs +++ b/tests/run-make/target-specs/rmake.rs @@ -20,13 +20,20 @@ fn main() { .target("my-incomplete-platform.json") .run_fail() .assert_stderr_contains("missing field `llvm-target`"); - let test_platform = rustc() + let _ = rustc() .input("foo.rs") .target("my-x86_64-unknown-linux-gnu-platform") .crate_type("lib") .emit("asm") .run_fail() .assert_stderr_contains("custom targets are unstable and require `-Zunstable-options`"); + let _ = rustc() + .input("foo.rs") + .target("my-awesome-platform.json") + .crate_type("lib") + .emit("asm") + .run_fail() + .assert_stderr_contains("custom targets are unstable and require `-Zunstable-options`"); rustc() .arg("-Zunstable-options") .env("RUST_TARGET_PATH", ".") diff --git a/tests/ui/check-cfg/values-target-json.rs b/tests/ui/check-cfg/values-target-json.rs index defb286ed19b..21b6af9b5560 100644 --- a/tests/ui/check-cfg/values-target-json.rs +++ b/tests/ui/check-cfg/values-target-json.rs @@ -4,7 +4,8 @@ //@ check-pass //@ no-auto-check-cfg //@ needs-llvm-components: x86 -//@ compile-flags: --crate-type=lib --check-cfg=cfg() --target={{src-base}}/check-cfg/my-awesome-platform.json +//@ compile-flags: --crate-type=lib --check-cfg=cfg() +//@ compile-flags: -Zunstable-options --target={{src-base}}/check-cfg/my-awesome-platform.json //@ ignore-backends: gcc #![feature(lang_items, no_core, auto_traits, rustc_attrs)] From fdfbe7305d1436594ffa1570f611054555327eef Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 25 Jan 2026 19:42:40 +0100 Subject: [PATCH 142/978] Only `Duration` constructors taking `u64` are covered --- clippy_lints/src/duration_suboptimal_units.rs | 5 +++-- tests/ui/duration_suboptimal_units.fixed | 5 +++++ tests/ui/duration_suboptimal_units.rs | 5 +++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/duration_suboptimal_units.rs b/clippy_lints/src/duration_suboptimal_units.rs index 8140585b70d3..19f44f8e959d 100644 --- a/clippy_lints/src/duration_suboptimal_units.rs +++ b/clippy_lints/src/duration_suboptimal_units.rs @@ -9,7 +9,7 @@ use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, QPath, RustcVersion}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt, UintTy}; use rustc_session::impl_lint_pass; use rustc_span::Symbol; @@ -76,13 +76,14 @@ impl LateLintPass<'_> for DurationSuboptimalUnits { .typeck_results() .node_type(func_ty.hir_id) .is_diag_item(cx, sym::Duration) + && matches!(cx.typeck_results().expr_ty_adjusted(arg).kind(), ty::Uint(UintTy::U64)) // We intentionally don't want to evaluate referenced constants, as we don't want to // recommend a literal value over using constants: // // let dur = Duration::from_secs(SIXTY); // ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Duration::from_mins(1)` && let Some(Constant::Int(value)) = ConstEvalCtxt::new(cx).eval_local(arg, expr.span.ctxt()) - && let value = u64::try_from(value).expect("All Duration::from_ constructors take a u64") + && let Ok(value) = u64::try_from(value) // Cannot fail // There is no need to promote e.g. 0 seconds to 0 hours && value != 0 && let Some((promoted_constructor, promoted_value)) = self.promote(cx, func_name.ident.name, value) diff --git a/tests/ui/duration_suboptimal_units.fixed b/tests/ui/duration_suboptimal_units.fixed index 98c4b6e965ba..515ec10e572b 100644 --- a/tests/ui/duration_suboptimal_units.fixed +++ b/tests/ui/duration_suboptimal_units.fixed @@ -89,3 +89,8 @@ mod my_duration { let dur = Duration::from_secs(60); } } + +fn issue16457() { + // Methods taking something else than `u64` are not covered + _ = Duration::from_nanos_u128(1 << 90); +} diff --git a/tests/ui/duration_suboptimal_units.rs b/tests/ui/duration_suboptimal_units.rs index c4f33a9f92e0..357c52cffb35 100644 --- a/tests/ui/duration_suboptimal_units.rs +++ b/tests/ui/duration_suboptimal_units.rs @@ -89,3 +89,8 @@ mod my_duration { let dur = Duration::from_secs(60); } } + +fn issue16457() { + // Methods taking something else than `u64` are not covered + _ = Duration::from_nanos_u128(1 << 90); +} From 996d72bce8845a4c4dcb0d41823cf0af4c11c59a Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Sat, 17 Jan 2026 17:53:10 +0100 Subject: [PATCH 143/978] compiletest: Support `--extern` modifiers with `proc-macro` directive So that `pub-priv1.rs` test does not have to (ab)use the `aux-crate` directive for this purpose. This is very edge-casey so I don't think we should document this in rustc-dev-guide. If someone needs to do this they will look at the code and easily find the functionality. This is a bit hacky since `--extern priv:pm.rs` is not valid, but we can make our directives work however we want. And I think this is a fine pragmatic approach. Doing it "the right way" would be a lot of work for not much gain. Plus, that work can be done incrementally in small steps in the future if wanted. --- .../compiletest/src/directives/auxiliary.rs | 20 +++++++++++++++++-- .../src/directives/auxiliary/tests.rs | 16 +++++++++++++++ src/tools/compiletest/src/runtest.rs | 2 +- tests/ui/privacy/pub-priv-dep/auxiliary/pm.rs | 5 ----- tests/ui/privacy/pub-priv-dep/pub-priv1.rs | 2 +- 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/tools/compiletest/src/directives/auxiliary.rs b/src/tools/compiletest/src/directives/auxiliary.rs index 14cbab640eb6..0e7e370adbd4 100644 --- a/src/tools/compiletest/src/directives/auxiliary.rs +++ b/src/tools/compiletest/src/directives/auxiliary.rs @@ -26,8 +26,12 @@ pub struct AuxCrate { } /// The value of a `proc-macro` directive. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, PartialEq, Eq)] pub(crate) struct ProcMacro { + /// Contains `--extern` modifiers, if any. See the tracking issue for more + /// info: + /// With `proc-macro: noprelude:bar.rs` this will be `noprelude`. + pub extern_modifiers: Option, /// With `proc-macro: bar.rs` this will be `bar.rs`. pub path: String, } @@ -108,5 +112,17 @@ fn parse_aux_crate(r: String) -> AuxCrate { } fn parse_proc_macro(r: String) -> ProcMacro { - ProcMacro { path: r.trim().to_string() } + let r = r.trim(); + + // Matches: + // path + // modifiers:path + let caps = static_regex!(r"^(?:(?[^=]*?):)?(?.*)$") + .captures(r) + .expect("can never fail"); + + let modifiers = caps.name("modifiers").map(|m| m.as_str().to_string()); + let path = caps["path"].to_string(); + + ProcMacro { extern_modifiers: modifiers, path } } diff --git a/src/tools/compiletest/src/directives/auxiliary/tests.rs b/src/tools/compiletest/src/directives/auxiliary/tests.rs index ad205eaabfda..74fff630692e 100644 --- a/src/tools/compiletest/src/directives/auxiliary/tests.rs +++ b/src/tools/compiletest/src/directives/auxiliary/tests.rs @@ -25,3 +25,19 @@ fn test_aux_crate_value_with_modifiers() { fn test_aux_crate_value_invalid() { parse_aux_crate("foo.rs".to_string()); } + +#[test] +fn test_proc_macro_value_no_modifiers() { + assert_eq!( + ProcMacro { extern_modifiers: None, path: "foo.rs".to_string() }, + parse_proc_macro("foo.rs".to_string()) + ); +} + +#[test] +fn test_proc_macro_value_with_modifiers() { + assert_eq!( + ProcMacro { extern_modifiers: Some("noprelude".to_string()), path: "foo.rs".to_string() }, + parse_proc_macro("noprelude:foo.rs".to_string()) + ); +} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 2bfb73f05d16..502db382e269 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1302,7 +1302,7 @@ impl<'test> TestCx<'test> { let crate_name = path_to_crate_name(&proc_macro.path); add_extern( rustc, - None, // `extern_modifiers` + proc_macro.extern_modifiers.as_deref(), &crate_name, &proc_macro.path, AuxType::ProcMacro, diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/pm.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/pm.rs index 9e2aa898afe8..d45f2639d182 100644 --- a/tests/ui/privacy/pub-priv-dep/auxiliary/pm.rs +++ b/tests/ui/privacy/pub-priv-dep/auxiliary/pm.rs @@ -1,8 +1,3 @@ -//@ force-host -//@ no-prefer-dynamic - -#![crate_type = "proc-macro"] - extern crate proc_macro; use proc_macro::TokenStream; diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs index eae0f9756a10..09ad59582d84 100644 --- a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs +++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs @@ -1,6 +1,6 @@ //@ aux-crate:priv:priv_dep=priv_dep.rs //@ aux-build:pub_dep.rs -//@ aux-crate:priv:pm=pm.rs +//@ proc-macro:priv:pm.rs //@ compile-flags: -Zunstable-options // Basic behavior check of exported_private_dependencies from either a public From 25234f8652f59a796617c44688e8d4696611c314 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 26 Jan 2026 18:24:52 +0100 Subject: [PATCH 144/978] Add two new target-specific intrinsics mapping --- src/intrinsic/llvm.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 10183c5ee526..fbf3050a8a15 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1061,13 +1061,18 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.xgetbv" => "__builtin_ia32_xgetbv", // NOTE: this doc specifies the equivalent GCC builtins: http://huonw.github.io/llvmint/llvmint/x86/index.html + // FIXME: Should handle other targets than `ia32`. "llvm.sqrt.v2f64" => "__builtin_ia32_sqrtpd", + // FIXME: Should handle other targets than `ia32`. + "llvm.sqrt.v4f32" => "__builtin_ia32_sqrtps", "llvm.sqrt.f32" => { let gcc_name = "__builtin_sqrtf"; let func = cx.context.get_builtin_function(gcc_name); cx.functions.borrow_mut().insert(gcc_name.to_string(), func); return func; } + // FIXME: Should handle other targets than `ia32`. + "llvm.smax.v4i32" => "__builtin_ia32_pmaxsd128", "llvm.x86.avx512.pmul.dq.512" => "__builtin_ia32_pmuldq512_mask", "llvm.x86.avx512.pmulu.dq.512" => "__builtin_ia32_pmuludq512_mask", "llvm.x86.avx512.max.ps.512" => "__builtin_ia32_maxps512_mask", From 436ae1e0a0d48967677bb6bf567d3d7c4697f498 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 26 Jan 2026 18:25:25 +0100 Subject: [PATCH 145/978] Add regression test for `llvm.sqrt.v4f64` and `llvm.smax.v4i32` mapping --- tests/run/simd-ffi.rs | 102 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 tests/run/simd-ffi.rs diff --git a/tests/run/simd-ffi.rs b/tests/run/simd-ffi.rs new file mode 100644 index 000000000000..67cc2e5b96e3 --- /dev/null +++ b/tests/run/simd-ffi.rs @@ -0,0 +1,102 @@ +// Compiler: +// +// Run-time: +// status: 0 + +// FIXME: Remove this test once stops +// ignoring GCC backend. + +#![allow(internal_features, non_camel_case_types)] +// we can compile to a variety of platforms, because we don't need +// cross-compiled standard libraries. +#![feature(no_core, auto_traits)] +#![no_core] +#![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items, rustc_attrs)] + +#[derive(Copy)] +#[repr(simd)] +pub struct f32x4([f32; 4]); + +extern "C" { + #[link_name = "llvm.sqrt.v4f32"] + fn vsqrt(x: f32x4) -> f32x4; +} + +pub fn foo(x: f32x4) -> f32x4 { + unsafe { vsqrt(x) } +} + +#[derive(Copy)] +#[repr(simd)] +pub struct i32x4([i32; 4]); + +extern "C" { + // _mm_sll_epi32 + #[cfg(all(any(target_arch = "x86", target_arch = "x86-64"), target_feature = "sse2"))] + #[link_name = "llvm.x86.sse2.psll.d"] + fn integer(a: i32x4, b: i32x4) -> i32x4; + + // vmaxq_s32 + #[cfg(target_arch = "arm")] + #[link_name = "llvm.arm.neon.vmaxs.v4i32"] + fn integer(a: i32x4, b: i32x4) -> i32x4; + // vmaxq_s32 + #[cfg(target_arch = "aarch64")] + #[link_name = "llvm.aarch64.neon.maxs.v4i32"] + fn integer(a: i32x4, b: i32x4) -> i32x4; + + // Use a generic LLVM intrinsic to do type checking on other platforms + #[cfg(not(any( + all(any(target_arch = "x86", target_arch = "x86-64"), target_feature = "sse2"), + target_arch = "arm", + target_arch = "aarch64" + )))] + #[link_name = "llvm.smax.v4i32"] + fn integer(a: i32x4, b: i32x4) -> i32x4; +} + +pub fn bar(a: i32x4, b: i32x4) -> i32x4 { + unsafe { integer(a, b) } +} + +#[lang = "pointee_sized"] +pub trait PointeeSized {} + +#[lang = "meta_sized"] +pub trait MetaSized: PointeeSized {} + +#[lang = "sized"] +pub trait Sized: MetaSized {} + +#[lang = "copy"] +pub trait Copy {} + +impl Copy for f32 {} +impl Copy for i32 {} +impl Copy for [f32; 4] {} +impl Copy for [i32; 4] {} + +pub mod marker { + pub use Copy; +} + +#[lang = "freeze"] +auto trait Freeze {} + +#[macro_export] +#[rustc_builtin_macro] +macro_rules! Copy { + () => {}; +} +#[macro_export] +#[rustc_builtin_macro] +macro_rules! derive { + () => {}; +} + +#[lang = "start"] +fn start(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize { + 0 +} + +fn main() {} From b7728f072e3eae7c4cb0dfab62d575414c37d88f Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Mon, 26 Jan 2026 17:31:34 +0000 Subject: [PATCH 146/978] Omit standard copyright notice Remove copyright notices for files licensed under the standard terms (MIT OR Apache-2.0). --- example/alloc_system.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/example/alloc_system.rs b/example/alloc_system.rs index 4d70122496b7..31457185f1a8 100644 --- a/example/alloc_system.rs +++ b/example/alloc_system.rs @@ -1,6 +1,3 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -// SPDX-FileCopyrightText: The Rust Project Developers (see https://thanks.rust-lang.org) - #![no_std] #![feature(allocator_api, rustc_private)] From 9f308b72685b460b289af189d1c255ca1b6fd9cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 8 Nov 2025 22:16:44 +0000 Subject: [PATCH 147/978] Do not mention `-Zmacro-backtrace` for std macros that are a wrapper around a compiler intrinsic --- tests/ui/recursive_format_impl.stderr | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/tests/ui/recursive_format_impl.stderr b/tests/ui/recursive_format_impl.stderr index 31960c7193b4..4361d612bf2a 100644 --- a/tests/ui/recursive_format_impl.stderr +++ b/tests/ui/recursive_format_impl.stderr @@ -12,72 +12,54 @@ error: using `self` as `Display` in `impl Display` will cause infinite recursion | LL | write!(f, "{}", self) | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:86:9 | LL | write!(f, "{}", &self) | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Debug` in `impl Debug` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:93:9 | LL | write!(f, "{:?}", &self) | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:103:9 | LL | write!(f, "{}", &&&self) | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:178:9 | LL | write!(f, "{}", &*self) | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Debug` in `impl Debug` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:185:9 | LL | write!(f, "{:?}", &*self) | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:202:9 | LL | write!(f, "{}", *self) | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:219:9 | LL | write!(f, "{}", **&&*self) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: using `self` as `Display` in `impl Display` will cause infinite recursion --> tests/ui/recursive_format_impl.rs:236:9 | LL | write!(f, "{}", &&**&&*self) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 10 previous errors From dfcfd73b2c3bc0c076226ebbb04554b689dd5041 Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Mon, 26 Jan 2026 17:57:34 +0000 Subject: [PATCH 148/978] fix: `cmp_owned` FP when `to_string` comes from macro input --- clippy_lints/src/operators/cmp_owned.rs | 12 ++++++--- clippy_lints/src/operators/mod.rs | 2 +- tests/ui/cmp_owned/with_suggestion.fixed | 32 +++++++++++++++++++++++ tests/ui/cmp_owned/with_suggestion.rs | 32 +++++++++++++++++++++++ tests/ui/cmp_owned/with_suggestion.stderr | 15 ++++++++++- 5 files changed, 87 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/operators/cmp_owned.rs b/clippy_lints/src/operators/cmp_owned.rs index 39097833a6c5..db55772f4e01 100644 --- a/clippy_lints/src/operators/cmp_owned.rs +++ b/clippy_lints/src/operators/cmp_owned.rs @@ -10,10 +10,10 @@ use rustc_span::symbol::sym; use super::CMP_OWNED; -pub(super) fn check(cx: &LateContext<'_>, op: BinOpKind, lhs: &Expr<'_>, rhs: &Expr<'_>) { +pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, op: BinOpKind, lhs: &Expr<'_>, rhs: &Expr<'_>) { if op.is_comparison() { - check_op(cx, lhs, rhs, true); - check_op(cx, rhs, lhs, false); + check_op(cx, e, lhs, rhs, true); + check_op(cx, e, rhs, lhs, false); } } @@ -35,7 +35,11 @@ fn symmetric_partial_eq<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: Ty<'t }) } -fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool) { +fn check_op(cx: &LateContext<'_>, outer: &Expr<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool) { + if !outer.span.eq_ctxt(expr.span) { + return; + } + let typeck = cx.typeck_results(); let (arg, arg_span) = match expr.kind { ExprKind::MethodCall(_, arg, [], _) diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs index 53b8e9e5d5ae..383b135dfa50 100644 --- a/clippy_lints/src/operators/mod.rs +++ b/clippy_lints/src/operators/mod.rs @@ -1038,7 +1038,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators { float_equality_without_abs::check(cx, e, op.node, lhs, rhs); integer_division::check(cx, e, op.node, lhs, rhs); integer_division_remainder_used::check(cx, op.node, lhs, rhs, e.span); - cmp_owned::check(cx, op.node, lhs, rhs); + cmp_owned::check(cx, e, op.node, lhs, rhs); float_cmp::check(cx, e, op.node, lhs, rhs); modulo_one::check(cx, e, op.node, rhs); modulo_arithmetic::check( diff --git a/tests/ui/cmp_owned/with_suggestion.fixed b/tests/ui/cmp_owned/with_suggestion.fixed index 4c3b13b30043..f65339605e75 100644 --- a/tests/ui/cmp_owned/with_suggestion.fixed +++ b/tests/ui/cmp_owned/with_suggestion.fixed @@ -112,3 +112,35 @@ fn issue16322(item: String) { println!("Ja!"); } } + +fn issue16458() { + macro_rules! partly_comes_from_macro { + ($i:ident: $ty:ty, $def:expr) => { + let _ = { + let res = <$ty>::default() == $def; + let _i: $ty = $def; + res + }; + }; + } + + partly_comes_from_macro! { + required_version: String, env!("HOME").to_string() + } + + macro_rules! all_comes_from_macro { + ($($i:ident: $ty:ty, $def:expr);+ $(;)*) => { + $( + let _ = { + let res = <$ty>::default() == "$def"; + //~^ cmp_owned + let _i: $ty = $def; + res + }; + )+ + }; + } + all_comes_from_macro! { + required_version: String, env!("HOME").to_string(); + } +} diff --git a/tests/ui/cmp_owned/with_suggestion.rs b/tests/ui/cmp_owned/with_suggestion.rs index a9d7509feaaf..ed2300c80eaa 100644 --- a/tests/ui/cmp_owned/with_suggestion.rs +++ b/tests/ui/cmp_owned/with_suggestion.rs @@ -112,3 +112,35 @@ fn issue16322(item: String) { println!("Ja!"); } } + +fn issue16458() { + macro_rules! partly_comes_from_macro { + ($i:ident: $ty:ty, $def:expr) => { + let _ = { + let res = <$ty>::default() == $def; + let _i: $ty = $def; + res + }; + }; + } + + partly_comes_from_macro! { + required_version: String, env!("HOME").to_string() + } + + macro_rules! all_comes_from_macro { + ($($i:ident: $ty:ty, $def:expr);+ $(;)*) => { + $( + let _ = { + let res = <$ty>::default() == "$def".to_string(); + //~^ cmp_owned + let _i: $ty = $def; + res + }; + )+ + }; + } + all_comes_from_macro! { + required_version: String, env!("HOME").to_string(); + } +} diff --git a/tests/ui/cmp_owned/with_suggestion.stderr b/tests/ui/cmp_owned/with_suggestion.stderr index 66544ce0c217..38d124baa4b5 100644 --- a/tests/ui/cmp_owned/with_suggestion.stderr +++ b/tests/ui/cmp_owned/with_suggestion.stderr @@ -55,5 +55,18 @@ error: this creates an owned instance just for comparison LL | if item == t!(frohes_neu_Jahr).to_string() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t!(frohes_neu_Jahr)` -error: aborting due to 9 previous errors +error: this creates an owned instance just for comparison + --> tests/ui/cmp_owned/with_suggestion.rs:135:51 + | +LL | let res = <$ty>::default() == "$def".to_string(); + | ^^^^^^^^^^^^^^^^^^ help: try: `"$def"` +... +LL | / all_comes_from_macro! { +LL | | required_version: String, env!("HOME").to_string(); +LL | | } + | |_____- in this macro invocation + | + = note: this error originates in the macro `all_comes_from_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 10 previous errors From c3ab233ca45075ec9306385633fb2f09999ac825 Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Mon, 26 Jan 2026 18:27:06 +0000 Subject: [PATCH 149/978] fix: `manual_dangling_ptr` FP when pointee type is not `Sized` --- clippy_lints/src/casts/manual_dangling_ptr.rs | 2 ++ tests/ui/manual_dangling_ptr.fixed | 12 ++++++++ tests/ui/manual_dangling_ptr.rs | 12 ++++++++ tests/ui/manual_dangling_ptr.stderr | 28 +++++++++++-------- 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/casts/manual_dangling_ptr.rs b/clippy_lints/src/casts/manual_dangling_ptr.rs index be1f406770ce..56779e8ce3d9 100644 --- a/clippy_lints/src/casts/manual_dangling_ptr.rs +++ b/clippy_lints/src/casts/manual_dangling_ptr.rs @@ -15,6 +15,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: let init_expr = expr_or_init(cx, from); if is_expr_const_aligned(cx, init_expr, ptr_ty.ty) && let Some(std_or_core) = std_or_core(cx) + && let pointee_ty = cx.typeck_results().node_type(ptr_ty.ty.hir_id) + && pointee_ty.is_sized(cx.tcx, cx.typing_env()) { let sugg_fn = match ptr_ty.mutbl { Mutability::Not => "ptr::dangling", diff --git a/tests/ui/manual_dangling_ptr.fixed b/tests/ui/manual_dangling_ptr.fixed index b6afe7898906..c6a6379194c9 100644 --- a/tests/ui/manual_dangling_ptr.fixed +++ b/tests/ui/manual_dangling_ptr.fixed @@ -1,3 +1,4 @@ +#![feature(extern_types)] #![warn(clippy::manual_dangling_ptr)] use std::mem; @@ -42,3 +43,14 @@ fn _msrv_1_84() { //~^ manual_dangling_ptr //~| manual_dangling_ptr } + +fn issue16459() { + unsafe extern "C" { + type Extern; + } + let _ = unsafe { &mut *(1 as *mut Extern) }; + + struct Empty; + let _ = unsafe { &mut *std::ptr::dangling_mut::() }; + //~^ manual_dangling_ptr +} diff --git a/tests/ui/manual_dangling_ptr.rs b/tests/ui/manual_dangling_ptr.rs index 581ad50113e2..338003fa41fd 100644 --- a/tests/ui/manual_dangling_ptr.rs +++ b/tests/ui/manual_dangling_ptr.rs @@ -1,3 +1,4 @@ +#![feature(extern_types)] #![warn(clippy::manual_dangling_ptr)] use std::mem; @@ -42,3 +43,14 @@ fn _msrv_1_84() { //~^ manual_dangling_ptr //~| manual_dangling_ptr } + +fn issue16459() { + unsafe extern "C" { + type Extern; + } + let _ = unsafe { &mut *(1 as *mut Extern) }; + + struct Empty; + let _ = unsafe { &mut *(1 as *mut Empty) }; + //~^ manual_dangling_ptr +} diff --git a/tests/ui/manual_dangling_ptr.stderr b/tests/ui/manual_dangling_ptr.stderr index e3bc9b16b0d9..7e1533f7a30d 100644 --- a/tests/ui/manual_dangling_ptr.stderr +++ b/tests/ui/manual_dangling_ptr.stderr @@ -1,5 +1,5 @@ error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:7:24 + --> tests/ui/manual_dangling_ptr.rs:8:24 | LL | let _: *const u8 = 1 as *const _; | ^^^^^^^^^^^^^ help: use: `std::ptr::dangling()` @@ -8,58 +8,64 @@ LL | let _: *const u8 = 1 as *const _; = help: to override `-D warnings` add `#[allow(clippy::manual_dangling_ptr)]` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:9:13 + --> tests/ui/manual_dangling_ptr.rs:10:13 | LL | let _ = 2 as *const u32; | ^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:11:13 + --> tests/ui/manual_dangling_ptr.rs:12:13 | LL | let _ = 4 as *mut f32; | ^^^^^^^^^^^^^ help: use: `std::ptr::dangling_mut::()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:14:13 + --> tests/ui/manual_dangling_ptr.rs:15:13 | LL | let _ = mem::align_of::() as *const u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:16:13 + --> tests/ui/manual_dangling_ptr.rs:17:13 | LL | let _ = mem::align_of::() as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:18:13 + --> tests/ui/manual_dangling_ptr.rs:19:13 | LL | let _ = mem::align_of::() as *const usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling::()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:21:9 + --> tests/ui/manual_dangling_ptr.rs:22:9 | LL | foo(4 as *const _, 4 as *mut _); | ^^^^^^^^^^^^^ help: use: `std::ptr::dangling()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:21:24 + --> tests/ui/manual_dangling_ptr.rs:22:24 | LL | foo(4 as *const _, 4 as *mut _); | ^^^^^^^^^^^ help: use: `std::ptr::dangling_mut()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:41:9 + --> tests/ui/manual_dangling_ptr.rs:42:9 | LL | foo(4 as *const _, 4 as *mut _); | ^^^^^^^^^^^^^ help: use: `std::ptr::dangling()` error: manual creation of a dangling pointer - --> tests/ui/manual_dangling_ptr.rs:41:24 + --> tests/ui/manual_dangling_ptr.rs:42:24 | LL | foo(4 as *const _, 4 as *mut _); | ^^^^^^^^^^^ help: use: `std::ptr::dangling_mut()` -error: aborting due to 10 previous errors +error: manual creation of a dangling pointer + --> tests/ui/manual_dangling_ptr.rs:54:28 + | +LL | let _ = unsafe { &mut *(1 as *mut Empty) }; + | ^^^^^^^^^^^^^^^^^ help: use: `std::ptr::dangling_mut::()` + +error: aborting due to 11 previous errors From 17f89e76abe4b4af4a2c551c3d79835df849eaa0 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Mon, 26 Jan 2026 11:11:40 -0800 Subject: [PATCH 150/978] Fix `useless_attribute` FP on `exported_private_dependencies` lint attributes. --- clippy_lints/src/attrs/useless_attribute.rs | 1 + clippy_utils/src/sym.rs | 1 + tests/ui/useless_attribute.fixed | 4 ++++ tests/ui/useless_attribute.rs | 4 ++++ 4 files changed, 10 insertions(+) diff --git a/clippy_lints/src/attrs/useless_attribute.rs b/clippy_lints/src/attrs/useless_attribute.rs index aa9a6654bee3..9a1e315ae530 100644 --- a/clippy_lints/src/attrs/useless_attribute.rs +++ b/clippy_lints/src/attrs/useless_attribute.rs @@ -31,6 +31,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) { | sym::dead_code | sym::deprecated | sym::deprecated_in_future + | sym::exported_private_dependencies | sym::hidden_glob_reexports | sym::unreachable_pub | sym::unused diff --git a/clippy_utils/src/sym.rs b/clippy_utils/src/sym.rs index 5d6f2241c7c0..e0b03ae4f7b2 100644 --- a/clippy_utils/src/sym.rs +++ b/clippy_utils/src/sym.rs @@ -147,6 +147,7 @@ generate! { exp, expect_err, expn_data, + exported_private_dependencies, extend, filter, filter_map, diff --git a/tests/ui/useless_attribute.fixed b/tests/ui/useless_attribute.fixed index e0bc23e0788c..dbe4b6fb50f3 100644 --- a/tests/ui/useless_attribute.fixed +++ b/tests/ui/useless_attribute.fixed @@ -42,6 +42,10 @@ mod foo { #[allow(deprecated)] pub use foo::Bar; +// don't lint on exported_private_dependencies for `use` items +#[allow(exported_private_dependencies)] +use {}; + // This should not trigger the lint. There's lint level definitions inside the external derive // that would trigger the useless_attribute lint. #[derive(DeriveSomething)] diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 30a4c354b238..44fb6733f054 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -42,6 +42,10 @@ mod foo { #[allow(deprecated)] pub use foo::Bar; +// don't lint on exported_private_dependencies for `use` items +#[allow(exported_private_dependencies)] +use {}; + // This should not trigger the lint. There's lint level definitions inside the external derive // that would trigger the useless_attribute lint. #[derive(DeriveSomething)] From 2e365985be4efcdad30d1fa800e3270e65c12799 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 23 Jan 2026 23:50:34 -0600 Subject: [PATCH 151/978] Stabilize `core::hint::cold_path` `cold_path` has been around unstably for a while and is a rather useful tool to have. It does what it is supposed to and there are no known remaining issues, so stabilize it here (including const). Newly stable API: // in core::hint pub const fn cold_path(); I have opted to exclude `likely` and `unlikely` for now since they have had some concerns about ease of use that `cold_path` doesn't suffer from. `cold_path` is also significantly more flexible; in addition to working with boolean `if` conditions, it can be used in `match` arms, `if let`, closures, and other control flow blocks. `likely` and `unlikely` are also possible to implement in user code via `cold_path`, if desired. --- library/core/src/hint.rs | 5 ++--- library/core/src/intrinsics/mod.rs | 3 +-- tests/codegen-llvm/hint/cold_path.rs | 1 - 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index dccac26e07e6..3692420be8fc 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -724,7 +724,6 @@ pub const fn unlikely(b: bool) -> bool { /// # Examples /// /// ``` -/// #![feature(cold_path)] /// use core::hint::cold_path; /// /// fn foo(x: &[i32]) { @@ -750,7 +749,6 @@ pub const fn unlikely(b: bool) -> bool { /// than the branch: /// /// ``` -/// #![feature(cold_path)] /// use core::hint::cold_path; /// /// #[inline(always)] @@ -777,7 +775,8 @@ pub const fn unlikely(b: bool) -> bool { /// } /// } /// ``` -#[unstable(feature = "cold_path", issue = "136873")] +#[stable(feature = "cold_path", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "cold_path", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] pub const fn cold_path() { crate::intrinsics::cold_path() diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 051dda731881..3ddea90652d1 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -409,8 +409,7 @@ pub const unsafe fn assume(b: bool) { /// Therefore, implementations must not require the user to uphold /// any safety invariants. /// -/// This intrinsic does not have a stable counterpart. -#[unstable(feature = "core_intrinsics", issue = "none")] +/// The stabilized version of this intrinsic is [`core::hint::cold_path`]. #[rustc_intrinsic] #[rustc_nounwind] #[miri::intrinsic_fallback_is_spec] diff --git a/tests/codegen-llvm/hint/cold_path.rs b/tests/codegen-llvm/hint/cold_path.rs index 149abe474f67..e6e7379322dd 100644 --- a/tests/codegen-llvm/hint/cold_path.rs +++ b/tests/codegen-llvm/hint/cold_path.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Copt-level=3 #![crate_type = "lib"] -#![feature(cold_path)] use std::hint::cold_path; From 7b6f82eea6d4a34cf61e85516899b58551b58193 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 26 Jan 2026 18:23:05 +0100 Subject: [PATCH 152/978] use `intrinsics::simd::simd_splat` --- crates/core_simd/src/vector.rs | 46 +++++++++++++++------------------- rust-toolchain.toml | 2 +- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs index 2dba5c83e112..5b3a689f3611 100644 --- a/crates/core_simd/src/vector.rs +++ b/crates/core_simd/src/vector.rs @@ -1,5 +1,7 @@ +use core::intrinsics::simd::SimdAlign; + use crate::simd::{ - Mask, MaskElement, Swizzle, + Mask, MaskElement, cmp::SimdPartialOrd, num::SimdUint, ptr::{SimdConstPtr, SimdMutPtr}, @@ -147,28 +149,8 @@ where #[inline] #[rustc_const_unstable(feature = "portable_simd", issue = "86656")] pub const fn splat(value: T) -> Self { - const fn splat_const(value: T) -> Simd - where - T: SimdElement, - { - Simd::from_array([value; N]) - } - - fn splat_rt(value: T) -> Simd - where - T: SimdElement, - { - // This is preferred over `[value; N]`, since it's explicitly a splat: - // https://github.com/rust-lang/rust/issues/97804 - struct Splat; - impl Swizzle for Splat { - const INDEX: [usize; N] = [0; N]; - } - - Splat::swizzle::(Simd::::from([value])) - } - - core::intrinsics::const_eval_select((value,), splat_const, splat_rt) + // SAFETY: T is a SimdElement, and the item type of Self. + unsafe { core::intrinsics::simd::simd_splat(value) } } /// Returns an array reference containing the entire SIMD vector. @@ -464,7 +446,7 @@ where /// value from `or` is passed through. /// /// # Safety - /// Enabled `ptr` elements must be safe to read as if by `std::ptr::read`. + /// Enabled `ptr` elements must be safe to read as if by `core::ptr::read`. #[must_use] #[inline] pub unsafe fn load_select_ptr( @@ -473,7 +455,13 @@ where or: Self, ) -> Self { // SAFETY: The safety of reading elements through `ptr` is ensured by the caller. - unsafe { core::intrinsics::simd::simd_masked_load(enable.to_simd(), ptr, or) } + unsafe { + core::intrinsics::simd::simd_masked_load::<_, _, _, { SimdAlign::Element }>( + enable.to_simd(), + ptr, + or, + ) + } } /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector. @@ -722,7 +710,13 @@ where #[inline] pub unsafe fn store_select_ptr(self, ptr: *mut T, enable: Mask<::Mask, N>) { // SAFETY: The safety of writing elements through `ptr` is ensured by the caller. - unsafe { core::intrinsics::simd::simd_masked_store(enable.to_simd(), ptr, self) } + unsafe { + core::intrinsics::simd::simd_masked_store::<_, _, _, { SimdAlign::Element }>( + enable.to_simd(), + ptr, + self, + ) + } } /// Writes the values in a SIMD vector to potentially discontiguous indices in `slice`. diff --git a/rust-toolchain.toml b/rust-toolchain.toml index ed4d7e8a801e..639d07df7337 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-09-30" +channel = "nightly-2026-01-26" components = ["rustfmt", "clippy", "miri", "rust-src"] From cd18a8d287d1a42f358d007ab72ec534b4cedd5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 12 Mar 2025 12:09:19 +0100 Subject: [PATCH 153/978] Tweak `VecCache` to improve performance --- .../rustc_data_structures/src/vec_cache.rs | 72 +++++++++++++------ .../src/vec_cache/tests.rs | 15 +++- 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_data_structures/src/vec_cache.rs b/compiler/rustc_data_structures/src/vec_cache.rs index 599970663db8..70524bae624a 100644 --- a/compiler/rustc_data_structures/src/vec_cache.rs +++ b/compiler/rustc_data_structures/src/vec_cache.rs @@ -29,8 +29,6 @@ struct Slot { struct SlotIndex { // the index of the bucket in VecCache (0 to 20) bucket_idx: usize, - // number of entries in that bucket - entries: usize, // the index of the slot within the bucket index_in_bucket: usize, } @@ -39,12 +37,12 @@ struct SlotIndex { // compile-time. Visiting all powers of two is enough to hit all the buckets. // // We confirm counts are accurate in the slot_index_exhaustive test. -const ENTRIES_BY_BUCKET: [usize; 21] = { - let mut entries = [0; 21]; +const ENTRIES_BY_BUCKET: [usize; BUCKETS] = { + let mut entries = [0; BUCKETS]; let mut key = 0; loop { let si = SlotIndex::from_index(key); - entries[si.bucket_idx] = si.entries; + entries[si.bucket_idx] = si.entries(); if key == 0 { key = 1; } else if key == (1 << 31) { @@ -56,7 +54,14 @@ const ENTRIES_BY_BUCKET: [usize; 21] = { entries }; +const BUCKETS: usize = 21; + impl SlotIndex { + /// The total possible number of entries in the bucket + const fn entries(&self) -> usize { + if self.bucket_idx == 0 { 1 << 12 } else { 1 << (self.bucket_idx + 11) } + } + // This unpacks a flat u32 index into identifying which bucket it belongs to and the offset // within that bucket. As noted in the VecCache docs, buckets double in size with each index. // Typically that would mean 31 buckets (2^0 + 2^1 ... + 2^31 = u32::MAX - 1), but to reduce @@ -70,18 +75,13 @@ impl SlotIndex { const fn from_index(idx: u32) -> Self { const FIRST_BUCKET_SHIFT: usize = 12; if idx < (1 << FIRST_BUCKET_SHIFT) { - return SlotIndex { - bucket_idx: 0, - entries: 1 << FIRST_BUCKET_SHIFT, - index_in_bucket: idx as usize, - }; + return SlotIndex { bucket_idx: 0, index_in_bucket: idx as usize }; } // We already ruled out idx 0, so this `ilog2` never panics (and the check optimizes away) let bucket = idx.ilog2() as usize; let entries = 1 << bucket; SlotIndex { bucket_idx: bucket - FIRST_BUCKET_SHIFT + 1, - entries, index_in_bucket: idx as usize - entries, } } @@ -98,7 +98,7 @@ impl SlotIndex { if ptr.is_null() { return None; } - assert!(self.index_in_bucket < self.entries); + debug_assert!(self.index_in_bucket < self.entries()); // SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this // must be inbounds. let slot = unsafe { ptr.add(self.index_in_bucket) }; @@ -126,11 +126,12 @@ impl SlotIndex { fn bucket_ptr(&self, bucket: &AtomicPtr>) -> *mut Slot { let ptr = bucket.load(Ordering::Acquire); - if ptr.is_null() { self.initialize_bucket(bucket) } else { ptr } + if ptr.is_null() { Self::initialize_bucket(bucket, self.bucket_idx) } else { ptr } } #[cold] - fn initialize_bucket(&self, bucket: &AtomicPtr>) -> *mut Slot { + #[inline(never)] + fn initialize_bucket(bucket: &AtomicPtr>, bucket_idx: usize) -> *mut Slot { static LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(()); // If we are initializing the bucket, then acquire a global lock. @@ -144,8 +145,8 @@ impl SlotIndex { // OK, now under the allocator lock, if we're still null then it's definitely us that will // initialize this bucket. if ptr.is_null() { - let bucket_layout = - std::alloc::Layout::array::>(self.entries as usize).unwrap(); + let bucket_len = SlotIndex { bucket_idx, index_in_bucket: 0 }.entries(); + let bucket_layout = std::alloc::Layout::array::>(bucket_len).unwrap(); // This is more of a sanity check -- this code is very cold, so it's safe to pay a // little extra cost here. assert!(bucket_layout.size() > 0); @@ -171,7 +172,7 @@ impl SlotIndex { let bucket = unsafe { buckets.get_unchecked(self.bucket_idx) }; let ptr = self.bucket_ptr(bucket); - assert!(self.index_in_bucket < self.entries); + debug_assert!(self.index_in_bucket < self.entries()); // SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this // must be inbounds. let slot = unsafe { ptr.add(self.index_in_bucket) }; @@ -204,6 +205,31 @@ impl SlotIndex { Err(_) => false, } } + + /// Inserts into the map, given that the slot is unique, so it won't race with other threads. + #[inline] + unsafe fn put_unique(&self, buckets: &[AtomicPtr>; 21], value: V, extra: u32) { + // SAFETY: `bucket_idx` is ilog2(u32).saturating_sub(11), which is at most 21, i.e., + // in-bounds of buckets. + let bucket = unsafe { buckets.get_unchecked(self.bucket_idx) }; + let ptr = self.bucket_ptr(bucket); + + debug_assert!(self.index_in_bucket < self.entries()); + // SAFETY: `bucket` was allocated (so <= isize in total bytes) to hold `entries`, so this + // must be inbounds. + let slot = unsafe { ptr.add(self.index_in_bucket) }; + + // SAFETY: We known our slot is unique as a precondition of this function, so this can't race. + unsafe { + (&raw mut (*slot).value).write(value); + } + + // SAFETY: initialized bucket has zeroed all memory within the bucket, so we are valid for + // AtomicU32 access. + let index_and_lock = unsafe { &(*slot).index_and_lock }; + + index_and_lock.store(extra.checked_add(2).unwrap(), Ordering::Release); + } } /// In-memory cache for queries whose keys are densely-numbered IDs @@ -229,11 +255,11 @@ pub struct VecCache { // Bucket 19: 1073741824 // Bucket 20: 2147483648 // The total number of entries if all buckets are initialized is u32::MAX-1. - buckets: [AtomicPtr>; 21], + buckets: [AtomicPtr>; BUCKETS], // In the compiler's current usage these are only *read* during incremental and self-profiling. // They are an optimization over iterating the full buckets array. - present: [AtomicPtr>; 21], + present: [AtomicPtr>; BUCKETS], len: AtomicUsize, key: PhantomData<(K, I)>, @@ -307,9 +333,11 @@ where let slot_idx = SlotIndex::from_index(key); if slot_idx.put(&self.buckets, value, index.index() as u32) { let present_idx = self.len.fetch_add(1, Ordering::Relaxed); - let slot = SlotIndex::from_index(present_idx as u32); - // We should always be uniquely putting due to `len` fetch_add returning unique values. - assert!(slot.put(&self.present, (), key)); + let slot = SlotIndex::from_index(u32::try_from(present_idx).unwrap()); + // SAFETY: We should always be uniquely putting due to `len` fetch_add returning unique values. + // We can't get here if `len` overflows because `put` will not succeed u32::MAX + 1 times + // as it will run out of slots. + unsafe { slot.put_unique(&self.present, (), key) }; } } diff --git a/compiler/rustc_data_structures/src/vec_cache/tests.rs b/compiler/rustc_data_structures/src/vec_cache/tests.rs index 9b60913ec922..f588442eee62 100644 --- a/compiler/rustc_data_structures/src/vec_cache/tests.rs +++ b/compiler/rustc_data_structures/src/vec_cache/tests.rs @@ -68,6 +68,13 @@ fn slot_entries_table() { ); } +#[test] +fn bucket_entries_matches() { + for i in 0..BUCKETS { + assert_eq!(SlotIndex { bucket_idx: i, index_in_bucket: 0 }.entries(), ENTRIES_BY_BUCKET[i]); + } +} + #[test] #[cfg(not(miri))] fn slot_index_exhaustive() { @@ -81,14 +88,18 @@ fn slot_index_exhaustive() { let mut prev = slot_idx; for idx in 1..=u32::MAX { let slot_idx = SlotIndex::from_index(idx); + + // SAFETY: Ensure indices don't go out of bounds of buckets. + assert!(slot_idx.index_in_bucket < slot_idx.entries()); + if prev.bucket_idx == slot_idx.bucket_idx { assert_eq!(prev.index_in_bucket + 1, slot_idx.index_in_bucket); } else { assert_eq!(slot_idx.index_in_bucket, 0); } - assert_eq!(buckets[slot_idx.bucket_idx], slot_idx.entries as u32); - assert_eq!(ENTRIES_BY_BUCKET[slot_idx.bucket_idx], slot_idx.entries, "{}", idx); + assert_eq!(buckets[slot_idx.bucket_idx], slot_idx.entries() as u32); + assert_eq!(ENTRIES_BY_BUCKET[slot_idx.bucket_idx], slot_idx.entries(), "{}", idx); prev = slot_idx; } From b3e93fc242cb08f3f18a295a574fdbb360ae1863 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 26 Jan 2026 21:58:18 +0100 Subject: [PATCH 154/978] use `cargo miri nextest` to parallelize miri tests --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96881687af05..05020108b5b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -244,5 +244,7 @@ jobs: PROPTEST_CASES: 16 steps: - uses: actions/checkout@v4 + - name: Install cargo-nextest + run: cargo install cargo-nextest --locked - name: Test (Miri) - run: cargo miri test + run: cargo miri nextest run -j4 From 808d349fff4a32e22b8bae3df7aec4d9e38ce30a Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 27 Jan 2026 00:18:16 +0100 Subject: [PATCH 155/978] experiment with cargo nextest partitions --- .github/workflows/ci.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 05020108b5b7..de7efa355283 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -240,11 +240,18 @@ jobs: miri: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + shard: [1, 2, 3, 4] env: PROPTEST_CASES: 16 steps: - uses: actions/checkout@v4 + - name: Install cargo-nextest - run: cargo install cargo-nextest --locked - - name: Test (Miri) - run: cargo miri nextest run -j4 + uses: taiki-e/install-action@nextest + + - name: Test (Miri) (partition ${{ matrix.shard }}/4) + run: | + cargo miri nextest run --partition count:${{ matrix.shard }}/4 From 2135bc1f1063073479b8b4c8e83fcb9a635f9ab0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 Jan 2026 15:00:59 +1100 Subject: [PATCH 156/978] Remove `rustc_lexer::cursor` module. It contains the `Cursor` type and an `impl Cursor` block with a few methods. But there is a larger `impl Cursor` block in the crate root. The only other thing in the `cursor` module is the simple `FrontmatterAllowed` type. So this commit just moves everything in the `cursor` module (which isn't much) into the crate root. --- compiler/rustc_lexer/src/cursor.rs | 125 --------------------------- compiler/rustc_lexer/src/lib.rs | 130 +++++++++++++++++++++++++++-- 2 files changed, 125 insertions(+), 130 deletions(-) delete mode 100644 compiler/rustc_lexer/src/cursor.rs diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs deleted file mode 100644 index 165262b82c75..000000000000 --- a/compiler/rustc_lexer/src/cursor.rs +++ /dev/null @@ -1,125 +0,0 @@ -use std::str::Chars; - -pub enum FrontmatterAllowed { - Yes, - No, -} - -/// Peekable iterator over a char sequence. -/// -/// Next characters can be peeked via `first` method, -/// and position can be shifted forward via `bump` method. -pub struct Cursor<'a> { - len_remaining: usize, - /// Iterator over chars. Slightly faster than a &str. - chars: Chars<'a>, - pub(crate) frontmatter_allowed: FrontmatterAllowed, - #[cfg(debug_assertions)] - prev: char, -} - -pub(crate) const EOF_CHAR: char = '\0'; - -impl<'a> Cursor<'a> { - pub fn new(input: &'a str, frontmatter_allowed: FrontmatterAllowed) -> Cursor<'a> { - Cursor { - len_remaining: input.len(), - chars: input.chars(), - frontmatter_allowed, - #[cfg(debug_assertions)] - prev: EOF_CHAR, - } - } - - pub fn as_str(&self) -> &'a str { - self.chars.as_str() - } - - /// Returns the last eaten symbol (or `'\0'` in release builds). - /// (For debug assertions only.) - pub(crate) fn prev(&self) -> char { - #[cfg(debug_assertions)] - { - self.prev - } - - #[cfg(not(debug_assertions))] - { - EOF_CHAR - } - } - - /// Peeks the next symbol from the input stream without consuming it. - /// If requested position doesn't exist, `EOF_CHAR` is returned. - /// However, getting `EOF_CHAR` doesn't always mean actual end of file, - /// it should be checked with `is_eof` method. - pub fn first(&self) -> char { - // `.next()` optimizes better than `.nth(0)` - self.chars.clone().next().unwrap_or(EOF_CHAR) - } - - /// Peeks the second symbol from the input stream without consuming it. - pub(crate) fn second(&self) -> char { - // `.next()` optimizes better than `.nth(1)` - let mut iter = self.chars.clone(); - iter.next(); - iter.next().unwrap_or(EOF_CHAR) - } - - /// Peeks the third symbol from the input stream without consuming it. - pub fn third(&self) -> char { - // `.next()` optimizes better than `.nth(2)` - let mut iter = self.chars.clone(); - iter.next(); - iter.next(); - iter.next().unwrap_or(EOF_CHAR) - } - - /// Checks if there is nothing more to consume. - pub(crate) fn is_eof(&self) -> bool { - self.chars.as_str().is_empty() - } - - /// Returns amount of already consumed symbols. - pub(crate) fn pos_within_token(&self) -> u32 { - (self.len_remaining - self.chars.as_str().len()) as u32 - } - - /// Resets the number of bytes consumed to 0. - pub(crate) fn reset_pos_within_token(&mut self) { - self.len_remaining = self.chars.as_str().len(); - } - - /// Moves to the next character. - pub(crate) fn bump(&mut self) -> Option { - let c = self.chars.next()?; - - #[cfg(debug_assertions)] - { - self.prev = c; - } - - Some(c) - } - - /// Moves to a substring by a number of bytes. - pub(crate) fn bump_bytes(&mut self, n: usize) { - self.chars = self.as_str()[n..].chars(); - } - - /// Eats symbols while predicate returns true or until the end of file is reached. - pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { - // It was tried making optimized version of this for eg. line comments, but - // LLVM can inline all of this and compile it down to fast iteration over bytes. - while predicate(self.first()) && !self.is_eof() { - self.bump(); - } - } - - pub(crate) fn eat_until(&mut self, byte: u8) { - self.chars = match memchr::memchr(byte, self.as_str().as_bytes()) { - Some(index) => self.as_str()[index..].chars(), - None => "".chars(), - } - } -} diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 27ffcbc943bd..9d3da6ef4930 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -25,15 +25,13 @@ #![deny(unstable_features)] // tidy-alphabetical-end -mod cursor; - #[cfg(test)] mod tests; +use std::str::Chars; + use LiteralKind::*; use TokenKind::*; -use cursor::EOF_CHAR; -pub use cursor::{Cursor, FrontmatterAllowed}; pub use unicode_ident::UNICODE_VERSION; use unicode_properties::UnicodeEmoji; @@ -407,7 +405,129 @@ pub fn is_ident(string: &str) -> bool { } } -impl Cursor<'_> { +pub enum FrontmatterAllowed { + Yes, + No, +} + +/// Peekable iterator over a char sequence. +/// +/// Next characters can be peeked via `first` method, +/// and position can be shifted forward via `bump` method. +pub struct Cursor<'a> { + len_remaining: usize, + /// Iterator over chars. Slightly faster than a &str. + chars: Chars<'a>, + pub(crate) frontmatter_allowed: FrontmatterAllowed, + #[cfg(debug_assertions)] + prev: char, +} + +const EOF_CHAR: char = '\0'; + +impl<'a> Cursor<'a> { + pub fn new(input: &'a str, frontmatter_allowed: FrontmatterAllowed) -> Cursor<'a> { + Cursor { + len_remaining: input.len(), + chars: input.chars(), + frontmatter_allowed, + #[cfg(debug_assertions)] + prev: EOF_CHAR, + } + } + + pub fn as_str(&self) -> &'a str { + self.chars.as_str() + } + + /// Returns the last eaten symbol (or `'\0'` in release builds). + /// (For debug assertions only.) + pub(crate) fn prev(&self) -> char { + #[cfg(debug_assertions)] + { + self.prev + } + + #[cfg(not(debug_assertions))] + { + EOF_CHAR + } + } + + /// Peeks the next symbol from the input stream without consuming it. + /// If requested position doesn't exist, `EOF_CHAR` is returned. + /// However, getting `EOF_CHAR` doesn't always mean actual end of file, + /// it should be checked with `is_eof` method. + pub fn first(&self) -> char { + // `.next()` optimizes better than `.nth(0)` + self.chars.clone().next().unwrap_or(EOF_CHAR) + } + + /// Peeks the second symbol from the input stream without consuming it. + pub(crate) fn second(&self) -> char { + // `.next()` optimizes better than `.nth(1)` + let mut iter = self.chars.clone(); + iter.next(); + iter.next().unwrap_or(EOF_CHAR) + } + + /// Peeks the third symbol from the input stream without consuming it. + pub fn third(&self) -> char { + // `.next()` optimizes better than `.nth(2)` + let mut iter = self.chars.clone(); + iter.next(); + iter.next(); + iter.next().unwrap_or(EOF_CHAR) + } + + /// Checks if there is nothing more to consume. + pub(crate) fn is_eof(&self) -> bool { + self.chars.as_str().is_empty() + } + + /// Returns amount of already consumed symbols. + pub(crate) fn pos_within_token(&self) -> u32 { + (self.len_remaining - self.chars.as_str().len()) as u32 + } + + /// Resets the number of bytes consumed to 0. + pub(crate) fn reset_pos_within_token(&mut self) { + self.len_remaining = self.chars.as_str().len(); + } + + /// Moves to the next character. + pub(crate) fn bump(&mut self) -> Option { + let c = self.chars.next()?; + + #[cfg(debug_assertions)] + { + self.prev = c; + } + + Some(c) + } + + /// Moves to a substring by a number of bytes. + pub(crate) fn bump_bytes(&mut self, n: usize) { + self.chars = self.as_str()[n..].chars(); + } + + /// Eats symbols while predicate returns true or until the end of file is reached. + pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { + // It was tried making optimized version of this for eg. line comments, but + // LLVM can inline all of this and compile it down to fast iteration over bytes. + while predicate(self.first()) && !self.is_eof() { + self.bump(); + } + } + + pub(crate) fn eat_until(&mut self, byte: u8) { + self.chars = match memchr::memchr(byte, self.as_str().as_bytes()) { + Some(index) => self.as_str()[index..].chars(), + None => "".chars(), + } + } + /// Parses a token from the input string. pub fn advance_token(&mut self) -> Token { let Some(first_char) = self.bump() else { From 506ea790caa945aa6541f371f98df39c999e149c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 Jan 2026 15:22:21 +1100 Subject: [PATCH 157/978] Move two `rustc_parse` error diagnostics. Every diagnostic struct in `rustc_parse` is in the `errors` module, except for `ForbiddenLetReason` and `MisspelledKw`. There's no good reason for this, and presumably it is just an accidental inconsistency. This commit moves them into `errors`. --- compiler/rustc_parse/src/errors.rs | 34 ++++++++++++++- .../rustc_parse/src/parser/diagnostics.rs | 24 ++--------- compiler/rustc_parse/src/parser/expr.rs | 41 ++++++------------- compiler/rustc_parse/src/parser/mod.rs | 1 - 4 files changed, 50 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 42327c7e343d..92ec1377d045 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -17,7 +17,7 @@ use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; use rustc_span::{Ident, Span, Symbol}; use crate::fluent_generated as fluent; -use crate::parser::{ForbiddenLetReason, TokenDescription}; +use crate::parser::TokenDescription; #[derive(Diagnostic)] #[diag(parse_maybe_report_ambiguous_plus)] @@ -3703,3 +3703,35 @@ pub(crate) struct StructLiteralWithoutPathLate { #[suggestion(applicability = "has-placeholders", code = "/* Type */ ", style = "verbose")] pub suggestion_span: Span, } + +/// Used to forbid `let` expressions in certain syntactic locations. +#[derive(Clone, Copy, Subdiagnostic)] +pub(crate) enum ForbiddenLetReason { + /// `let` is not valid and the source environment is not important + OtherForbidden, + /// A let chain with the `||` operator + #[note(parse_not_supported_or)] + NotSupportedOr(#[primary_span] Span), + /// A let chain with invalid parentheses + /// + /// For example, `let 1 = 1 && (expr && expr)` is allowed + /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not + #[note(parse_not_supported_parentheses)] + NotSupportedParentheses(#[primary_span] Span), +} + +#[derive(Debug, rustc_macros::Subdiagnostic)] +#[suggestion( + parse_misspelled_kw, + applicability = "machine-applicable", + code = "{similar_kw}", + style = "verbose" +)] +pub(crate) struct MisspelledKw { + // We use a String here because `Symbol::into_diag_arg` calls `Symbol::to_ident_string`, which + // prefix the keyword with a `r#` because it aims to print the symbol as an identifier. + pub similar_kw: String, + #[primary_span] + pub span: Span, + pub is_incorrect_case: bool, +} diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 60e12fa05adf..cb8a291c7fa0 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -35,10 +35,10 @@ use crate::errors::{ ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg, HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse, - PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst, - StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, SuggAddMissingLetStmt, - SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, TernaryOperatorSuggestion, - UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, + MisspelledKw, PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, + SelfParamNotFirst, StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, + SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, + TernaryOperatorSuggestion, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType, }; use crate::parser::FnContext; @@ -212,22 +212,6 @@ impl std::fmt::Display for UnaryFixity { } } -#[derive(Debug, rustc_macros::Subdiagnostic)] -#[suggestion( - parse_misspelled_kw, - applicability = "machine-applicable", - code = "{similar_kw}", - style = "verbose" -)] -struct MisspelledKw { - // We use a String here because `Symbol::into_diag_arg` calls `Symbol::to_ident_string`, which - // prefix the keyword with a `r#` because it aims to print the symbol as an identifier. - similar_kw: String, - #[primary_span] - span: Span, - is_incorrect_case: bool, -} - /// Checks if the given `lookup` identifier is similar to any keyword symbol in `candidates`. /// /// This is a specialized version of [`Symbol::find_similar`] that constructs an error when a diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index c31a4798b471..8ba7493f6f11 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -21,7 +21,6 @@ use rustc_ast::{ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic}; use rustc_literal_escaper::unescape_char; -use rustc_macros::Subdiagnostic; use rustc_session::errors::{ExprParenthesesNeeded, report_lit_error}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; @@ -2770,7 +2769,7 @@ impl<'a> Parser<'a> { let recovered = if !restrictions.contains(Restrictions::ALLOW_LET) { let err = errors::ExpectedExpressionFoundLet { span: self.token.span, - reason: ForbiddenLetReason::OtherForbidden, + reason: errors::ForbiddenLetReason::OtherForbidden, missing_let: None, comparison: None, }; @@ -4169,22 +4168,6 @@ pub(crate) fn could_be_unclosed_char_literal(ident: Ident) -> bool { && unescape_char(ident.without_first_quote().name.as_str()).is_ok() } -/// Used to forbid `let` expressions in certain syntactic locations. -#[derive(Clone, Copy, Subdiagnostic)] -pub(crate) enum ForbiddenLetReason { - /// `let` is not valid and the source environment is not important - OtherForbidden, - /// A let chain with the `||` operator - #[note(parse_not_supported_or)] - NotSupportedOr(#[primary_span] Span), - /// A let chain with invalid parentheses - /// - /// For example, `let 1 = 1 && (expr && expr)` is allowed - /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not - #[note(parse_not_supported_parentheses)] - NotSupportedParentheses(#[primary_span] Span), -} - /// Whether let chains are allowed on all editions, or it's edition dependent (allowed only on /// 2024 and later). In case of edition dependence, specify the currently present edition. pub enum LetChainsPolicy { @@ -4205,7 +4188,7 @@ struct CondChecker<'a> { parser: &'a Parser<'a>, let_chains_policy: LetChainsPolicy, depth: u32, - forbid_let_reason: Option, + forbid_let_reason: Option, missing_let: Option, comparison: Option, } @@ -4226,14 +4209,13 @@ impl<'a> CondChecker<'a> { impl MutVisitor for CondChecker<'_> { fn visit_expr(&mut self, e: &mut Expr) { self.depth += 1; - use ForbiddenLetReason::*; let span = e.span; match e.kind { ExprKind::Let(_, _, _, ref mut recovered @ Recovered::No) => { if let Some(reason) = self.forbid_let_reason { let error = match reason { - NotSupportedOr(or_span) => { + errors::ForbiddenLetReason::NotSupportedOr(or_span) => { self.parser.dcx().emit_err(errors::OrInLetChain { span: or_span }) } _ => self.parser.dcx().emit_err(errors::ExpectedExpressionFoundLet { @@ -4260,24 +4242,27 @@ impl MutVisitor for CondChecker<'_> { mut_visit::walk_expr(self, e); } ExprKind::Binary(Spanned { node: BinOpKind::Or, span: or_span }, _, _) - if let None | Some(NotSupportedOr(_)) = self.forbid_let_reason => + if let None | Some(errors::ForbiddenLetReason::NotSupportedOr(_)) = + self.forbid_let_reason => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(NotSupportedOr(or_span)); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::NotSupportedOr(or_span)); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } ExprKind::Paren(ref inner) - if let None | Some(NotSupportedParentheses(_)) = self.forbid_let_reason => + if let None | Some(errors::ForbiddenLetReason::NotSupportedParentheses(_)) = + self.forbid_let_reason => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(NotSupportedParentheses(inner.span)); + self.forbid_let_reason = + Some(errors::ForbiddenLetReason::NotSupportedParentheses(inner.span)); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } ExprKind::Assign(ref lhs, _, span) => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(OtherForbidden); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden); let missing_let = self.missing_let; if let ExprKind::Binary(_, _, rhs) = &lhs.kind && let ExprKind::Path(_, _) @@ -4310,7 +4295,7 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::Tup(_) | ExprKind::Paren(_) => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(OtherForbidden); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } @@ -4318,7 +4303,7 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::Type(ref mut op, _) | ExprKind::UnsafeBinderCast(_, ref mut op, _) => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(OtherForbidden); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden); self.visit_expr(op); self.forbid_let_reason = forbid_let_reason; } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 3ef73a55d47d..81aaac0004ec 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -20,7 +20,6 @@ use std::{fmt, mem, slice}; use attr_wrapper::{AttrWrapper, UsePreAttrPos}; pub use diagnostics::AttemptLocalParseRecovery; -pub(crate) use expr::ForbiddenLetReason; // Public to use it for custom `if` expressions in rustfmt forks like https://github.com/tucant/rustfmt pub use expr::LetChainsPolicy; pub(crate) use item::{FnContext, FnParseMode}; From b33fdb2c7093fb414833936d830e2e1135cebf9b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 Jan 2026 15:47:00 +1100 Subject: [PATCH 158/978] Move `TokenDescription`. From the `parser` module to the `errors` module, which is where most of its uses are. This means the `errors` module no longer depends on the `parser` module, removing a cyclic dependency between the two modules. --- compiler/rustc_parse/src/errors.rs | 32 ++++++++++++++++++++++++-- compiler/rustc_parse/src/parser/mod.rs | 31 +------------------------ 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 92ec1377d045..7d0acc333773 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use std::path::PathBuf; -use rustc_ast::token::Token; +use rustc_ast::token::{self, InvisibleOrigin, MetaVarKind, Token}; use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::{Path, Visibility}; use rustc_errors::codes::*; @@ -17,7 +17,6 @@ use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; use rustc_span::{Ident, Span, Symbol}; use crate::fluent_generated as fluent; -use crate::parser::TokenDescription; #[derive(Diagnostic)] #[diag(parse_maybe_report_ambiguous_plus)] @@ -3735,3 +3734,32 @@ pub(crate) struct MisspelledKw { pub span: Span, pub is_incorrect_case: bool, } + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub(super) enum TokenDescription { + ReservedIdentifier, + Keyword, + ReservedKeyword, + DocComment, + + // Expanded metavariables are wrapped in invisible delimiters which aren't + // pretty-printed. In error messages we must handle these specially + // otherwise we get confusing things in messages like "expected `(`, found + // ``". It's better to say e.g. "expected `(`, found type metavariable". + MetaVar(MetaVarKind), +} + +impl TokenDescription { + pub(super) fn from_token(token: &Token) -> Option { + match token.kind { + _ if token.is_special_ident() => Some(TokenDescription::ReservedIdentifier), + _ if token.is_used_keyword() => Some(TokenDescription::Keyword), + _ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword), + token::DocComment(..) => Some(TokenDescription::DocComment), + token::OpenInvisible(InvisibleOrigin::MetaVar(kind)) => { + Some(TokenDescription::MetaVar(kind)) + } + _ => None, + } + } +} diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 81aaac0004ec..0ff0b6622936 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -49,7 +49,7 @@ use token_type::TokenTypeSet; pub use token_type::{ExpKeywordPair, ExpTokenPair, TokenType}; use tracing::debug; -use crate::errors::{self, IncorrectVisibilityRestriction, NonStringAbiLiteral}; +use crate::errors::{self, IncorrectVisibilityRestriction, NonStringAbiLiteral, TokenDescription}; use crate::exp; #[cfg(test)] @@ -307,35 +307,6 @@ impl From for Trailing { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub(super) enum TokenDescription { - ReservedIdentifier, - Keyword, - ReservedKeyword, - DocComment, - - // Expanded metavariables are wrapped in invisible delimiters which aren't - // pretty-printed. In error messages we must handle these specially - // otherwise we get confusing things in messages like "expected `(`, found - // ``". It's better to say e.g. "expected `(`, found type metavariable". - MetaVar(MetaVarKind), -} - -impl TokenDescription { - pub(super) fn from_token(token: &Token) -> Option { - match token.kind { - _ if token.is_special_ident() => Some(TokenDescription::ReservedIdentifier), - _ if token.is_used_keyword() => Some(TokenDescription::Keyword), - _ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword), - token::DocComment(..) => Some(TokenDescription::DocComment), - token::OpenInvisible(InvisibleOrigin::MetaVar(kind)) => { - Some(TokenDescription::MetaVar(kind)) - } - _ => None, - } - } -} - pub fn token_descr(token: &Token) -> String { let s = pprust::token_to_string(token).to_string(); From bcb76f4ea6ee380972b1187423def5091c4ef25c Mon Sep 17 00:00:00 2001 From: zakie Date: Tue, 27 Jan 2026 14:57:42 +0900 Subject: [PATCH 159/978] docs: fix outdated Debian Ports ISO reference --- src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md index 1efea86df92b..5334a176027f 100644 --- a/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md +++ b/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md @@ -52,7 +52,7 @@ Atari systems or emulated environments such as QEMU version 4.2 or newer or ARAn ISO images for installation are provided by the Debian Ports team and can be obtained from the Debian CD image server available at: -[https://cdimage.debian.org/cdimage/ports/current](https://cdimage.debian.org/cdimage/ports/current/) +[https://cdimage.debian.org/cdimage/ports/](https://cdimage.debian.org/cdimage/ports/) Documentation for Debian/m68k is available on the Debian Wiki at: From 50a9b17d7c7d291ba1e8ad181a4e90e87247fd2f Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Mon, 26 Jan 2026 22:07:44 -0800 Subject: [PATCH 160/978] Remove duplicated code in `slice/index.rs` Looks like `const fn` is far enough along now that we can just not have these two copies any more, and have one call the other. --- library/core/src/slice/index.rs | 42 ++++----------------------------- 1 file changed, 4 insertions(+), 38 deletions(-) diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index d8ed521f4435..097310dc8fb0 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -910,29 +910,7 @@ where R: [const] ops::RangeBounds + [const] Destruct, { let len = bounds.end; - - let end = match range.end_bound() { - ops::Bound::Included(&end) if end >= len => slice_index_fail(0, end, len), - // Cannot overflow because `end < len` implies `end < usize::MAX`. - ops::Bound::Included(&end) => end + 1, - - ops::Bound::Excluded(&end) if end > len => slice_index_fail(0, end, len), - ops::Bound::Excluded(&end) => end, - ops::Bound::Unbounded => len, - }; - - let start = match range.start_bound() { - ops::Bound::Excluded(&start) if start >= end => slice_index_fail(start, end, len), - // Cannot overflow because `start < end` implies `start < usize::MAX`. - ops::Bound::Excluded(&start) => start + 1, - - ops::Bound::Included(&start) if start > end => slice_index_fail(start, end, len), - ops::Bound::Included(&start) => start, - - ops::Bound::Unbounded => 0, - }; - - ops::Range { start, end } + into_slice_range(len, (range.start_bound().cloned(), range.end_bound().cloned())) } /// Performs bounds checking of a range without panicking. @@ -972,20 +950,8 @@ where R: ops::RangeBounds, { let len = bounds.end; - - let start = match range.start_bound() { - ops::Bound::Included(&start) => start, - ops::Bound::Excluded(start) => start.checked_add(1)?, - ops::Bound::Unbounded => 0, - }; - - let end = match range.end_bound() { - ops::Bound::Included(end) => end.checked_add(1)?, - ops::Bound::Excluded(&end) => end, - ops::Bound::Unbounded => len, - }; - - if start > end || end > len { None } else { Some(ops::Range { start, end }) } + let r = into_range(len, (range.start_bound().cloned(), range.end_bound().cloned()))?; + if r.start > r.end || r.end > len { None } else { Some(r) } } /// Converts a pair of `ops::Bound`s into `ops::Range` without performing any @@ -1036,7 +1002,7 @@ pub(crate) const fn into_range( /// Converts pair of `ops::Bound`s into `ops::Range`. /// Panics on overflowing indices. -pub(crate) fn into_slice_range( +pub(crate) const fn into_slice_range( len: usize, (start, end): (ops::Bound, ops::Bound), ) -> ops::Range { From 3d6f46c6f1ab182e50bb0c90186367f81b7f9379 Mon Sep 17 00:00:00 2001 From: zakie Date: Tue, 27 Jan 2026 18:55:15 +0900 Subject: [PATCH 161/978] docs: point m68k install link to final Debian 12.0 release --- src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md index 5334a176027f..c15a57c1ceac 100644 --- a/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md +++ b/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md @@ -52,7 +52,7 @@ Atari systems or emulated environments such as QEMU version 4.2 or newer or ARAn ISO images for installation are provided by the Debian Ports team and can be obtained from the Debian CD image server available at: -[https://cdimage.debian.org/cdimage/ports/](https://cdimage.debian.org/cdimage/ports/) +[https://cdimage.debian.org/cdimage/ports/12.0/m68k/](https://cdimage.debian.org/cdimage/ports/12.0/m68k/) Documentation for Debian/m68k is available on the Debian Wiki at: From 52525bd27d663011e2e8e7e56448c44b90ad6a8a Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Mon, 19 Jan 2026 18:02:45 +0000 Subject: [PATCH 162/978] Codegen tests for Arm Cortex-R82 This PR adds checks to the `aarch64v8r-unknown-none` target to verify that if the Cortex-R82 CPU is enabled (with `-Ctarget-cpu=cortex-r82`), that the appropriate additional AArch64 features are enabled. This is important because Cortex-R82 is (currently) the only processor implementing Armv8-R AArch64 and it implements a number of Armv8 features over and above the baseline for the architecture. Many of these features are of interest to safety-critical firmware development (for example `FEAT_RASv1p1`, which adds support for the *RAS Common Fault Injection Model Extension*) and so we anticipate them being enabled when building such firmware. We are offering these tests upstream in-lieu of a full Cortex-R82 specific target because we understand the Project has a preference for architecture-baseline targets over CPU-specific targets. This PR builds on and requires https://github.com/rust-lang/rust/pull/150863, but we've pulled them out as a separate PR. This PR was developed by Ferrous Systems on behalf of Arm. Arm is the owner of these changes. --- tests/ui/asm/aarch64v8r.rs | 6 +- tests/ui/asm/cortex-r82.rs | 176 +++++++++++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 tests/ui/asm/cortex-r82.rs diff --git a/tests/ui/asm/aarch64v8r.rs b/tests/ui/asm/aarch64v8r.rs index 6b582bb730f0..abc254ad5f8e 100644 --- a/tests/ui/asm/aarch64v8r.rs +++ b/tests/ui/asm/aarch64v8r.rs @@ -1,11 +1,15 @@ // Codegen test of mandatory Armv8-R AArch64 extensions +// The Cortex-R82 CPU is an implementation of the Arm v8-R AArch64 ISA so +// it also implements the ISA-level mandatory extensions. We check that with a revision //@ add-minicore -//@ revisions: hf sf +//@ revisions: hf sf r82 //@ [hf] compile-flags: --target aarch64v8r-unknown-none //@ [hf] needs-llvm-components: aarch64 //@ [sf] compile-flags: --target aarch64v8r-unknown-none-softfloat //@ [sf] needs-llvm-components: aarch64 +//@ [r82] compile-flags: --target aarch64v8r-unknown-none -C target-cpu=cortex-r82 +//@ [r82] needs-llvm-components: aarch64 //@ build-pass //@ ignore-backends: gcc diff --git a/tests/ui/asm/cortex-r82.rs b/tests/ui/asm/cortex-r82.rs new file mode 100644 index 000000000000..a64349b37af7 --- /dev/null +++ b/tests/ui/asm/cortex-r82.rs @@ -0,0 +1,176 @@ +// Codegen test of mandatory Cortex-R82 extensions + +//@ add-minicore +//@ compile-flags: --target aarch64v8r-unknown-none -C target-cpu=cortex-r82 +//@ needs-llvm-components: aarch64 +//@ build-pass +//@ ignore-backends: gcc + +#![deny(dead_code)] +#![feature(no_core)] +#![no_core] +#![no_main] +#![crate_type = "rlib"] + +extern crate minicore; +use minicore::*; + +/* # Mandatory extensions + * + * A `//` comment indicates that the extension has no associated assembly instruction and cannot + * be codegen tested + * A `/* */` comment indicates that the extension is being tested in the ISA level codegen test + * (`tests/ui/asm/aarch64v8r.rs`) + * + * ## References: + * + * - Arm Cortex-R82 Processor Technical Reference Manual Revision r3p1 (102670_0301_06_en Issue 6) + * section 3.2.1 has the list of mandatory extensions + * - Arm Architecture Reference Manual for A-profile architecture (ARM DDI 0487) -- has the + * mapping from features to instructions + * - Feature names in A-profile architecture (109697_0100_02_en Version 1.0) -- overview of what + * each extension mean + * */ +pub fn mandatory_extensions() { + // FEAT_GICv3 + // FEAT_GICv3p1 + // FEAT_GICv3_TDIR + feat_pmuv3(); + // FEAT_ETMv4 + // FEAT_ETMv4p1 + // FEAT_ETMv4p2 + // FEAT_ETMv4p3 + // FEAT_ETMv4p4 + // FEAT_ETMv4p5 + /* FEAT_RAS */ + // FEAT_PCSRv8 + feat_ssbs(); + feat_ssbs2(); + // FEAT_CSV2 + // FEAT_CSV2_1p1 + // FEAT_CSV3 + feat_sb(); + feat_specres(); + feat_dgh(); + // FEAT_nTLBPA + /* FEAT_CRC32 */ + /* FEAT_LSE */ + feat_rdm(); + /* FEAT_HPDS */ + /* FEAT_PAN */ + // FEAT_HAFDBS + // FEAT_PMUv3p1 + // FEAT_TTCNP + // FEAT_XNX + /* FEAT_UAO */ + feat_pan2(); + feat_dpb(); + /* FEAT_Debugv8p2 */ + /* FEAT_ASMv8p2 */ + // FEAT_IESB + feat_fp16(); + // FEAT_PCSRv8p2 + feat_dotprod(); + feat_fhm(); + feat_dpb2(); + /* FEAT_PAuth */ + // FEAT_PACQARMA3 + // FEAT_PAuth2 + // FEAT_FPAC + // FEAT_FPACCOMBINE + // FEAT_CONSTPACFIELD + feat_jscvt(); + /* FEAT_LRCPC */ + feat_fcma(); + // FEAT_DoPD + // FEAT_SEL2 + /* FEAT_S2FWB */ + /* FEAT_DIT */ + /* FEAT_IDST */ + /* FEAT_FlagM */ + /* FEAT_LSE2 */ + /* FEAT_LRCPC2 */ + /* FEAT_TLBIOS */ + /* FEAT_TLBIRANGE */ + /* FEAT_TTL */ + // FEAT_BBM + // FEAT_CNTSC + feat_rasv1p1(); + // FEAT_Debugv8p4 + feat_pmuv3p4(); + feat_trf(); + // FEAT_TTST + // FEAT_E0PD +} + +fn feat_pmuv3() { + unsafe { asm!("mrs x0, PMCCFILTR_EL0") } +} + +fn feat_ssbs() { + unsafe { asm!("msr SSBS, 1") } +} + +fn feat_ssbs2() { + unsafe { asm!("mrs x0, SSBS") } +} + +fn feat_sb() { + unsafe { asm!("sb") } +} + +fn feat_specres() { + unsafe { asm!("cfp rctx, x0") } +} + +fn feat_dgh() { + unsafe { asm!("dgh") } +} + +fn feat_rdm() { + unsafe { asm!("sqrdmlah v0.4h, v1.4h, v2.4h") } +} + +fn feat_pan2() { + unsafe { asm!("AT S1E1RP, x0") } +} + +fn feat_dpb() { + unsafe { asm!("DC CVAP, x0") } +} + +fn feat_fp16() { + unsafe { asm!("fmulx h0, h1, h2") } +} + +fn feat_dotprod() { + unsafe { asm!("sdot V0.4S, V1.16B, V2.16B") } +} + +fn feat_fhm() { + unsafe { asm!("fmlal v0.2s, v1.2h, v2.2h") } +} + +fn feat_dpb2() { + unsafe { asm!("DC CVADP, x0") } +} + +fn feat_jscvt() { + unsafe { asm!("fjcvtzs w0, d1") } +} + +fn feat_fcma() { + unsafe { asm!("fcadd v0.4h, v1.4h, v2.4h, #90") } +} + +fn feat_rasv1p1() { + unsafe { asm!("mrs x0, ERXMISC2_EL1") } +} + +fn feat_pmuv3p4() { + unsafe { asm!("mrs x0, PMMIR_EL1") } +} + +fn feat_trf() { + unsafe { asm!("tsb csync") } +} From d463a8d1729d6d94384206a9ff91e22b2fed5bcd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 27 Jan 2026 16:24:34 +0100 Subject: [PATCH 163/978] Update `askama` version to `0.15.2` --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 560f1e8d7fbe..43d6c82b34cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ walkdir = "2.3" filetime = "0.2.9" itertools = "0.12" pulldown-cmark = { version = "0.11", default-features = false, features = ["html"] } -askama = { version = "0.15", default-features = false, features = ["alloc", "config", "derive"] } +askama = { version = "0.15.2", default-features = false, features = ["alloc", "config", "derive"] } [dev-dependencies.toml] version = "0.9.7" From e9474927b7cbb5683f3c5c22e4d06f88337b4a2f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 27 Jan 2026 14:47:34 +0000 Subject: [PATCH 164/978] Remove -Alinker-messages This lint is allowed by default nowadays. --- src/bootstrap/src/core/builder/cargo.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 7150b2b0d59f..6849450b391e 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -331,10 +331,6 @@ impl Cargo { self.rustflags.arg("-Clink-arg=-gz"); } - // Ignore linker warnings for now. These are complicated to fix and don't affect the build. - // FIXME: we should really investigate these... - self.rustflags.arg("-Alinker-messages"); - // Throughout the build Cargo can execute a number of build scripts // compiling C/C++ code and we need to pass compilers, archivers, flags, etc // obtained previously to those build scripts. From 3f62540a797cd33617b8b098e90016b004e36899 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 27 Jan 2026 14:58:24 +0000 Subject: [PATCH 165/978] Only set CFG_COMPILER_HOST_TRIPLE when building rustc --- src/bootstrap/src/core/build_steps/compile.rs | 3 +++ src/bootstrap/src/core/builder/cargo.rs | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 405ab9f6eaa2..adba8f19894a 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1378,6 +1378,9 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS } } + // The host this new compiler will *run* on. + cargo.env("CFG_COMPILER_HOST_TRIPLE", target.triple); + if builder.config.rust_verify_llvm_ir { cargo.env("RUSTC_VERIFY_LLVM_IR", "1"); } diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 6849450b391e..130159111e7e 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -1288,8 +1288,6 @@ impl Builder<'_> { // // FIXME: should update code to not require this env var - // The host this new compiler will *run* on. - cargo.env("CFG_COMPILER_HOST_TRIPLE", target.triple); // The host this new compiler is being *built* on. cargo.env("CFG_COMPILER_BUILD_TRIPLE", compiler.host.triple); From 1331517a47396255c2a7c11efb531fa5d0c4f7c0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 27 Jan 2026 15:03:43 +0000 Subject: [PATCH 166/978] Unset WINAPI_NO_BUNDLED_LIBRARIES Rustc no longer depends on winapi. Only cg_clif, cg_gcc and rustfmt still use it, none of which are libraries to compile against. And in case of both cg_clif and cg_gcc it never ends up in an artifact we ship. For cg_clif it only shows up when the jit mode is enabled, which is not the case for the version we ship. For cg_gcc it is used by a test executable, which isn't shipped either. --- src/bootstrap/src/core/builder/cargo.rs | 35 ------------------------- 1 file changed, 35 deletions(-) diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 130159111e7e..567fb44113d8 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -1294,41 +1294,6 @@ impl Builder<'_> { // Set this for all builds to make sure doc builds also get it. cargo.env("CFG_RELEASE_CHANNEL", &self.config.channel); - // This one's a bit tricky. As of the time of this writing the compiler - // links to the `winapi` crate on crates.io. This crate provides raw - // bindings to Windows system functions, sort of like libc does for - // Unix. This crate also, however, provides "import libraries" for the - // MinGW targets. There's an import library per dll in the windows - // distribution which is what's linked to. These custom import libraries - // are used because the winapi crate can reference Windows functions not - // present in the MinGW import libraries. - // - // For example MinGW may ship libdbghelp.a, but it may not have - // references to all the functions in the dbghelp dll. Instead the - // custom import library for dbghelp in the winapi crates has all this - // information. - // - // Unfortunately for us though the import libraries are linked by - // default via `-ldylib=winapi_foo`. That is, they're linked with the - // `dylib` type with a `winapi_` prefix (so the winapi ones don't - // conflict with the system MinGW ones). This consequently means that - // the binaries we ship of things like rustc_codegen_llvm (aka the rustc_codegen_llvm - // DLL) when linked against *again*, for example with procedural macros - // or plugins, will trigger the propagation logic of `-ldylib`, passing - // `-lwinapi_foo` to the linker again. This isn't actually available in - // our distribution, however, so the link fails. - // - // To solve this problem we tell winapi to not use its bundled import - // libraries. This means that it will link to the system MinGW import - // libraries by default, and the `-ldylib=foo` directives will still get - // passed to the final linker, but they'll look like `-lfoo` which can - // be resolved because MinGW has the import library. The downside is we - // don't get newer functions from Windows, but we don't use any of them - // anyway. - if !mode.is_tool() { - cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1"); - } - // verbose cargo output is very noisy, so only enable it with -vv for _ in 0..self.verbosity.saturating_sub(1) { cargo.arg("--verbose"); From be639943a0665c4ad49993c8b52b8341be8f6bdd Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 27 Jan 2026 15:06:31 +0000 Subject: [PATCH 167/978] Remove a couple of unnecessary stage checks These flags should be available on the bootstrap compiler. --- src/bootstrap/src/core/builder/cargo.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 567fb44113d8..262bb7fc6b79 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -1252,13 +1252,7 @@ impl Builder<'_> { // when compiling the standard library, since this might be linked into the final outputs // produced by rustc. Since this mitigation is only available on Windows, only enable it // for the standard library in case the compiler is run on a non-Windows platform. - // This is not needed for stage 0 artifacts because these will only be used for building - // the stage 1 compiler. - if cfg!(windows) - && mode == Mode::Std - && self.config.control_flow_guard - && compiler.stage >= 1 - { + if cfg!(windows) && mode == Mode::Std && self.config.control_flow_guard { rustflags.arg("-Ccontrol-flow-guard"); } @@ -1266,9 +1260,7 @@ impl Builder<'_> { // standard library, since this might be linked into the final outputs produced by rustc. // Since this mitigation is only available on Windows, only enable it for the standard // library in case the compiler is run on a non-Windows platform. - // This is not needed for stage 0 artifacts because these will only be used for building - // the stage 1 compiler. - if cfg!(windows) && mode == Mode::Std && self.config.ehcont_guard && compiler.stage >= 1 { + if cfg!(windows) && mode == Mode::Std && self.config.ehcont_guard { rustflags.arg("-Zehcont-guard"); } From 257ea3bbee8d2a4d3cc9346863606d86560e06de Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 27 Jan 2026 15:32:06 +0000 Subject: [PATCH 168/978] Remove outdated fixme --- src/bootstrap/src/core/builder/cargo.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 262bb7fc6b79..42502e1b1451 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -1277,8 +1277,6 @@ impl Builder<'_> { rustdocflags.arg("--crate-version").arg(&rust_version); // Environment variables *required* throughout the build - // - // FIXME: should update code to not require this env var // The host this new compiler is being *built* on. cargo.env("CFG_COMPILER_BUILD_TRIPLE", compiler.host.triple); From 90f0f4b75f0a79d39abc712f51e3ad674ccb4e8c Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Mon, 12 Jan 2026 12:59:47 +0530 Subject: [PATCH 169/978] std: sys: uefi: os: Implement join_paths - PATHS_SEP is defined as global const since I will implement split_paths in the future. - Tested using OVMF using QEMU. Signed-off-by: Ayush Singh --- library/std/src/env.rs | 4 ++-- library/std/src/sys/pal/uefi/os.rs | 26 +++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 5c068ad2471a..6669fada60d2 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -518,8 +518,8 @@ pub struct JoinPathsError { /// /// Returns an [`Err`] (containing an error message) if one of the input /// [`Path`]s contains an invalid character for constructing the `PATH` -/// variable (a double quote on Windows or a colon on Unix), or if the system -/// does not have a `PATH`-like variable (e.g. UEFI or WASI). +/// variable (a double quote on Windows or a colon on Unix or semicolon on +/// UEFI), or if the system does not have a `PATH`-like variable (e.g. WASI). /// /// # Examples /// diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs index 178f7f506341..5b9785c8371e 100644 --- a/library/std/src/sys/pal/uefi/os.rs +++ b/library/std/src/sys/pal/uefi/os.rs @@ -5,10 +5,13 @@ use super::{helpers, unsupported_err}; use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; use crate::os::uefi; +use crate::os::uefi::ffi::{OsStrExt, OsStringExt}; use crate::path::{self, PathBuf}; use crate::ptr::NonNull; use crate::{fmt, io}; +const PATHS_SEP: u16 = b';' as u16; + pub fn getcwd() -> io::Result { match helpers::open_shell() { Some(shell) => { @@ -54,17 +57,34 @@ impl<'a> Iterator for SplitPaths<'a> { #[derive(Debug)] pub struct JoinPathsError; -pub fn join_paths(_paths: I) -> Result +// UEFI Shell Path variable is defined in Section 3.6.1 +// [UEFI Shell Specification](https://uefi.org/sites/default/files/resources/UEFI_Shell_2_2.pdf). +pub fn join_paths(paths: I) -> Result where I: Iterator, T: AsRef, { - Err(JoinPathsError) + let mut joined = Vec::new(); + + for (i, path) in paths.enumerate() { + if i > 0 { + joined.push(PATHS_SEP) + } + + let v = path.as_ref().encode_wide().collect::>(); + if v.contains(&PATHS_SEP) { + return Err(JoinPathsError); + } + + joined.extend_from_slice(&v); + } + + Ok(OsString::from_wide(&joined)) } impl fmt::Display for JoinPathsError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - "not supported on this platform yet".fmt(f) + "path segment contains `;`".fmt(f) } } From 3a48b9fe1ada4dfacefe376d879a4af9b07a7a34 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 6 Nov 2025 18:51:01 +0300 Subject: [PATCH 170/978] Stabilize `atomic_try_update` and deprecate fetch_update starting 1.99.0 --- library/alloc/src/sync.rs | 2 +- library/core/src/alloc/global.rs | 2 +- library/core/src/sync/atomic.rs | 255 ++++-------------- library/std/src/sys/sync/condvar/xous.rs | 2 +- library/std/src/sys/sync/rwlock/futex.rs | 4 +- library/std/src/sys/sync/rwlock/queue.rs | 6 +- ...tem-interior-mutations-const-atomics.fixed | 1 - ...t-item-interior-mutations-const-atomics.rs | 1 - ...em-interior-mutations-const-atomics.stderr | 88 +++--- .../lint-invalid-atomic-ordering-update.rs | 2 - ...lint-invalid-atomic-ordering-update.stderr | 60 ++--- 11 files changed, 141 insertions(+), 282 deletions(-) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index a5e4fab916ab..dc82357dd146 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -3270,7 +3270,7 @@ impl Weak { // Acquire is necessary for the success case to synchronise with `Arc::new_cyclic`, when the inner // value can be initialized after `Weak` references have already been created. In that case, we // expect to observe the fully initialized value. - if self.inner()?.strong.fetch_update(Acquire, Relaxed, checked_increment).is_ok() { + if self.inner()?.strong.try_update(Acquire, Relaxed, checked_increment).is_ok() { // SAFETY: pointer is not null, verified in checked_increment unsafe { Some(Arc::from_inner_in(self.ptr, self.alloc.clone())) } } else { diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs index 9b80e3b70fa2..d18e1f525d10 100644 --- a/library/core/src/alloc/global.rs +++ b/library/core/src/alloc/global.rs @@ -57,7 +57,7 @@ use crate::{cmp, ptr}; /// let mut allocated = 0; /// if self /// .remaining -/// .fetch_update(Relaxed, Relaxed, |mut remaining| { +/// .try_update(Relaxed, Relaxed, |mut remaining| { /// if size > remaining { /// return None; /// } diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 22f46ec385ce..adc2bbcde51b 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1287,73 +1287,27 @@ impl AtomicBool { self.v.get().cast() } - /// Fetches the value, and applies a function to it that returns an optional - /// new value. Returns a `Result` of `Ok(previous_value)` if the function - /// returned `Some(_)`, else `Err(previous_value)`. - /// - /// Note: This may call the function multiple times if the value has been - /// changed from other threads in the meantime, as long as the function - /// returns `Some(_)`, but the function will have been applied only once to - /// the stored value. - /// - /// `fetch_update` takes two [`Ordering`] arguments to describe the memory - /// ordering of this operation. The first describes the required ordering for - /// when the operation finally succeeds while the second describes the - /// required ordering for loads. These correspond to the success and failure - /// orderings of [`AtomicBool::compare_exchange`] respectively. - /// - /// Using [`Acquire`] as success ordering makes the store part of this - /// operation [`Relaxed`], and using [`Release`] makes the final successful - /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], - /// [`Acquire`] or [`Relaxed`]. - /// - /// **Note:** This method is only available on platforms that support atomic - /// operations on `u8`. - /// - /// # Considerations - /// - /// This method is not magic; it is not provided by the hardware, and does not act like a - /// critical section or mutex. - /// - /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to - /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem]. - /// - /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem - /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap - /// - /// # Examples - /// - /// ```rust - /// use std::sync::atomic::{AtomicBool, Ordering}; - /// - /// let x = AtomicBool::new(false); - /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(false)); - /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(false)); - /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(true)); - /// assert_eq!(x.load(Ordering::SeqCst), false); - /// ``` + /// An alias for [`AtomicBool::try_update`]. #[inline] #[stable(feature = "atomic_fetch_update", since = "1.53.0")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] + #[deprecated( + since = "1.99.0", + note = "renamed to `try_update` for consistency", + suggestion = "try_update" + )] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, - mut f: F, + f: F, ) -> Result where F: FnMut(bool) -> Option, { - let mut prev = self.load(fetch_order); - while let Some(next) = f(prev) { - match self.compare_exchange_weak(prev, next, set_order, fetch_order) { - x @ Ok(_) => return x, - Err(next_prev) => prev = next_prev, - } - } - Err(prev) + self.try_update(set_order, fetch_order, f) } /// Fetches the value, and applies a function to it that returns an optional @@ -1395,7 +1349,6 @@ impl AtomicBool { /// # Examples /// /// ```rust - /// #![feature(atomic_try_update)] /// use std::sync::atomic::{AtomicBool, Ordering}; /// /// let x = AtomicBool::new(false); @@ -1405,7 +1358,7 @@ impl AtomicBool { /// assert_eq!(x.load(Ordering::SeqCst), false); /// ``` #[inline] - #[unstable(feature = "atomic_try_update", issue = "135894")] + #[stable(feature = "atomic_try_update", since = "CURRENT_RUSTC_VERSION")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] @@ -1413,11 +1366,16 @@ impl AtomicBool { &self, set_order: Ordering, fetch_order: Ordering, - f: impl FnMut(bool) -> Option, + mut f: impl FnMut(bool) -> Option, ) -> Result { - // FIXME(atomic_try_update): this is currently an unstable alias to `fetch_update`; - // when stabilizing, turn `fetch_update` into a deprecated alias to `try_update`. - self.fetch_update(set_order, fetch_order, f) + let mut prev = self.load(fetch_order); + while let Some(next) = f(prev) { + match self.compare_exchange_weak(prev, next, set_order, fetch_order) { + x @ Ok(_) => return x, + Err(next_prev) => prev = next_prev, + } + } + Err(prev) } /// Fetches the value, applies a function to it that it return a new value. @@ -1454,7 +1412,6 @@ impl AtomicBool { /// # Examples /// /// ```rust - /// #![feature(atomic_try_update)] /// /// use std::sync::atomic::{AtomicBool, Ordering}; /// @@ -1464,7 +1421,7 @@ impl AtomicBool { /// assert_eq!(x.load(Ordering::SeqCst), false); /// ``` #[inline] - #[unstable(feature = "atomic_try_update", issue = "135894")] + #[stable(feature = "atomic_try_update", since = "CURRENT_RUSTC_VERSION")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] @@ -2000,83 +1957,27 @@ impl AtomicPtr { unsafe { atomic_compare_exchange_weak(self.p.get(), current, new, success, failure) } } - /// Fetches the value, and applies a function to it that returns an optional - /// new value. Returns a `Result` of `Ok(previous_value)` if the function - /// returned `Some(_)`, else `Err(previous_value)`. - /// - /// Note: This may call the function multiple times if the value has been - /// changed from other threads in the meantime, as long as the function - /// returns `Some(_)`, but the function will have been applied only once to - /// the stored value. - /// - /// `fetch_update` takes two [`Ordering`] arguments to describe the memory - /// ordering of this operation. The first describes the required ordering for - /// when the operation finally succeeds while the second describes the - /// required ordering for loads. These correspond to the success and failure - /// orderings of [`AtomicPtr::compare_exchange`] respectively. - /// - /// Using [`Acquire`] as success ordering makes the store part of this - /// operation [`Relaxed`], and using [`Release`] makes the final successful - /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], - /// [`Acquire`] or [`Relaxed`]. - /// - /// **Note:** This method is only available on platforms that support atomic - /// operations on pointers. - /// - /// # Considerations - /// - /// This method is not magic; it is not provided by the hardware, and does not act like a - /// critical section or mutex. - /// - /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to - /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem], - /// which is a particularly common pitfall for pointers! - /// - /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem - /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap - /// - /// # Examples - /// - /// ```rust - /// use std::sync::atomic::{AtomicPtr, Ordering}; - /// - /// let ptr: *mut _ = &mut 5; - /// let some_ptr = AtomicPtr::new(ptr); - /// - /// let new: *mut _ = &mut 10; - /// assert_eq!(some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(ptr)); - /// let result = some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| { - /// if x == ptr { - /// Some(new) - /// } else { - /// None - /// } - /// }); - /// assert_eq!(result, Ok(ptr)); - /// assert_eq!(some_ptr.load(Ordering::SeqCst), new); - /// ``` + /// An alias for [`AtomicPtr::try_update`]. #[inline] #[stable(feature = "atomic_fetch_update", since = "1.53.0")] #[cfg(target_has_atomic = "ptr")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] + #[deprecated( + since = "1.99.0", + note = "renamed to `try_update` for consistency", + suggestion = "try_update" + )] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, - mut f: F, + f: F, ) -> Result<*mut T, *mut T> where F: FnMut(*mut T) -> Option<*mut T>, { - let mut prev = self.load(fetch_order); - while let Some(next) = f(prev) { - match self.compare_exchange_weak(prev, next, set_order, fetch_order) { - x @ Ok(_) => return x, - Err(next_prev) => prev = next_prev, - } - } - Err(prev) + self.try_update(set_order, fetch_order, f) } /// Fetches the value, and applies a function to it that returns an optional /// new value. Returns a `Result` of `Ok(previous_value)` if the function @@ -2118,7 +2019,6 @@ impl AtomicPtr { /// # Examples /// /// ```rust - /// #![feature(atomic_try_update)] /// use std::sync::atomic::{AtomicPtr, Ordering}; /// /// let ptr: *mut _ = &mut 5; @@ -2137,7 +2037,7 @@ impl AtomicPtr { /// assert_eq!(some_ptr.load(Ordering::SeqCst), new); /// ``` #[inline] - #[unstable(feature = "atomic_try_update", issue = "135894")] + #[stable(feature = "atomic_try_update", since = "CURRENT_RUSTC_VERSION")] #[cfg(target_has_atomic = "ptr")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] @@ -2145,11 +2045,16 @@ impl AtomicPtr { &self, set_order: Ordering, fetch_order: Ordering, - f: impl FnMut(*mut T) -> Option<*mut T>, + mut f: impl FnMut(*mut T) -> Option<*mut T>, ) -> Result<*mut T, *mut T> { - // FIXME(atomic_try_update): this is currently an unstable alias to `fetch_update`; - // when stabilizing, turn `fetch_update` into a deprecated alias to `try_update`. - self.fetch_update(set_order, fetch_order, f) + let mut prev = self.load(fetch_order); + while let Some(next) = f(prev) { + match self.compare_exchange_weak(prev, next, set_order, fetch_order) { + x @ Ok(_) => return x, + Err(next_prev) => prev = next_prev, + } + } + Err(prev) } /// Fetches the value, applies a function to it that it return a new value. @@ -2188,7 +2093,6 @@ impl AtomicPtr { /// # Examples /// /// ```rust - /// #![feature(atomic_try_update)] /// /// use std::sync::atomic::{AtomicPtr, Ordering}; /// @@ -2201,7 +2105,7 @@ impl AtomicPtr { /// assert_eq!(some_ptr.load(Ordering::SeqCst), new); /// ``` #[inline] - #[unstable(feature = "atomic_try_update", issue = "135894")] + #[stable(feature = "atomic_try_update", since = "CURRENT_RUSTC_VERSION")] #[cfg(target_has_atomic = "8")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] @@ -3399,69 +3303,25 @@ macro_rules! atomic_int { unsafe { atomic_xor(self.v.get(), val, order) } } - /// Fetches the value, and applies a function to it that returns an optional - /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else - /// `Err(previous_value)`. - /// - /// Note: This may call the function multiple times if the value has been changed from other threads in - /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied - /// only once to the stored value. - /// - /// `fetch_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation. - /// The first describes the required ordering for when the operation finally succeeds while the second - /// describes the required ordering for loads. These correspond to the success and failure orderings of - #[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange`]")] - /// respectively. - /// - /// Using [`Acquire`] as success ordering makes the store part - /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load - /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. - /// - /// **Note**: This method is only available on platforms that support atomic operations on - #[doc = concat!("[`", $s_int_type, "`].")] - /// - /// # Considerations - /// - /// This method is not magic; it is not provided by the hardware, and does not act like a - /// critical section or mutex. - /// - /// It is implemented on top of an atomic [compare-and-swap operation], and thus is subject to - /// the usual drawbacks of CAS operations. In particular, be careful of the [ABA problem] - /// if this atomic integer is an index or more generally if knowledge of only the *bitwise value* - /// of the atomic is not in and of itself sufficient to ensure any required preconditions. - /// - /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem - /// [compare-and-swap operation]: https://en.wikipedia.org/wiki/Compare-and-swap - /// - /// # Examples - /// - /// ```rust - #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] - /// - #[doc = concat!("let x = ", stringify!($atomic_type), "::new(7);")] - /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7)); - /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7)); - /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8)); - /// assert_eq!(x.load(Ordering::SeqCst), 9); - /// ``` + /// An alias for + #[doc = concat!("[`", stringify!($atomic_type), "::try_update`]")] + /// . #[inline] #[stable(feature = "no_more_cas", since = "1.45.0")] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] + #[deprecated( + since = "1.99.0", + note = "renamed to `try_update` for consistency", + suggestion = "try_update" + )] pub fn fetch_update(&self, set_order: Ordering, fetch_order: Ordering, - mut f: F) -> Result<$int_type, $int_type> + f: F) -> Result<$int_type, $int_type> where F: FnMut($int_type) -> Option<$int_type> { - let mut prev = self.load(fetch_order); - while let Some(next) = f(prev) { - match self.compare_exchange_weak(prev, next, set_order, fetch_order) { - x @ Ok(_) => return x, - Err(next_prev) => prev = next_prev - } - } - Err(prev) + self.try_update(set_order, fetch_order, f) } /// Fetches the value, and applies a function to it that returns an optional @@ -3503,7 +3363,6 @@ macro_rules! atomic_int { /// # Examples /// /// ```rust - /// #![feature(atomic_try_update)] #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] /// #[doc = concat!("let x = ", stringify!($atomic_type), "::new(7);")] @@ -3513,7 +3372,7 @@ macro_rules! atomic_int { /// assert_eq!(x.load(Ordering::SeqCst), 9); /// ``` #[inline] - #[unstable(feature = "atomic_try_update", issue = "135894")] + #[stable(feature = "atomic_try_update", since = "CURRENT_RUSTC_VERSION")] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] @@ -3521,11 +3380,16 @@ macro_rules! atomic_int { &self, set_order: Ordering, fetch_order: Ordering, - f: impl FnMut($int_type) -> Option<$int_type>, + mut f: impl FnMut($int_type) -> Option<$int_type>, ) -> Result<$int_type, $int_type> { - // FIXME(atomic_try_update): this is currently an unstable alias to `fetch_update`; - // when stabilizing, turn `fetch_update` into a deprecated alias to `try_update`. - self.fetch_update(set_order, fetch_order, f) + let mut prev = self.load(fetch_order); + while let Some(next) = f(prev) { + match self.compare_exchange_weak(prev, next, set_order, fetch_order) { + x @ Ok(_) => return x, + Err(next_prev) => prev = next_prev + } + } + Err(prev) } /// Fetches the value, applies a function to it that it return a new value. @@ -3566,7 +3430,6 @@ macro_rules! atomic_int { /// # Examples /// /// ```rust - /// #![feature(atomic_try_update)] #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] /// #[doc = concat!("let x = ", stringify!($atomic_type), "::new(7);")] @@ -3575,7 +3438,7 @@ macro_rules! atomic_int { /// assert_eq!(x.load(Ordering::SeqCst), 9); /// ``` #[inline] - #[unstable(feature = "atomic_try_update", issue = "135894")] + #[stable(feature = "atomic_try_update", since = "CURRENT_RUSTC_VERSION")] #[$cfg_cas] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_should_not_be_called_on_const_items] diff --git a/library/std/src/sys/sync/condvar/xous.rs b/library/std/src/sys/sync/condvar/xous.rs index 21a1587214a1..5d1b14443c62 100644 --- a/library/std/src/sys/sync/condvar/xous.rs +++ b/library/std/src/sys/sync/condvar/xous.rs @@ -38,7 +38,7 @@ impl Condvar { // possible for `counter` to decrease due to a condvar timing out, in which // case the corresponding `timed_out` will increase accordingly. let Ok(waiter_count) = - self.counter.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |counter| { + self.counter.try_update(Ordering::Relaxed, Ordering::Relaxed, |counter| { if counter == 0 { return None; } else { diff --git a/library/std/src/sys/sync/rwlock/futex.rs b/library/std/src/sys/sync/rwlock/futex.rs index 961819cae8d6..0e8e954de075 100644 --- a/library/std/src/sys/sync/rwlock/futex.rs +++ b/library/std/src/sys/sync/rwlock/futex.rs @@ -86,7 +86,7 @@ impl RwLock { #[inline] pub fn try_read(&self) -> bool { self.state - .fetch_update(Acquire, Relaxed, |s| is_read_lockable(s).then(|| s + READ_LOCKED)) + .try_update(Acquire, Relaxed, |s| is_read_lockable(s).then(|| s + READ_LOCKED)) .is_ok() } @@ -164,7 +164,7 @@ impl RwLock { #[inline] pub fn try_write(&self) -> bool { self.state - .fetch_update(Acquire, Relaxed, |s| is_unlocked(s).then(|| s + WRITE_LOCKED)) + .try_update(Acquire, Relaxed, |s| is_unlocked(s).then(|| s + WRITE_LOCKED)) .is_ok() } diff --git a/library/std/src/sys/sync/rwlock/queue.rs b/library/std/src/sys/sync/rwlock/queue.rs index 62f084acfd25..b41a65f7303b 100644 --- a/library/std/src/sys/sync/rwlock/queue.rs +++ b/library/std/src/sys/sync/rwlock/queue.rs @@ -329,7 +329,7 @@ impl RwLock { #[inline] pub fn try_read(&self) -> bool { - self.state.fetch_update(Acquire, Relaxed, read_lock).is_ok() + self.state.try_update(Acquire, Relaxed, read_lock).is_ok() } #[inline] @@ -343,7 +343,7 @@ impl RwLock { pub fn try_write(&self) -> bool { // Atomically set the `LOCKED` bit. This is lowered to a single atomic instruction on most // modern processors (e.g. "lock bts" on x86 and "ldseta" on modern AArch64), and therefore - // is more efficient than `fetch_update(lock(true))`, which can spuriously fail if a new + // is more efficient than `try_update(lock(true))`, which can spuriously fail if a new // node is appended to the queue. self.state.fetch_or(LOCKED, Acquire).addr() & LOCKED == 0 } @@ -453,7 +453,7 @@ impl RwLock { #[inline] pub unsafe fn read_unlock(&self) { - match self.state.fetch_update(Release, Acquire, |state| { + match self.state.try_update(Release, Acquire, |state| { if state.addr() & QUEUED == 0 { // If there are no threads queued, simply decrement the reader count. let count = state.addr() - (SINGLE | LOCKED); diff --git a/tests/ui/lint/const-item-interior-mutations-const-atomics.fixed b/tests/ui/lint/const-item-interior-mutations-const-atomics.fixed index 17737e5cb8b9..8441d69a309a 100644 --- a/tests/ui/lint/const-item-interior-mutations-const-atomics.fixed +++ b/tests/ui/lint/const-item-interior-mutations-const-atomics.fixed @@ -3,7 +3,6 @@ #![allow(deprecated)] #![allow(dead_code)] -#![feature(atomic_try_update)] use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicU32, Ordering}; diff --git a/tests/ui/lint/const-item-interior-mutations-const-atomics.rs b/tests/ui/lint/const-item-interior-mutations-const-atomics.rs index 4180b2340df6..65973fb378e5 100644 --- a/tests/ui/lint/const-item-interior-mutations-const-atomics.rs +++ b/tests/ui/lint/const-item-interior-mutations-const-atomics.rs @@ -3,7 +3,6 @@ #![allow(deprecated)] #![allow(dead_code)] -#![feature(atomic_try_update)] use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicU32, Ordering}; diff --git a/tests/ui/lint/const-item-interior-mutations-const-atomics.stderr b/tests/ui/lint/const-item-interior-mutations-const-atomics.stderr index 17823366d406..908a19682899 100644 --- a/tests/ui/lint/const-item-interior-mutations-const-atomics.stderr +++ b/tests/ui/lint/const-item-interior-mutations-const-atomics.stderr @@ -1,5 +1,5 @@ warning: mutation of an interior mutable `const` item with call to `store` - --> $DIR/const-item-interior-mutations-const-atomics.rs:13:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:12:14 | LL | let _a = A.store(true, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL + static A: AtomicBool = AtomicBool::new(false); | warning: mutation of an interior mutable `const` item with call to `swap` - --> $DIR/const-item-interior-mutations-const-atomics.rs:16:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:15:14 | LL | let _a = A.swap(true, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,7 +34,7 @@ LL + static A: AtomicBool = AtomicBool::new(false); | warning: mutation of an interior mutable `const` item with call to `compare_and_swap` - --> $DIR/const-item-interior-mutations-const-atomics.rs:19:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:18:14 | LL | let _a = A.compare_and_swap(false, true, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL + static A: AtomicBool = AtomicBool::new(false); | warning: mutation of an interior mutable `const` item with call to `compare_exchange` - --> $DIR/const-item-interior-mutations-const-atomics.rs:22:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:21:14 | LL | let _a = A.compare_exchange(false, true, Ordering::SeqCst, Ordering::Relaxed); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL + static A: AtomicBool = AtomicBool::new(false); | warning: mutation of an interior mutable `const` item with call to `compare_exchange_weak` - --> $DIR/const-item-interior-mutations-const-atomics.rs:25:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:24:14 | LL | let _a = A.compare_exchange_weak(false, true, Ordering::SeqCst, Ordering::Relaxed); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + static A: AtomicBool = AtomicBool::new(false); | warning: mutation of an interior mutable `const` item with call to `fetch_and` - --> $DIR/const-item-interior-mutations-const-atomics.rs:28:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:27:14 | LL | let _a = A.fetch_and(true, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -102,7 +102,7 @@ LL + static A: AtomicBool = AtomicBool::new(false); | warning: mutation of an interior mutable `const` item with call to `fetch_nand` - --> $DIR/const-item-interior-mutations-const-atomics.rs:31:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:30:14 | LL | let _a = A.fetch_nand(true, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -119,7 +119,7 @@ LL + static A: AtomicBool = AtomicBool::new(false); | warning: mutation of an interior mutable `const` item with call to `fetch_or` - --> $DIR/const-item-interior-mutations-const-atomics.rs:34:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:33:14 | LL | let _a = A.fetch_or(true, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -136,7 +136,7 @@ LL + static A: AtomicBool = AtomicBool::new(false); | warning: mutation of an interior mutable `const` item with call to `fetch_xor` - --> $DIR/const-item-interior-mutations-const-atomics.rs:37:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:36:14 | LL | let _a = A.fetch_xor(true, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -153,7 +153,7 @@ LL + static A: AtomicBool = AtomicBool::new(false); | warning: mutation of an interior mutable `const` item with call to `fetch_not` - --> $DIR/const-item-interior-mutations-const-atomics.rs:40:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:39:14 | LL | let _a = A.fetch_not(Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -170,7 +170,7 @@ LL + static A: AtomicBool = AtomicBool::new(false); | warning: mutation of an interior mutable `const` item with call to `fetch_update` - --> $DIR/const-item-interior-mutations-const-atomics.rs:43:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:42:14 | LL | let _a = A.fetch_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(true)); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -187,7 +187,7 @@ LL + static A: AtomicBool = AtomicBool::new(false); | warning: mutation of an interior mutable `const` item with call to `try_update` - --> $DIR/const-item-interior-mutations-const-atomics.rs:46:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:45:14 | LL | let _a = A.try_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(false)); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -204,7 +204,7 @@ LL + static A: AtomicBool = AtomicBool::new(false); | warning: mutation of an interior mutable `const` item with call to `update` - --> $DIR/const-item-interior-mutations-const-atomics.rs:49:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:48:14 | LL | let _a = A.update(Ordering::SeqCst, Ordering::Relaxed, |_| true); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -221,7 +221,7 @@ LL + static A: AtomicBool = AtomicBool::new(false); | warning: mutation of an interior mutable `const` item with call to `store` - --> $DIR/const-item-interior-mutations-const-atomics.rs:56:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:55:14 | LL | let _a = A.store(std::ptr::null_mut(), Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -238,7 +238,7 @@ LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); | warning: mutation of an interior mutable `const` item with call to `swap` - --> $DIR/const-item-interior-mutations-const-atomics.rs:59:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:58:14 | LL | let _a = A.swap(std::ptr::null_mut(), Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -255,7 +255,7 @@ LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); | warning: mutation of an interior mutable `const` item with call to `compare_and_swap` - --> $DIR/const-item-interior-mutations-const-atomics.rs:62:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:61:14 | LL | let _a = A.compare_and_swap(std::ptr::null_mut(), std::ptr::null_mut(), Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -272,7 +272,7 @@ LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); | warning: mutation of an interior mutable `const` item with call to `compare_exchange` - --> $DIR/const-item-interior-mutations-const-atomics.rs:65:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:64:14 | LL | let _a = A.compare_exchange( | ^ `A` is a interior mutable `const` item of type `AtomicPtr` @@ -296,7 +296,7 @@ LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); | warning: mutation of an interior mutable `const` item with call to `compare_exchange_weak` - --> $DIR/const-item-interior-mutations-const-atomics.rs:73:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:72:14 | LL | let _a = A.compare_exchange_weak( | ^ `A` is a interior mutable `const` item of type `AtomicPtr` @@ -320,7 +320,7 @@ LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); | warning: mutation of an interior mutable `const` item with call to `fetch_update` - --> $DIR/const-item-interior-mutations-const-atomics.rs:81:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:80:14 | LL | let _a = A.fetch_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(std::ptr::null_mut())); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -337,7 +337,7 @@ LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); | warning: mutation of an interior mutable `const` item with call to `try_update` - --> $DIR/const-item-interior-mutations-const-atomics.rs:84:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:83:14 | LL | let _a = A.try_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(std::ptr::null_mut())); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -354,7 +354,7 @@ LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); | warning: mutation of an interior mutable `const` item with call to `update` - --> $DIR/const-item-interior-mutations-const-atomics.rs:87:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:86:14 | LL | let _a = A.update(Ordering::SeqCst, Ordering::Relaxed, |_| std::ptr::null_mut()); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -371,7 +371,7 @@ LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); | warning: mutation of an interior mutable `const` item with call to `fetch_ptr_add` - --> $DIR/const-item-interior-mutations-const-atomics.rs:90:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:89:14 | LL | let _a = A.fetch_ptr_add(1, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -388,7 +388,7 @@ LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); | warning: mutation of an interior mutable `const` item with call to `fetch_ptr_sub` - --> $DIR/const-item-interior-mutations-const-atomics.rs:93:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:92:14 | LL | let _a = A.fetch_ptr_sub(1, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -405,7 +405,7 @@ LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); | warning: mutation of an interior mutable `const` item with call to `fetch_byte_add` - --> $DIR/const-item-interior-mutations-const-atomics.rs:96:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:95:14 | LL | let _a = A.fetch_byte_add(1, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -422,7 +422,7 @@ LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); | warning: mutation of an interior mutable `const` item with call to `fetch_byte_sub` - --> $DIR/const-item-interior-mutations-const-atomics.rs:99:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:98:14 | LL | let _a = A.fetch_byte_sub(1, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -439,7 +439,7 @@ LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); | warning: mutation of an interior mutable `const` item with call to `fetch_and` - --> $DIR/const-item-interior-mutations-const-atomics.rs:102:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:101:14 | LL | let _a = A.fetch_and(1, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -456,7 +456,7 @@ LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); | warning: mutation of an interior mutable `const` item with call to `fetch_or` - --> $DIR/const-item-interior-mutations-const-atomics.rs:105:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:104:14 | LL | let _a = A.fetch_or(1, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -473,7 +473,7 @@ LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); | warning: mutation of an interior mutable `const` item with call to `fetch_xor` - --> $DIR/const-item-interior-mutations-const-atomics.rs:108:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:107:14 | LL | let _a = A.fetch_xor(1, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -490,7 +490,7 @@ LL + static A: AtomicPtr = AtomicPtr::new(std::ptr::null_mut()); | warning: mutation of an interior mutable `const` item with call to `store` - --> $DIR/const-item-interior-mutations-const-atomics.rs:115:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:114:14 | LL | let _a = A.store(1, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -507,7 +507,7 @@ LL + static A: AtomicU32 = AtomicU32::new(0); | warning: mutation of an interior mutable `const` item with call to `swap` - --> $DIR/const-item-interior-mutations-const-atomics.rs:118:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:117:14 | LL | let _a = A.swap(2, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -524,7 +524,7 @@ LL + static A: AtomicU32 = AtomicU32::new(0); | warning: mutation of an interior mutable `const` item with call to `compare_and_swap` - --> $DIR/const-item-interior-mutations-const-atomics.rs:121:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:120:14 | LL | let _a = A.compare_and_swap(2, 3, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -541,7 +541,7 @@ LL + static A: AtomicU32 = AtomicU32::new(0); | warning: mutation of an interior mutable `const` item with call to `compare_exchange` - --> $DIR/const-item-interior-mutations-const-atomics.rs:124:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:123:14 | LL | let _a = A.compare_exchange(3, 4, Ordering::SeqCst, Ordering::Relaxed); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -558,7 +558,7 @@ LL + static A: AtomicU32 = AtomicU32::new(0); | warning: mutation of an interior mutable `const` item with call to `compare_exchange_weak` - --> $DIR/const-item-interior-mutations-const-atomics.rs:127:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:126:14 | LL | let _a = A.compare_exchange_weak(4, 5, Ordering::SeqCst, Ordering::Relaxed); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -575,7 +575,7 @@ LL + static A: AtomicU32 = AtomicU32::new(0); | warning: mutation of an interior mutable `const` item with call to `fetch_add` - --> $DIR/const-item-interior-mutations-const-atomics.rs:130:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:129:14 | LL | let _a = A.fetch_add(1, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -592,7 +592,7 @@ LL + static A: AtomicU32 = AtomicU32::new(0); | warning: mutation of an interior mutable `const` item with call to `fetch_sub` - --> $DIR/const-item-interior-mutations-const-atomics.rs:133:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:132:14 | LL | let _a = A.fetch_sub(1, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -609,7 +609,7 @@ LL + static A: AtomicU32 = AtomicU32::new(0); | warning: mutation of an interior mutable `const` item with call to `fetch_add` - --> $DIR/const-item-interior-mutations-const-atomics.rs:136:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:135:14 | LL | let _a = A.fetch_add(2, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -626,7 +626,7 @@ LL + static A: AtomicU32 = AtomicU32::new(0); | warning: mutation of an interior mutable `const` item with call to `fetch_nand` - --> $DIR/const-item-interior-mutations-const-atomics.rs:139:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:138:14 | LL | let _a = A.fetch_nand(1, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -643,7 +643,7 @@ LL + static A: AtomicU32 = AtomicU32::new(0); | warning: mutation of an interior mutable `const` item with call to `fetch_or` - --> $DIR/const-item-interior-mutations-const-atomics.rs:142:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:141:14 | LL | let _a = A.fetch_or(1, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -660,7 +660,7 @@ LL + static A: AtomicU32 = AtomicU32::new(0); | warning: mutation of an interior mutable `const` item with call to `fetch_xor` - --> $DIR/const-item-interior-mutations-const-atomics.rs:145:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:144:14 | LL | let _a = A.fetch_xor(1, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -677,7 +677,7 @@ LL + static A: AtomicU32 = AtomicU32::new(0); | warning: mutation of an interior mutable `const` item with call to `fetch_update` - --> $DIR/const-item-interior-mutations-const-atomics.rs:148:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:147:14 | LL | let _a = A.fetch_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(10)); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -694,7 +694,7 @@ LL + static A: AtomicU32 = AtomicU32::new(0); | warning: mutation of an interior mutable `const` item with call to `try_update` - --> $DIR/const-item-interior-mutations-const-atomics.rs:151:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:150:14 | LL | let _a = A.try_update(Ordering::SeqCst, Ordering::Relaxed, |_| Some(11)); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -711,7 +711,7 @@ LL + static A: AtomicU32 = AtomicU32::new(0); | warning: mutation of an interior mutable `const` item with call to `update` - --> $DIR/const-item-interior-mutations-const-atomics.rs:154:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:153:14 | LL | let _a = A.update(Ordering::SeqCst, Ordering::Relaxed, |_| 12); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -728,7 +728,7 @@ LL + static A: AtomicU32 = AtomicU32::new(0); | warning: mutation of an interior mutable `const` item with call to `fetch_max` - --> $DIR/const-item-interior-mutations-const-atomics.rs:157:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:156:14 | LL | let _a = A.fetch_max(20, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -745,7 +745,7 @@ LL + static A: AtomicU32 = AtomicU32::new(0); | warning: mutation of an interior mutable `const` item with call to `fetch_min` - --> $DIR/const-item-interior-mutations-const-atomics.rs:160:14 + --> $DIR/const-item-interior-mutations-const-atomics.rs:159:14 | LL | let _a = A.fetch_min(5, Ordering::SeqCst); | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-update.rs b/tests/ui/lint/lint-invalid-atomic-ordering-update.rs index ac41e7cee0c2..0cb87d4eab1b 100644 --- a/tests/ui/lint/lint-invalid-atomic-ordering-update.rs +++ b/tests/ui/lint/lint-invalid-atomic-ordering-update.rs @@ -1,6 +1,4 @@ //@ only-x86_64 -#![feature(atomic_try_update)] - use std::sync::atomic::{AtomicIsize, Ordering}; fn main() { diff --git a/tests/ui/lint/lint-invalid-atomic-ordering-update.stderr b/tests/ui/lint/lint-invalid-atomic-ordering-update.stderr index 8c266bacf314..5a5efbd85b0a 100644 --- a/tests/ui/lint/lint-invalid-atomic-ordering-update.stderr +++ b/tests/ui/lint/lint-invalid-atomic-ordering-update.stderr @@ -1,5 +1,5 @@ error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:73:47 + --> $DIR/lint-invalid-atomic-ordering-update.rs:71:47 | LL | let _ = x.fetch_update(Ordering::Relaxed, Ordering::AcqRel, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^ invalid failure ordering @@ -8,7 +8,7 @@ LL | let _ = x.fetch_update(Ordering::Relaxed, Ordering::AcqRel, |old| Some( = note: `#[deny(invalid_atomic_ordering)]` on by default error: `try_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `try_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:75:45 + --> $DIR/lint-invalid-atomic-ordering-update.rs:73:45 | LL | let _ = x.try_update(Ordering::Relaxed, Ordering::AcqRel, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^ invalid failure ordering @@ -16,7 +16,7 @@ LL | let _ = x.try_update(Ordering::Relaxed, Ordering::AcqRel, |old| Some(ol = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:77:41 + --> $DIR/lint-invalid-atomic-ordering-update.rs:75:41 | LL | let _ = x.update(Ordering::Relaxed, Ordering::AcqRel, |old| old + 1); | ^^^^^^^^^^^^^^^^ invalid failure ordering @@ -24,7 +24,7 @@ LL | let _ = x.update(Ordering::Relaxed, Ordering::AcqRel, |old| old + 1); = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:80:47 + --> $DIR/lint-invalid-atomic-ordering-update.rs:78:47 | LL | let _ = x.fetch_update(Ordering::Acquire, Ordering::AcqRel, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^ invalid failure ordering @@ -32,7 +32,7 @@ LL | let _ = x.fetch_update(Ordering::Acquire, Ordering::AcqRel, |old| Some( = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `try_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `try_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:82:45 + --> $DIR/lint-invalid-atomic-ordering-update.rs:80:45 | LL | let _ = x.try_update(Ordering::Acquire, Ordering::AcqRel, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^ invalid failure ordering @@ -40,7 +40,7 @@ LL | let _ = x.try_update(Ordering::Acquire, Ordering::AcqRel, |old| Some(ol = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:84:41 + --> $DIR/lint-invalid-atomic-ordering-update.rs:82:41 | LL | let _ = x.update(Ordering::Acquire, Ordering::AcqRel, |old| old + 1); | ^^^^^^^^^^^^^^^^ invalid failure ordering @@ -48,7 +48,7 @@ LL | let _ = x.update(Ordering::Acquire, Ordering::AcqRel, |old| old + 1); = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:87:47 + --> $DIR/lint-invalid-atomic-ordering-update.rs:85:47 | LL | let _ = x.fetch_update(Ordering::Release, Ordering::AcqRel, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^ invalid failure ordering @@ -56,7 +56,7 @@ LL | let _ = x.fetch_update(Ordering::Release, Ordering::AcqRel, |old| Some( = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `try_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `try_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:89:45 + --> $DIR/lint-invalid-atomic-ordering-update.rs:87:45 | LL | let _ = x.try_update(Ordering::Release, Ordering::AcqRel, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^ invalid failure ordering @@ -64,7 +64,7 @@ LL | let _ = x.try_update(Ordering::Release, Ordering::AcqRel, |old| Some(ol = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:91:41 + --> $DIR/lint-invalid-atomic-ordering-update.rs:89:41 | LL | let _ = x.update(Ordering::Release, Ordering::AcqRel, |old| old + 1); | ^^^^^^^^^^^^^^^^ invalid failure ordering @@ -72,7 +72,7 @@ LL | let _ = x.update(Ordering::Release, Ordering::AcqRel, |old| old + 1); = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:94:46 + --> $DIR/lint-invalid-atomic-ordering-update.rs:92:46 | LL | let _ = x.fetch_update(Ordering::AcqRel, Ordering::AcqRel, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^ invalid failure ordering @@ -80,7 +80,7 @@ LL | let _ = x.fetch_update(Ordering::AcqRel, Ordering::AcqRel, |old| Some(o = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `try_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `try_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:96:44 + --> $DIR/lint-invalid-atomic-ordering-update.rs:94:44 | LL | let _ = x.try_update(Ordering::AcqRel, Ordering::AcqRel, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^ invalid failure ordering @@ -88,7 +88,7 @@ LL | let _ = x.try_update(Ordering::AcqRel, Ordering::AcqRel, |old| Some(old = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:98:40 + --> $DIR/lint-invalid-atomic-ordering-update.rs:96:40 | LL | let _ = x.update(Ordering::AcqRel, Ordering::AcqRel, |old| old + 1); | ^^^^^^^^^^^^^^^^ invalid failure ordering @@ -96,7 +96,7 @@ LL | let _ = x.update(Ordering::AcqRel, Ordering::AcqRel, |old| old + 1); = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:101:46 + --> $DIR/lint-invalid-atomic-ordering-update.rs:99:46 | LL | let _ = x.fetch_update(Ordering::SeqCst, Ordering::AcqRel, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^ invalid failure ordering @@ -104,7 +104,7 @@ LL | let _ = x.fetch_update(Ordering::SeqCst, Ordering::AcqRel, |old| Some(o = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `try_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `try_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:103:44 + --> $DIR/lint-invalid-atomic-ordering-update.rs:101:44 | LL | let _ = x.try_update(Ordering::SeqCst, Ordering::AcqRel, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^ invalid failure ordering @@ -112,7 +112,7 @@ LL | let _ = x.try_update(Ordering::SeqCst, Ordering::AcqRel, |old| Some(old = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:105:40 + --> $DIR/lint-invalid-atomic-ordering-update.rs:103:40 | LL | let _ = x.update(Ordering::SeqCst, Ordering::AcqRel, |old| old + 1); | ^^^^^^^^^^^^^^^^ invalid failure ordering @@ -120,7 +120,7 @@ LL | let _ = x.update(Ordering::SeqCst, Ordering::AcqRel, |old| old + 1); = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:110:47 + --> $DIR/lint-invalid-atomic-ordering-update.rs:108:47 | LL | let _ = x.fetch_update(Ordering::Relaxed, Ordering::Release, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^^ invalid failure ordering @@ -128,7 +128,7 @@ LL | let _ = x.fetch_update(Ordering::Relaxed, Ordering::Release, |old| Some = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `try_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `try_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:112:45 + --> $DIR/lint-invalid-atomic-ordering-update.rs:110:45 | LL | let _ = x.try_update(Ordering::Relaxed, Ordering::Release, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^^ invalid failure ordering @@ -136,7 +136,7 @@ LL | let _ = x.try_update(Ordering::Relaxed, Ordering::Release, |old| Some(o = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:114:41 + --> $DIR/lint-invalid-atomic-ordering-update.rs:112:41 | LL | let _ = x.update(Ordering::Relaxed, Ordering::Release, |old| old + 1); | ^^^^^^^^^^^^^^^^^ invalid failure ordering @@ -144,7 +144,7 @@ LL | let _ = x.update(Ordering::Relaxed, Ordering::Release, |old| old + 1); = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:117:47 + --> $DIR/lint-invalid-atomic-ordering-update.rs:115:47 | LL | let _ = x.fetch_update(Ordering::Acquire, Ordering::Release, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^^ invalid failure ordering @@ -152,7 +152,7 @@ LL | let _ = x.fetch_update(Ordering::Acquire, Ordering::Release, |old| Some = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `try_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `try_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:119:45 + --> $DIR/lint-invalid-atomic-ordering-update.rs:117:45 | LL | let _ = x.try_update(Ordering::Acquire, Ordering::Release, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^^ invalid failure ordering @@ -160,7 +160,7 @@ LL | let _ = x.try_update(Ordering::Acquire, Ordering::Release, |old| Some(o = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:121:41 + --> $DIR/lint-invalid-atomic-ordering-update.rs:119:41 | LL | let _ = x.update(Ordering::Acquire, Ordering::Release, |old| old + 1); | ^^^^^^^^^^^^^^^^^ invalid failure ordering @@ -168,7 +168,7 @@ LL | let _ = x.update(Ordering::Acquire, Ordering::Release, |old| old + 1); = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:124:47 + --> $DIR/lint-invalid-atomic-ordering-update.rs:122:47 | LL | let _ = x.fetch_update(Ordering::Release, Ordering::Release, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^^ invalid failure ordering @@ -176,7 +176,7 @@ LL | let _ = x.fetch_update(Ordering::Release, Ordering::Release, |old| Some = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `try_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `try_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:126:45 + --> $DIR/lint-invalid-atomic-ordering-update.rs:124:45 | LL | let _ = x.try_update(Ordering::Release, Ordering::Release, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^^ invalid failure ordering @@ -184,7 +184,7 @@ LL | let _ = x.try_update(Ordering::Release, Ordering::Release, |old| Some(o = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:128:41 + --> $DIR/lint-invalid-atomic-ordering-update.rs:126:41 | LL | let _ = x.update(Ordering::Release, Ordering::Release, |old| old + 1); | ^^^^^^^^^^^^^^^^^ invalid failure ordering @@ -192,7 +192,7 @@ LL | let _ = x.update(Ordering::Release, Ordering::Release, |old| old + 1); = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:131:46 + --> $DIR/lint-invalid-atomic-ordering-update.rs:129:46 | LL | let _ = x.fetch_update(Ordering::AcqRel, Ordering::Release, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^^ invalid failure ordering @@ -200,7 +200,7 @@ LL | let _ = x.fetch_update(Ordering::AcqRel, Ordering::Release, |old| Some( = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `try_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `try_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:133:44 + --> $DIR/lint-invalid-atomic-ordering-update.rs:131:44 | LL | let _ = x.try_update(Ordering::AcqRel, Ordering::Release, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^^ invalid failure ordering @@ -208,7 +208,7 @@ LL | let _ = x.try_update(Ordering::AcqRel, Ordering::Release, |old| Some(ol = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:135:40 + --> $DIR/lint-invalid-atomic-ordering-update.rs:133:40 | LL | let _ = x.update(Ordering::AcqRel, Ordering::Release, |old| old + 1); | ^^^^^^^^^^^^^^^^^ invalid failure ordering @@ -216,7 +216,7 @@ LL | let _ = x.update(Ordering::AcqRel, Ordering::Release, |old| old + 1); = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:138:46 + --> $DIR/lint-invalid-atomic-ordering-update.rs:136:46 | LL | let _ = x.fetch_update(Ordering::SeqCst, Ordering::Release, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^^ invalid failure ordering @@ -224,7 +224,7 @@ LL | let _ = x.fetch_update(Ordering::SeqCst, Ordering::Release, |old| Some( = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `try_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `try_update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:140:44 + --> $DIR/lint-invalid-atomic-ordering-update.rs:138:44 | LL | let _ = x.try_update(Ordering::SeqCst, Ordering::Release, |old| Some(old + 1)); | ^^^^^^^^^^^^^^^^^ invalid failure ordering @@ -232,7 +232,7 @@ LL | let _ = x.try_update(Ordering::SeqCst, Ordering::Release, |old| Some(ol = help: consider using `Acquire` or `Relaxed` failure ordering instead error: `update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `update` does not result in a write - --> $DIR/lint-invalid-atomic-ordering-update.rs:142:40 + --> $DIR/lint-invalid-atomic-ordering-update.rs:140:40 | LL | let _ = x.update(Ordering::SeqCst, Ordering::Release, |old| old + 1); | ^^^^^^^^^^^^^^^^^ invalid failure ordering From b7077f6b381909efe6dfc1c1d68d718d41f1bdc5 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Tue, 27 Jan 2026 15:55:30 -0500 Subject: [PATCH 171/978] Add missing autodiff run-make tests to the install docs --- src/doc/rustc-dev-guide/src/autodiff/installation.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc-dev-guide/src/autodiff/installation.md b/src/doc/rustc-dev-guide/src/autodiff/installation.md index 5300c12459a1..e05fdc1160f2 100644 --- a/src/doc/rustc-dev-guide/src/autodiff/installation.md +++ b/src/doc/rustc-dev-guide/src/autodiff/installation.md @@ -28,6 +28,7 @@ You can then run our test cases: ./x test --stage 1 tests/codegen-llvm/autodiff ./x test --stage 1 tests/pretty/autodiff ./x test --stage 1 tests/ui/autodiff +./x test --stage 1 tests/run-make/autodiff ./x test --stage 1 tests/ui/feature-gates/feature-gate-autodiff.rs ``` From c60ae4dcf255fe6f82525b4b496244bdfeec97d6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 27 Jan 2026 22:41:35 +0100 Subject: [PATCH 172/978] Add code comment explaining how the CSS selector works for deprecated items --- src/librustdoc/html/static/css/rustdoc.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index b62d6b15cf36..df92938ec820 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -2656,6 +2656,10 @@ However, it's not needed with smaller screen width because the doc/code block is .deprecated-count { display: none; } +/* +The `:not(:empty)` is a little trick to not have to add conditions in JS to hide/show the marker. +It's entirely based on whether it has content and if the setting is enabled. +*/ .hide-deprecated-items .deprecated-count:not(:empty) { display: block; margin: 10px 0; From 324e366b686dbbad63120ee613e07e2cdcc6579c Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 28 Jan 2026 00:58:05 +0100 Subject: [PATCH 173/978] remove usage of `stdarch_x86_avx512` which is now stable --- crates/core_simd/src/lib.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs index 3e5ebe19e4db..fe26d99b9194 100644 --- a/crates/core_simd/src/lib.rs +++ b/crates/core_simd/src/lib.rs @@ -31,10 +31,6 @@ any(target_arch = "powerpc", target_arch = "powerpc64"), feature(stdarch_powerpc) )] -#![cfg_attr( - all(target_arch = "x86_64", target_feature = "avx512f"), - feature(stdarch_x86_avx512) -)] #![warn(missing_docs, clippy::missing_inline_in_public_items)] // basically all items, really #![deny( unsafe_op_in_unsafe_fn, From 829c314f2820a330d09b58c2e8c9a7d1b6991341 Mon Sep 17 00:00:00 2001 From: mu001999 Date: Wed, 28 Jan 2026 01:18:37 +0800 Subject: [PATCH 174/978] Check proj's parent when checking dyn compatibility --- .../src/traits/dyn_compatibility.rs | 9 ++++++--- .../const-generics/mgca/type-const-used-in-trait.rs | 13 +++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 tests/ui/const-generics/mgca/type-const-used-in-trait.rs diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index be70612653ce..9371b55b6363 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -8,6 +8,7 @@ use std::ops::ControlFlow; use rustc_errors::FatalError; use rustc_hir::attrs::AttributeKind; +use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, LangItem, find_attr}; use rustc_middle::query::Providers; @@ -833,8 +834,10 @@ impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { match ct.kind() { ty::ConstKind::Unevaluated(proj) if self.tcx.features().min_generic_const_args() => { match self.allow_self_projections { - AllowSelfProjections::Yes => { - let trait_def_id = self.tcx.parent(proj.def); + AllowSelfProjections::Yes + if let trait_def_id = self.tcx.parent(proj.def) + && self.tcx.def_kind(trait_def_id) == DefKind::Trait => + { let trait_ref = ty::TraitRef::from_assoc(self.tcx, trait_def_id, proj.args); // Only walk contained consts if the parent trait is not a supertrait. @@ -844,7 +847,7 @@ impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { ct.super_visit_with(self) } } - AllowSelfProjections::No => ct.super_visit_with(self), + _ => ct.super_visit_with(self), } } _ => ct.super_visit_with(self), diff --git a/tests/ui/const-generics/mgca/type-const-used-in-trait.rs b/tests/ui/const-generics/mgca/type-const-used-in-trait.rs new file mode 100644 index 000000000000..c98c14775a0f --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-used-in-trait.rs @@ -0,0 +1,13 @@ +//@ check-pass + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +#[type_const] +const N: usize = 2; + +trait CollectArray { + fn inner_array(&mut self) -> [A; N]; +} + +fn main() {} From 7e6d3a29767a7fc184c51b3e8ebf123b19aa4b66 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Sun, 18 Jan 2026 21:33:10 +0900 Subject: [PATCH 175/978] Add section to tests/ui/README.md --- tests/ui/README.md | 131 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 125 insertions(+), 6 deletions(-) diff --git a/tests/ui/README.md b/tests/ui/README.md index 4c91f313a735..7788e7c2335c 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -22,6 +22,12 @@ These tests exercise alloc error handling. See . +## `tests/ui/annotate-moves` + +These tests exercise the `annotate-moves` feature. + +See [`annotate-moves` | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/annotate-moves.html) + ## `tests/ui/annotate-snippet` These tests exercise the [`annotate-snippets`]-based emitter implementation. @@ -34,6 +40,12 @@ These tests exercise the [`annotate-snippets`]-based emitter implementation. These tests deal with anonymous parameters (no name, only type), a deprecated feature that becomes a hard error in Edition 2018. +## `tests/ui/any` + +These tests exercise the `try_as_dyn` feature. + +See [`core::any::try_as_dyn`](https://doc.rust-lang.org/nightly/core/any/fn.try_as_dyn.html) + ## `tests/ui/argfile`: External files providing command line arguments These tests exercise rustc reading command line arguments from an externally provided argfile (`@argsfile`). @@ -244,6 +256,14 @@ See: This directory only contains one highly specific test. Other coinduction tests can be found down the deeply located `tests/ui/traits/next-solver/cycles/coinduction/` subdirectory. +## `tests/ui/collections` + +These tests exercise the `collections` library. + +See [`std::collections`](https://doc.rust-lang.org/std/collections/index.html) + +**FIXME**: consider merge with `tests/ui/btreemap` and `tests/ui/hashmap` + ## `tests/ui/command/`: `std::process::Command` This directory is actually for the standard library [`std::process::Command`](https://doc.rust-lang.org/std/process/struct.Command.html) type, where some tests are too difficult or inconvenient to write as unit tests or integration tests within the standard library itself. @@ -380,6 +400,18 @@ These tests use the unstable command line option `query-dep-graph` to examine th Tests for `#[deprecated]` attribute and `deprecated_in_future` internal lint. +## `tests/ui/deref-patterns`: `#![feature(deref_patterns)]` and `#![feature(string_deref_patterns)]` + +Tests for `#![feature(deref_patterns)]` and `#![feature(string_deref_patterns)]`. See [Deref patterns | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/language-features/deref-patterns.html). + +**FIXME**: May have some overlap with `tests/ui/pattern/deref-patterns`. + +## `tests/ui/deref` + +Tests for `Deref` and `DerefMut` traits. + +See [`std::ops::Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) and [`std::ops::DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html) + ## `tests/ui/derived-errors/`: Derived Error Messages Tests for quality of diagnostics involving suppression of cascading errors in some cases to avoid overwhelming the user. @@ -430,6 +462,10 @@ Exercises diagnostics for when a code block attempts to gain ownership of a non- Exercises diagnostics for disallowed struct destructuring. +## `tests/ui/dist` + +Tests that require distribution artifacts. + ## `tests/ui/dollar-crate/`: `$crate` used with the `use` keyword There are a few rules - which are checked in this directory - to follow when using `$crate` - it must be used in the start of a `use` line and is a reserved identifier. @@ -492,6 +528,10 @@ These tests run in specific Rust editions, such as Rust 2015 or Rust 2018, and c **FIXME**: Maybe regroup `rust-2018`, `rust-2021` and `rust-2024` under this umbrella? +## `tests/ui/eii`: Externally Implementable Items + +Exercises `eii` keyword. + ## `tests/ui/empty/`: Various tests related to the concept of "empty" **FIXME**: These tests need better homes, this is not very informative. @@ -571,6 +611,10 @@ See: - [`ffi_const` | The Unstable book](https://doc.rust-lang.org/unstable-book/language-features/ffi-const.html) - [`ffi_pure` | The Unstable book](https://doc.rust-lang.org/beta/unstable-book/language-features/ffi-pure.html) +## `tests/ui/float` + +See: [Tracking Issue for `f16` and `f128` float types #116909](https://github.com/rust-lang/rust/issues/116909) + ## `tests/ui/fmt/` Exercises the `format!` macro. @@ -579,6 +623,10 @@ Exercises the `format!` macro. A broad category of tests on functions. +## `tests/ui/fn_traits` + +Tests for `#![feature(fn_traits)]`. See [`fn_traits` | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/library-features/fn-traits.html). + ## `tests/ui/force-inlining/`: `#[rustc_force_inline]` Tests for `#[rustc_force_inline]`, which will force a function to always be labelled as inline by the compiler (it will be inserted at the point of its call instead of being used as a normal function call.) If the compiler is unable to inline the function, an error will be reported. See . @@ -653,6 +701,10 @@ See: - [Higher-ranked trait bounds | rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/traits/hrtb.html) - [Higher-ranked trait bounds | Nomicon](https://doc.rust-lang.org/nomicon/hrtb.html) +## `tests/ui/higher-ranked-trait-bounds` + +**FIXME**: move to `tests/ui/higher-ranked/trait-bounds` + ## `tests/ui/hygiene/` This seems to have been originally intended for "hygienic macros" - macros which work in all contexts, independent of what surrounds them. However, this category has grown into a mish-mash of many tests that may belong in the other directories. @@ -835,6 +887,10 @@ Tests exercising analysis for unused variables, unreachable statements, function **FIXME**: This seems unrelated to "liveness" as defined in the rustc compiler guide. Is this misleadingly named? https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/lifetime_parameters.html#liveness-and-universal-regions +## `tests/ui/loop-match` + +Tests for `loop` with `match` expressions. + ## `tests/ui/loops/` Tests on the `loop` construct. @@ -981,6 +1037,15 @@ Contains a single test. Check that we reject the ancient Rust syntax `x <- y` an **FIXME**: Definitely should be rehomed, maybe to `tests/ui/deprecation/`. +## `tests/ui/offload` + +Exercises the offload feature. + +See: + +- [`std::offload` | rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/offload/internals.html) +- [Tracking Issue for GPU-offload #131513](https://github.com/rust-lang/rust/issues/131513) + ## `tests/ui/offset-of/` Exercises the [`std::mem::offset_of` macro](https://doc.rust-lang.org/beta/std/mem/macro.offset_of.html). @@ -1039,6 +1104,16 @@ Broad category of tests surrounding patterns. See [Patterns | Reference](https:/ **FIXME**: Some overlap with `tests/ui/match/`. +## `tests/ui/pin` + +**FIXME**: Consider merging with `tests/ui/pin-macro`. + +## `tests/ui/pin-ergonomics` + +Exercises the `#![feature(pin_ergonomics)]` feature. + +See [Tracking issue for pin ergonomics #130494](https://github.com/rust-lang/rust/issues/130494) + ## `tests/ui/pin-macro/` See [`std::pin`](https://doc.rust-lang.org/std/pin/). @@ -1103,6 +1178,12 @@ Reachability tests, primarily unreachable code and coercions into the never type **FIXME**: Check for overlap with `ui/liveness`. +## `tests/ui/reborrow` + +Exercises the `#![feature(reborrow)]` feature. + +See [Tracking Issue for Reborrow trait lang experiment #145612](https://github.com/rust-lang/rust/issues/145612) + ## `tests/ui/recursion/` Broad category of tests exercising recursions (compile test and run time), in functions, macros, `type` definitions, and more. @@ -1115,6 +1196,12 @@ Sets a recursion limit on recursive code. **FIXME**: Should be merged with `tests/ui/recursion/`. +## `tests/ui/reflection/` + +Exercises the `#![feature(type_info)]` feature. + +See [Tracking Issue for type_info #146922](https://github.com/rust-lang/rust/issues/146922) + ## `tests/ui/regions/` **FIXME**: Maybe merge with `ui/lifetimes`. @@ -1157,9 +1244,17 @@ Exercises `.rmeta` crate metadata and the `--emit=metadata` cli flag. Tests for runtime environment on which Rust programs are executed. E.g. Unix `SIGPIPE`. -## `tests/ui/rust-{2018,2021,2024}/` +## `tests/ui/rust-2018` -Tests that exercise behaviors and features that are specific to editions. +Tests that exercise behaviors and features specific to the Rust 2018 edition. + +## `tests/ui/rust-2021` + +Tests that exercise behaviors and features specific to the Rust 2021 edition. + +## `tests/ui/rust-2024` + +Tests that exercise behaviors and features specific to the Rust 2024 edition. ## `tests/ui/rustc-env` @@ -1169,10 +1264,20 @@ Tests on environmental variables that affect `rustc`. Hybrid tests that exercises `rustdoc`, and also some joint `rustdoc`/`rustc` interactions. +## `tests/ui/sanitize-attr` + +Tests for the `#![feature(sanitize)]` attribute. + +See [Sanitize | The Unstable Book](https://doc.rust-lang.org/unstable-book/language-features/sanitize.html). + ## `tests/ui/sanitizer/` Exercises sanitizer support. See [Sanitizer | The rustc book](https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html). +## `tests/ui/scalable-vectors` + +See [Tracking Issue for Scalable Vectors #145052](https://github.com/rust-lang/rust/issues/145052) + ## `tests/ui/self/`: `self` keyword Tests with erroneous ways of using `self`, such as using `this.x` syntax as seen in other languages, having it not be the first argument, or using it in a non-associated function (no `impl` or `trait`). It also contains correct uses of `self` which have previously been observed to cause ICEs. @@ -1211,6 +1316,12 @@ This is a test directory for the specific error case where a lifetime never gets While many tests here involve the `Sized` trait directly, some instead test, for example the slight variations between returning a zero-sized `Vec` and a `Vec` with one item, where one has no known type and the other does. +## `tests/ui/sized-hierarchy` + +Tests for `#![feature(sized_hierarchy)]` attribute. + +See [Tracking Issue for Sized Hierarchy #144404](https://github.com/rust-lang/rust/issues/144404) + ## `tests/ui/span/` An assorted collection of tests that involves specific diagnostic spans. @@ -1225,6 +1336,10 @@ See [Tracking issue for specialization (RFC 1210) #31844](https://github.com/rus Stability attributes used internally by the standard library: `#[stable()]` and `#[unstable()]`. +## `tests/ui/stack-probes` + +**FIXME**: Contains a single test, should likely be rehomed to `tests/ui/abi`. + ## `tests/ui/rustc_public-ir-print/` Some tests for pretty printing of rustc_public's IR. @@ -1359,6 +1474,10 @@ Tests surrounding [`std::mem::transmute`](https://doc.rust-lang.org/std/mem/fn.t Exercises compiler development support flag `-Z treat-err-as-bug`. +## `tests/ui/trimmed-paths/` + +Tests for the `#[doc(hidden)]` items. + ## `tests/ui/trivial-bounds/` `#![feature(trivial_bounds)]`. See [RFC 2056 Allow trivial where clause constraints](https://github.com/rust-lang/rfcs/blob/master/text/2056-allow-trivial-where-clause-constraints.md). @@ -1401,10 +1520,6 @@ General collection of type checking related tests. General collection of type inference related tests. -## `tests/ui/typeof/` - -`typeof` keyword, reserved but unimplemented. - ## `tests/ui/ufcs/` See [RFC 0132 Unified Function Call Syntax](https://github.com/rust-lang/rfcs/blob/master/text/0132-ufcs.md). @@ -1487,6 +1602,10 @@ See: Exercises the `unused_crate_dependencies` lint. +## `tests/ui/unstable-feature-bound` + +Tests for gating and diagnostics when unstable features are used. + ## `tests/ui/unwind-abis/` **FIXME**: Contains a single test, should likely be rehomed to `tests/ui/abi/`. From 500dc3c9c0416309be257d4c80457fa1165f0723 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Sun, 18 Jan 2026 23:44:09 +0900 Subject: [PATCH 176/978] Reorder tests/ui/README.md --- tests/ui/README.md | 152 ++++++++++++++++++++++----------------------- 1 file changed, 76 insertions(+), 76 deletions(-) diff --git a/tests/ui/README.md b/tests/ui/README.md index 7788e7c2335c..237cfb9c4f07 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -10,18 +10,18 @@ These tests deal with *Application Binary Interfaces* (ABI), mostly relating to Tests for unsupported ABIs can be made cross-platform by using the `extern "rust-invalid"` ABI, which is considered unsupported on every platform. -## `tests/ui/allocator` - -These tests exercise `#![feature(allocator_api)]` and the `#[global_allocator]` attribute. - -See [Allocator traits and `std::heap` #32838](https://github.com/rust-lang/rust/issues/32838). - ## `tests/ui/alloc-error` These tests exercise alloc error handling. See . +## `tests/ui/allocator` + +These tests exercise `#![feature(allocator_api)]` and the `#[global_allocator]` attribute. + +See [Allocator traits and `std::heap` #32838](https://github.com/rust-lang/rust/issues/32838). + ## `tests/ui/annotate-moves` These tests exercise the `annotate-moves` feature. @@ -52,14 +52,14 @@ These tests exercise rustc reading command line arguments from an externally pro See [Implement `@argsfile` to read arguments from command line #63576](https://github.com/rust-lang/rust/issues/63576). -## `tests/ui/array-slice-vec`: Arrays, slices and vectors - -Exercises various aspects surrounding basic collection types `[]`, `&[]` and `Vec`. E.g. type-checking, out-of-bounds indices, attempted instructions which are allowed in other programming languages, and more. - ## `tests/ui/argument-suggestions`: Argument suggestions Calling a function with the wrong number of arguments causes a compilation failure, but the compiler is able to, in some cases, provide suggestions on how to fix the error, such as which arguments to add or delete. These tests exercise the quality of such diagnostics. +## `tests/ui/array-slice-vec`: Arrays, slices and vectors + +Exercises various aspects surrounding basic collection types `[]`, `&[]` and `Vec`. E.g. type-checking, out-of-bounds indices, attempted instructions which are allowed in other programming languages, and more. + ## `tests/ui/asm`: `asm!` macro These tests exercise the `asm!` macro, which is used for adding inline assembly. @@ -184,6 +184,10 @@ See [RFC 3729: Hierarchy of Sized traits](https://github.com/rust-lang/rfcs/pull Defining custom auto traits with the `auto` keyword belongs to `tests/ui/auto-traits/` instead. +## `tests/ui/c-variadic`: C Variadic Function + +Tests for FFI with C varargs (`va_list`). + ## `tests/ui/cast/`: Type Casting Tests for type casting using the `as` operator. Includes tests for valid/invalid casts between primitive types, trait objects, and custom types. For example, check that trying to cast `i32` into `bool` results in a helpful error message. @@ -202,16 +206,16 @@ Tests for the `--check-cfg` compiler mechanism for checking cfg configurations, See [Checking conditional configurations | The rustc book](https://doc.rust-lang.org/rustc/check-cfg.html). -## `tests/ui/closure_context/`: Closure type inference in context - -Tests for closure type inference with respect to surrounding scopes, mostly quality of diagnostics. - ## `tests/ui/closure-expected-type/`: Closure type inference Tests targeted at how we deduce the types of closure arguments. This process is a result of some heuristics which take into account the *expected type* we have alongside the *actual types* that we get from inputs. **FIXME**: Appears to have significant overlap with `tests/ui/closure_context` and `tests/ui/functions-closures/closure-expected-type`. Needs further investigation. +## `tests/ui/closure_context`: Closure type inference in context + +Tests for closure type inference with respect to surrounding scopes, mostly quality of diagnostics. + ## `tests/ui/closures/`: General Closure Tests Any closure-focused tests that does not fit in the other more specific closure subdirectories belong here. E.g. syntax, `move`, lifetimes. @@ -305,10 +309,6 @@ See: - [Tracking Issue for complex generic constants: `feature(generic_const_exprs)` #76560](https://github.com/rust-lang/rust/issues/76560) - [Const generics | Reference](https://doc.rust-lang.org/reference/items/generics.html#const-generics) -## `tests/ui/const_prop/`: Constant Propagation - -Tests exercising `ConstProp` mir-opt pass (mostly regression tests). See . - ## `tests/ui/const-ptr/`: Constant Pointers Tests exercise const raw pointers. E.g. pointer arithmetic, casting and dereferencing, always with a `const`. @@ -319,6 +319,10 @@ See: - [`std::ptr`](https://doc.rust-lang.org/std/ptr/index.html) - [Pointer types | Reference](https://doc.rust-lang.org/reference/types/pointer.html) +## `tests/ui/const_prop`: Constant Propagation + +Tests exercising `ConstProp` mir-opt pass (mostly regression tests). See . + ## `tests/ui/consts/`: General Constant Evaluation Anything to do with constants, which does not fit in the previous two `const` categories, goes here. This does not always imply use of the `const` keyword - other values considered constant, such as defining an enum variant as `enum Foo { Variant = 5 }` also counts. @@ -360,10 +364,6 @@ Tests for `#[bench]`, `#[test_case]` attributes and the `custom_test_frameworks` See [Tracking issue for eRFC 2318, Custom test frameworks #50297](https://github.com/rust-lang/rust/issues/50297). -## `tests/ui/c-variadic/`: C Variadic Function - -Tests for FFI with C varargs (`va_list`). - ## `tests/ui/cycle-trait/`: Trait Cycle Detection Tests for detection and handling of cyclic trait dependencies. @@ -400,16 +400,16 @@ These tests use the unstable command line option `query-dep-graph` to examine th Tests for `#[deprecated]` attribute and `deprecated_in_future` internal lint. +## `tests/ui/deref` + +Tests for `Deref` and `DerefMut` traits. + ## `tests/ui/deref-patterns`: `#![feature(deref_patterns)]` and `#![feature(string_deref_patterns)]` Tests for `#![feature(deref_patterns)]` and `#![feature(string_deref_patterns)]`. See [Deref patterns | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/language-features/deref-patterns.html). **FIXME**: May have some overlap with `tests/ui/pattern/deref-patterns`. -## `tests/ui/deref` - -Tests for `Deref` and `DerefMut` traits. - See [`std::ops::Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) and [`std::ops::DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html) ## `tests/ui/derived-errors/`: Derived Error Messages @@ -438,6 +438,10 @@ These tests revolve around command-line flags which change the way error/warning **FIXME**: Check redundancy with `annotate-snippet`, which is another emitter. +## `tests/ui/diagnostic-width`: `--diagnostic-width` + +Everything to do with `--diagnostic-width`. + ## `tests/ui/diagnostic_namespace/` Exercises `#[diagnostic::*]` namespaced attributes. See [RFC 3368 Diagnostic attribute namespace](https://github.com/rust-lang/rfcs/blob/master/text/3368-diagnostic-attribute-namespace.md). @@ -446,10 +450,6 @@ Exercises `#[diagnostic::*]` namespaced attributes. See [RFC 3368 Diagnostic att This directory contains tests and infrastructure related to the diagnostics system, including support for translatable diagnostics -## `tests/ui/diagnostic-width/`: `--diagnostic-width` - -Everything to do with `--diagnostic-width`. - ## `tests/ui/did_you_mean/` Tests for miscellaneous suggestions. @@ -497,10 +497,6 @@ Tests for dynamically-sized types (DSTs). See [Dynamically Sized Types | Referen Tests about duplicated symbol names and associated errors, such as using the `#[export_name]` attribute to rename a function with the same name as another function. -## `tests/ui/dynamically-sized-types/`: Dynamically Sized Types - -**FIXME**: should be coalesced with `tests/ui/dst`. - ## `tests/ui/dyn-compatibility/`: Dyn-compatibility Tests for dyn-compatibility of traits. @@ -522,6 +518,10 @@ The `dyn` keyword is used to highlight that calls to methods on the associated T See [`dyn` keyword](https://doc.rust-lang.org/std/keyword.dyn.html). +## `tests/ui/dynamically-sized-types`: Dynamically Sized Types + +**FIXME**: should be coalesced with `tests/ui/dst`. + ## `tests/ui/editions/`: Rust edition-specific peculiarities These tests run in specific Rust editions, such as Rust 2015 or Rust 2018, and check errors and functionality related to specific now-deprecated idioms and features. @@ -627,6 +627,12 @@ A broad category of tests on functions. Tests for `#![feature(fn_traits)]`. See [`fn_traits` | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/library-features/fn-traits.html). +## `tests/ui/for-loop-while` + +Anything to do with loops and `for`, `loop` and `while` keywords to express them. + +**FIXME**: After `ui/for` is merged into this, also carry over its SUMMARY text. + ## `tests/ui/force-inlining/`: `#[rustc_force_inline]` Tests for `#[rustc_force_inline]`, which will force a function to always be labelled as inline by the compiler (it will be inserted at the point of its call instead of being used as a normal function call.) If the compiler is unable to inline the function, an error will be reported. See . @@ -637,12 +643,6 @@ Tests for `extern "C"` and `extern "Rust`. **FIXME**: Check for potential overlap/merge with `ui/c-variadic` and/or `ui/extern`. -## `tests/ui/for-loop-while/` - -Anything to do with loops and `for`, `loop` and `while` keywords to express them. - -**FIXME**: After `ui/for` is merged into this, also carry over its SUMMARY text. - ## `tests/ui/frontmatter/` Tests for `#![feature(frontmatter)]`. See [Tracking Issue for `frontmatter` #136889](https://github.com/rust-lang/rust/issues/136889). @@ -651,12 +651,6 @@ Tests for `#![feature(frontmatter)]`. See [Tracking Issue for `frontmatter` #136 Tests for diagnostics when there may be identically named types that need further qualifications to disambiguate. -## `tests/ui/functional-struct-update/` - -Functional Struct Update is the name for the idiom by which one can write `..` at the end of a struct literal expression to fill in all remaining fields of the struct literal by using `` as the source for them. - -See [RFC 0736 Privacy-respecting Functional Struct Update](https://github.com/rust-lang/rfcs/blob/master/text/0736-privacy-respecting-fru.md). - ## `tests/ui/function-pointer/` Tests on function pointers, such as testing their compatibility with higher-ranked trait bounds. @@ -666,6 +660,12 @@ See: - [Function pointer types | Reference](https://doc.rust-lang.org/reference/types/function-pointer.html) - [Higher-ranked trait bounds | Nomicon](https://doc.rust-lang.org/nomicon/hrtb.html) +## `tests/ui/functional-struct-update/` + +Functional Struct Update is the name for the idiom by which one can write `..` at the end of a struct literal expression to fill in all remaining fields of the struct literal by using `` as the source for them. + +See [RFC 0736 Privacy-respecting Functional Struct Update](https://github.com/rust-lang/rfcs/blob/master/text/0736-privacy-respecting-fru.md). + ## `tests/ui/functions-closures/` Tests on closures. See [Closure expressions | Reference](https://doc.rust-lang.org/reference/expressions/closure-expr.html). @@ -721,14 +721,14 @@ This test category revolves around trait objects with `Sized` having illegal ope Tests on lifetime elision in impl function signatures. See [Lifetime elision | Nomicon](https://doc.rust-lang.org/nomicon/lifetime-elision.html). -## `tests/ui/implied-bounds/` - -See [Implied bounds | Reference](https://doc.rust-lang.org/reference/trait-bounds.html#implied-bounds). - ## `tests/ui/impl-trait/` Tests for trait impls. +## `tests/ui/implied-bounds/` + +See [Implied bounds | Reference](https://doc.rust-lang.org/reference/trait-bounds.html#implied-bounds). + ## `tests/ui/imports/` Tests for module system and imports. @@ -854,6 +854,12 @@ Broad directory on lifetimes, including proper specifiers, lifetimes not living These tests exercises numerical limits, such as `[[u8; 1518599999]; 1518600000]`. +## `tests/ui/link-native-libs/` + +Tests for `#[link(name = "", kind = "")]` and `-l` command line flag. + +See [Tracking Issue for linking modifiers for native libraries #81490](https://github.com/rust-lang/rust/issues/81490). + ## `tests/ui/linkage-attr/` Tests for the linkage attribute `#[linkage]` of `#![feature(linkage)]`. @@ -866,12 +872,6 @@ Tests on code which fails during the linking stage, or which contain arguments a See [Linkage | Reference](https://doc.rust-lang.org/reference/linkage.html). -## `tests/ui/link-native-libs/` - -Tests for `#[link(name = "", kind = "")]` and `-l` command line flag. - -See [Tracking Issue for linking modifiers for native libraries #81490](https://github.com/rust-lang/rust/issues/81490). - ## `tests/ui/lint/` Tests for the lint infrastructure, lint levels, lint reasons, etc. @@ -997,6 +997,10 @@ See [RFC 3550 New Range](https://github.com/rust-lang/rfcs/blob/master/text/3550 Tests for Non-lexical lifetimes. See [RFC 2094 NLL](https://rust-lang.github.io/rfcs/2094-nll.html). +## `tests/ui/no_std/` + +Tests for where the standard library is disabled through `#![no_std]`. + ## `tests/ui/non_modrs_mods/` Despite the size of the directory, this is a single test, spawning a sprawling `mod` dependency tree and checking its successful build. @@ -1009,10 +1013,6 @@ A very similar principle as `non_modrs_mods`, but with an added inline `mod` sta **FIXME**: Consider merge with `tests/ui/modules/`, keeping the directory structure. -## `tests/ui/no_std/` - -Tests for where the standard library is disabled through `#![no_std]`. - ## `tests/ui/not-panic/` Tests checking various types, such as `&RefCell`, and whether they are not `UnwindSafe` as expected. @@ -1134,6 +1134,10 @@ Exercises the `-Z print-type-sizes` flag. Exercises on name privacy. E.g. the meaning of `pub`, `pub(crate)`, etc. +## `tests/ui/proc-macro/` + +Broad category of tests on proc-macros. See [Procedural Macros | Reference](https://doc.rust-lang.org/reference/procedural-macros.html). + ## `tests/ui/process/` Some standard library process tests which are hard to write within standard library crate tests. @@ -1142,10 +1146,6 @@ Some standard library process tests which are hard to write within standard libr Some standard library process termination tests which are hard to write within standard library crate tests. -## `tests/ui/proc-macro/` - -Broad category of tests on proc-macros. See [Procedural Macros | Reference](https://doc.rust-lang.org/reference/procedural-macros.html). - ## `tests/ui/ptr_ops/`: Using operations on a pointer Contains only 2 tests, related to a single issue, which was about an error caused by using addition on a pointer to `i8`. @@ -1260,6 +1260,10 @@ Tests that exercise behaviors and features specific to the Rust 2024 edition. Tests on environmental variables that affect `rustc`. +## `tests/ui/rustc_public-ir-print` + +Some tests for pretty printing of rustc_public's IR. + ## `tests/ui/rustdoc` Hybrid tests that exercises `rustdoc`, and also some joint `rustdoc`/`rustc` interactions. @@ -1340,10 +1344,6 @@ Stability attributes used internally by the standard library: `#[stable()]` and **FIXME**: Contains a single test, should likely be rehomed to `tests/ui/abi`. -## `tests/ui/rustc_public-ir-print/` - -Some tests for pretty printing of rustc_public's IR. - ## `tests/ui/stack-protector/`: `-Z stack-protector` command line flag See [Tracking Issue for stabilizing stack smashing protection (i.e., `-Z stack-protector`) #114903](https://github.com/rust-lang/rust/issues/114903). @@ -1512,14 +1512,14 @@ Tests for `type` aliases in the context of `enum` variants, such as that applied `#![feature(type_alias_impl_trait)]`. See [Type Alias Impl Trait | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/language-features/type-alias-impl-trait.html). -## `tests/ui/typeck/` - -General collection of type checking related tests. - ## `tests/ui/type-inference/` General collection of type inference related tests. +## `tests/ui/typeck` + +General collection of type checking related tests. + ## `tests/ui/ufcs/` See [RFC 0132 Unified Function Call Syntax](https://github.com/rust-lang/rfcs/blob/master/text/0132-ufcs.md). @@ -1598,14 +1598,14 @@ See: **FIXME**: Seems to also contain more generic tests that fit in `tests/ui/unsized/`. -## `tests/ui/unused-crate-deps/` - -Exercises the `unused_crate_dependencies` lint. - ## `tests/ui/unstable-feature-bound` Tests for gating and diagnostics when unstable features are used. +## `tests/ui/unused-crate-deps` + +Exercises the `unused_crate_dependencies` lint. + ## `tests/ui/unwind-abis/` **FIXME**: Contains a single test, should likely be rehomed to `tests/ui/abi/`. From a08541085aa3390ddf88339a2adeb29e8a118315 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Thu, 1 Jan 2026 21:05:02 +0900 Subject: [PATCH 177/978] Add subdirectory change detection to tidy --- src/tools/tidy/src/ui_tests.rs | 69 ++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index bf51810810a6..b5643034d45c 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -73,6 +73,57 @@ pub fn check(root_path: &Path, tidy_ctx: TidyCtx) { )); } } + + // The list of subdirectories in ui tests. + // Compare previous subdirectory with current subdirectory + // to sync with `tests/ui/README.md`. + // See + let mut prev_line = String::new(); + let mut is_sorted = true; + let documented_subdirs: BTreeSet<_> = include_str!("../../../../tests/ui/README.md") + .lines() + .filter_map(|line| { + static_regex!(r"^##.*?`(?[^`]+)`").captures(line).map(|cap| { + let dir = &cap["dir"]; + // FIXME(reddevilmidzy) normalize subdirs title in tests/ui/README.md + if dir.ends_with('/') { + dir.strip_suffix('/').unwrap().to_string() + } else { + dir.to_string() + } + }) + }) + .inspect(|line| { + if prev_line.as_str() > line.as_str() { + is_sorted = false; + } + + prev_line = line.clone(); + }) + .collect(); + let filesystem_subdirs = collect_ui_tests_subdirs(&path); + let is_modified = !filesystem_subdirs.eq(&documented_subdirs); + + if !is_sorted { + check.error("`tests/ui/README.md` is not in order"); + } + if is_modified { + for directory in documented_subdirs.symmetric_difference(&filesystem_subdirs) { + if documented_subdirs.contains(directory) { + check.error(format!( + "ui subdirectory `{directory}` is listed in `tests/ui/README.md` but does not exist in the filesystem" + )); + } else { + check.error(format!( + "ui subdirectory `{directory}` exists in the filesystem but is not documented in `tests/ui/README.md`" + )); + } + } + check.error( + "`tests/ui/README.md` subdirectory listing is out of sync with the filesystem. \ + Please add or remove subdirectory entries (## headers with backtick-wrapped names) to match the actual directories in `tests/ui/`" + ); + } } fn deny_new_top_level_ui_tests(check: &mut RunningCheck, tests_path: &Path) { @@ -137,6 +188,24 @@ fn recursively_check_ui_tests<'issues>( remaining_issue_names } +fn collect_ui_tests_subdirs(path: &Path) -> BTreeSet { + let ui = path.join("ui"); + let entries = std::fs::read_dir(ui.as_path()).unwrap(); + + entries + .filter_map(|entry| entry.ok()) + .map(|entry| entry.path()) + .filter(|path| path.is_dir()) + .map(|dir_path| { + let dir_path = dir_path.strip_prefix(path).unwrap(); + format!( + "tests/{}", + dir_path.to_string_lossy().replace(std::path::MAIN_SEPARATOR_STR, "/") + ) + }) + .collect() +} + fn check_unexpected_extension(check: &mut RunningCheck, file_path: &Path, ext: &str) { const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files From ce03e7b33ab1e26bb9a553dd35f0af06b372b7a9 Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Tue, 27 Jan 2026 18:29:25 +0100 Subject: [PATCH 178/978] Avoid miri error in `slice::sort` under Stacked Borrows See comment in code. Fixes: https://github.com/rust-lang/rust/pull/131065 --- library/alloctests/tests/sort/tests.rs | 8 ++++++++ library/core/src/slice/sort/stable/quicksort.rs | 9 ++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/library/alloctests/tests/sort/tests.rs b/library/alloctests/tests/sort/tests.rs index d321f8df5189..09b76773d6b2 100644 --- a/library/alloctests/tests/sort/tests.rs +++ b/library/alloctests/tests/sort/tests.rs @@ -362,6 +362,13 @@ fn sort_vs_sort_by_impl() { assert_eq!(input_sort_by, expected); } +pub fn box_value_impl() { + for len in [3, 9, 35, 56, 132] { + test_is_sorted::, S>(len, Box::new, patterns::random); + test_is_sorted::, S>(len, Box::new, |len| patterns::random_sorted(len, 80.0)); + } +} + gen_sort_test_fns_with_default_patterns!( correct_i32, |len, pattern_fn| test_is_sorted::(len, |val| val, pattern_fn), @@ -967,6 +974,7 @@ define_instantiate_sort_tests!( [miri_yes, fixed_seed_rand_vec_prefix], [miri_yes, int_edge], [miri_yes, sort_vs_sort_by], + [miri_yes, box_value], [miri_yes, correct_i32_random], [miri_yes, correct_i32_random_z1], [miri_yes, correct_i32_random_d2], diff --git a/library/core/src/slice/sort/stable/quicksort.rs b/library/core/src/slice/sort/stable/quicksort.rs index 734a495ce225..acc8a5e838e1 100644 --- a/library/core/src/slice/sort/stable/quicksort.rs +++ b/library/core/src/slice/sort/stable/quicksort.rs @@ -1,6 +1,6 @@ //! This module contains a stable quicksort and partition implementation. -use crate::mem::{ManuallyDrop, MaybeUninit}; +use crate::mem::MaybeUninit; use crate::slice::sort::shared::FreezeMarker; use crate::slice::sort::shared::pivot::choose_pivot; use crate::slice::sort::shared::smallsort::StableSmallSortTypeImpl; @@ -41,8 +41,11 @@ pub fn quicksort bool>( // SAFETY: We only access the temporary copy for Freeze types, otherwise // self-modifications via `is_less` would not be observed and this would // be unsound. Our temporary copy does not escape this scope. - let pivot_copy = unsafe { ManuallyDrop::new(ptr::read(&v[pivot_pos])) }; - let pivot_ref = (!has_direct_interior_mutability::()).then_some(&*pivot_copy); + // We use `MaybeUninit` to avoid re-tag issues. FIXME: use `MaybeDangling`. + let pivot_copy = unsafe { ptr::read((&raw const v[pivot_pos]).cast::>()) }; + let pivot_ref = + // SAFETY: We created the value in an init state. + (!has_direct_interior_mutability::()).then_some(unsafe { &*pivot_copy.as_ptr() }); // We choose a pivot, and check if this pivot is equal to our left // ancestor. If true, we do a partition putting equal elements on the From e88259366689a0daf0d57edfd42004f067f02dc7 Mon Sep 17 00:00:00 2001 From: Matheus Date: Tue, 27 Jan 2026 22:24:38 -0300 Subject: [PATCH 179/978] Fix grammar in doc comments in `conf.rs` --- book/src/lint_configuration.md | 4 ++-- clippy_config/src/conf.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 68ef93d7cbf9..57ac01828e59 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -246,7 +246,7 @@ A list of crate names to allow duplicates of ## `allowed-idents-below-min-chars` Allowed names below the minimum allowed characters. The value `".."` can be used as part of -the list to indicate, that the configured values should be appended to the default +the list to indicate that the configured values should be appended to the default configuration of Clippy. By default, any configuration will replace the default value. **Default Value:** `["i", "j", "x", "y", "z", "w", "n"]` @@ -570,7 +570,7 @@ The list of disallowed types, written as fully qualified paths. ## `doc-valid-idents` The list of words this lint should not consider as identifiers needing ticks. The value -`".."` can be used as part of the list to indicate, that the configured values should be appended to the +`".."` can be used as part of the list to indicate that the configured values should be appended to the default configuration of Clippy. By default, any configuration will replace the default value. For example: * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 2e7ef3a8b020..3f4997a395a8 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -423,7 +423,7 @@ define_Conf! { #[lints(multiple_crate_versions)] allowed_duplicate_crates: Vec = Vec::new(), /// Allowed names below the minimum allowed characters. The value `".."` can be used as part of - /// the list to indicate, that the configured values should be appended to the default + /// the list to indicate that the configured values should be appended to the default /// configuration of Clippy. By default, any configuration will replace the default value. #[lints(min_ident_chars)] allowed_idents_below_min_chars: Vec = @@ -620,7 +620,7 @@ define_Conf! { #[lints(disallowed_types)] disallowed_types: Vec = Vec::new(), /// The list of words this lint should not consider as identifiers needing ticks. The value - /// `".."` can be used as part of the list to indicate, that the configured values should be appended to the + /// `".."` can be used as part of the list to indicate that the configured values should be appended to the /// default configuration of Clippy. By default, any configuration will replace the default value. For example: /// * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. /// * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. From 890e50de69b40c9a9f3b7a636286c066df2c9c52 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 28 Jan 2026 09:57:16 -0600 Subject: [PATCH 180/978] Stabilize feature(push_mut) --- library/alloc/src/collections/linked_list.rs | 6 ++---- library/alloc/src/collections/vec_deque/mod.rs | 9 +++------ library/alloc/src/vec/mod.rs | 9 ++------- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 6cab5728a281..3889fca30bc8 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -854,7 +854,6 @@ impl LinkedList { /// # Examples /// /// ``` - /// #![feature(push_mut)] /// use std::collections::LinkedList; /// /// let mut dl = LinkedList::from([1, 2, 3]); @@ -863,7 +862,7 @@ impl LinkedList { /// *ptr += 4; /// assert_eq!(dl.front().unwrap(), &6); /// ``` - #[unstable(feature = "push_mut", issue = "135974")] + #[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")] #[must_use = "if you don't need a reference to the value, use `LinkedList::push_front` instead"] pub fn push_front_mut(&mut self, elt: T) -> &mut T { let mut node = @@ -926,7 +925,6 @@ impl LinkedList { /// # Examples /// /// ``` - /// #![feature(push_mut)] /// use std::collections::LinkedList; /// /// let mut dl = LinkedList::from([1, 2, 3]); @@ -935,7 +933,7 @@ impl LinkedList { /// *ptr += 4; /// assert_eq!(dl.back().unwrap(), &6); /// ``` - #[unstable(feature = "push_mut", issue = "135974")] + #[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")] #[must_use = "if you don't need a reference to the value, use `LinkedList::push_back` instead"] pub fn push_back_mut(&mut self, elt: T) -> &mut T { let mut node = diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index c51317a1a68f..eda29db44257 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -2168,7 +2168,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(push_mut)] /// use std::collections::VecDeque; /// /// let mut d = VecDeque::from([1, 2, 3]); @@ -2176,7 +2175,7 @@ impl VecDeque { /// *x -= 1; /// assert_eq!(d.front(), Some(&7)); /// ``` - #[unstable(feature = "push_mut", issue = "135974")] + #[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")] #[must_use = "if you don't need a reference to the value, use `VecDeque::push_front` instead"] pub fn push_front_mut(&mut self, value: T) -> &mut T { if self.is_full() { @@ -2212,7 +2211,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(push_mut)] /// use std::collections::VecDeque; /// /// let mut d = VecDeque::from([1, 2, 3]); @@ -2220,7 +2218,7 @@ impl VecDeque { /// *x += 1; /// assert_eq!(d.back(), Some(&10)); /// ``` - #[unstable(feature = "push_mut", issue = "135974")] + #[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")] #[must_use = "if you don't need a reference to the value, use `VecDeque::push_back` instead"] pub fn push_back_mut(&mut self, value: T) -> &mut T { if self.is_full() { @@ -2419,7 +2417,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(push_mut)] /// use std::collections::VecDeque; /// /// let mut vec_deque = VecDeque::from([1, 2, 3]); @@ -2428,7 +2425,7 @@ impl VecDeque { /// *x += 7; /// assert_eq!(vec_deque, &[1, 12, 2, 3]); /// ``` - #[unstable(feature = "push_mut", issue = "135974")] + #[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")] #[must_use = "if you don't need a reference to the value, use `VecDeque::insert` instead"] pub fn insert_mut(&mut self, index: usize, value: T) -> &mut T { assert!(index <= self.len(), "index out of bounds"); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index aaf22e80ec60..6cbe89d9da4f 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1003,9 +1003,6 @@ const impl Vec { /// # Examples /// /// ``` - /// #![feature(push_mut)] - /// - /// /// let mut vec = vec![1, 2]; /// let last = vec.push_mut(3); /// assert_eq!(*last, 3); @@ -1023,7 +1020,7 @@ const impl Vec { /// vector's elements to a larger allocation. This expensive operation is /// offset by the *capacity* *O*(1) insertions it allows. #[inline] - #[unstable(feature = "push_mut", issue = "135974")] + #[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")] #[must_use = "if you don't need a reference to the value, use `Vec::push` instead"] pub fn push_mut(&mut self, value: T) -> &mut T { // Inform codegen that the length does not change across grow_one(). @@ -2196,7 +2193,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(push_mut)] /// let mut vec = vec![1, 3, 5, 9]; /// let x = vec.insert_mut(3, 6); /// *x += 1; @@ -2210,7 +2206,7 @@ impl Vec { /// the insertion index is 0. #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "push_mut", issue = "135974")] + #[stable(feature = "push_mut", since = "CURRENT_RUSTC_VERSION")] #[track_caller] #[must_use = "if you don't need a reference to the value, use `Vec::insert` instead"] pub fn insert_mut(&mut self, index: usize, element: T) -> &mut T { @@ -2689,7 +2685,6 @@ impl Vec { /// Takes *O*(1) time. #[inline] #[unstable(feature = "vec_push_within_capacity", issue = "100486")] - // #[unstable(feature = "push_mut", issue = "135974")] pub fn push_within_capacity(&mut self, value: T) -> Result<&mut T, T> { if self.len == self.buf.capacity() { return Err(value); From bd1c36a115eee3542053a38be5e996b8e7908bc4 Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 28 Jan 2026 11:14:09 -0600 Subject: [PATCH 181/978] rustdoc(main.js): use typeof in register_type_impls for isTrait this allows TypeScript to understand the relation between isTrait and traitName's type, getting rid of a type error. --- src/librustdoc/html/static/js/main.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index a26683e2e9bb..f980c92d8f7a 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -973,8 +973,8 @@ function preLoadCss(cssUrl) { for (const impList of imp[nonnull(window.currentCrate)]) { const types = impList.slice(2); const text = impList[0]; - const isTrait = impList[1] !== 0; const traitName = impList[1]; + const isTrait = typeof traitName === "string"; // @ts-expect-error if (types.indexOf(selfPath) === -1) { continue; @@ -1057,7 +1057,6 @@ function preLoadCss(cssUrl) { const li = document.createElement("li"); const a = document.createElement("a"); a.href = `#${nonnull(template.content.querySelector(".impl")).id}`; - // @ts-expect-error a.textContent = traitName; li.appendChild(a); // @ts-expect-error From f5f2ca0dc62b4a6d38ba221ef64090172da7f569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heath=20Dutton=F0=9F=95=B4=EF=B8=8F?= Date: Thu, 1 Jan 2026 17:25:25 -0500 Subject: [PATCH 182/978] Improve move error diagnostic for `AsyncFn` closures When an async closure captures a variable by move but is constrained to `AsyncFn` or `AsyncFnMut`, the error message now explains that the closure kind is the issue and points to the trait bound, similar to the existing diagnostic for `Fn`/`FnMut` closures. --- .../src/diagnostics/move_errors.rs | 199 ++++++++++++------ .../move-from-async-fn-bound.rs | 13 ++ .../move-from-async-fn-bound.stderr | 30 +++ 3 files changed, 178 insertions(+), 64 deletions(-) create mode 100644 tests/ui/async-await/async-closures/move-from-async-fn-bound.rs create mode 100644 tests/ui/async-await/async-closures/move-from-async-fn-bound.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index f83931d37599..986ade57fb31 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -1,3 +1,4 @@ +use rustc_abi::FieldIdx; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::Visitor; @@ -7,7 +8,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex}; use rustc_span::def_id::DefId; -use rustc_span::{BytePos, DUMMY_SP, ExpnKind, MacroKind, Span}; +use rustc_span::{BytePos, ExpnKind, MacroKind, Span}; use rustc_trait_selection::error_reporting::traits::FindExprBySpan; use rustc_trait_selection::infer::InferCtxtExt; use tracing::debug; @@ -472,49 +473,30 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if def_id.as_local() == Some(self.mir_def_id()) && let Some(upvar_field) = upvar_field => { - let closure_kind_ty = closure_args.as_closure().kind_ty(); - let closure_kind = match closure_kind_ty.to_opt_closure_kind() { - Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind, - Some(ty::ClosureKind::FnOnce) => { - bug!("closure kind does not match first argument type") - } - None => bug!("closure kind not inferred by borrowck"), - }; - let capture_description = - format!("captured variable in an `{closure_kind}` closure"); - - let upvar = &self.upvars[upvar_field.index()]; - let upvar_hir_id = upvar.get_root_variable(); - let upvar_name = upvar.to_string(tcx); - let upvar_span = tcx.hir_span(upvar_hir_id); - - let place_name = self.describe_any_place(move_place.as_ref()); - - let place_description = - if self.is_upvar_field_projection(move_place.as_ref()).is_some() { - format!("{place_name}, a {capture_description}") - } else { - format!("{place_name}, as `{upvar_name}` is a {capture_description}") - }; - - debug!( - "report: closure_kind_ty={:?} closure_kind={:?} place_description={:?}", - closure_kind_ty, closure_kind, place_description, - ); - - let closure_span = tcx.def_span(def_id); - - self.cannot_move_out_of(span, &place_description) - .with_span_label(upvar_span, "captured outer variable") - .with_span_label( - closure_span, - format!("captured by this `{closure_kind}` closure"), - ) - .with_span_help( - self.get_closure_bound_clause_span(*def_id), - "`Fn` and `FnMut` closures require captured values to be able to be \ - consumed multiple times, but `FnOnce` closures may consume them only once", - ) + self.report_closure_move_error( + span, + move_place, + *def_id, + closure_args.as_closure().kind_ty(), + upvar_field, + ty::Asyncness::No, + ) + } + ty::CoroutineClosure(def_id, closure_args) + if def_id.as_local() == Some(self.mir_def_id()) + && let Some(upvar_field) = upvar_field + && self + .get_closure_bound_clause_span(*def_id, ty::Asyncness::Yes) + .is_some() => + { + self.report_closure_move_error( + span, + move_place, + *def_id, + closure_args.as_coroutine_closure().kind_ty(), + upvar_field, + ty::Asyncness::Yes, + ) } _ => { let source = self.borrowed_content_source(deref_base); @@ -563,45 +545,134 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { err } - fn get_closure_bound_clause_span(&self, def_id: DefId) -> Span { + fn report_closure_move_error( + &self, + span: Span, + move_place: Place<'tcx>, + def_id: DefId, + closure_kind_ty: Ty<'tcx>, + upvar_field: FieldIdx, + asyncness: ty::Asyncness, + ) -> Diag<'infcx> { + let tcx = self.infcx.tcx; + + let closure_kind = match closure_kind_ty.to_opt_closure_kind() { + Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind, + Some(ty::ClosureKind::FnOnce) => { + bug!("closure kind does not match first argument type") + } + None => bug!("closure kind not inferred by borrowck"), + }; + + let async_prefix = if asyncness.is_async() { "Async" } else { "" }; + let capture_description = + format!("captured variable in an `{async_prefix}{closure_kind}` closure"); + + let upvar = &self.upvars[upvar_field.index()]; + let upvar_hir_id = upvar.get_root_variable(); + let upvar_name = upvar.to_string(tcx); + let upvar_span = tcx.hir_span(upvar_hir_id); + + let place_name = self.describe_any_place(move_place.as_ref()); + + let place_description = if self.is_upvar_field_projection(move_place.as_ref()).is_some() { + format!("{place_name}, a {capture_description}") + } else { + format!("{place_name}, as `{upvar_name}` is a {capture_description}") + }; + + debug!(?closure_kind_ty, ?closure_kind, ?place_description); + + let closure_span = tcx.def_span(def_id); + + let help_msg = format!( + "`{async_prefix}Fn` and `{async_prefix}FnMut` closures require captured values to \ + be able to be consumed multiple times, but `{async_prefix}FnOnce` closures may \ + consume them only once" + ); + + let mut err = self + .cannot_move_out_of(span, &place_description) + .with_span_label(upvar_span, "captured outer variable") + .with_span_label( + closure_span, + format!("captured by this `{async_prefix}{closure_kind}` closure"), + ); + + if let Some(bound_span) = self.get_closure_bound_clause_span(def_id, asyncness) { + err.span_help(bound_span, help_msg); + } else if !asyncness.is_async() { + // For sync closures, always emit the help message even without a span. + // For async closures, we only enter this branch if we found a valid span + // (due to the match guard), so no fallback is needed. + err.help(help_msg); + } + + err + } + + fn get_closure_bound_clause_span( + &self, + def_id: DefId, + asyncness: ty::Asyncness, + ) -> Option { let tcx = self.infcx.tcx; let typeck_result = tcx.typeck(self.mir_def_id()); // Check whether the closure is an argument to a call, if so, // get the instantiated where-bounds of that call. let closure_hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); - let hir::Node::Expr(parent) = tcx.parent_hir_node(closure_hir_id) else { return DUMMY_SP }; + let hir::Node::Expr(parent) = tcx.parent_hir_node(closure_hir_id) else { return None }; let predicates = match parent.kind { hir::ExprKind::Call(callee, _) => { - let Some(ty) = typeck_result.node_type_opt(callee.hir_id) else { return DUMMY_SP }; - let ty::FnDef(fn_def_id, args) = ty.kind() else { return DUMMY_SP }; + let ty = typeck_result.node_type_opt(callee.hir_id)?; + let ty::FnDef(fn_def_id, args) = ty.kind() else { return None }; tcx.predicates_of(fn_def_id).instantiate(tcx, args) } hir::ExprKind::MethodCall(..) => { - let Some((_, method)) = typeck_result.type_dependent_def(parent.hir_id) else { - return DUMMY_SP; - }; + let (_, method) = typeck_result.type_dependent_def(parent.hir_id)?; let args = typeck_result.node_args(parent.hir_id); tcx.predicates_of(method).instantiate(tcx, args) } - _ => return DUMMY_SP, + _ => return None, }; - // Check whether one of the where-bounds requires the closure to impl `Fn[Mut]`. + // Check whether one of the where-bounds requires the closure to impl `Fn[Mut]` + // or `AsyncFn[Mut]`. for (pred, span) in predicates.predicates.iter().zip(predicates.spans.iter()) { - if let Some(clause) = pred.as_trait_clause() - && let ty::Closure(clause_closure_def_id, _) = clause.self_ty().skip_binder().kind() - && *clause_closure_def_id == def_id - && (tcx.lang_items().fn_mut_trait() == Some(clause.def_id()) - || tcx.lang_items().fn_trait() == Some(clause.def_id())) - { - // Found `` - // We point at the `Fn()` or `FnMut()` bound that coerced the closure, which - // could be changed to `FnOnce()` to avoid the move error. - return *span; + let dominated_by_fn_trait = self + .closure_clause_kind(*pred, def_id, asyncness) + .is_some_and(|kind| matches!(kind, ty::ClosureKind::Fn | ty::ClosureKind::FnMut)); + if dominated_by_fn_trait { + // Found `` or + // ``. + // We point at the bound that coerced the closure, which could be changed + // to `FnOnce()` or `AsyncFnOnce()` to avoid the move error. + return Some(*span); } } - DUMMY_SP + None + } + + /// If `pred` is a trait clause binding the closure `def_id` to `Fn`/`FnMut`/`FnOnce` + /// (or their async equivalents based on `asyncness`), returns the corresponding + /// `ClosureKind`. Otherwise returns `None`. + fn closure_clause_kind( + &self, + pred: ty::Clause<'tcx>, + def_id: DefId, + asyncness: ty::Asyncness, + ) -> Option { + let tcx = self.infcx.tcx; + let clause = pred.as_trait_clause()?; + let kind = match asyncness { + ty::Asyncness::Yes => tcx.async_fn_trait_kind_from_def_id(clause.def_id()), + ty::Asyncness::No => tcx.fn_trait_kind_from_def_id(clause.def_id()), + }?; + match clause.self_ty().skip_binder().kind() { + ty::Closure(id, _) | ty::CoroutineClosure(id, _) if *id == def_id => Some(kind), + _ => None, + } } fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diag<'_>, span: Span) { diff --git a/tests/ui/async-await/async-closures/move-from-async-fn-bound.rs b/tests/ui/async-await/async-closures/move-from-async-fn-bound.rs new file mode 100644 index 000000000000..fbd8aac2515b --- /dev/null +++ b/tests/ui/async-await/async-closures/move-from-async-fn-bound.rs @@ -0,0 +1,13 @@ +//@ edition:2021 +// Test that a by-ref `AsyncFn` closure gets an error when it tries to +// consume a value, with a helpful diagnostic pointing to the bound. + +fn call(_: F) where F: AsyncFn() {} + +fn main() { + let y = vec![format!("World")]; + call(async || { + //~^ ERROR cannot move out of `y`, a captured variable in an `AsyncFn` closure + y.into_iter(); + }); +} diff --git a/tests/ui/async-await/async-closures/move-from-async-fn-bound.stderr b/tests/ui/async-await/async-closures/move-from-async-fn-bound.stderr new file mode 100644 index 000000000000..1a881db2a37d --- /dev/null +++ b/tests/ui/async-await/async-closures/move-from-async-fn-bound.stderr @@ -0,0 +1,30 @@ +error[E0507]: cannot move out of `y`, a captured variable in an `AsyncFn` closure + --> $DIR/move-from-async-fn-bound.rs:9:10 + | +LL | let y = vec![format!("World")]; + | - captured outer variable +LL | call(async || { + | ^^^^^^^^ + | | + | captured by this `AsyncFn` closure + | `y` is moved here +LL | +LL | y.into_iter(); + | - + | | + | variable moved due to use in coroutine + | move occurs because `y` has type `Vec`, which does not implement the `Copy` trait + | +help: `AsyncFn` and `AsyncFnMut` closures require captured values to be able to be consumed multiple times, but `AsyncFnOnce` closures may consume them only once + --> $DIR/move-from-async-fn-bound.rs:5:27 + | +LL | fn call(_: F) where F: AsyncFn() {} + | ^^^^^^^^^ +help: consider cloning the value if the performance cost is acceptable + | +LL | y.clone().into_iter(); + | ++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0507`. From 457148406f7fbeaee433d9b966d458a6033b4758 Mon Sep 17 00:00:00 2001 From: lolbinarycat Date: Wed, 28 Jan 2026 12:38:09 -0600 Subject: [PATCH 183/978] Refer to debug-logging bootstrap config by its full path. --- src/doc/rustc-dev-guide/src/tracing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tracing.md b/src/doc/rustc-dev-guide/src/tracing.md index 4d52f9c86508..1005ad2c2346 100644 --- a/src/doc/rustc-dev-guide/src/tracing.md +++ b/src/doc/rustc-dev-guide/src/tracing.md @@ -183,7 +183,7 @@ rustc. While calls to `error!`, `warn!` and `info!` are included in every build of the compiler, calls to `debug!` and `trace!` are only included in the program if -`debug-logging=true` is turned on in bootstrap.toml (it is +`rust.debug-logging=true` is turned on in bootstrap.toml (it is turned off by default), so if you don't see `DEBUG` logs, especially if you run the compiler with `RUSTC_LOG=rustc rustc some.rs` and only see `INFO` logs, make sure that `debug-logging=true` is turned on in your From fb995ef5b3731fb627653a93cf54cea5ad1783ed Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 9 Dec 2025 14:56:56 -0600 Subject: [PATCH 184/978] test(frontmatter): Show behavior for straw cr --- tests/ui/frontmatter/content-cr.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/ui/frontmatter/content-cr.rs diff --git a/tests/ui/frontmatter/content-cr.rs b/tests/ui/frontmatter/content-cr.rs new file mode 100644 index 000000000000..768282fc2b93 --- /dev/null +++ b/tests/ui/frontmatter/content-cr.rs @@ -0,0 +1,11 @@ +--- +package.name = " " +package.description = "é" +--- + +// ignore-tidy-cr +//@ check-pass + +#![feature(frontmatter)] + +pub fn main() {} From e9122481a4e8a98b76b9c8668d3973d867f1bf6b Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 9 Dec 2025 15:56:10 -0600 Subject: [PATCH 185/978] refactor(parse): Be consistent in naming --- compiler/rustc_parse/src/lexer/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 7c969dd7f9f4..6c9ecd75cdbc 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -598,9 +598,9 @@ impl<'psess, 'src> Lexer<'psess, 'src> { let s = self.str_from(start); let real_start = s.find("---").unwrap(); let frontmatter_opening_pos = BytePos(real_start as u32) + start; - let s_new = &s[real_start..]; - let within = s_new.trim_start_matches('-'); - let len_opening = s_new.len() - within.len(); + let real_s = &s[real_start..]; + let within = real_s.trim_start_matches('-'); + let len_opening = real_s.len() - within.len(); let frontmatter_opening_end_pos = frontmatter_opening_pos + BytePos(len_opening as u32); if has_invalid_preceding_whitespace { From 053b947aa910c500c5da3ada8b11bd50d3457ffb Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 9 Dec 2025 16:02:32 -0600 Subject: [PATCH 186/978] refactor(parse): Consistently use real_s --- compiler/rustc_parse/src/lexer/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 6c9ecd75cdbc..4fbc8f3938ad 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -615,7 +615,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { } if invalid_infostring { - let line_end = s[real_start..].find('\n').unwrap_or(s[real_start..].len()); + let line_end = real_s.find('\n').unwrap_or(real_s.len()); let span = self.mk_sp( frontmatter_opening_end_pos, frontmatter_opening_pos + BytePos(line_end as u32), From dd5539251c3a5eb6ad33b036d79b3f47238cb1ab Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 9 Dec 2025 16:11:43 -0600 Subject: [PATCH 187/978] refactor(parse): Use a common frame of reference --- compiler/rustc_parse/src/lexer/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 4fbc8f3938ad..4d0139e179f4 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -623,10 +623,10 @@ impl<'psess, 'src> Lexer<'psess, 'src> { self.dcx().emit_err(errors::FrontmatterInvalidInfostring { span }); } - let last_line_start = within.rfind('\n').map_or(0, |i| i + 1); - let last_line = &within[last_line_start..]; + let last_line_start = real_s.rfind('\n').map_or(0, |i| i + 1); + let last_line = &real_s[last_line_start..]; let last_line_trimmed = last_line.trim_start_matches(is_horizontal_whitespace); - let last_line_start_pos = frontmatter_opening_end_pos + BytePos(last_line_start as u32); + let last_line_start_pos = frontmatter_opening_pos + BytePos(last_line_start as u32); let frontmatter_span = self.mk_sp(frontmatter_opening_pos, self.pos); self.psess.gated_spans.gate(sym::frontmatter, frontmatter_span); From 52d4ef12a88ce0ead3cc5ac96b6778e3a33b3583 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 9 Dec 2025 15:54:26 -0600 Subject: [PATCH 188/978] fix(parser): Disallow CR in frontmatter T-lang came back on the stabilization PR asking for CR to be disallowed to leave room for all stray CRs to be rejected in the future. At that point, the test can remain but the implementation can be removed. If that plan does not go through, we'll need to re-evaluate - whether this is more lint-like and should defer to the calling tool that is managing the frontmatter - how much Rust should treat the frontmatter as Rust and apply the same grammar restrictions of "no stray CR" (like raw string literals) --- compiler/rustc_parse/messages.ftl | 3 ++- compiler/rustc_parse/src/errors.rs | 7 +++++++ compiler/rustc_parse/src/lexer/mod.rs | 10 +++++++++- tests/ui/frontmatter/content-cr.rs | 3 +-- tests/ui/frontmatter/content-cr.stderr | 8 ++++++++ 5 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 tests/ui/frontmatter/content-cr.stderr diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 449d0b964fd4..3f3300117460 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -98,6 +98,8 @@ parse_bare_cr = {$double_quotes -> } .escape = escape the character +parse_bare_cr_in_frontmatter = bare CR not allowed in frontmatter + parse_bare_cr_in_raw_string = bare CR not allowed in raw string parse_binder_and_polarity = `for<...>` binder not allowed with `{$polarity}` trait polarity modifier @@ -352,7 +354,6 @@ parse_frontmatter_length_mismatch = frontmatter close does not match the opening parse_frontmatter_too_many_dashes = too many `-` symbols: frontmatter openings may be delimited by up to 255 `-` symbols, but found {$len_opening} parse_frontmatter_unclosed = unclosed frontmatter .note = frontmatter opening here was not closed - parse_function_body_equals_expr = function body cannot be `= expression;` .suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;` diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 42327c7e343d..4e789a321649 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -829,6 +829,13 @@ pub(crate) struct FrontmatterTooManyDashes { pub len_opening: usize, } +#[derive(Diagnostic)] +#[diag(parse_bare_cr_in_frontmatter)] +pub(crate) struct BareCrFrontmatter { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(parse_leading_plus_not_supported)] pub(crate) struct LeadingPlusNotSupported { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 4d0139e179f4..f9bf50de091a 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -614,8 +614,8 @@ impl<'psess, 'src> Lexer<'psess, 'src> { }); } + let line_end = real_s.find('\n').unwrap_or(real_s.len()); if invalid_infostring { - let line_end = real_s.find('\n').unwrap_or(real_s.len()); let span = self.mk_sp( frontmatter_opening_end_pos, frontmatter_opening_pos + BytePos(line_end as u32), @@ -624,6 +624,14 @@ impl<'psess, 'src> Lexer<'psess, 'src> { } let last_line_start = real_s.rfind('\n').map_or(0, |i| i + 1); + + let content = &real_s[line_end..last_line_start]; + if let Some(cr_offset) = content.find('\r') { + let cr_pos = start + BytePos((real_start + line_end + cr_offset) as u32); + let span = self.mk_sp(cr_pos, cr_pos + BytePos(1 as u32)); + self.dcx().emit_err(errors::BareCrFrontmatter { span }); + } + let last_line = &real_s[last_line_start..]; let last_line_trimmed = last_line.trim_start_matches(is_horizontal_whitespace); let last_line_start_pos = frontmatter_opening_pos + BytePos(last_line_start as u32); diff --git a/tests/ui/frontmatter/content-cr.rs b/tests/ui/frontmatter/content-cr.rs index 768282fc2b93..71bede928f37 100644 --- a/tests/ui/frontmatter/content-cr.rs +++ b/tests/ui/frontmatter/content-cr.rs @@ -1,10 +1,9 @@ --- -package.name = " " +package.name = " " # //~ ERROR bare CR not allowed in frontmatter package.description = "é" --- // ignore-tidy-cr -//@ check-pass #![feature(frontmatter)] diff --git a/tests/ui/frontmatter/content-cr.stderr b/tests/ui/frontmatter/content-cr.stderr new file mode 100644 index 000000000000..d59b899cc4c3 --- /dev/null +++ b/tests/ui/frontmatter/content-cr.stderr @@ -0,0 +1,8 @@ +error: bare CR not allowed in frontmatter + --> $DIR/content-cr.rs:2:17 + | +LL | package.name = "␍" # + | ^ + +error: aborting due to 1 previous error + From 4a6325de8ddea6e5a1ef148be919a12420257307 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 28 Jan 2026 14:07:36 -0500 Subject: [PATCH 189/978] Set gcc language name and compilation unit name --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- libgccjit.version | 2 +- src/context.rs | 7 +++++++ src/lib.rs | 2 ++ 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dea1207b05da..3b497f83cc0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "3.1.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff80f4d6d0749eab3a69122210b3a1fdd52edb6162781aadd7c4842e26983683" +checksum = "ef03c8ae23826a0755b980999a553a262c61f2f585245e647192d95bf09eee79" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f81d901767ddba371a619fa9bba657066a4d3c5607ee69bbb557c1c5ba9bf85" +checksum = "0ff511da413e4a5da6f09607748395ba37525e01ba7d322cbec3efc43095dd60" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 18847f50d46a..97735e49e84b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ default = ["master"] [dependencies] object = { version = "0.37.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "3.1.1", features = ["dlopen"] } +gccjit = { version = "3.2.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. diff --git a/libgccjit.version b/libgccjit.version index bab62f642365..e49b36557350 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -0081ca6631abdfa02bf42bc85aaf507b8a0e6beb +586d798e864fb33b1b4e842c5493a653841a7c02 diff --git a/src/context.rs b/src/context.rs index dbb89a4ff7db..6143d27725e8 100644 --- a/src/context.rs +++ b/src/context.rs @@ -19,6 +19,8 @@ use rustc_middle::ty::layout::{ }; use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt}; use rustc_session::Session; +#[cfg(feature = "master")] +use rustc_session::config::DebugInfo; use rustc_span::source_map::respan; use rustc_span::{DUMMY_SP, Span}; use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi}; @@ -143,6 +145,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { supports_f64_type: bool, supports_f128_type: bool, ) -> Self { + #[cfg(feature = "master")] + if tcx.sess.opts.debuginfo != DebugInfo::None { + context.set_filename(codegen_unit.name().as_str()); + } + let create_type = |ctype, rust_type| { let layout = tcx .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(rust_type)) diff --git a/src/lib.rs b/src/lib.rs index 96d3a0024f41..a8265cc86fa1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -240,6 +240,8 @@ impl CodegenBackend for GccCodegenBackend { #[cfg(feature = "master")] { + gccjit::set_lang_name(c"GNU Rust"); + let target_cpu = target_cpu(sess); // Get the second TargetInfo with the correct CPU features by setting the arch. From 91850e90de096eb37364358e8a4eb7e0b30284ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Wed, 28 Jan 2026 22:05:10 +0100 Subject: [PATCH 190/978] Avoid `unsafe fn` in aarch64, powerpc and s390x tests --- .../crates/core_arch/src/aarch64/neon/mod.rs | 264 ++++----- .../crates/core_arch/src/powerpc/altivec.rs | 528 ++++++++++-------- .../crates/core_arch/src/powerpc/vsx.rs | 34 +- .../crates/core_arch/src/s390x/vector.rs | 135 +++-- 4 files changed, 536 insertions(+), 425 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs index b172b57f3254..bac45742393c 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs @@ -569,47 +569,46 @@ mod tests { use crate::core_arch::aarch64::test_support::*; use crate::core_arch::arm_shared::test_support::*; use crate::core_arch::{aarch64::neon::*, aarch64::*, simd::*}; - use std::mem::transmute; use stdarch_test::simd_test; #[simd_test(enable = "neon")] - unsafe fn test_vadd_f64() { - let a = 1.; - let b = 8.; - let e = 9.; - let r: f64 = transmute(vadd_f64(transmute(a), transmute(b))); + fn test_vadd_f64() { + let a = f64x1::from_array([1.]); + let b = f64x1::from_array([8.]); + let e = f64x1::from_array([9.]); + let r = f64x1::from(vadd_f64(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vaddq_f64() { + fn test_vaddq_f64() { let a = f64x2::new(1., 2.); let b = f64x2::new(8., 7.); let e = f64x2::new(9., 9.); - let r: f64x2 = transmute(vaddq_f64(transmute(a), transmute(b))); + let r = f64x2::from(vaddq_f64(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vadd_s64() { - let a = 1_i64; - let b = 8_i64; - let e = 9_i64; - let r: i64 = transmute(vadd_s64(transmute(a), transmute(b))); + fn test_vadd_s64() { + let a = i64x1::from_array([1]); + let b = i64x1::from_array([8]); + let e = i64x1::from_array([9]); + let r = i64x1::from(vadd_s64(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vadd_u64() { - let a = 1_u64; - let b = 8_u64; - let e = 9_u64; - let r: u64 = transmute(vadd_u64(transmute(a), transmute(b))); + fn test_vadd_u64() { + let a = u64x1::from_array([1]); + let b = u64x1::from_array([8]); + let e = u64x1::from_array([9]); + let r = u64x1::from(vadd_u64(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vaddd_s64() { + fn test_vaddd_s64() { let a = 1_i64; let b = 8_i64; let e = 9_i64; @@ -618,7 +617,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vaddd_u64() { + fn test_vaddd_u64() { let a = 1_u64; let b = 8_u64; let e = 9_u64; @@ -627,25 +626,25 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vext_p64() { - let a: i64x1 = i64x1::new(0); - let b: i64x1 = i64x1::new(1); - let e: i64x1 = i64x1::new(0); - let r: i64x1 = transmute(vext_p64::<0>(transmute(a), transmute(b))); + fn test_vext_p64() { + let a = u64x1::new(0); + let b = u64x1::new(1); + let e = u64x1::new(0); + let r = u64x1::from(vext_p64::<0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vext_f64() { - let a: f64x1 = f64x1::new(0.); - let b: f64x1 = f64x1::new(1.); - let e: f64x1 = f64x1::new(0.); - let r: f64x1 = transmute(vext_f64::<0>(transmute(a), transmute(b))); + fn test_vext_f64() { + let a = f64x1::new(0.); + let b = f64x1::new(1.); + let e = f64x1::new(0.); + let r = f64x1::from(vext_f64::<0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vshld_n_s64() { + fn test_vshld_n_s64() { let a: i64 = 1; let e: i64 = 4; let r: i64 = vshld_n_s64::<2>(a); @@ -653,7 +652,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vshld_n_u64() { + fn test_vshld_n_u64() { let a: u64 = 1; let e: u64 = 4; let r: u64 = vshld_n_u64::<2>(a); @@ -661,7 +660,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vshrd_n_s64() { + fn test_vshrd_n_s64() { let a: i64 = 4; let e: i64 = 1; let r: i64 = vshrd_n_s64::<2>(a); @@ -669,7 +668,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vshrd_n_u64() { + fn test_vshrd_n_u64() { let a: u64 = 4; let e: u64 = 1; let r: u64 = vshrd_n_u64::<2>(a); @@ -677,7 +676,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vsrad_n_s64() { + fn test_vsrad_n_s64() { let a: i64 = 1; let b: i64 = 4; let e: i64 = 2; @@ -686,7 +685,7 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vsrad_n_u64() { + fn test_vsrad_n_u64() { let a: u64 = 1; let b: u64 = 4; let e: u64 = 2; @@ -695,293 +694,300 @@ mod tests { } #[simd_test(enable = "neon")] - unsafe fn test_vdup_n_f64() { + fn test_vdup_n_f64() { let a: f64 = 3.3; let e = f64x1::new(3.3); - let r: f64x1 = transmute(vdup_n_f64(a)); + let r = f64x1::from(vdup_n_f64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdup_n_p64() { + fn test_vdup_n_p64() { let a: u64 = 3; let e = u64x1::new(3); - let r: u64x1 = transmute(vdup_n_p64(a)); + let r = u64x1::from(vdup_n_p64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_n_f64() { + fn test_vdupq_n_f64() { let a: f64 = 3.3; let e = f64x2::new(3.3, 3.3); - let r: f64x2 = transmute(vdupq_n_f64(a)); + let r = f64x2::from(vdupq_n_f64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vdupq_n_p64() { + fn test_vdupq_n_p64() { let a: u64 = 3; let e = u64x2::new(3, 3); - let r: u64x2 = transmute(vdupq_n_p64(a)); + let r = u64x2::from(vdupq_n_p64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmov_n_p64() { + fn test_vmov_n_p64() { let a: u64 = 3; let e = u64x1::new(3); - let r: u64x1 = transmute(vmov_n_p64(a)); + let r = u64x1::from(vmov_n_p64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmov_n_f64() { + fn test_vmov_n_f64() { let a: f64 = 3.3; let e = f64x1::new(3.3); - let r: f64x1 = transmute(vmov_n_f64(a)); + let r = f64x1::from(vmov_n_f64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmovq_n_p64() { + fn test_vmovq_n_p64() { let a: u64 = 3; let e = u64x2::new(3, 3); - let r: u64x2 = transmute(vmovq_n_p64(a)); + let r = u64x2::from(vmovq_n_p64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vmovq_n_f64() { + fn test_vmovq_n_f64() { let a: f64 = 3.3; let e = f64x2::new(3.3, 3.3); - let r: f64x2 = transmute(vmovq_n_f64(a)); + let r = f64x2::from(vmovq_n_f64(a)); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vget_high_f64() { + fn test_vget_high_f64() { let a = f64x2::new(1.0, 2.0); let e = f64x1::new(2.0); - let r: f64x1 = transmute(vget_high_f64(transmute(a))); + let r = f64x1::from(vget_high_f64(a.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vget_high_p64() { + fn test_vget_high_p64() { let a = u64x2::new(1, 2); let e = u64x1::new(2); - let r: u64x1 = transmute(vget_high_p64(transmute(a))); + let r = u64x1::from(vget_high_p64(a.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vget_low_f64() { + fn test_vget_low_f64() { let a = f64x2::new(1.0, 2.0); let e = f64x1::new(1.0); - let r: f64x1 = transmute(vget_low_f64(transmute(a))); + let r = f64x1::from(vget_low_f64(a.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vget_low_p64() { + fn test_vget_low_p64() { let a = u64x2::new(1, 2); let e = u64x1::new(1); - let r: u64x1 = transmute(vget_low_p64(transmute(a))); + let r = u64x1::from(vget_low_p64(a.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vget_lane_f64() { + fn test_vget_lane_f64() { let v = f64x1::new(1.0); - let r = vget_lane_f64::<0>(transmute(v)); + let r = vget_lane_f64::<0>(v.into()); assert_eq!(r, 1.0); } #[simd_test(enable = "neon")] - unsafe fn test_vgetq_lane_f64() { + fn test_vgetq_lane_f64() { let v = f64x2::new(0.0, 1.0); - let r = vgetq_lane_f64::<1>(transmute(v)); + let r = vgetq_lane_f64::<1>(v.into()); assert_eq!(r, 1.0); - let r = vgetq_lane_f64::<0>(transmute(v)); + let r = vgetq_lane_f64::<0>(v.into()); assert_eq!(r, 0.0); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_s64() { - let a: i64x1 = i64x1::new(1); - let b: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let r: i64x1 = transmute(vcopy_lane_s64::<0, 0>(transmute(a), transmute(b))); + fn test_vcopy_lane_s64() { + let a = i64x1::new(1); + let b = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let e = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let r = i64x1::from(vcopy_lane_s64::<0, 0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_u64() { - let a: u64x1 = u64x1::new(1); - let b: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcopy_lane_u64::<0, 0>(transmute(a), transmute(b))); + fn test_vcopy_lane_u64() { + let a = u64x1::new(1); + let b = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let e = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r = u64x1::from(vcopy_lane_u64::<0, 0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_p64() { - let a: i64x1 = i64x1::new(1); - let b: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let r: i64x1 = transmute(vcopy_lane_p64::<0, 0>(transmute(a), transmute(b))); + fn test_vcopy_lane_p64() { + let a = u64x1::new(1); + let b = u64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let e = u64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let r = u64x1::from(vcopy_lane_p64::<0, 0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_lane_f64() { - let a: f64 = 1.; - let b: f64 = 0.; - let e: f64 = 0.; - let r: f64 = transmute(vcopy_lane_f64::<0, 0>(transmute(a), transmute(b))); + fn test_vcopy_lane_f64() { + let a = f64x1::from_array([1.]); + let b = f64x1::from_array([0.]); + let e = f64x1::from_array([0.]); + let r = f64x1::from(vcopy_lane_f64::<0, 0>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_s64() { - let a: i64x1 = i64x1::new(1); - let b: i64x2 = i64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let r: i64x1 = transmute(vcopy_laneq_s64::<0, 1>(transmute(a), transmute(b))); + fn test_vcopy_laneq_s64() { + let a = i64x1::new(1); + let b = i64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); + let e = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let r = i64x1::from(vcopy_laneq_s64::<0, 1>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_u64() { - let a: u64x1 = u64x1::new(1); - let b: u64x2 = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); - let e: u64x1 = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); - let r: u64x1 = transmute(vcopy_laneq_u64::<0, 1>(transmute(a), transmute(b))); + fn test_vcopy_laneq_u64() { + let a = u64x1::new(1); + let b = u64x2::new(0, 0xFF_FF_FF_FF_FF_FF_FF_FF); + let e = u64x1::new(0xFF_FF_FF_FF_FF_FF_FF_FF); + let r = u64x1::from(vcopy_laneq_u64::<0, 1>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_p64() { - let a: i64x1 = i64x1::new(1); - let b: i64x2 = i64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); - let e: i64x1 = i64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); - let r: i64x1 = transmute(vcopy_laneq_p64::<0, 1>(transmute(a), transmute(b))); + fn test_vcopy_laneq_p64() { + let a = u64x1::new(1); + let b = u64x2::new(0, 0x7F_FF_FF_FF_FF_FF_FF_FF); + let e = u64x1::new(0x7F_FF_FF_FF_FF_FF_FF_FF); + let r = u64x1::from(vcopy_laneq_p64::<0, 1>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vcopy_laneq_f64() { - let a: f64 = 1.; - let b: f64x2 = f64x2::new(0., 0.5); - let e: f64 = 0.5; - let r: f64 = transmute(vcopy_laneq_f64::<0, 1>(transmute(a), transmute(b))); + fn test_vcopy_laneq_f64() { + let a = f64x1::from_array([1.]); + let b = f64x2::from_array([0., 0.5]); + let e = f64x1::from_array([0.5]); + let r = f64x1::from(vcopy_laneq_f64::<0, 1>(a.into(), b.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vbsl_f64() { + fn test_vbsl_f64() { let a = u64x1::new(0x8000000000000000); let b = f64x1::new(-1.23f64); let c = f64x1::new(2.34f64); let e = f64x1::new(-2.34f64); - let r: f64x1 = transmute(vbsl_f64(transmute(a), transmute(b), transmute(c))); + let r = f64x1::from(vbsl_f64(a.into(), b.into(), c.into())); assert_eq!(r, e); } + #[simd_test(enable = "neon")] - unsafe fn test_vbsl_p64() { + fn test_vbsl_p64() { let a = u64x1::new(1); let b = u64x1::new(u64::MAX); let c = u64x1::new(u64::MIN); let e = u64x1::new(1); - let r: u64x1 = transmute(vbsl_p64(transmute(a), transmute(b), transmute(c))); + let r = u64x1::from(vbsl_p64(a.into(), b.into(), c.into())); assert_eq!(r, e); } + #[simd_test(enable = "neon")] - unsafe fn test_vbslq_f64() { + fn test_vbslq_f64() { let a = u64x2::new(1, 0x8000000000000000); let b = f64x2::new(f64::MAX, -1.23f64); let c = f64x2::new(f64::MIN, 2.34f64); let e = f64x2::new(f64::MIN, -2.34f64); - let r: f64x2 = transmute(vbslq_f64(transmute(a), transmute(b), transmute(c))); + let r = f64x2::from(vbslq_f64(a.into(), b.into(), c.into())); assert_eq!(r, e); } + #[simd_test(enable = "neon")] - unsafe fn test_vbslq_p64() { + fn test_vbslq_p64() { let a = u64x2::new(u64::MAX, 1); let b = u64x2::new(u64::MAX, u64::MAX); let c = u64x2::new(u64::MIN, u64::MIN); let e = u64x2::new(u64::MAX, 1); - let r: u64x2 = transmute(vbslq_p64(transmute(a), transmute(b), transmute(c))); + let r = u64x2::from(vbslq_p64(a.into(), b.into(), c.into())); assert_eq!(r, e); } #[simd_test(enable = "neon")] - unsafe fn test_vld1_f64() { + fn test_vld1_f64() { let a: [f64; 2] = [0., 1.]; let e = f64x1::new(1.); - let r: f64x1 = transmute(vld1_f64(a[1..].as_ptr())); + let r = unsafe { f64x1::from(vld1_f64(a[1..].as_ptr())) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_f64() { + fn test_vld1q_f64() { let a: [f64; 3] = [0., 1., 2.]; let e = f64x2::new(1., 2.); - let r: f64x2 = transmute(vld1q_f64(a[1..].as_ptr())); + let r = unsafe { f64x2::from(vld1q_f64(a[1..].as_ptr())) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vld1_dup_f64() { + fn test_vld1_dup_f64() { let a: [f64; 2] = [1., 42.]; let e = f64x1::new(42.); - let r: f64x1 = transmute(vld1_dup_f64(a[1..].as_ptr())); + let r = unsafe { f64x1::from(vld1_dup_f64(a[1..].as_ptr())) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_dup_f64() { + fn test_vld1q_dup_f64() { let elem: f64 = 42.; let e = f64x2::new(42., 42.); - let r: f64x2 = transmute(vld1q_dup_f64(&elem)); + let r = unsafe { f64x2::from(vld1q_dup_f64(&elem)) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vld1_lane_f64() { + fn test_vld1_lane_f64() { let a = f64x1::new(0.); let elem: f64 = 42.; let e = f64x1::new(42.); - let r: f64x1 = transmute(vld1_lane_f64::<0>(&elem, transmute(a))); + let r = unsafe { f64x1::from(vld1_lane_f64::<0>(&elem, a.into())) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vld1q_lane_f64() { + fn test_vld1q_lane_f64() { let a = f64x2::new(0., 1.); let elem: f64 = 42.; let e = f64x2::new(0., 42.); - let r: f64x2 = transmute(vld1q_lane_f64::<1>(&elem, transmute(a))); + let r = unsafe { f64x2::from(vld1q_lane_f64::<1>(&elem, a.into())) }; assert_eq!(r, e) } #[simd_test(enable = "neon")] - unsafe fn test_vst1_f64() { + fn test_vst1_f64() { let mut vals = [0_f64; 2]; let a = f64x1::new(1.); - vst1_f64(vals[1..].as_mut_ptr(), transmute(a)); + unsafe { + vst1_f64(vals[1..].as_mut_ptr(), a.into()); + } assert_eq!(vals[0], 0.); assert_eq!(vals[1], 1.); } #[simd_test(enable = "neon")] - unsafe fn test_vst1q_f64() { + fn test_vst1q_f64() { let mut vals = [0_f64; 3]; let a = f64x2::new(1., 2.); - vst1q_f64(vals[1..].as_mut_ptr(), transmute(a)); + unsafe { + vst1q_f64(vals[1..].as_mut_ptr(), a.into()); + } assert_eq!(vals[0], 0.); assert_eq!(vals[1], 1.); diff --git a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs index fb1a9d8ed9e2..7786a6731b4c 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs @@ -47,6 +47,54 @@ types! { pub struct vector_float(4 x f32); } +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for vector_bool_char { + #[inline] + fn from(value: m8x16) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for m8x16 { + #[inline] + fn from(value: vector_bool_char) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for vector_bool_short { + #[inline] + fn from(value: m16x8) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for m16x8 { + #[inline] + fn from(value: vector_bool_short) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for vector_bool_int { + #[inline] + fn from(value: m32x4) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for m32x4 { + #[inline] + fn from(value: vector_bool_int) -> Self { + unsafe { transmute(value) } + } +} + #[allow(improper_ctypes)] unsafe extern "C" { #[link_name = "llvm.ppc.altivec.lvx"] @@ -4653,22 +4701,22 @@ mod tests { }; { $name: ident, $fn:ident, $ty: ident -> $ty_out: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); - let b: s_t_l!($ty) = transmute($ty::new($($b),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); + let b: s_t_l!($ty) = $ty::new($($b),+).into(); let d = $ty_out::new($($d),+); - let r : $ty_out = transmute($fn(a, b)); + let r = $ty_out::from(unsafe { $fn(a, b) }); assert_eq!(d, r); } }; { $name: ident, $fn:ident, $ty: ident -> $ty_out: ident, [$($a:expr),+], [$($b:expr),+], $d:expr } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); - let b: s_t_l!($ty) = transmute($ty::new($($b),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); + let b: s_t_l!($ty) = $ty::new($($b),+).into(); - let r : $ty_out = transmute($fn(a, b)); + let r = $ty_out::from(unsafe { $fn(a, b) }); assert_eq!($d, r); } } @@ -4677,11 +4725,11 @@ mod tests { macro_rules! test_vec_1 { { $name: ident, $fn:ident, f32x4, [$($a:expr),+], ~[$($d:expr),+] } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: vector_float = transmute(f32x4::new($($a),+)); + fn $name() { + let a = vector_float::from(f32x4::new($($a),+)); - let d: vector_float = transmute(f32x4::new($($d),+)); - let r = transmute(vec_cmple(vec_abs(vec_sub($fn(a), d)), vec_splats(f32::EPSILON))); + let d = vector_float::from(f32x4::new($($d),+)); + let r = m32x4::from(unsafe { vec_cmple(vec_abs(vec_sub($fn(a), d)), vec_splats(f32::EPSILON)) }); let e = m32x4::new(true, true, true, true); assert_eq!(e, r); } @@ -4691,18 +4739,18 @@ mod tests { }; { $name: ident, $fn:ident, $ty: ident -> $ty_out: ident, [$($a:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); let d = $ty_out::new($($d),+); - let r : $ty_out = transmute($fn(a)); + let r = $ty_out::from(unsafe { $fn(a) }); assert_eq!(d, r); } } } #[simd_test(enable = "altivec")] - unsafe fn test_vec_ld() { + fn test_vec_ld() { let pat = [ u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), u8x16::new( @@ -4711,14 +4759,14 @@ mod tests { ]; for off in 0..16 { - let v: u8x16 = transmute(vec_ld(0, (pat.as_ptr() as *const u8).offset(off))); + let v = u8x16::from(unsafe { vec_ld(0, (pat.as_ptr() as *const u8).offset(off)) }); assert_eq!( v, u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) ); } for off in 16..32 { - let v: u8x16 = transmute(vec_ld(0, (pat.as_ptr() as *const u8).offset(off))); + let v = u8x16::from(unsafe { vec_ld(0, (pat.as_ptr() as *const u8).offset(off)) }); assert_eq!( v, u8x16::new( @@ -4729,7 +4777,7 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_xl() { + fn test_vec_xl() { let pat = [ u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), u8x16::new( @@ -4738,7 +4786,7 @@ mod tests { ]; for off in 0..16 { - let val: u8x16 = transmute(vec_xl(0, (pat.as_ptr() as *const u8).offset(off))); + let val = u8x16::from(unsafe { vec_xl(0, (pat.as_ptr() as *const u8).offset(off)) }); for i in 0..16 { let v = val.extract_dyn(i); assert_eq!(off as usize + i, v as usize); @@ -4747,14 +4795,16 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_xst() { - let v: vector_unsigned_char = transmute(u8x16::new( + fn test_vec_xst() { + let v = vector_unsigned_char::from(u8x16::new( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, )); for off in 0..16 { let mut buf = [0u8; 32]; - vec_xst(v, 0, (buf.as_mut_ptr() as *mut u8).offset(off)); + unsafe { + vec_xst(v, 0, (buf.as_mut_ptr() as *mut u8).offset(off)); + } for i in 0..16 { assert_eq!(i as u8, buf[off as usize..][i]); } @@ -4762,7 +4812,7 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_ldl() { + fn test_vec_ldl() { let pat = [ u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), u8x16::new( @@ -4771,14 +4821,14 @@ mod tests { ]; for off in 0..16 { - let v: u8x16 = transmute(vec_ldl(0, (pat.as_ptr() as *const u8).offset(off))); + let v = u8x16::from(unsafe { vec_ldl(0, (pat.as_ptr() as *const u8).offset(off)) }); assert_eq!( v, u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) ); } for off in 16..32 { - let v: u8x16 = transmute(vec_ldl(0, (pat.as_ptr() as *const u8).offset(off))); + let v = u8x16::from(unsafe { vec_ldl(0, (pat.as_ptr() as *const u8).offset(off)) }); assert_eq!( v, u8x16::new( @@ -4789,30 +4839,30 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_lde_u8() { + fn test_vec_lde_u8() { let pat = [u8x16::new( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, )]; for off in 0..16 { - let v: u8x16 = transmute(vec_lde(off, pat.as_ptr() as *const u8)); + let v = u8x16::from(unsafe { vec_lde(off, pat.as_ptr() as *const u8) }); assert_eq!(off as u8, v.extract_dyn(off as _)); } } #[simd_test(enable = "altivec")] - unsafe fn test_vec_lde_u16() { + fn test_vec_lde_u16() { let pat = [u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)]; for off in 0..8 { - let v: u16x8 = transmute(vec_lde(off * 2, pat.as_ptr() as *const u16)); + let v = u16x8::from(unsafe { vec_lde(off * 2, pat.as_ptr() as *const u16) }); assert_eq!(off as u16, v.extract_dyn(off as _)); } } #[simd_test(enable = "altivec")] - unsafe fn test_vec_lde_u32() { + fn test_vec_lde_u32() { let pat = [u32x4::new(0, 1, 2, 3)]; for off in 0..4 { - let v: u32x4 = transmute(vec_lde(off * 4, pat.as_ptr() as *const u32)); + let v = u32x4::from(unsafe { vec_lde(off * 4, pat.as_ptr() as *const u32) }); assert_eq!(off as u32, v.extract_dyn(off as _)); } } @@ -5818,9 +5868,9 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_cmpb() { - let a: vector_float = transmute(f32x4::new(0.1, 0.5, 0.6, 0.9)); - let b: vector_float = transmute(f32x4::new(-0.1, 0.5, -0.6, 0.9)); + fn test_vec_cmpb() { + let a = vector_float::from(f32x4::new(0.1, 0.5, 0.6, 0.9)); + let b = vector_float::from(f32x4::new(-0.1, 0.5, -0.6, 0.9)); let d = i32x4::new( -0b10000000000000000000000000000000, 0, @@ -5828,15 +5878,15 @@ mod tests { 0, ); - assert_eq!(d, transmute(vec_cmpb(a, b))); + assert_eq!(d, i32x4::from(unsafe { vec_cmpb(a, b) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_ceil() { - let a: vector_float = transmute(f32x4::new(0.1, 0.5, 0.6, 0.9)); + fn test_vec_ceil() { + let a = vector_float::from(f32x4::new(0.1, 0.5, 0.6, 0.9)); let d = f32x4::new(1.0, 1.0, 1.0, 1.0); - assert_eq!(d, transmute(vec_ceil(a))); + assert_eq!(d, f32x4::from(unsafe { vec_ceil(a) })); } test_vec_2! { test_vec_andc, vec_andc, i32x4, @@ -5926,11 +5976,11 @@ mod tests { macro_rules! test_vec_abs { { $name: ident, $ty: ident, $a: expr, $d: expr } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a = vec_splats($a); - let a: s_t_l!($ty) = vec_abs(a); + fn $name() { + let a = unsafe { vec_splats($a) }; + let a: s_t_l!($ty) = unsafe { vec_abs(a) }; let d = $ty::splat($d); - assert_eq!(d, transmute(a)); + assert_eq!(d, $ty::from(a)); } } } @@ -5943,11 +5993,11 @@ mod tests { macro_rules! test_vec_abss { { $name: ident, $ty: ident, $a: expr, $d: expr } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a = vec_splats($a); - let a: s_t_l!($ty) = vec_abss(a); + fn $name() { + let a = unsafe { vec_splats($a) }; + let a: s_t_l!($ty) = unsafe { vec_abss(a) }; let d = $ty::splat($d); - assert_eq!(d, transmute(a)); + assert_eq!(d, $ty::from(a)); } } } @@ -5959,10 +6009,10 @@ mod tests { macro_rules! test_vec_splats { { $name: ident, $ty: ident, $a: expr } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = vec_splats($a); + fn $name() { + let a: s_t_l!($ty) = unsafe { vec_splats($a) }; let d = $ty::splat($a); - assert_eq!(d, transmute(a)); + assert_eq!(d, $ty::from(a)); } } } @@ -5978,10 +6028,10 @@ mod tests { macro_rules! test_vec_splat { { $name: ident, $fun: ident, $ty: ident, $a: expr, $b: expr} => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a = $fun::<$a>(); + fn $name() { + let a = unsafe { $fun::<$a>() }; let d = $ty::splat($b); - assert_eq!(d, transmute(a)); + assert_eq!(d, $ty::from(a)); } } } @@ -6073,12 +6123,12 @@ mod tests { macro_rules! test_vec_min { { $name: ident, $ty: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); - let b: s_t_l!($ty) = transmute($ty::new($($b),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); + let b: s_t_l!($ty) = $ty::new($($b),+).into(); let d = $ty::new($($d),+); - let r : $ty = transmute(vec_min(a, b)); + let r = $ty::from(unsafe { vec_min(a, b) }); assert_eq!(d, r); } } @@ -6117,12 +6167,12 @@ mod tests { macro_rules! test_vec_max { { $name: ident, $ty: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); - let b: s_t_l!($ty) = transmute($ty::new($($b),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); + let b: s_t_l!($ty) = $ty::new($($b),+).into(); let d = $ty::new($($d),+); - let r : $ty = transmute(vec_max(a, b)); + let r = $ty::from(unsafe { vec_max(a, b) }); assert_eq!(d, r); } } @@ -6163,13 +6213,13 @@ mod tests { $shorttype:ident, $longtype:ident, [$($a:expr),+], [$($b:expr),+], [$($c:expr),+], [$($d:expr),+]} => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: $longtype = transmute($shorttype::new($($a),+)); - let b: $longtype = transmute($shorttype::new($($b),+)); - let c: vector_unsigned_char = transmute(u8x16::new($($c),+)); + fn $name() { + let a = $longtype::from($shorttype::new($($a),+)); + let b = $longtype::from($shorttype::new($($b),+)); + let c = vector_unsigned_char::from(u8x16::new($($c),+)); let d = $shorttype::new($($d),+); - let r: $shorttype = transmute(vec_perm(a, b, c)); + let r = $shorttype::from(unsafe { vec_perm(a, b, c) }); assert_eq!(d, r); } } @@ -6249,8 +6299,8 @@ mod tests { [0.0, 1.0, 1.0, 1.1]} #[simd_test(enable = "altivec")] - unsafe fn test_vec_madds() { - let a: vector_signed_short = transmute(i16x8::new( + fn test_vec_madds() { + let a = vector_signed_short::from(i16x8::new( 0 * 256, 1 * 256, 2 * 256, @@ -6260,19 +6310,19 @@ mod tests { 6 * 256, 7 * 256, )); - let b: vector_signed_short = transmute(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_signed_short = transmute(i16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); + let b = vector_signed_short::from(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_signed_short::from(i16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); let d = i16x8::new(0, 3, 6, 9, 12, 15, 18, 21); - assert_eq!(d, transmute(vec_madds(a, b, c))); + assert_eq!(d, i16x8::from(unsafe { vec_madds(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_madd_float() { - let a: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); - let b: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); - let c: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); + fn test_vec_madd_float() { + let a = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); + let b = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); + let c = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); let d = f32x4::new( 0.1 * 0.1 + 0.1, 0.2 * 0.2 + 0.2, @@ -6280,26 +6330,26 @@ mod tests { 0.4 * 0.4 + 0.4, ); - assert_eq!(d, transmute(vec_madd(a, b, c))); + assert_eq!(d, f32x4::from(unsafe { vec_madd(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_nmsub_float() { - let a: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); - let b: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); - let c: vector_float = transmute(f32x4::new(0.1, 0.2, 0.3, 0.4)); + fn test_vec_nmsub_float() { + let a = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); + let b = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); + let c = vector_float::from(f32x4::new(0.1, 0.2, 0.3, 0.4)); let d = f32x4::new( -(0.1 * 0.1 - 0.1), -(0.2 * 0.2 - 0.2), -(0.3 * 0.3 - 0.3), -(0.4 * 0.4 - 0.4), ); - assert_eq!(d, transmute(vec_nmsub(a, b, c))); + assert_eq!(d, f32x4::from(unsafe { vec_nmsub(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mradds() { - let a: vector_signed_short = transmute(i16x8::new( + fn test_vec_mradds() { + let a = vector_signed_short::from(i16x8::new( 0 * 256, 1 * 256, 2 * 256, @@ -6309,25 +6359,25 @@ mod tests { 6 * 256, 7 * 256, )); - let b: vector_signed_short = transmute(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_signed_short = transmute(i16x8::new(0, 1, 2, 3, 4, 5, 6, i16::MAX - 1)); + let b = vector_signed_short::from(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_signed_short::from(i16x8::new(0, 1, 2, 3, 4, 5, 6, i16::MAX - 1)); let d = i16x8::new(0, 3, 6, 9, 12, 15, 18, i16::MAX); - assert_eq!(d, transmute(vec_mradds(a, b, c))); + assert_eq!(d, i16x8::from(unsafe { vec_mradds(a, b, c) })); } macro_rules! test_vec_mladd { {$name:ident, $sa:ident, $la:ident, $sbc:ident, $lbc:ident, $sd:ident, [$($a:expr),+], [$($b:expr),+], [$($c:expr),+], [$($d:expr),+]} => { #[simd_test(enable = "altivec")] - unsafe fn $name() { - let a: $la = transmute($sa::new($($a),+)); - let b: $lbc = transmute($sbc::new($($b),+)); - let c = transmute($sbc::new($($c),+)); + fn $name() { + let a = $la::from($sa::new($($a),+)); + let b = $lbc::from($sbc::new($($b),+)); + let c = $sbc::new($($c),+).into(); let d = $sd::new($($d),+); - assert_eq!(d, transmute(vec_mladd(a, b, c))); + assert_eq!(d, $sd::from(unsafe { vec_mladd(a, b, c) })); } } } @@ -6335,24 +6385,24 @@ mod tests { test_vec_mladd! { test_vec_mladd_u16x8_u16x8, u16x8, vector_unsigned_short, u16x8, vector_unsigned_short, u16x8, [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 2, 6, 12, 20, 30, 42, 56] } - test_vec_mladd! { test_vec_mladd_u16x8_i16x8, u16x8, vector_unsigned_short, i16x8, vector_unsigned_short, i16x8, + test_vec_mladd! { test_vec_mladd_u16x8_i16x8, u16x8, vector_unsigned_short, i16x8, vector_signed_short, i16x8, [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 2, 6, 12, 20, 30, 42, 56] } test_vec_mladd! { test_vec_mladd_i16x8_u16x8, i16x8, vector_signed_short, u16x8, vector_unsigned_short, i16x8, [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 2, 6, 12, 20, 30, 42, 56] } - test_vec_mladd! { test_vec_mladd_i16x8_i16x8, i16x8, vector_signed_short, i16x8, vector_unsigned_short, i16x8, + test_vec_mladd! { test_vec_mladd_i16x8_i16x8, i16x8, vector_signed_short, i16x8, vector_signed_short, i16x8, [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7], [0, 2, 6, 12, 20, 30, 42, 56] } #[simd_test(enable = "altivec")] - unsafe fn test_vec_msum_unsigned_char() { - let a: vector_unsigned_char = - transmute(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); - let b: vector_unsigned_char = transmute(u8x16::new( + fn test_vec_msum_unsigned_char() { + let a = + vector_unsigned_char::from(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); + let b = vector_unsigned_char::from(u8x16::new( 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, )); - let c: vector_unsigned_int = transmute(u32x4::new(0, 1, 2, 3)); + let c = vector_unsigned_int::from(u32x4::new(0, 1, 2, 3)); let d = u32x4::new( (0 + 1 + 2 + 3) * 255 + 0, (4 + 5 + 6 + 7) * 255 + 1, @@ -6360,17 +6410,17 @@ mod tests { (4 + 5 + 6 + 7) * 255 + 3, ); - assert_eq!(d, transmute(vec_msum(a, b, c))); + assert_eq!(d, u32x4::from(unsafe { vec_msum(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_msum_signed_char() { - let a: vector_signed_char = transmute(i8x16::new( + fn test_vec_msum_signed_char() { + let a = vector_signed_char::from(i8x16::new( 0, -1, 2, -3, 1, -1, 1, -1, 0, 1, 2, 3, 4, -5, -6, -7, )); - let b: vector_unsigned_char = - transmute(i8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); - let c: vector_signed_int = transmute(u32x4::new(0, 1, 2, 3)); + let b = + vector_unsigned_char::from(u8x16::new(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); + let c = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new( (0 - 1 + 2 - 3) + 0, (0) + 1, @@ -6378,11 +6428,12 @@ mod tests { (4 - 5 - 6 - 7) + 3, ); - assert_eq!(d, transmute(vec_msum(a, b, c))); + assert_eq!(d, i32x4::from(unsafe { vec_msum(a, b, c) })); } + #[simd_test(enable = "altivec")] - unsafe fn test_vec_msum_unsigned_short() { - let a: vector_unsigned_short = transmute(u16x8::new( + fn test_vec_msum_unsigned_short() { + let a = vector_unsigned_short::from(u16x8::new( 0 * 256, 1 * 256, 2 * 256, @@ -6392,9 +6443,8 @@ mod tests { 6 * 256, 7 * 256, )); - let b: vector_unsigned_short = - transmute(u16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_unsigned_int = transmute(u32x4::new(0, 1, 2, 3)); + let b = vector_unsigned_short::from(u16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_unsigned_int::from(u32x4::new(0, 1, 2, 3)); let d = u32x4::new( (0 + 1) * 256 * 256 + 0, (2 + 3) * 256 * 256 + 1, @@ -6402,12 +6452,12 @@ mod tests { (6 + 7) * 256 * 256 + 3, ); - assert_eq!(d, transmute(vec_msum(a, b, c))); + assert_eq!(d, u32x4::from(unsafe { vec_msum(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_msum_signed_short() { - let a: vector_signed_short = transmute(i16x8::new( + fn test_vec_msum_signed_short() { + let a = vector_signed_short::from(i16x8::new( 0 * 256, -1 * 256, 2 * 256, @@ -6417,8 +6467,8 @@ mod tests { 6 * 256, -7 * 256, )); - let b: vector_signed_short = transmute(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); + let b = vector_signed_short::from(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new( (0 - 1) * 256 * 256 + 0, (2 - 3) * 256 * 256 + 1, @@ -6426,12 +6476,12 @@ mod tests { (6 - 7) * 256 * 256 + 3, ); - assert_eq!(d, transmute(vec_msum(a, b, c))); + assert_eq!(d, i32x4::from(unsafe { vec_msum(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_msums_unsigned() { - let a: vector_unsigned_short = transmute(u16x8::new( + fn test_vec_msums_unsigned() { + let a = vector_unsigned_short::from(u16x8::new( 0 * 256, 1 * 256, 2 * 256, @@ -6441,9 +6491,8 @@ mod tests { 6 * 256, 7 * 256, )); - let b: vector_unsigned_short = - transmute(u16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_unsigned_int = transmute(u32x4::new(0, 1, 2, 3)); + let b = vector_unsigned_short::from(u16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_unsigned_int::from(u32x4::new(0, 1, 2, 3)); let d = u32x4::new( (0 + 1) * 256 * 256 + 0, (2 + 3) * 256 * 256 + 1, @@ -6451,12 +6500,12 @@ mod tests { (6 + 7) * 256 * 256 + 3, ); - assert_eq!(d, transmute(vec_msums(a, b, c))); + assert_eq!(d, u32x4::from(unsafe { vec_msums(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_msums_signed() { - let a: vector_signed_short = transmute(i16x8::new( + fn test_vec_msums_signed() { + let a = vector_signed_short::from(i16x8::new( 0 * 256, -1 * 256, 2 * 256, @@ -6466,8 +6515,8 @@ mod tests { 6 * 256, -7 * 256, )); - let b: vector_signed_short = transmute(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); - let c: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); + let b = vector_signed_short::from(i16x8::new(256, 256, 256, 256, 256, 256, 256, 256)); + let c = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new( (0 - 1) * 256 * 256 + 0, (2 - 3) * 256 * 256 + 1, @@ -6475,23 +6524,23 @@ mod tests { (6 - 7) * 256 * 256 + 3, ); - assert_eq!(d, transmute(vec_msums(a, b, c))); + assert_eq!(d, i32x4::from(unsafe { vec_msums(a, b, c) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_sum2s() { - let a: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); - let b: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); + fn test_vec_sum2s() { + let a = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); + let b = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new(0, 0 + 1 + 1, 0, 2 + 3 + 3); - assert_eq!(d, transmute(vec_sum2s(a, b))); + assert_eq!(d, i32x4::from(unsafe { vec_sum2s(a, b) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_sum4s_unsigned_char() { - let a: vector_unsigned_char = - transmute(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); - let b: vector_unsigned_int = transmute(u32x4::new(0, 1, 2, 3)); + fn test_vec_sum4s_unsigned_char() { + let a = + vector_unsigned_char::from(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); + let b = vector_unsigned_int::from(u32x4::new(0, 1, 2, 3)); let d = u32x4::new( 0 + 1 + 2 + 3 + 0, 4 + 5 + 6 + 7 + 1, @@ -6499,13 +6548,13 @@ mod tests { 4 + 5 + 6 + 7 + 3, ); - assert_eq!(d, transmute(vec_sum4s(a, b))); + assert_eq!(d, u32x4::from(unsafe { vec_sum4s(a, b) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_sum4s_signed_char() { - let a: vector_signed_char = - transmute(i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); - let b: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); + fn test_vec_sum4s_signed_char() { + let a = + vector_signed_char::from(i8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); + let b = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new( 0 + 1 + 2 + 3 + 0, 4 + 5 + 6 + 7 + 1, @@ -6513,109 +6562,110 @@ mod tests { 4 + 5 + 6 + 7 + 3, ); - assert_eq!(d, transmute(vec_sum4s(a, b))); + assert_eq!(d, i32x4::from(unsafe { vec_sum4s(a, b) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_sum4s_signed_short() { - let a: vector_signed_short = transmute(i16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); - let b: vector_signed_int = transmute(i32x4::new(0, 1, 2, 3)); + fn test_vec_sum4s_signed_short() { + let a = vector_signed_short::from(i16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); + let b = vector_signed_int::from(i32x4::new(0, 1, 2, 3)); let d = i32x4::new(0 + 1 + 0, 2 + 3 + 1, 4 + 5 + 2, 6 + 7 + 3); - assert_eq!(d, transmute(vec_sum4s(a, b))); + assert_eq!(d, i32x4::from(unsafe { vec_sum4s(a, b) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mule_unsigned_char() { - let a: vector_unsigned_char = - transmute(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); + fn test_vec_mule_unsigned_char() { + let a = + vector_unsigned_char::from(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); let d = u16x8::new(0 * 0, 2 * 2, 4 * 4, 6 * 6, 0 * 0, 2 * 2, 4 * 4, 6 * 6); - assert_eq!(d, transmute(vec_mule(a, a))); + assert_eq!(d, u16x8::from(unsafe { vec_mule(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mule_signed_char() { - let a: vector_signed_char = transmute(i8x16::new( + fn test_vec_mule_signed_char() { + let a = vector_signed_char::from(i8x16::new( 0, 1, -2, 3, -4, 5, -6, 7, 0, 1, 2, 3, 4, 5, 6, 7, )); let d = i16x8::new(0 * 0, 2 * 2, 4 * 4, 6 * 6, 0 * 0, 2 * 2, 4 * 4, 6 * 6); - assert_eq!(d, transmute(vec_mule(a, a))); + assert_eq!(d, i16x8::from(unsafe { vec_mule(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mule_unsigned_short() { - let a: vector_unsigned_short = transmute(u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); + fn test_vec_mule_unsigned_short() { + let a = vector_unsigned_short::from(u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); let d = u32x4::new(0 * 0, 2 * 2, 4 * 4, 6 * 6); - assert_eq!(d, transmute(vec_mule(a, a))); + assert_eq!(d, u32x4::from(unsafe { vec_mule(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mule_signed_short() { - let a: vector_signed_short = transmute(i16x8::new(0, 1, -2, 3, -4, 5, -6, 7)); + fn test_vec_mule_signed_short() { + let a = vector_signed_short::from(i16x8::new(0, 1, -2, 3, -4, 5, -6, 7)); let d = i32x4::new(0 * 0, 2 * 2, 4 * 4, 6 * 6); - assert_eq!(d, transmute(vec_mule(a, a))); + assert_eq!(d, i32x4::from(unsafe { vec_mule(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mulo_unsigned_char() { - let a: vector_unsigned_char = - transmute(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); + fn test_vec_mulo_unsigned_char() { + let a = + vector_unsigned_char::from(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7)); let d = u16x8::new(1 * 1, 3 * 3, 5 * 5, 7 * 7, 1 * 1, 3 * 3, 5 * 5, 7 * 7); - assert_eq!(d, transmute(vec_mulo(a, a))); + assert_eq!(d, u16x8::from(unsafe { vec_mulo(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mulo_signed_char() { - let a: vector_signed_char = transmute(i8x16::new( + fn test_vec_mulo_signed_char() { + let a = vector_signed_char::from(i8x16::new( 0, 1, -2, 3, -4, 5, -6, 7, 0, 1, 2, 3, 4, 5, 6, 7, )); let d = i16x8::new(1 * 1, 3 * 3, 5 * 5, 7 * 7, 1 * 1, 3 * 3, 5 * 5, 7 * 7); - assert_eq!(d, transmute(vec_mulo(a, a))); + assert_eq!(d, i16x8::from(unsafe { vec_mulo(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mulo_unsigned_short() { - let a: vector_unsigned_short = transmute(u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); + fn test_vec_mulo_unsigned_short() { + let a = vector_unsigned_short::from(u16x8::new(0, 1, 2, 3, 4, 5, 6, 7)); let d = u32x4::new(1 * 1, 3 * 3, 5 * 5, 7 * 7); - assert_eq!(d, transmute(vec_mulo(a, a))); + assert_eq!(d, u32x4::from(unsafe { vec_mulo(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn test_vec_mulo_signed_short() { - let a: vector_signed_short = transmute(i16x8::new(0, 1, -2, 3, -4, 5, -6, 7)); + fn test_vec_mulo_signed_short() { + let a = vector_signed_short::from(i16x8::new(0, 1, -2, 3, -4, 5, -6, 7)); let d = i32x4::new(1 * 1, 3 * 3, 5 * 5, 7 * 7); - assert_eq!(d, transmute(vec_mulo(a, a))); + assert_eq!(d, i32x4::from(unsafe { vec_mulo(a, a) })); } #[simd_test(enable = "altivec")] - unsafe fn vec_add_i32x4_i32x4() { + fn vec_add_i32x4_i32x4() { let x = i32x4::new(1, 2, 3, 4); let y = i32x4::new(4, 3, 2, 1); - let x: vector_signed_int = transmute(x); - let y: vector_signed_int = transmute(y); - let z = vec_add(x, y); - assert_eq!(i32x4::splat(5), transmute(z)); + let x = vector_signed_int::from(x); + let y = vector_signed_int::from(y); + let z = unsafe { vec_add(x, y) }; + assert_eq!(i32x4::splat(5), i32x4::from(z)); } #[simd_test(enable = "altivec")] - unsafe fn vec_ctf_u32() { - let v: vector_unsigned_int = transmute(u32x4::new(u32::MIN, u32::MAX, u32::MAX, 42)); - let v2 = vec_ctf::<1, _>(v); - let r2: vector_float = transmute(f32x4::new(0.0, 2147483600.0, 2147483600.0, 21.0)); - let v4 = vec_ctf::<2, _>(v); - let r4: vector_float = transmute(f32x4::new(0.0, 1073741800.0, 1073741800.0, 10.5)); - let v8 = vec_ctf::<3, _>(v); - let r8: vector_float = transmute(f32x4::new(0.0, 536870900.0, 536870900.0, 5.25)); + fn vec_ctf_u32() { + let v = vector_unsigned_int::from(u32x4::new(u32::MIN, u32::MAX, u32::MAX, 42)); + let v2 = unsafe { vec_ctf::<1, _>(v) }; + let r2 = vector_float::from(f32x4::new(0.0, 2147483600.0, 2147483600.0, 21.0)); + let v4 = unsafe { vec_ctf::<2, _>(v) }; + let r4 = vector_float::from(f32x4::new(0.0, 1073741800.0, 1073741800.0, 10.5)); + let v8 = unsafe { vec_ctf::<3, _>(v) }; + let r8 = vector_float::from(f32x4::new(0.0, 536870900.0, 536870900.0, 5.25)); let check = |a, b| { - let r = transmute(vec_cmple(vec_abs(vec_sub(a, b)), vec_splats(f32::EPSILON))); + let r = + m32x4::from(unsafe { vec_cmple(vec_abs(vec_sub(a, b)), vec_splats(f32::EPSILON)) }); let e = m32x4::new(true, true, true, true); assert_eq!(e, r); }; @@ -6626,26 +6676,32 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_ctu() { + fn test_vec_ctu() { let v = u32x4::new(u32::MIN, u32::MAX, u32::MAX, 42); - let v2: u32x4 = transmute(vec_ctu::<1>(transmute(f32x4::new( - 0.0, - 2147483600.0, - 2147483600.0, - 21.0, - )))); - let v4: u32x4 = transmute(vec_ctu::<2>(transmute(f32x4::new( - 0.0, - 1073741800.0, - 1073741800.0, - 10.5, - )))); - let v8: u32x4 = transmute(vec_ctu::<3>(transmute(f32x4::new( - 0.0, - 536870900.0, - 536870900.0, - 5.25, - )))); + let v2 = u32x4::from(unsafe { + vec_ctu::<1>(vector_float::from(f32x4::new( + 0.0, + 2147483600.0, + 2147483600.0, + 21.0, + ))) + }); + let v4 = u32x4::from(unsafe { + vec_ctu::<2>(vector_float::from(f32x4::new( + 0.0, + 1073741800.0, + 1073741800.0, + 10.5, + ))) + }); + let v8 = u32x4::from(unsafe { + vec_ctu::<3>(vector_float::from(f32x4::new( + 0.0, + 536870900.0, + 536870900.0, + 5.25, + ))) + }); assert_eq!(v2, v); assert_eq!(v4, v); @@ -6653,18 +6709,18 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn vec_ctf_i32() { - let v: vector_signed_int = transmute(i32x4::new(i32::MIN, i32::MAX, i32::MAX - 42, 42)); - let v2 = vec_ctf::<1, _>(v); - let r2: vector_float = - transmute(f32x4::new(-1073741800.0, 1073741800.0, 1073741800.0, 21.0)); - let v4 = vec_ctf::<2, _>(v); - let r4: vector_float = transmute(f32x4::new(-536870900.0, 536870900.0, 536870900.0, 10.5)); - let v8 = vec_ctf::<3, _>(v); - let r8: vector_float = transmute(f32x4::new(-268435460.0, 268435460.0, 268435460.0, 5.25)); + fn vec_ctf_i32() { + let v = vector_signed_int::from(i32x4::new(i32::MIN, i32::MAX, i32::MAX - 42, 42)); + let v2 = unsafe { vec_ctf::<1, _>(v) }; + let r2 = vector_float::from(f32x4::new(-1073741800.0, 1073741800.0, 1073741800.0, 21.0)); + let v4 = unsafe { vec_ctf::<2, _>(v) }; + let r4 = vector_float::from(f32x4::new(-536870900.0, 536870900.0, 536870900.0, 10.5)); + let v8 = unsafe { vec_ctf::<3, _>(v) }; + let r8 = vector_float::from(f32x4::new(-268435460.0, 268435460.0, 268435460.0, 5.25)); let check = |a, b| { - let r = transmute(vec_cmple(vec_abs(vec_sub(a, b)), vec_splats(f32::EPSILON))); + let r = + m32x4::from(unsafe { vec_cmple(vec_abs(vec_sub(a, b)), vec_splats(f32::EPSILON)) }); println!("{:?} {:?}", a, b); let e = m32x4::new(true, true, true, true); assert_eq!(e, r); @@ -6676,26 +6732,32 @@ mod tests { } #[simd_test(enable = "altivec")] - unsafe fn test_vec_cts() { + fn test_vec_cts() { let v = i32x4::new(i32::MIN, i32::MAX, i32::MAX, 42); - let v2: i32x4 = transmute(vec_cts::<1>(transmute(f32x4::new( - -1073741800.0, - 1073741800.0, - 1073741800.0, - 21.0, - )))); - let v4: i32x4 = transmute(vec_cts::<2>(transmute(f32x4::new( - -536870900.0, - 536870900.0, - 536870900.0, - 10.5, - )))); - let v8: i32x4 = transmute(vec_cts::<3>(transmute(f32x4::new( - -268435460.0, - 268435460.0, - 268435460.0, - 5.25, - )))); + let v2 = i32x4::from(unsafe { + vec_cts::<1>(transmute(f32x4::new( + -1073741800.0, + 1073741800.0, + 1073741800.0, + 21.0, + ))) + }); + let v4 = i32x4::from(unsafe { + vec_cts::<2>(transmute(f32x4::new( + -536870900.0, + 536870900.0, + 536870900.0, + 10.5, + ))) + }); + let v8 = i32x4::from(unsafe { + vec_cts::<3>(transmute(f32x4::new( + -268435460.0, + 268435460.0, + 268435460.0, + 5.25, + ))) + }); assert_eq!(v2, v); assert_eq!(v4, v); diff --git a/library/stdarch/crates/core_arch/src/powerpc/vsx.rs b/library/stdarch/crates/core_arch/src/powerpc/vsx.rs index ca9fcaabe8b2..0aac23617340 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/vsx.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/vsx.rs @@ -9,6 +9,7 @@ #![allow(non_camel_case_types)] use crate::core_arch::powerpc::*; +use crate::core_arch::simd::*; #[cfg(test)] use stdarch_test::assert_instr; @@ -34,6 +35,22 @@ types! { // pub struct vector_unsigned___int128 = i128x1; } +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for vector_bool_long { + #[inline] + fn from(value: m64x2) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_powerpc", issue = "111145")] +impl From for m64x2 { + #[inline] + fn from(value: vector_bool_long) -> Self { + unsafe { transmute(value) } + } +} + #[allow(improper_ctypes)] unsafe extern "C" { #[link_name = "llvm.ppc.altivec.vperm"] @@ -46,7 +63,6 @@ unsafe extern "C" { mod sealed { use super::*; - use crate::core_arch::simd::*; #[unstable(feature = "stdarch_powerpc", issue = "111145")] pub trait VectorPermDI { @@ -221,14 +237,16 @@ mod tests { macro_rules! test_vec_xxpermdi { {$name:ident, $shorttype:ident, $longtype:ident, [$($a:expr),+], [$($b:expr),+], [$($c:expr),+], [$($d:expr),+]} => { #[simd_test(enable = "vsx")] - unsafe fn $name() { - let a: $longtype = transmute($shorttype::new($($a),+, $($b),+)); - let b = transmute($shorttype::new($($c),+, $($d),+)); + fn $name() { + let a = $longtype::from($shorttype::new($($a),+, $($b),+)); + let b = $longtype::from($shorttype::new($($c),+, $($d),+)); - assert_eq!($shorttype::new($($a),+, $($c),+), transmute(vec_xxpermdi::<_, 0>(a, b))); - assert_eq!($shorttype::new($($b),+, $($c),+), transmute(vec_xxpermdi::<_, 1>(a, b))); - assert_eq!($shorttype::new($($a),+, $($d),+), transmute(vec_xxpermdi::<_, 2>(a, b))); - assert_eq!($shorttype::new($($b),+, $($d),+), transmute(vec_xxpermdi::<_, 3>(a, b))); + unsafe { + assert_eq!($shorttype::new($($a),+, $($c),+), $shorttype::from(vec_xxpermdi::<_, 0>(a, b))); + assert_eq!($shorttype::new($($b),+, $($c),+), $shorttype::from(vec_xxpermdi::<_, 1>(a, b))); + assert_eq!($shorttype::new($($a),+, $($d),+), $shorttype::from(vec_xxpermdi::<_, 2>(a, b))); + assert_eq!($shorttype::new($($b),+, $($d),+), $shorttype::from(vec_xxpermdi::<_, 3>(a, b))); + } } } } diff --git a/library/stdarch/crates/core_arch/src/s390x/vector.rs b/library/stdarch/crates/core_arch/src/s390x/vector.rs index e1f841030c00..346cd674df66 100644 --- a/library/stdarch/crates/core_arch/src/s390x/vector.rs +++ b/library/stdarch/crates/core_arch/src/s390x/vector.rs @@ -51,6 +51,54 @@ types! { pub struct vector_double(2 x f64); } +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for vector_bool_char { + #[inline] + fn from(value: m8x16) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for m8x16 { + #[inline] + fn from(value: vector_bool_char) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for vector_bool_short { + #[inline] + fn from(value: m16x8) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for m16x8 { + #[inline] + fn from(value: vector_bool_short) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for vector_bool_int { + #[inline] + fn from(value: m32x4) -> Self { + unsafe { transmute(value) } + } +} + +#[unstable(feature = "stdarch_s390x", issue = "135681")] +impl From for m32x4 { + #[inline] + fn from(value: vector_bool_int) -> Self { + unsafe { transmute(value) } + } +} + #[repr(C, packed)] struct PackedTuple { x: T, @@ -6051,27 +6099,16 @@ mod tests { } macro_rules! test_vec_1 { - { $name: ident, $fn:ident, f32x4, [$($a:expr),+], ~[$($d:expr),+] } => { - #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: vector_float = transmute(f32x4::new($($a),+)); - - let d: vector_float = transmute(f32x4::new($($d),+)); - let r = transmute(vec_cmple(vec_abs(vec_sub($fn(a), d)), vec_splats(f32::EPSILON))); - let e = m32x4::new(true, true, true, true); - assert_eq!(e, r); - } - }; { $name: ident, $fn:ident, $ty: ident, [$($a:expr),+], [$($d:expr),+] } => { test_vec_1! { $name, $fn, $ty -> $ty, [$($a),+], [$($d),+] } }; { $name: ident, $fn:ident, $ty: ident -> $ty_out: ident, [$($a:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); + fn $name() { + let a: s_t_l!($ty) = $ty::new($($a),+).into(); let d = $ty_out::new($($d),+); - let r : $ty_out = transmute($fn(a)); + let r = $ty_out::from(unsafe { $fn(a) }); assert_eq!(d, r); } } @@ -6086,35 +6123,23 @@ mod tests { }; { $name: ident, $fn:ident, $ty1: ident, $ty2: ident -> $ty_out: ident, [$($a:expr),+], [$($b:expr),+], [$($d:expr),+] } => { #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: s_t_l!($ty1) = transmute($ty1::new($($a),+)); - let b: s_t_l!($ty2) = transmute($ty2::new($($b),+)); + fn $name() { + let a: s_t_l!($ty1) = $ty1::new($($a),+).into(); + let b: s_t_l!($ty2) = $ty2::new($($b),+).into(); let d = $ty_out::new($($d),+); - let r : $ty_out = transmute($fn(a, b)); + let r = $ty_out::from(unsafe { $fn(a, b) }); assert_eq!(d, r); } }; - { $name: ident, $fn:ident, $ty: ident -> $ty_out: ident, [$($a:expr),+], [$($b:expr),+], $d:expr } => { - #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: s_t_l!($ty) = transmute($ty::new($($a),+)); - let b: s_t_l!($ty) = transmute($ty::new($($b),+)); - - let r : $ty_out = transmute($fn(a, b)); - assert_eq!($d, r); - } - } } #[simd_test(enable = "vector")] - unsafe fn vec_add_i32x4_i32x4() { - let x = i32x4::new(1, 2, 3, 4); - let y = i32x4::new(4, 3, 2, 1); - let x: vector_signed_int = transmute(x); - let y: vector_signed_int = transmute(y); - let z = vec_add(x, y); - assert_eq!(i32x4::splat(5), transmute(z)); + fn vec_add_i32x4_i32x4() { + let x = vector_signed_int::from(i32x4::new(1, 2, 3, 4)); + let y = vector_signed_int::from(i32x4::new(4, 3, 2, 1)); + let z = unsafe { vec_add(x, y) }; + assert_eq!(i32x4::splat(5), i32x4::from(z)); } macro_rules! test_vec_sub { @@ -6232,11 +6257,11 @@ mod tests { macro_rules! test_vec_abs { { $name: ident, $ty: ident, $a: expr, $d: expr } => { #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: s_t_l!($ty) = vec_splats($a); - let a: s_t_l!($ty) = vec_abs(a); + fn $name() { + let a: s_t_l!($ty) = unsafe { vec_splats($a) }; + let a: s_t_l!($ty) = unsafe { vec_abs(a) }; let d = $ty::splat($d); - assert_eq!(d, transmute(a)); + assert_eq!(d, $ty::from(a)); } } } @@ -6386,7 +6411,7 @@ mod tests { [0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 16], [4, 2, 1, 8] } - test_vec_2! { test_vec_sral_pos, vec_sral, u32x4, u8x16 -> i32x4, + test_vec_2! { test_vec_sral_pos, vec_sral, u32x4, u8x16 -> u32x4, [0b1000, 0b1000, 0b1000, 0b1000], [0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 16], [4, 2, 1, 8] } @@ -6423,13 +6448,13 @@ mod tests { $shorttype:ident, $longtype:ident, [$($a:expr),+], [$($b:expr),+], [$($c:expr),+], [$($d:expr),+]} => { #[simd_test(enable = "vector")] - unsafe fn $name() { - let a: $longtype = transmute($shorttype::new($($a),+)); - let b: $longtype = transmute($shorttype::new($($b),+)); - let c: vector_unsigned_char = transmute(u8x16::new($($c),+)); + fn $name() { + let a = $longtype::from($shorttype::new($($a),+)); + let b = $longtype::from($shorttype::new($($b),+)); + let c = vector_unsigned_char::from(u8x16::new($($c),+)); let d = $shorttype::new($($d),+); - let r: $shorttype = transmute(vec_perm(a, b, c)); + let r = $shorttype::from(unsafe { vec_perm(a, b, c) }); assert_eq!(d, r); } } @@ -6512,46 +6537,46 @@ mod tests { [core::f32::consts::PI, 1.0, 25.0, 2.0], [core::f32::consts::PI.sqrt(), 1.0, 5.0, core::f32::consts::SQRT_2] } - test_vec_2! { test_vec_find_any_eq, vec_find_any_eq, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_eq, vec_find_any_eq, i32x4, i32x4 -> i32x4, [1, -2, 3, -4], [-5, 3, -7, 8], - [0, 0, 0xFFFFFFFF, 0] + [0, 0, !0, 0] } - test_vec_2! { test_vec_find_any_ne, vec_find_any_ne, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_ne, vec_find_any_ne, i32x4, i32x4 -> i32x4, [1, -2, 3, -4], [-5, 3, -7, 8], - [0xFFFFFFFF, 0xFFFFFFFF, 0, 0xFFFFFFFF] + [!0, !0, 0, !0] } - test_vec_2! { test_vec_find_any_eq_idx_1, vec_find_any_eq_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_eq_idx_1, vec_find_any_eq_idx, i32x4, i32x4 -> i32x4, [1, 2, 3, 4], [5, 3, 7, 8], [0, 8, 0, 0] } - test_vec_2! { test_vec_find_any_eq_idx_2, vec_find_any_eq_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_eq_idx_2, vec_find_any_eq_idx, i32x4, i32x4 -> i32x4, [1, 2, 3, 4], [5, 6, 7, 8], [0, 16, 0, 0] } - test_vec_2! { test_vec_find_any_ne_idx_1, vec_find_any_ne_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_ne_idx_1, vec_find_any_ne_idx, i32x4, i32x4 -> i32x4, [1, 2, 3, 4], [1, 5, 3, 4], [0, 4, 0, 0] } - test_vec_2! { test_vec_find_any_ne_idx_2, vec_find_any_ne_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_ne_idx_2, vec_find_any_ne_idx, i32x4, i32x4 -> i32x4, [1, 2, 3, 4], [1, 2, 3, 4], [0, 16, 0, 0] } - test_vec_2! { test_vec_find_any_eq_or_0_idx_1, vec_find_any_eq_or_0_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_eq_or_0_idx_1, vec_find_any_eq_or_0_idx, i32x4, i32x4 -> i32x4, [1, 2, 0, 4], [5, 6, 7, 8], [0, 8, 0, 0] } - test_vec_2! { test_vec_find_any_ne_or_0_idx_1, vec_find_any_ne_or_0_idx, i32x4, i32x4 -> u32x4, + test_vec_2! { test_vec_find_any_ne_or_0_idx_1, vec_find_any_ne_or_0_idx, i32x4, i32x4 -> i32x4, [1, 2, 0, 4], [1, 2, 3, 4], [0, 8, 0, 0] From e1417f408e0c1f35dd695da6c68e176faacfb4d9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 28 Jan 2026 22:06:18 +0100 Subject: [PATCH 191/978] Update `askama` to `0.15.3` --- Cargo.lock | 16 ++++++++-------- src/ci/citool/Cargo.toml | 2 +- src/librustdoc/Cargo.toml | 2 +- src/tools/generate-copyright/Cargo.toml | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 63c7d97bce43..35ad4472e6a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -184,9 +184,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "askama" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03341eae1125472b0672fbf35cc9aa7b74cd8e0c3d02f02c28a04678f12aaa7a" +checksum = "10a800c6f7c005e5bcb76ff0b9e61c9e54ad379ce4e83a88ed14ff487a73776d" dependencies = [ "askama_macros", "itoa", @@ -197,9 +197,9 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "461bd78f3da90b5e44eee4272cfb1c4832aa3dcdb6c370aedd3eb253d2b9e3ca" +checksum = "0cb7657165bac49b5c533850e7cd67c1c60059aefc31088f89aa431c8a90d5d9" dependencies = [ "askama_parser", "basic-toml", @@ -214,18 +214,18 @@ dependencies = [ [[package]] name = "askama_macros" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba49fb22ee3074574b8510abd9495d4f0bb9b8f87e8e45ee31e2cee508f7a8e5" +checksum = "e55eacd3e54d32483cd10d0a881a0f28a40f3a763704ac9b8693edc39d7321c7" dependencies = [ "askama_derive", ] [[package]] name = "askama_parser" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e33eb7484958aaa1f27e9adb556f5d557331cd891bdbb33781bc1f9550b6f6e" +checksum = "20c3df8886ab5acdcd76eee93b3e2df1ef734251438b5b942b5fea22c50d2a0f" dependencies = [ "rustc-hash 2.1.1", "serde", diff --git a/src/ci/citool/Cargo.toml b/src/ci/citool/Cargo.toml index b394c6fbefff..c2a926b3eaef 100644 --- a/src/ci/citool/Cargo.toml +++ b/src/ci/citool/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] anyhow = "1" -askama = "0.15.2" +askama = "0.15.3" clap = { version = "4.5", features = ["derive"] } csv = "1" diff = "0.1" diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 43006435fcde..efc44a8a2d51 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -10,7 +10,7 @@ path = "lib.rs" [dependencies] # tidy-alphabetical-start arrayvec = { version = "0.7", default-features = false } -askama = { version = "0.15.2", default-features = false, features = ["alloc", "config", "derive"] } +askama = { version = "0.15.3", default-features = false, features = ["alloc", "config", "derive"] } base64 = "0.21.7" indexmap = { version = "2", features = ["serde"] } itertools = "0.12" diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml index e1a5ca31a1db..965f7f992e75 100644 --- a/src/tools/generate-copyright/Cargo.toml +++ b/src/tools/generate-copyright/Cargo.toml @@ -8,7 +8,7 @@ description = "Produces a manifest of all the copyrighted materials in the Rust [dependencies] anyhow = "1.0.65" -askama = "0.15.2" +askama = "0.15.3" cargo_metadata = "0.21" serde = { version = "1.0.147", features = ["derive"] } serde_json = "1.0.85" From 9e61014a8a0bb1f1d7911511c303a7ae2a9c2a7d Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 28 Jan 2026 08:59:16 +0100 Subject: [PATCH 192/978] Convert `parse_nested_meta` to `parse_args_with` for `#[diagnostic]` --- .../src/diagnostics/diagnostic_builder.rs | 76 +++---- .../session-diagnostic/diagnostic-derive.rs | 10 +- .../diagnostic-derive.stderr | 192 +++++++----------- 3 files changed, 124 insertions(+), 154 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index cbc70b55d7ee..e71c84c805a7 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -2,6 +2,7 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote, quote_spanned}; +use syn::parse::ParseStream; use syn::spanned::Spanned; use syn::{Attribute, Meta, Path, Token, Type, parse_quote}; use synstructure::{BindingInfo, Structure, VariantInfo}; @@ -42,7 +43,7 @@ pub(crate) struct DiagnosticDeriveVariantBuilder { /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that /// has the actual diagnostic message. - pub slug: SpannedOption, + pub slug: Option, /// Error codes are a optional part of the struct attribute - this is only set to detect /// multiple specifications. @@ -111,7 +112,7 @@ impl DiagnosticDeriveKind { impl DiagnosticDeriveVariantBuilder { pub(crate) fn primary_message(&self) -> Option<&Path> { - match self.slug.value_ref() { + match self.slug.as_ref() { None => { span_err(self.span, "diagnostic slug not specified") .help( @@ -209,47 +210,54 @@ impl DiagnosticDeriveVariantBuilder { let name = attr.path().segments.last().unwrap().ident.to_string(); let name = name.as_str(); - let mut first = true; - if name == "diag" { let mut tokens = TokenStream::new(); - attr.parse_nested_meta(|nested| { - let path = &nested.path; + attr.parse_args_with(|input: ParseStream<'_>| { + let mut input = &*input; + let slug_recovery_point = input.fork(); - if first && (nested.input.is_empty() || nested.input.peek(Token![,])) { - self.slug.set_once(path.clone(), path.span().unwrap()); - first = false; - return Ok(()); + let slug = input.parse::()?; + if input.is_empty() || input.peek(Token![,]) { + self.slug = Some(slug); + } else { + input = &slug_recovery_point; } - first = false; - - let Ok(nested) = nested.value() else { - span_err( - nested.input.span().unwrap(), - "diagnostic slug must be the first argument", - ) - .emit(); - return Ok(()); - }; - - if path.is_ident("code") { - self.code.set_once((), path.span().unwrap()); - - let code = nested.parse::()?; - tokens.extend(quote! { - diag.code(#code); - }); - } else { - span_err(path.span().unwrap(), "unknown argument") - .note("only the `code` parameter is valid after the slug") + while !input.is_empty() { + input.parse::()?; + // Allow trailing comma + if input.is_empty() { + break; + } + let arg_name: Path = input.parse::()?; + if input.peek(Token![,]) { + span_err( + arg_name.span().unwrap(), + "diagnostic slug must be the first argument", + ) .emit(); - - // consume the buffer so we don't have syntax errors from syn - let _ = nested.parse::(); + continue; + } + let arg_name = arg_name.require_ident()?; + input.parse::()?; + let arg_value = input.parse::()?; + match arg_name.to_string().as_str() { + "code" => { + self.code.set_once((), arg_name.span().unwrap()); + tokens.extend(quote! { + diag.code(#arg_value); + }); + } + _ => { + span_err(arg_name.span().unwrap(), "unknown argument") + .note("only the `code` parameter is valid after the slug") + .emit(); + } + } } Ok(()) })?; + return Ok(tokens); } diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index fcae379d982f..506ec7f88a82 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -80,20 +80,17 @@ struct InvalidNestedStructAttr {} #[derive(Diagnostic)] #[diag(nonsense("foo"), code = E0123, slug = "foo")] -//~^ ERROR diagnostic slug must be the first argument -//~| ERROR diagnostic slug not specified +//~^ ERROR derive(Diagnostic): diagnostic slug not specified struct InvalidNestedStructAttr1 {} #[derive(Diagnostic)] #[diag(nonsense = "...", code = E0123, slug = "foo")] -//~^ ERROR unknown argument -//~| ERROR diagnostic slug not specified +//~^ ERROR diagnostic slug not specified struct InvalidNestedStructAttr2 {} #[derive(Diagnostic)] #[diag(nonsense = 4, code = E0123, slug = "foo")] -//~^ ERROR unknown argument -//~| ERROR diagnostic slug not specified +//~^ ERROR diagnostic slug not specified struct InvalidNestedStructAttr3 {} #[derive(Diagnostic)] @@ -113,7 +110,6 @@ struct WrongPlaceField { #[diag(no_crate_example, code = E0123)] #[diag(no_crate_example, code = E0456)] //~^ ERROR specified multiple times -//~^^ ERROR specified multiple times struct DiagSpecifiedTwice {} #[derive(Diagnostic)] diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index cf5c0c2e6491..29132b8325f3 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -48,12 +48,6 @@ LL | #[diag(code = E0123)] | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` -error: derive(Diagnostic): diagnostic slug must be the first argument - --> $DIR/diagnostic-derive.rs:82:16 - | -LL | #[diag(nonsense("foo"), code = E0123, slug = "foo")] - | ^ - error: derive(Diagnostic): diagnostic slug not specified --> $DIR/diagnostic-derive.rs:82:1 | @@ -62,32 +56,16 @@ LL | #[diag(nonsense("foo"), code = E0123, slug = "foo")] | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` -error: derive(Diagnostic): unknown argument - --> $DIR/diagnostic-derive.rs:88:8 - | -LL | #[diag(nonsense = "...", code = E0123, slug = "foo")] - | ^^^^^^^^ - | - = note: only the `code` parameter is valid after the slug - error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:88:1 + --> $DIR/diagnostic-derive.rs:87:1 | LL | #[diag(nonsense = "...", code = E0123, slug = "foo")] | ^ | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` -error: derive(Diagnostic): unknown argument - --> $DIR/diagnostic-derive.rs:94:8 - | -LL | #[diag(nonsense = 4, code = E0123, slug = "foo")] - | ^^^^^^^^ - | - = note: only the `code` parameter is valid after the slug - error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:94:1 + --> $DIR/diagnostic-derive.rs:92:1 | LL | #[diag(nonsense = 4, code = E0123, slug = "foo")] | ^ @@ -95,7 +73,7 @@ LL | #[diag(nonsense = 4, code = E0123, slug = "foo")] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): unknown argument - --> $DIR/diagnostic-derive.rs:100:40 + --> $DIR/diagnostic-derive.rs:97:40 | LL | #[diag(no_crate_example, code = E0123, slug = "foo")] | ^^^^ @@ -103,55 +81,43 @@ LL | #[diag(no_crate_example, code = E0123, slug = "foo")] = note: only the `code` parameter is valid after the slug error: derive(Diagnostic): `#[suggestion = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:107:5 + --> $DIR/diagnostic-derive.rs:104:5 | LL | #[suggestion = "bar"] | ^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive.rs:114:8 - | -LL | #[diag(no_crate_example, code = E0456)] - | ^^^^^^^^^^^^^^^^ - | -note: previously specified here - --> $DIR/diagnostic-derive.rs:113:8 - | -LL | #[diag(no_crate_example, code = E0123)] - | ^^^^^^^^^^^^^^^^ - -error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive.rs:114:26 + --> $DIR/diagnostic-derive.rs:111:26 | LL | #[diag(no_crate_example, code = E0456)] | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:113:26 + --> $DIR/diagnostic-derive.rs:110:26 | LL | #[diag(no_crate_example, code = E0123)] | ^^^^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive.rs:120:40 + --> $DIR/diagnostic-derive.rs:116:40 | LL | #[diag(no_crate_example, code = E0123, code = E0456)] | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:120:26 + --> $DIR/diagnostic-derive.rs:116:26 | LL | #[diag(no_crate_example, code = E0123, code = E0456)] | ^^^^ error: derive(Diagnostic): diagnostic slug must be the first argument - --> $DIR/diagnostic-derive.rs:125:43 + --> $DIR/diagnostic-derive.rs:121:26 | LL | #[diag(no_crate_example, no_crate::example, code = E0123)] - | ^ + | ^^^^^^^^ error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:130:1 + --> $DIR/diagnostic-derive.rs:126:1 | LL | struct KindNotProvided {} | ^^^^^^ @@ -159,7 +125,7 @@ LL | struct KindNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:133:1 + --> $DIR/diagnostic-derive.rs:129:1 | LL | #[diag(code = E0123)] | ^ @@ -167,31 +133,31 @@ LL | #[diag(code = E0123)] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:144:5 + --> $DIR/diagnostic-derive.rs:140:5 | LL | #[primary_span] | ^ error: derive(Diagnostic): `#[nonsense]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:152:5 + --> $DIR/diagnostic-derive.rs:148:5 | LL | #[nonsense] | ^ error: derive(Diagnostic): the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:169:5 + --> $DIR/diagnostic-derive.rs:165:5 | LL | #[label(no_crate_label)] | ^ error: derive(Diagnostic): `name` doesn't refer to a field on this type - --> $DIR/diagnostic-derive.rs:177:46 + --> $DIR/diagnostic-derive.rs:173:46 | LL | #[suggestion(no_crate_suggestion, code = "{name}")] | ^^^^^^^^ error: invalid format string: expected `}` but string was terminated - --> $DIR/diagnostic-derive.rs:182:10 + --> $DIR/diagnostic-derive.rs:178:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ expected `}` in format string @@ -200,7 +166,7 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: unmatched `}` found - --> $DIR/diagnostic-derive.rs:192:10 + --> $DIR/diagnostic-derive.rs:188:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ unmatched `}` in format string @@ -209,19 +175,19 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: derive(Diagnostic): the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:212:5 + --> $DIR/diagnostic-derive.rs:208:5 | LL | #[label(no_crate_label)] | ^ error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:231:5 + --> $DIR/diagnostic-derive.rs:227:5 | LL | #[suggestion(no_crate_suggestion)] | ^ error: derive(Diagnostic): invalid nested attribute - --> $DIR/diagnostic-derive.rs:239:18 + --> $DIR/diagnostic-derive.rs:235:18 | LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^ @@ -229,13 +195,13 @@ LL | #[suggestion(nonsense = "bar")] = help: only `no_span`, `style`, `code` and `applicability` are valid nested attributes error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:239:5 + --> $DIR/diagnostic-derive.rs:235:5 | LL | #[suggestion(nonsense = "bar")] | ^ error: derive(Diagnostic): invalid nested attribute - --> $DIR/diagnostic-derive.rs:248:18 + --> $DIR/diagnostic-derive.rs:244:18 | LL | #[suggestion(msg = "bar")] | ^^^ @@ -243,13 +209,13 @@ LL | #[suggestion(msg = "bar")] = help: only `no_span`, `style`, `code` and `applicability` are valid nested attributes error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:248:5 + --> $DIR/diagnostic-derive.rs:244:5 | LL | #[suggestion(msg = "bar")] | ^ error: derive(Diagnostic): wrong field type for suggestion - --> $DIR/diagnostic-derive.rs:271:5 + --> $DIR/diagnostic-derive.rs:267:5 | LL | #[suggestion(no_crate_suggestion, code = "This is suggested code")] | ^ @@ -257,79 +223,79 @@ LL | #[suggestion(no_crate_suggestion, code = "This is suggested code")] = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive.rs:287:24 + --> $DIR/diagnostic-derive.rs:283:24 | LL | suggestion: (Span, Span, Applicability), | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:287:18 + --> $DIR/diagnostic-derive.rs:283:18 | LL | suggestion: (Span, Span, Applicability), | ^^^^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive.rs:295:33 + --> $DIR/diagnostic-derive.rs:291:33 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:295:18 + --> $DIR/diagnostic-derive.rs:291:18 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ error: derive(Diagnostic): `#[label = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:302:5 + --> $DIR/diagnostic-derive.rs:298:5 | LL | #[label = "bar"] | ^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive.rs:453:5 + --> $DIR/diagnostic-derive.rs:449:5 | LL | #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")] | ^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:455:24 + --> $DIR/diagnostic-derive.rs:451:24 | LL | suggestion: (Span, Applicability), | ^^^^^^^^^^^^^ error: derive(Diagnostic): invalid applicability - --> $DIR/diagnostic-derive.rs:461:69 + --> $DIR/diagnostic-derive.rs:457:69 | LL | #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")] | ^^^^^^^^ error: derive(Diagnostic): the `#[help(...)]` attribute can only be applied to fields of type `Span`, `MultiSpan`, `bool` or `()` - --> $DIR/diagnostic-derive.rs:528:5 + --> $DIR/diagnostic-derive.rs:524:5 | LL | #[help(no_crate_help)] | ^ error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute - --> $DIR/diagnostic-derive.rs:537:32 + --> $DIR/diagnostic-derive.rs:533:32 | LL | #[label(no_crate_label, foo)] | ^ error: derive(Diagnostic): only `no_span` is a valid nested attribute - --> $DIR/diagnostic-derive.rs:545:29 + --> $DIR/diagnostic-derive.rs:541:29 | LL | #[label(no_crate_label, foo = "...")] | ^^^ error: derive(Diagnostic): only `no_span` is a valid nested attribute - --> $DIR/diagnostic-derive.rs:553:29 + --> $DIR/diagnostic-derive.rs:549:29 | LL | #[label(no_crate_label, foo("..."))] | ^^^ error: derive(Diagnostic): `#[primary_span]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:565:5 + --> $DIR/diagnostic-derive.rs:561:5 | LL | #[primary_span] | ^ @@ -337,13 +303,13 @@ LL | #[primary_span] = help: the `primary_span` field attribute is not valid for lint diagnostics error: derive(Diagnostic): `#[error(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:585:1 + --> $DIR/diagnostic-derive.rs:581:1 | LL | #[error(no_crate_example, code = E0123)] | ^ error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:585:1 + --> $DIR/diagnostic-derive.rs:581:1 | LL | #[error(no_crate_example, code = E0123)] | ^ @@ -351,13 +317,13 @@ LL | #[error(no_crate_example, code = E0123)] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): `#[warn_(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:592:1 + --> $DIR/diagnostic-derive.rs:588:1 | LL | #[warn_(no_crate_example, code = E0123)] | ^ error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:592:1 + --> $DIR/diagnostic-derive.rs:588:1 | LL | #[warn_(no_crate_example, code = E0123)] | ^ @@ -365,13 +331,13 @@ LL | #[warn_(no_crate_example, code = E0123)] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:599:1 + --> $DIR/diagnostic-derive.rs:595:1 | LL | #[lint(no_crate_example, code = E0123)] | ^ error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:599:1 + --> $DIR/diagnostic-derive.rs:595:1 | LL | #[lint(no_crate_example, code = E0123)] | ^ @@ -379,13 +345,13 @@ LL | #[lint(no_crate_example, code = E0123)] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:606:1 + --> $DIR/diagnostic-derive.rs:602:1 | LL | #[lint(no_crate_example, code = E0123)] | ^ error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:606:1 + --> $DIR/diagnostic-derive.rs:602:1 | LL | #[lint(no_crate_example, code = E0123)] | ^ @@ -393,19 +359,19 @@ LL | #[lint(no_crate_example, code = E0123)] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive.rs:615:53 + --> $DIR/diagnostic-derive.rs:611:53 | LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:615:39 + --> $DIR/diagnostic-derive.rs:611:39 | LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] | ^^^^ error: derive(Diagnostic): wrong types for suggestion - --> $DIR/diagnostic-derive.rs:624:24 + --> $DIR/diagnostic-derive.rs:620:24 | LL | suggestion: (Span, usize), | ^^^^^ @@ -413,7 +379,7 @@ LL | suggestion: (Span, usize), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: derive(Diagnostic): wrong types for suggestion - --> $DIR/diagnostic-derive.rs:632:17 + --> $DIR/diagnostic-derive.rs:628:17 | LL | suggestion: (Span,), | ^^^^^^^ @@ -421,13 +387,13 @@ LL | suggestion: (Span,), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:639:5 + --> $DIR/diagnostic-derive.rs:635:5 | LL | #[suggestion(no_crate_suggestion)] | ^ error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:646:1 + --> $DIR/diagnostic-derive.rs:642:1 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^ @@ -435,7 +401,7 @@ LL | #[multipart_suggestion(no_crate_suggestion)] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:649:1 + --> $DIR/diagnostic-derive.rs:645:1 | LL | #[multipart_suggestion()] | ^ @@ -443,7 +409,7 @@ LL | #[multipart_suggestion()] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:653:5 + --> $DIR/diagnostic-derive.rs:649:5 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^ @@ -451,7 +417,7 @@ LL | #[multipart_suggestion(no_crate_suggestion)] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:661:1 + --> $DIR/diagnostic-derive.rs:657:1 | LL | #[suggestion(no_crate_suggestion, code = "...")] | ^ @@ -459,7 +425,7 @@ LL | #[suggestion(no_crate_suggestion, code = "...")] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: derive(Diagnostic): `#[label]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:670:1 + --> $DIR/diagnostic-derive.rs:666:1 | LL | #[label] | ^ @@ -467,73 +433,73 @@ LL | #[label] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:704:5 + --> $DIR/diagnostic-derive.rs:700:5 | LL | #[subdiagnostic(bad)] | ^ error: derive(Diagnostic): `#[subdiagnostic = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:712:5 + --> $DIR/diagnostic-derive.rs:708:5 | LL | #[subdiagnostic = "bad"] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:720:5 + --> $DIR/diagnostic-derive.rs:716:5 | LL | #[subdiagnostic(bad, bad)] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:728:5 + --> $DIR/diagnostic-derive.rs:724:5 | LL | #[subdiagnostic("bad")] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:736:5 + --> $DIR/diagnostic-derive.rs:732:5 | LL | #[subdiagnostic(eager)] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:744:5 + --> $DIR/diagnostic-derive.rs:740:5 | LL | #[subdiagnostic(eager)] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:765:5 + --> $DIR/diagnostic-derive.rs:761:5 | LL | #[subdiagnostic(eager)] | ^ error: derive(Diagnostic): expected at least one string literal for `code(...)` - --> $DIR/diagnostic-derive.rs:796:23 + --> $DIR/diagnostic-derive.rs:792:23 | LL | #[suggestion(code())] | ^ error: derive(Diagnostic): `code(...)` must contain only string literals - --> $DIR/diagnostic-derive.rs:804:23 + --> $DIR/diagnostic-derive.rs:800:23 | LL | #[suggestion(code(foo))] | ^^^ error: unexpected token, expected `)` - --> $DIR/diagnostic-derive.rs:804:23 + --> $DIR/diagnostic-derive.rs:800:23 | LL | #[suggestion(code(foo))] | ^^^ error: expected string literal - --> $DIR/diagnostic-derive.rs:813:25 + --> $DIR/diagnostic-derive.rs:809:25 | LL | #[suggestion(code = 3)] | ^ error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:828:5 + --> $DIR/diagnostic-derive.rs:824:5 | LL | #[suggestion(no_crate_suggestion, code = "")] | ^ @@ -549,13 +515,13 @@ LL | #[nonsense(no_crate_example, code = E0123)] | ^^^^^^^^ error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:152:7 + --> $DIR/diagnostic-derive.rs:148:7 | LL | #[nonsense] | ^^^^^^^^ error: cannot find attribute `error` in this scope - --> $DIR/diagnostic-derive.rs:585:3 + --> $DIR/diagnostic-derive.rs:581:3 | LL | #[error(no_crate_example, code = E0123)] | ^^^^^ @@ -567,7 +533,7 @@ LL | struct ErrorAttribute {} | error: cannot find attribute `warn_` in this scope - --> $DIR/diagnostic-derive.rs:592:3 + --> $DIR/diagnostic-derive.rs:588:3 | LL | #[warn_(no_crate_example, code = E0123)] | ^^^^^ @@ -579,7 +545,7 @@ LL + #[warn(no_crate_example, code = E0123)] | error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:599:3 + --> $DIR/diagnostic-derive.rs:595:3 | LL | #[lint(no_crate_example, code = E0123)] | ^^^^ @@ -591,7 +557,7 @@ LL + #[link(no_crate_example, code = E0123)] | error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:606:3 + --> $DIR/diagnostic-derive.rs:602:3 | LL | #[lint(no_crate_example, code = E0123)] | ^^^^ @@ -603,7 +569,7 @@ LL + #[link(no_crate_example, code = E0123)] | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:646:3 + --> $DIR/diagnostic-derive.rs:642:3 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^ @@ -615,7 +581,7 @@ LL | struct MultipartSuggestion { | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:649:3 + --> $DIR/diagnostic-derive.rs:645:3 | LL | #[multipart_suggestion()] | ^^^^^^^^^^^^^^^^^^^^ @@ -627,7 +593,7 @@ LL | struct MultipartSuggestion { | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:653:7 + --> $DIR/diagnostic-derive.rs:649:7 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^ @@ -641,7 +607,7 @@ LL | #[diag(nonsense, code = E0123)] | ^^^^^^^^ not found in `crate::fluent_generated` error[E0425]: cannot find value `__code_34` in this scope - --> $DIR/diagnostic-derive.rs:810:10 + --> $DIR/diagnostic-derive.rs:806:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ not found in this scope @@ -649,7 +615,7 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Hello: IntoDiagArg` is not satisfied - --> $DIR/diagnostic-derive.rs:351:12 + --> $DIR/diagnostic-derive.rs:347:12 | LL | #[derive(Diagnostic)] | ---------- required by a bound introduced by this call @@ -670,7 +636,7 @@ note: required by a bound in `Diag::<'a, G>::arg` = note: in this macro invocation = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 85 previous errors +error: aborting due to 81 previous errors Some errors have detailed explanations: E0277, E0425. For more information about an error, try `rustc --explain E0277`. From 5d21a21695d56b74ea249f269ee10195251008b7 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 28 Jan 2026 22:18:44 +0100 Subject: [PATCH 193/978] Convert `parse_nested_meta` to `parse_args_with` for `#[subdiagnostic]` --- .../src/diagnostics/subdiagnostic.rs | 51 ++-- .../rustc_macros/src/diagnostics/utils.rs | 242 ++++++++---------- .../session-diagnostic/diagnostic-derive.rs | 2 +- .../diagnostic-derive.stderr | 14 +- .../subdiagnostic-derive.rs | 7 +- .../subdiagnostic-derive.stderr | 46 ++-- 6 files changed, 165 insertions(+), 197 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index dcd0116d804d..189d83c42160 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -1,9 +1,10 @@ #![deny(unused_must_use)] -use proc_macro2::TokenStream; +use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; +use syn::parse::ParseStream; use syn::spanned::Spanned; -use syn::{Attribute, Meta, MetaList, Path}; +use syn::{Attribute, Meta, MetaList, Path, Token}; use synstructure::{BindingInfo, Structure, VariantInfo}; use super::utils::SubdiagnosticVariant; @@ -437,23 +438,35 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let mut code = None; - list.parse_nested_meta(|nested| { - if nested.path.is_ident("code") { - let code_field = new_code_ident(); - let span = nested.path.span().unwrap(); - let formatting_init = build_suggestion_code( - &code_field, - nested, - self, - AllowMultipleAlternatives::No, - ); - code.set_once((code_field, formatting_init), span); - } else { - span_err( - nested.path.span().unwrap(), - "`code` is the only valid nested attribute", - ) - .emit(); + list.parse_args_with(|input: ParseStream<'_>| { + while !input.is_empty() { + let arg_name = input.parse::()?; + match arg_name.to_string().as_str() { + "code" => { + let code_field = new_code_ident(); + let formatting_init = build_suggestion_code( + &code_field, + input, + self, + AllowMultipleAlternatives::No, + )?; + code.set_once( + (code_field, formatting_init), + arg_name.span().unwrap(), + ); + } + _ => { + span_err( + arg_name.span().unwrap(), + "`code` is the only valid nested attribute", + ) + .emit(); + } + } + if input.is_empty() { + break; + } + input.parse::()?; } Ok(()) })?; diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index c310b99d5351..6ca2c90abb90 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -6,7 +6,7 @@ use std::str::FromStr; use proc_macro::Span; use proc_macro2::{Ident, TokenStream}; use quote::{ToTokens, format_ident, quote}; -use syn::meta::ParseNestedMeta; +use syn::parse::ParseStream; use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::{Attribute, Field, LitStr, Meta, Path, Token, Type, TypeTuple, parenthesized}; @@ -428,64 +428,51 @@ pub(super) enum AllowMultipleAlternatives { } fn parse_suggestion_values( - nested: ParseNestedMeta<'_>, + nested: ParseStream<'_>, allow_multiple: AllowMultipleAlternatives, ) -> syn::Result> { - let values = if let Ok(val) = nested.value() { - vec![val.parse()?] - } else { - let content; - parenthesized!(content in nested.input); + if nested.parse::().is_ok() { + return Ok(vec![nested.parse::()?]); + } - if let AllowMultipleAlternatives::No = allow_multiple { + let content; + parenthesized!(content in nested); + if let AllowMultipleAlternatives::No = allow_multiple { + span_err(content.span().unwrap(), "expected exactly one string literal for `code = ...`") + .emit(); + return Ok(vec![]); + } + + let literals = Punctuated::::parse_terminated(&content); + Ok(match literals { + Ok(p) if p.is_empty() => { span_err( - nested.input.span().unwrap(), - "expected exactly one string literal for `code = ...`", + content.span().unwrap(), + "expected at least one string literal for `code(...)`", ) .emit(); vec![] - } else { - let literals = Punctuated::::parse_terminated(&content); - - match literals { - Ok(p) if p.is_empty() => { - span_err( - content.span().unwrap(), - "expected at least one string literal for `code(...)`", - ) - .emit(); - vec![] - } - Ok(p) => p.into_iter().collect(), - Err(_) => { - span_err( - content.span().unwrap(), - "`code(...)` must contain only string literals", - ) - .emit(); - vec![] - } - } } - }; - - Ok(values) + Ok(p) => p.into_iter().collect(), + Err(_) => { + span_err(content.span().unwrap(), "`code(...)` must contain only string literals") + .emit(); + vec![] + } + }) } /// Constructs the `format!()` invocation(s) necessary for a `#[suggestion*(code = "foo")]` or /// `#[suggestion*(code("foo", "bar"))]` attribute field pub(super) fn build_suggestion_code( code_field: &Ident, - nested: ParseNestedMeta<'_>, + nested: ParseStream<'_>, fields: &impl HasFieldMap, allow_multiple: AllowMultipleAlternatives, -) -> TokenStream { - let values = match parse_suggestion_values(nested, allow_multiple) { - Ok(x) => x, - Err(e) => return e.into_compile_error(), - }; +) -> Result { + let values = parse_suggestion_values(nested, allow_multiple)?; - if let AllowMultipleAlternatives::Yes = allow_multiple { + Ok(if let AllowMultipleAlternatives::Yes = allow_multiple { let formatted_strings: Vec<_> = values .into_iter() .map(|value| fields.build_format(&value.value(), value.span())) @@ -497,7 +484,7 @@ pub(super) fn build_suggestion_code( } else { // error handled previously quote! { let #code_field = String::new(); } - } + }) } /// Possible styles for suggestion subdiagnostics. @@ -709,112 +696,95 @@ impl SubdiagnosticVariant { let mut code = None; let mut suggestion_kind = None; - let mut first = true; let mut slug = None; let mut no_span = false; - list.parse_nested_meta(|nested| { - if nested.input.is_empty() || nested.input.peek(Token![,]) { - if first { - slug = Some(nested.path); - } else if nested.path.is_ident("no_span") { - no_span = true; - } else { - span_err(nested.input.span().unwrap(), "a diagnostic slug must be the first argument to the attribute").emit(); + list.parse_args_with(|input: ParseStream<'_>| { + let mut is_first = true; + while !input.is_empty() { + let arg_name: Path = input.parse::()?; + let arg_name_span = arg_name.span().unwrap(); + if input.is_empty() || input.parse::().is_ok() { + if is_first { + slug = Some(arg_name); + is_first = false; + } else { + span_err(arg_name_span, "a diagnostic slug must be the first argument to the attribute").emit(); + } + continue } + is_first = false; - first = false; - return Ok(()); - } + match (arg_name.require_ident()?.to_string().as_str(), &mut kind) { + // ("no_span", _) => no_span = true, + ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => { + let code_init = build_suggestion_code( + &code_field, + &input, + fields, + AllowMultipleAlternatives::Yes, + )?; + code.set_once(code_init, arg_name_span); + } + ( + "applicability", + SubdiagnosticKind::Suggestion { applicability, .. } + | SubdiagnosticKind::MultipartSuggestion { applicability, .. }, + ) => { + input.parse::()?; + let value = input.parse::()?; + let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| { + span_err(value.span().unwrap(), "invalid applicability").emit(); + Applicability::Unspecified + }); + applicability.set_once(value, span); + } + ( + "style", + SubdiagnosticKind::Suggestion { .. } + | SubdiagnosticKind::MultipartSuggestion { .. }, + ) => { + input.parse::()?; + let value = input.parse::()?; - first = false; + let value = value.value().parse().unwrap_or_else(|()| { + span_err(value.span().unwrap(), "invalid suggestion style") + .help("valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`") + .emit(); + SuggestionKind::Normal + }); - let nested_name = nested.path.segments.last().unwrap().ident.to_string(); - let nested_name = nested_name.as_str(); + suggestion_kind.set_once(value, span); + } - let path_span = nested.path.span().unwrap(); - let val_span = nested.input.span().unwrap(); - macro_rules! get_string { - () => {{ - let Ok(value) = nested.value().and_then(|x| x.parse::()) else { - span_err(val_span, "expected `= \"xxx\"`").emit(); - return Ok(()); - }; - value - }}; - } - - let mut has_errors = false; - let input = nested.input; - - match (nested_name, &mut kind) { - ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => { - let code_init = build_suggestion_code( - code_field, - nested, - fields, - AllowMultipleAlternatives::Yes, - ); - code.set_once(code_init, path_span); - } - ( - "applicability", - SubdiagnosticKind::Suggestion { applicability, .. } - | SubdiagnosticKind::MultipartSuggestion { applicability, .. }, - ) => { - let value = get_string!(); - let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| { - span_err(value.span().unwrap(), "invalid applicability").emit(); - has_errors = true; - Applicability::Unspecified - }); - applicability.set_once(value, span); - } - ( - "style", - SubdiagnosticKind::Suggestion { .. } - | SubdiagnosticKind::MultipartSuggestion { .. }, - ) => { - let value = get_string!(); - - let value = value.value().parse().unwrap_or_else(|()| { - span_err(value.span().unwrap(), "invalid suggestion style") - .help("valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`") + // Invalid nested attribute + (_, SubdiagnosticKind::Suggestion { .. }) => { + span_err(arg_name_span, "invalid nested attribute") + .help( + "only `no_span`, `style`, `code` and `applicability` are valid nested attributes", + ) .emit(); - has_errors = true; - SuggestionKind::Normal - }); - - suggestion_kind.set_once(value, span); + // Consume the rest of the input to avoid spamming errors + let _ = input.parse::(); + } + (_, SubdiagnosticKind::MultipartSuggestion { .. }) => { + span_err(arg_name_span, "invalid nested attribute") + .help("only `no_span`, `style` and `applicability` are valid nested attributes") + .emit(); + // Consume the rest of the input to avoid spamming errors + let _ = input.parse::(); + } + _ => { + span_err(arg_name_span, "only `no_span` is a valid nested attribute").emit(); + // Consume the rest of the input to avoid spamming errors + let _ = input.parse::(); + } } - // Invalid nested attribute - (_, SubdiagnosticKind::Suggestion { .. }) => { - span_err(path_span, "invalid nested attribute") - .help( - "only `no_span`, `style`, `code` and `applicability` are valid nested attributes", - ) - .emit(); - has_errors = true; - } - (_, SubdiagnosticKind::MultipartSuggestion { .. }) => { - span_err(path_span, "invalid nested attribute") - .help("only `no_span`, `style` and `applicability` are valid nested attributes") - .emit(); - has_errors = true; - } - _ => { - span_err(path_span, "only `no_span` is a valid nested attribute").emit(); - has_errors = true; - } + if input.is_empty() { break } + input.parse::()?; } - - if has_errors { - // Consume the rest of the input to avoid spamming errors - let _ = input.parse::(); - } - Ok(()) })?; diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index 506ec7f88a82..72b414362c72 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -803,7 +803,7 @@ struct SuggestionsInvalidItem { sub: Span, } -#[derive(Diagnostic)] //~ ERROR cannot find value `__code_34` in this scope +#[derive(Diagnostic)] #[diag(no_crate_example)] struct SuggestionsInvalidLiteral { #[suggestion(code = 3)] diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 29132b8325f3..3ccf89cedec7 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -277,10 +277,10 @@ LL | #[help(no_crate_help)] | ^ error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute - --> $DIR/diagnostic-derive.rs:533:32 + --> $DIR/diagnostic-derive.rs:533:29 | LL | #[label(no_crate_label, foo)] - | ^ + | ^^^ error: derive(Diagnostic): only `no_span` is a valid nested attribute --> $DIR/diagnostic-derive.rs:541:29 @@ -606,14 +606,6 @@ error[E0425]: cannot find value `nonsense` in module `crate::fluent_generated` LL | #[diag(nonsense, code = E0123)] | ^^^^^^^^ not found in `crate::fluent_generated` -error[E0425]: cannot find value `__code_34` in this scope - --> $DIR/diagnostic-derive.rs:806:10 - | -LL | #[derive(Diagnostic)] - | ^^^^^^^^^^ not found in this scope - | - = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) - error[E0277]: the trait bound `Hello: IntoDiagArg` is not satisfied --> $DIR/diagnostic-derive.rs:347:12 | @@ -636,7 +628,7 @@ note: required by a bound in `Diag::<'a, G>::arg` = note: in this macro invocation = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 81 previous errors +error: aborting due to 80 previous errors Some errors have detailed explanations: E0277, E0425. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index 941668ad602e..578fc728de53 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -95,7 +95,7 @@ struct G { #[derive(Subdiagnostic)] #[label("...")] -//~^ ERROR unexpected literal in nested attribute, expected ident +//~^ ERROR expected identifier struct H { #[primary_span] span: Span, @@ -775,7 +775,7 @@ struct SuggestionStyleInvalid1 { #[derive(Subdiagnostic)] #[suggestion(no_crate_example, code = "", style = 42)] -//~^ ERROR expected `= "xxx"` +//~^ ERROR expected string literal struct SuggestionStyleInvalid2 { #[primary_span] sub: Span, @@ -791,8 +791,7 @@ struct SuggestionStyleInvalid3 { #[derive(Subdiagnostic)] #[suggestion(no_crate_example, code = "", style("foo"))] -//~^ ERROR expected `= "xxx"` -//~| ERROR expected `,` +//~^ ERROR expected `=` struct SuggestionStyleInvalid4 { #[primary_span] sub: Span, diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index c31da4421d25..568d75d838fe 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -34,7 +34,7 @@ error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label( LL | #[label(bug = "...")] | ^ -error: unexpected literal in nested attribute, expected ident +error: expected identifier --> $DIR/subdiagnostic-derive.rs:97:9 | LL | #[label("...")] @@ -175,10 +175,10 @@ LL | | } | |_^ error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute - --> $DIR/subdiagnostic-derive.rs:317:44 + --> $DIR/subdiagnostic-derive.rs:317:27 | LL | #[label(no_crate_example, no_crate::example)] - | ^ + | ^^^^^^^^ error: derive(Diagnostic): attribute specified multiple times --> $DIR/subdiagnostic-derive.rs:330:5 @@ -381,10 +381,10 @@ LL | #[applicability] | ^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:663:34 + --> $DIR/subdiagnostic-derive.rs:663:28 | LL | #[suggestion_part(code("foo"))] - | ^ + | ^^^^^ error: unexpected token, expected `)` --> $DIR/subdiagnostic-derive.rs:663:28 @@ -393,10 +393,10 @@ LL | #[suggestion_part(code("foo"))] | ^^^^^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:673:41 + --> $DIR/subdiagnostic-derive.rs:673:28 | LL | #[suggestion_part(code("foo", "bar"))] - | ^ + | ^^^^^ error: unexpected token, expected `)` --> $DIR/subdiagnostic-derive.rs:673:28 @@ -405,10 +405,10 @@ LL | #[suggestion_part(code("foo", "bar"))] | ^^^^^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:683:30 + --> $DIR/subdiagnostic-derive.rs:683:28 | LL | #[suggestion_part(code(3))] - | ^ + | ^ error: unexpected token, expected `)` --> $DIR/subdiagnostic-derive.rs:683:28 @@ -417,10 +417,10 @@ LL | #[suggestion_part(code(3))] | ^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:693:29 + --> $DIR/subdiagnostic-derive.rs:693:28 | LL | #[suggestion_part(code())] - | ^ + | ^ error: expected string literal --> $DIR/subdiagnostic-derive.rs:702:30 @@ -464,32 +464,26 @@ LL | #[suggestion(no_crate_example, code = "", style = "foo")] | = help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only` -error: derive(Diagnostic): expected `= "xxx"` - --> $DIR/subdiagnostic-derive.rs:777:49 +error: expected string literal + --> $DIR/subdiagnostic-derive.rs:777:51 | LL | #[suggestion(no_crate_example, code = "", style = 42)] - | ^ + | ^^ error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute - --> $DIR/subdiagnostic-derive.rs:785:48 + --> $DIR/subdiagnostic-derive.rs:785:43 | LL | #[suggestion(no_crate_example, code = "", style)] - | ^ + | ^^^^^ -error: derive(Diagnostic): expected `= "xxx"` - --> $DIR/subdiagnostic-derive.rs:793:48 - | -LL | #[suggestion(no_crate_example, code = "", style("foo"))] - | ^ - -error: expected `,` +error: expected `=` --> $DIR/subdiagnostic-derive.rs:793:48 | LL | #[suggestion(no_crate_example, code = "", style("foo"))] | ^ error: derive(Diagnostic): `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:805:5 + --> $DIR/subdiagnostic-derive.rs:804:5 | LL | #[primary_span] | ^ @@ -498,7 +492,7 @@ LL | #[primary_span] = help: to create a suggestion with multiple spans, use `#[multipart_suggestion]` instead error: derive(Diagnostic): suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:802:1 + --> $DIR/subdiagnostic-derive.rs:801:1 | LL | #[suggestion(no_crate_example, code = "")] | ^ @@ -557,5 +551,5 @@ error: cannot find attribute `bar` in this scope LL | #[bar("...")] | ^^^ -error: aborting due to 84 previous errors +error: aborting due to 83 previous errors From 0bf3f5d51cb853884240792818d81e70daec6ab7 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 25 Jan 2026 22:41:56 +0100 Subject: [PATCH 194/978] Remove unused `no_span` option --- .../src/diagnostics/diagnostic_builder.rs | 2 +- .../src/diagnostics/subdiagnostic.rs | 23 ++++++------------- .../rustc_macros/src/diagnostics/utils.rs | 15 +++++------- .../session-diagnostic/diagnostic-derive.rs | 4 ++-- .../diagnostic-derive.stderr | 8 +++---- .../subdiagnostic-derive.rs | 12 +++++----- .../subdiagnostic-derive.stderr | 14 +++++------ 7 files changed, 33 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index e71c84c805a7..748d1d3a60f3 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -192,7 +192,7 @@ impl DiagnosticDeriveVariantBuilder { SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(), }); - Ok(Some((subdiag.kind, slug, subdiag.no_span))) + Ok(Some((subdiag.kind, slug, false))) } /// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 189d83c42160..e00d175fc295 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -188,13 +188,11 @@ impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics { } impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { - fn identify_kind( - &mut self, - ) -> Result, DiagnosticDeriveError> { + fn identify_kind(&mut self) -> Result, DiagnosticDeriveError> { let mut kind_slugs = vec![]; for attr in self.variant.ast().attrs { - let Some(SubdiagnosticVariant { kind, slug, no_span }) = + let Some(SubdiagnosticVariant { kind, slug }) = SubdiagnosticVariant::from_attr(attr, self)? else { // Some attributes aren't errors - like documentation comments - but also aren't @@ -214,7 +212,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { ); }; - kind_slugs.push((kind, slug, no_span)); + kind_slugs.push((kind, slug)); } Ok(kind_slugs) @@ -505,8 +503,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { pub(crate) fn into_tokens(&mut self) -> Result { let kind_slugs = self.identify_kind()?; - let kind_stats: KindsStatistics = - kind_slugs.iter().map(|(kind, _slug, _no_span)| kind).collect(); + let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect(); let init = if kind_stats.has_multipart_suggestion { quote! { let mut suggestions = Vec::new(); } @@ -539,17 +536,13 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let diag = &self.parent.diag; let mut calls = TokenStream::new(); - for (kind, slug, no_span) in kind_slugs { + for (kind, slug) in kind_slugs { let message = format_ident!("__message"); calls.extend( quote! { let #message = #diag.eagerly_translate(crate::fluent_generated::#slug); }, ); - let name = format_ident!( - "{}{}", - if span_field.is_some() && !no_span { "span_" } else { "" }, - kind - ); + let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); let call = match kind { SubdiagnosticKind::Suggestion { suggestion_kind, @@ -601,9 +594,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } } _ => { - if let Some(span) = span_field - && !no_span - { + if let Some(span) = span_field { quote! { #diag.#name(#span, #message); } } else { quote! { #diag.#name(#message); } diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 6ca2c90abb90..4c73e6d453e9 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -592,12 +592,11 @@ pub(super) enum SubdiagnosticKind { pub(super) struct SubdiagnosticVariant { pub(super) kind: SubdiagnosticKind, pub(super) slug: Option, - pub(super) no_span: bool, } impl SubdiagnosticVariant { /// Constructs a `SubdiagnosticVariant` from a field or type attribute such as `#[note]`, - /// `#[error(parser::add_paren, no_span)]` or `#[suggestion(code = "...")]`. Returns the + /// `#[error(parser::add_paren)]` or `#[suggestion(code = "...")]`. Returns the /// `SubdiagnosticKind` and the diagnostic slug, if specified. pub(super) fn from_attr( attr: &Attribute, @@ -681,7 +680,7 @@ impl SubdiagnosticVariant { | SubdiagnosticKind::HelpOnce | SubdiagnosticKind::Warn | SubdiagnosticKind::MultipartSuggestion { .. } => { - return Ok(Some(SubdiagnosticVariant { kind, slug: None, no_span: false })); + return Ok(Some(SubdiagnosticVariant { kind, slug: None })); } SubdiagnosticKind::Suggestion { .. } => { throw_span_err!(span, "suggestion without `code = \"...\"`") @@ -697,7 +696,6 @@ impl SubdiagnosticVariant { let mut suggestion_kind = None; let mut slug = None; - let mut no_span = false; list.parse_args_with(|input: ParseStream<'_>| { let mut is_first = true; @@ -716,7 +714,6 @@ impl SubdiagnosticVariant { is_first = false; match (arg_name.require_ident()?.to_string().as_str(), &mut kind) { - // ("no_span", _) => no_span = true, ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => { let code_init = build_suggestion_code( &code_field, @@ -762,7 +759,7 @@ impl SubdiagnosticVariant { (_, SubdiagnosticKind::Suggestion { .. }) => { span_err(arg_name_span, "invalid nested attribute") .help( - "only `no_span`, `style`, `code` and `applicability` are valid nested attributes", + "only `style`, `code` and `applicability` are valid nested attributes", ) .emit(); // Consume the rest of the input to avoid spamming errors @@ -770,13 +767,13 @@ impl SubdiagnosticVariant { } (_, SubdiagnosticKind::MultipartSuggestion { .. }) => { span_err(arg_name_span, "invalid nested attribute") - .help("only `no_span`, `style` and `applicability` are valid nested attributes") + .help("only `style` and `applicability` are valid nested attributes") .emit(); // Consume the rest of the input to avoid spamming errors let _ = input.parse::(); } _ => { - span_err(arg_name_span, "only `no_span` is a valid nested attribute").emit(); + span_err(arg_name_span, "no nested attribute expected here").emit(); // Consume the rest of the input to avoid spamming errors let _ = input.parse::(); } @@ -821,7 +818,7 @@ impl SubdiagnosticVariant { | SubdiagnosticKind::Warn => {} } - Ok(Some(SubdiagnosticVariant { kind, slug, no_span })) + Ok(Some(SubdiagnosticVariant { kind, slug })) } } diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index 72b414362c72..798eca68b1c9 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -539,7 +539,7 @@ struct LabelWithTrailingPath { #[diag(no_crate_example, code = E0123)] struct LabelWithTrailingNameValue { #[label(no_crate_label, foo = "...")] - //~^ ERROR only `no_span` is a valid nested attribute + //~^ ERROR no nested attribute expected here span: Span, } @@ -547,7 +547,7 @@ struct LabelWithTrailingNameValue { #[diag(no_crate_example, code = E0123)] struct LabelWithTrailingList { #[label(no_crate_label, foo("..."))] - //~^ ERROR only `no_span` is a valid nested attribute + //~^ ERROR no nested attribute expected here span: Span, } diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 3ccf89cedec7..9ecb6c15767e 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -192,7 +192,7 @@ error: derive(Diagnostic): invalid nested attribute LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^ | - = help: only `no_span`, `style`, `code` and `applicability` are valid nested attributes + = help: only `style`, `code` and `applicability` are valid nested attributes error: derive(Diagnostic): suggestion without `code = "..."` --> $DIR/diagnostic-derive.rs:235:5 @@ -206,7 +206,7 @@ error: derive(Diagnostic): invalid nested attribute LL | #[suggestion(msg = "bar")] | ^^^ | - = help: only `no_span`, `style`, `code` and `applicability` are valid nested attributes + = help: only `style`, `code` and `applicability` are valid nested attributes error: derive(Diagnostic): suggestion without `code = "..."` --> $DIR/diagnostic-derive.rs:244:5 @@ -282,13 +282,13 @@ error: derive(Diagnostic): a diagnostic slug must be the first argument to the a LL | #[label(no_crate_label, foo)] | ^^^ -error: derive(Diagnostic): only `no_span` is a valid nested attribute +error: derive(Diagnostic): no nested attribute expected here --> $DIR/diagnostic-derive.rs:541:29 | LL | #[label(no_crate_label, foo = "...")] | ^^^ -error: derive(Diagnostic): only `no_span` is a valid nested attribute +error: derive(Diagnostic): no nested attribute expected here --> $DIR/diagnostic-derive.rs:549:29 | LL | #[label(no_crate_label, foo("..."))] diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index 578fc728de53..b2e7b4c61daa 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -85,7 +85,7 @@ struct F { #[derive(Subdiagnostic)] #[label(bug = "...")] -//~^ ERROR only `no_span` is a valid nested attribute +//~^ ERROR no nested attribute expected here //~| ERROR diagnostic slug must be first argument struct G { #[primary_span] @@ -104,7 +104,7 @@ struct H { #[derive(Subdiagnostic)] #[label(slug = 4)] -//~^ ERROR only `no_span` is a valid nested attribute +//~^ ERROR no nested attribute expected here //~| ERROR diagnostic slug must be first argument struct J { #[primary_span] @@ -114,7 +114,7 @@ struct J { #[derive(Subdiagnostic)] #[label(slug("..."))] -//~^ ERROR only `no_span` is a valid nested attribute +//~^ ERROR no nested attribute expected here //~| ERROR diagnostic slug must be first argument struct K { #[primary_span] @@ -133,7 +133,7 @@ struct M { #[derive(Subdiagnostic)] #[label(no_crate_example, code = "...")] -//~^ ERROR only `no_span` is a valid nested attribute +//~^ ERROR no nested attribute expected here struct N { #[primary_span] span: Span, @@ -142,7 +142,7 @@ struct N { #[derive(Subdiagnostic)] #[label(no_crate_example, applicability = "machine-applicable")] -//~^ ERROR only `no_span` is a valid nested attribute +//~^ ERROR no nested attribute expected here struct O { #[primary_span] span: Span, @@ -214,7 +214,7 @@ enum T { enum U { #[label(code = "...")] //~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute - //~| ERROR only `no_span` is a valid nested attribute + //~| ERROR no nested attribute expected here A { #[primary_span] span: Span, diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index 568d75d838fe..63634741e934 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -22,7 +22,7 @@ error: derive(Diagnostic): `#[label = ...]` is not a valid attribute LL | #[label = "..."] | ^ -error: derive(Diagnostic): only `no_span` is a valid nested attribute +error: derive(Diagnostic): no nested attribute expected here --> $DIR/subdiagnostic-derive.rs:87:9 | LL | #[label(bug = "...")] @@ -40,7 +40,7 @@ error: expected identifier LL | #[label("...")] | ^^^^^ -error: derive(Diagnostic): only `no_span` is a valid nested attribute +error: derive(Diagnostic): no nested attribute expected here --> $DIR/subdiagnostic-derive.rs:106:9 | LL | #[label(slug = 4)] @@ -52,7 +52,7 @@ error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label( LL | #[label(slug = 4)] | ^ -error: derive(Diagnostic): only `no_span` is a valid nested attribute +error: derive(Diagnostic): no nested attribute expected here --> $DIR/subdiagnostic-derive.rs:116:9 | LL | #[label(slug("..."))] @@ -70,13 +70,13 @@ error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label( LL | #[label()] | ^ -error: derive(Diagnostic): only `no_span` is a valid nested attribute +error: derive(Diagnostic): no nested attribute expected here --> $DIR/subdiagnostic-derive.rs:135:27 | LL | #[label(no_crate_example, code = "...")] | ^^^^ -error: derive(Diagnostic): only `no_span` is a valid nested attribute +error: derive(Diagnostic): no nested attribute expected here --> $DIR/subdiagnostic-derive.rs:144:27 | LL | #[label(no_crate_example, applicability = "machine-applicable")] @@ -112,7 +112,7 @@ error: derive(Diagnostic): `#[bar(...)]` is not a valid attribute LL | #[bar("...")] | ^ -error: derive(Diagnostic): only `no_span` is a valid nested attribute +error: derive(Diagnostic): no nested attribute expected here --> $DIR/subdiagnostic-derive.rs:215:13 | LL | #[label(code = "...")] @@ -292,7 +292,7 @@ error: derive(Diagnostic): invalid nested attribute LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] | ^^^^ | - = help: only `no_span`, `style` and `applicability` are valid nested attributes + = help: only `style` and `applicability` are valid nested attributes error: derive(Diagnostic): multipart suggestion without any `#[suggestion_part(...)]` fields --> $DIR/subdiagnostic-derive.rs:530:1 From 2e8347abf4147d2bffe4d7989a21b17ae04cdb57 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 28 Jan 2026 22:30:29 +0100 Subject: [PATCH 195/978] Remove `HasFieldMap` trait in favour of passing `FieldMap` directly --- .../src/diagnostics/diagnostic_builder.rs | 10 +- .../src/diagnostics/subdiagnostic.rs | 18 +- .../rustc_macros/src/diagnostics/utils.rs | 190 +++++++++--------- 3 files changed, 101 insertions(+), 117 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 748d1d3a60f3..25110fd4f908 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -12,7 +12,7 @@ use crate::diagnostics::error::{ DiagnosticDeriveError, span_err, throw_invalid_attr, throw_span_err, }; use crate::diagnostics::utils::{ - FieldInfo, FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind, + FieldInfo, FieldInnerTy, FieldMap, SetOnce, SpannedOption, SubdiagnosticKind, build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error, should_generate_arg, type_is_bool, type_is_unit, type_matches_path, }; @@ -50,12 +50,6 @@ pub(crate) struct DiagnosticDeriveVariantBuilder { pub code: SpannedOption<()>, } -impl HasFieldMap for DiagnosticDeriveVariantBuilder { - fn get_field_binding(&self, field: &String) -> Option<&TokenStream> { - self.field_map.get(field) - } -} - impl DiagnosticDeriveKind { /// 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 @@ -170,7 +164,7 @@ impl DiagnosticDeriveVariantBuilder { &self, attr: &Attribute, ) -> Result, DiagnosticDeriveError> { - let Some(subdiag) = SubdiagnosticVariant::from_attr(attr, self)? else { + let Some(subdiag) = SubdiagnosticVariant::from_attr(attr, &self.field_map)? else { // Some attributes aren't errors - like documentation comments - but also aren't // subdiagnostics. return Ok(None); diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index e00d175fc295..db2a19ab85ba 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -12,10 +12,10 @@ use crate::diagnostics::error::{ DiagnosticDeriveError, invalid_attr, span_err, throw_invalid_attr, throw_span_err, }; use crate::diagnostics::utils::{ - AllowMultipleAlternatives, FieldInfo, FieldInnerTy, FieldMap, HasFieldMap, SetOnce, - SpannedOption, SubdiagnosticKind, build_field_mapping, build_suggestion_code, is_doc_comment, - new_code_ident, report_error_if_not_applied_to_applicability, - report_error_if_not_applied_to_span, should_generate_arg, + AllowMultipleAlternatives, FieldInfo, FieldInnerTy, FieldMap, SetOnce, SpannedOption, + SubdiagnosticKind, build_field_mapping, build_suggestion_code, is_doc_comment, new_code_ident, + report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, + should_generate_arg, }; /// The central struct for constructing the `add_to_diag` method from an annotated struct. @@ -143,12 +143,6 @@ struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> { is_enum: bool, } -impl<'parent, 'a> HasFieldMap for SubdiagnosticDeriveVariantBuilder<'parent, 'a> { - fn get_field_binding(&self, field: &String) -> Option<&TokenStream> { - self.fields.get(field) - } -} - /// Provides frequently-needed information about the diagnostic kinds being derived for this type. #[derive(Clone, Copy, Debug)] struct KindsStatistics { @@ -193,7 +187,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { for attr in self.variant.ast().attrs { let Some(SubdiagnosticVariant { kind, slug }) = - SubdiagnosticVariant::from_attr(attr, self)? + SubdiagnosticVariant::from_attr(attr, &self.fields)? else { // Some attributes aren't errors - like documentation comments - but also aren't // subdiagnostics. @@ -445,7 +439,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let formatting_init = build_suggestion_code( &code_field, input, - self, + &self.fields, AllowMultipleAlternatives::No, )?; code.set_once( diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 4c73e6d453e9..f084ba60ae3f 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -261,108 +261,104 @@ impl SetOnce for SpannedOption { pub(super) type FieldMap = HashMap; -pub(crate) trait HasFieldMap { - /// Returns the binding for the field with the given name, if it exists on the type. - fn get_field_binding(&self, field: &String) -> Option<&TokenStream>; +/// In the strings in the attributes supplied to this macro, we want callers to be able to +/// reference fields in the format string. For example: +/// +/// ```ignore (not-usage-example) +/// /// Suggest `==` when users wrote `===`. +/// #[suggestion(slug = "parser-not-javascript-eq", code = "{lhs} == {rhs}")] +/// struct NotJavaScriptEq { +/// #[primary_span] +/// span: Span, +/// lhs: Ident, +/// rhs: Ident, +/// } +/// ``` +/// +/// We want to automatically pick up that `{lhs}` refers `self.lhs` and `{rhs}` refers to +/// `self.rhs`, then generate this call to `format!`: +/// +/// ```ignore (not-usage-example) +/// format!("{lhs} == {rhs}", lhs = self.lhs, rhs = self.rhs) +/// ``` +/// +/// This function builds the entire call to `format!`. +pub(super) fn build_format( + field_map: &FieldMap, + input: &str, + span: proc_macro2::Span, +) -> TokenStream { + // This set is used later to generate the final format string. To keep builds reproducible, + // the iteration order needs to be deterministic, hence why we use a `BTreeSet` here + // instead of a `HashSet`. + let mut referenced_fields: BTreeSet = BTreeSet::new(); - /// In the strings in the attributes supplied to this macro, we want callers to be able to - /// reference fields in the format string. For example: - /// - /// ```ignore (not-usage-example) - /// /// Suggest `==` when users wrote `===`. - /// #[suggestion(slug = "parser-not-javascript-eq", code = "{lhs} == {rhs}")] - /// struct NotJavaScriptEq { - /// #[primary_span] - /// span: Span, - /// lhs: Ident, - /// rhs: Ident, - /// } - /// ``` - /// - /// We want to automatically pick up that `{lhs}` refers `self.lhs` and `{rhs}` refers to - /// `self.rhs`, then generate this call to `format!`: - /// - /// ```ignore (not-usage-example) - /// format!("{lhs} == {rhs}", lhs = self.lhs, rhs = self.rhs) - /// ``` - /// - /// This function builds the entire call to `format!`. - fn build_format(&self, input: &str, span: proc_macro2::Span) -> TokenStream { - // This set is used later to generate the final format string. To keep builds reproducible, - // the iteration order needs to be deterministic, hence why we use a `BTreeSet` here - // instead of a `HashSet`. - let mut referenced_fields: BTreeSet = BTreeSet::new(); + // At this point, we can start parsing the format string. + let mut it = input.chars().peekable(); - // At this point, we can start parsing the format string. - let mut it = input.chars().peekable(); - - // Once the start of a format string has been found, process the format string and spit out - // the referenced fields. Leaves `it` sitting on the closing brace of the format string, so - // the next call to `it.next()` retrieves the next character. - while let Some(c) = it.next() { - if c != '{' { - continue; - } - if *it.peek().unwrap_or(&'\0') == '{' { - assert_eq!(it.next().unwrap(), '{'); - continue; - } - let mut eat_argument = || -> Option { - let mut result = String::new(); - // Format specifiers look like: - // - // format := '{' [ argument ] [ ':' format_spec ] '}' . - // - // Therefore, we only need to eat until ':' or '}' to find the argument. - while let Some(c) = it.next() { - result.push(c); - let next = *it.peek().unwrap_or(&'\0'); - if next == '}' { - break; - } else if next == ':' { - // Eat the ':' character. - assert_eq!(it.next().unwrap(), ':'); - break; - } - } - // Eat until (and including) the matching '}' - while it.next()? != '}' { - continue; - } - Some(result) - }; - - if let Some(referenced_field) = eat_argument() { - referenced_fields.insert(referenced_field); - } + // Once the start of a format string has been found, process the format string and spit out + // the referenced fields. Leaves `it` sitting on the closing brace of the format string, so + // the next call to `it.next()` retrieves the next character. + while let Some(c) = it.next() { + if c != '{' { + continue; } + if *it.peek().unwrap_or(&'\0') == '{' { + assert_eq!(it.next().unwrap(), '{'); + continue; + } + let mut eat_argument = || -> Option { + let mut result = String::new(); + // Format specifiers look like: + // + // format := '{' [ argument ] [ ':' format_spec ] '}' . + // + // Therefore, we only need to eat until ':' or '}' to find the argument. + while let Some(c) = it.next() { + result.push(c); + let next = *it.peek().unwrap_or(&'\0'); + if next == '}' { + break; + } else if next == ':' { + // Eat the ':' character. + assert_eq!(it.next().unwrap(), ':'); + break; + } + } + // Eat until (and including) the matching '}' + while it.next()? != '}' { + continue; + } + Some(result) + }; - // At this point, `referenced_fields` contains a set of the unique fields that were - // referenced in the format string. Generate the corresponding "x = self.x" format - // string parameters: - let args = referenced_fields.into_iter().map(|field: String| { - let field_ident = format_ident!("{}", field); - let value = match self.get_field_binding(&field) { - Some(value) => value.clone(), - // This field doesn't exist. Emit a diagnostic. - None => { - span_err( - span.unwrap(), - format!("`{field}` doesn't refer to a field on this type"), - ) + if let Some(referenced_field) = eat_argument() { + referenced_fields.insert(referenced_field); + } + } + + // At this point, `referenced_fields` contains a set of the unique fields that were + // referenced in the format string. Generate the corresponding "x = self.x" format + // string parameters: + let args = referenced_fields.into_iter().map(|field: String| { + let field_ident = format_ident!("{}", field); + let value = match field_map.get(&field) { + Some(value) => value.clone(), + // This field doesn't exist. Emit a diagnostic. + None => { + span_err(span.unwrap(), format!("`{field}` doesn't refer to a field on this type")) .emit(); - quote! { - "{#field}" - } + quote! { + "{#field}" } - }; - quote! { - #field_ident = #value } - }); + }; quote! { - format!(#input #(,#args)*) + #field_ident = #value } + }); + quote! { + format!(#input #(,#args)*) } } @@ -467,7 +463,7 @@ fn parse_suggestion_values( pub(super) fn build_suggestion_code( code_field: &Ident, nested: ParseStream<'_>, - fields: &impl HasFieldMap, + fields: &FieldMap, allow_multiple: AllowMultipleAlternatives, ) -> Result { let values = parse_suggestion_values(nested, allow_multiple)?; @@ -475,11 +471,11 @@ pub(super) fn build_suggestion_code( Ok(if let AllowMultipleAlternatives::Yes = allow_multiple { let formatted_strings: Vec<_> = values .into_iter() - .map(|value| fields.build_format(&value.value(), value.span())) + .map(|value| build_format(fields, &value.value(), value.span())) .collect(); quote! { let #code_field = [#(#formatted_strings),*].into_iter(); } } else if let [value] = values.as_slice() { - let formatted_str = fields.build_format(&value.value(), value.span()); + let formatted_str = build_format(fields, &value.value(), value.span()); quote! { let #code_field = #formatted_str; } } else { // error handled previously @@ -600,7 +596,7 @@ impl SubdiagnosticVariant { /// `SubdiagnosticKind` and the diagnostic slug, if specified. pub(super) fn from_attr( attr: &Attribute, - fields: &impl HasFieldMap, + fields: &FieldMap, ) -> Result, DiagnosticDeriveError> { // Always allow documentation comments. if is_doc_comment(attr) { From 6eb9c02a96b6086481a80b64019d950d6c385d7a Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 28 Jan 2026 22:40:28 +0100 Subject: [PATCH 196/978] Subscribe myself to translation diagnostics --- triagebot.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 1572c4c8d045..eb25d6e1b201 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1182,11 +1182,11 @@ cc = ["@Muscraft"] [mentions."compiler/rustc_errors/src/translation.rs"] message = "`rustc_errors::translation` was changed" -cc = ["@davidtwco", "@TaKO8Ki"] +cc = ["@davidtwco", "@TaKO8Ki", "@JonathanBrouwer"] [mentions."compiler/rustc_macros/src/diagnostics"] message = "`rustc_macros::diagnostics` was changed" -cc = ["@davidtwco", "@TaKO8Ki"] +cc = ["@davidtwco", "@TaKO8Ki", "@JonathanBrouwer"] [mentions."compiler/rustc_public"] message = "This PR changes rustc_public" From 49c9b0a7bf0dba213361fa181a2770c76652a0cf Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 28 Jan 2026 17:01:51 -0500 Subject: [PATCH 197/978] Update to nightly-2026-01-28 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 86ae738d4483..2168c8e72cfb 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-12-20" +channel = "nightly-2026-01-28" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From bd71a5f4b0e38ea80ed3f0a0df33440b93d88312 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 28 Jan 2026 17:02:09 -0500 Subject: [PATCH 198/978] Implement new f16/f128 intrinsics and implement dummy va_end --- src/intrinsic/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 7b8d8602bcae..9a08003a7fb2 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -167,6 +167,7 @@ fn get_simple_function_f128<'gcc, 'tcx>( let f128_type = cx.type_f128(); let func_name = match name { sym::ceilf128 => "ceilf128", + sym::fabsf128 => "fabsf128", sym::floorf128 => "floorf128", sym::truncf128 => "truncf128", sym::roundf128 => "roundf128", @@ -221,6 +222,7 @@ fn f16_builtin<'gcc, 'tcx>( let builtin_name = match name { sym::ceilf16 => "__builtin_ceilf", sym::copysignf16 => "__builtin_copysignf", + sym::fabsf16 => "fabsf", sym::floorf16 => "__builtin_floorf", sym::fmaf16 => "fmaf", sym::maxnumf16 => "__builtin_fmaxf", @@ -287,6 +289,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } sym::ceilf16 | sym::copysignf16 + | sym::fabsf16 | sym::floorf16 | sym::fmaf16 | sym::maxnumf16 @@ -687,7 +690,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } fn va_end(&mut self, _va_list: RValue<'gcc>) -> RValue<'gcc> { - unimplemented!(); + // TODO(antoyo): implement. + self.context.new_rvalue_from_int(self.int_type, 0) } } From b71ff51277dbd5907a7a8089b5d926a02e53d44d Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Wed, 28 Jan 2026 00:58:13 -0500 Subject: [PATCH 199/978] Update std and tests to match std::simd API (remove LaneCount bound and rename to_int to to_simd) --- library/core/src/slice/mod.rs | 2 -- src/tools/miri/tests/pass/intrinsics/portable-simd.rs | 10 +++++----- tests/ui/simd/dont-invalid-bitcast-masks.rs | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 139d2a4b4272..429f90acec34 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -4443,7 +4443,6 @@ impl [T] { where Simd: AsRef<[T; LANES]>, T: simd::SimdElement, - simd::LaneCount: simd::SupportedLaneCount, { // These are expected to always match, as vector types are laid out like // arrays per , but we @@ -4479,7 +4478,6 @@ impl [T] { where Simd: AsMut<[T; LANES]>, T: simd::SimdElement, - simd::LaneCount: simd::SupportedLaneCount, { // These are expected to always match, as vector types are laid out like // arrays per , but we diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs index 56c000633e58..6c5e06518f56 100644 --- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs +++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs @@ -471,7 +471,7 @@ fn simd_ops_i32() { fn simd_mask() { use std::intrinsics::simd::*; - let intmask = Mask::from_int(i32x4::from_array([0, -1, 0, 0])); + let intmask = Mask::from_simd(i32x4::from_array([0, -1, 0, 0])); assert_eq!(intmask, Mask::from_array([false, true, false, false])); assert_eq!(intmask.to_array(), [false, true, false, false]); @@ -486,8 +486,8 @@ fn simd_mask() { // Also directly call intrinsic, to test both kinds of return types. unsafe { - let bitmask1: u16 = simd_bitmask(mask.to_int()); - let bitmask2: [u8; 2] = simd_bitmask(mask.to_int()); + let bitmask1: u16 = simd_bitmask(mask.to_simd()); + let bitmask2: [u8; 2] = simd_bitmask(mask.to_simd()); if cfg!(target_endian = "little") { assert_eq!(bitmask1, 0b1010001101001001); assert_eq!(bitmask2, [0b01001001, 0b10100011]); @@ -506,8 +506,8 @@ fn simd_mask() { assert_eq!(bitmask, 0b1000); assert_eq!(Mask::::from_bitmask(bitmask), mask); unsafe { - let bitmask1: u8 = simd_bitmask(mask.to_int()); - let bitmask2: [u8; 1] = simd_bitmask(mask.to_int()); + let bitmask1: u8 = simd_bitmask(mask.to_simd()); + let bitmask2: [u8; 1] = simd_bitmask(mask.to_simd()); if cfg!(target_endian = "little") { assert_eq!(bitmask1, 0b1000); assert_eq!(bitmask2, [0b1000]); diff --git a/tests/ui/simd/dont-invalid-bitcast-masks.rs b/tests/ui/simd/dont-invalid-bitcast-masks.rs index 3d8376207cd0..1e2d097198d0 100644 --- a/tests/ui/simd/dont-invalid-bitcast-masks.rs +++ b/tests/ui/simd/dont-invalid-bitcast-masks.rs @@ -12,6 +12,6 @@ use std::simd::num::*; pub unsafe fn mask_to_array(mask: u8) -> [i32; 8] { let mut output = [0; 8]; let m = masksizex8::from_bitmask(mask as _); - output.copy_from_slice(&m.to_int().cast::().to_array()); + output.copy_from_slice(&m.to_simd().cast::().to_array()); output } From 2a96ea0beefef3c9bfbbca803565e7afb6732b17 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 29 Jan 2026 10:35:05 +1100 Subject: [PATCH 200/978] Make `QueryDispatcher::Qcx` an associated type --- compiler/rustc_query_impl/src/lib.rs | 15 +-- compiler/rustc_query_impl/src/plumbing.rs | 11 +- .../src/query/dispatcher.rs | 44 ++++--- .../rustc_query_system/src/query/plumbing.rs | 108 ++++++++---------- 4 files changed, 86 insertions(+), 92 deletions(-) diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index b628224db536..d6310b62b275 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -67,11 +67,11 @@ impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDA // This is `impl QueryDispatcher for SemiDynamicQueryDispatcher`. impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> - QueryDispatcher> - for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE> + QueryDispatcher for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE> where for<'a> C::Key: HashStable>, { + type Qcx = QueryCtxt<'tcx>; type Key = C::Key; type Value = C::Value; type Cache = C; @@ -104,10 +104,7 @@ where } #[inline(always)] - fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache - where - 'tcx: 'a, - { + fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache { // Safety: // This is just manually doing the subfield referencing through pointer math. unsafe { @@ -215,15 +212,13 @@ where /// on the type `rustc_query_impl::query_impl::$name::QueryType`. trait QueryDispatcherUnerased<'tcx> { type UnerasedValue; - type Dispatcher: QueryDispatcher>; + type Dispatcher: QueryDispatcher>; const NAME: &'static &'static str; fn query_dispatcher(tcx: TyCtxt<'tcx>) -> Self::Dispatcher; - fn restore_val( - value: >>::Value, - ) -> Self::UnerasedValue; + fn restore_val(value: ::Value) -> Self::UnerasedValue; } pub fn query_system<'a>( diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 6ead03a527a7..0223981fd55d 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -414,7 +414,7 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>( } pub(crate) fn query_key_hash_verify<'tcx>( - query: impl QueryDispatcher>, + query: impl QueryDispatcher>, qcx: QueryCtxt<'tcx>, ) { let _timer = qcx.tcx.prof.generic_activity_with_arg("query_key_hash_verify_for", query.name()); @@ -442,7 +442,7 @@ pub(crate) fn query_key_hash_verify<'tcx>( fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) where - Q: QueryDispatcher>, + Q: QueryDispatcher>, { debug_assert!(tcx.dep_graph.is_green(&dep_node)); @@ -488,7 +488,7 @@ where fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool where - Q: QueryDispatcher>, + Q: QueryDispatcher>, { // We must avoid ever having to call `force_from_dep_node()` for a // `DepNode::codegen_unit`: @@ -523,8 +523,7 @@ pub(crate) fn make_dep_kind_vtable_for_query<'tcx, Q>( where Q: QueryDispatcherUnerased<'tcx>, { - let fingerprint_style = - >>::Key::fingerprint_style(); + let fingerprint_style = ::Key::fingerprint_style(); if is_anon || !fingerprint_style.reconstructible() { return DepKindVTable { @@ -731,7 +730,7 @@ macro_rules! define_queries { } #[inline(always)] - fn restore_val(value: >>::Value) -> Self::UnerasedValue { + fn restore_val(value: ::Value) -> Self::UnerasedValue { restore::>(value) } } diff --git a/compiler/rustc_query_system/src/query/dispatcher.rs b/compiler/rustc_query_system/src/query/dispatcher.rs index bba1703dfbb6..1ca76a70364c 100644 --- a/compiler/rustc_query_system/src/query/dispatcher.rs +++ b/compiler/rustc_query_system/src/query/dispatcher.rs @@ -5,13 +5,18 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_span::ErrorGuaranteed; use super::QueryStackFrameExtra; -use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex}; +use crate::dep_graph::{DepKind, DepNode, DepNodeParams, HasDepContext, SerializedDepNodeIndex}; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; use crate::query::{CycleError, CycleErrorHandling, DepNodeIndex, QueryContext, QueryState}; pub type HashResult = Option, &V) -> Fingerprint>; +/// Unambiguous shorthand for `::DepContext`. +#[expect(type_alias_bounds)] +type DepContextOf = + <::Qcx as HasDepContext>::DepContext; + /// Trait that can be used as a vtable for a single query, providing operations /// and metadata for that query. /// @@ -20,12 +25,15 @@ pub type HashResult = Option, &V) -> Fingerp /// Those types are not visible from this `rustc_query_system` crate. /// /// "Dispatcher" should be understood as a near-synonym of "vtable". -pub trait QueryDispatcher: Copy { +pub trait QueryDispatcher: Copy { fn name(self) -> &'static str; + /// Query context used by this dispatcher, i.e. `rustc_query_impl::QueryCtxt`. + type Qcx: QueryContext; + // `Key` and `Value` are `Copy` instead of `Clone` to ensure copying them stays cheap, // but it isn't necessary. - type Key: DepNodeParams + Eq + Hash + Copy + Debug; + type Key: DepNodeParams> + Eq + Hash + Copy + Debug; type Value: Copy; type Cache: QueryCache; @@ -33,36 +41,40 @@ pub trait QueryDispatcher: Copy { fn format_value(self) -> fn(&Self::Value) -> String; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_state<'a>(self, tcx: Qcx) -> &'a QueryState - where - Qcx: 'a; + fn query_state<'a>( + self, + tcx: Self::Qcx, + ) -> &'a QueryState::QueryInfo>; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_cache<'a>(self, tcx: Qcx) -> &'a Self::Cache - where - Qcx: 'a; + fn query_cache<'a>(self, tcx: Self::Qcx) -> &'a Self::Cache; - fn cache_on_disk(self, tcx: Qcx::DepContext, key: &Self::Key) -> bool; + fn cache_on_disk(self, tcx: DepContextOf, key: &Self::Key) -> bool; // Don't use this method to compute query results, instead use the methods on TyCtxt - fn execute_query(self, tcx: Qcx::DepContext, k: Self::Key) -> Self::Value; + fn execute_query(self, tcx: DepContextOf, k: Self::Key) -> Self::Value; - fn compute(self, tcx: Qcx, key: Self::Key) -> Self::Value; + fn compute(self, tcx: Self::Qcx, key: Self::Key) -> Self::Value; fn try_load_from_disk( self, - tcx: Qcx, + tcx: Self::Qcx, key: &Self::Key, prev_index: SerializedDepNodeIndex, index: DepNodeIndex, ) -> Option; - fn loadable_from_disk(self, qcx: Qcx, key: &Self::Key, idx: SerializedDepNodeIndex) -> bool; + fn loadable_from_disk( + self, + qcx: Self::Qcx, + key: &Self::Key, + idx: SerializedDepNodeIndex, + ) -> bool; /// Synthesize an error value to let compilation continue after a cycle. fn value_from_cycle_error( self, - tcx: Qcx::DepContext, + tcx: DepContextOf, cycle_error: &CycleError, guar: ErrorGuaranteed, ) -> Self::Value; @@ -77,7 +89,7 @@ pub trait QueryDispatcher: Copy { fn hash_result(self) -> HashResult; // Just here for convenience and checking that the key matches the kind, don't override this. - fn construct_dep_node(self, tcx: Qcx::DepContext, key: &Self::Key) -> DepNode { + fn construct_dep_node(self, tcx: DepContextOf, key: &Self::Key) -> DepNode { DepNode::construct(tcx, self.dep_kind(), key) } } diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 9afad1546e9e..7e9f83e8fe82 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -19,7 +19,9 @@ use rustc_span::{DUMMY_SP, Span}; use tracing::instrument; use super::{QueryDispatcher, QueryStackFrameExtra}; -use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams}; +use crate::dep_graph::{ + DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams, HasDepContext, +}; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; use crate::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, report_cycle}; @@ -124,24 +126,22 @@ where #[cold] #[inline(never)] -fn mk_cycle(query: Q, qcx: Qcx, cycle_error: CycleError) -> Q::Value +fn mk_cycle(query: Q, qcx: Q::Qcx, cycle_error: CycleError) -> Q::Value where - Q: QueryDispatcher, - Qcx: QueryContext, + Q: QueryDispatcher, { let error = report_cycle(qcx.dep_context().sess(), &cycle_error); handle_cycle_error(query, qcx, &cycle_error, error) } -fn handle_cycle_error( +fn handle_cycle_error( query: Q, - qcx: Qcx, + qcx: Q::Qcx, cycle_error: &CycleError, error: Diag<'_>, ) -> Q::Value where - Q: QueryDispatcher, - Qcx: QueryContext, + Q: QueryDispatcher, { match query.cycle_error_handling() { CycleErrorHandling::Error => { @@ -272,15 +272,14 @@ where #[cold] #[inline(never)] -fn cycle_error( +fn cycle_error( query: Q, - qcx: Qcx, + qcx: Q::Qcx, try_execute: QueryJobId, span: Span, ) -> (Q::Value, Option) where - Q: QueryDispatcher, - Qcx: QueryContext, + Q: QueryDispatcher, { // Ensure there was no errors collecting all active jobs. // We need the complete map to ensure we find a cycle to break. @@ -291,17 +290,16 @@ where } #[inline(always)] -fn wait_for_query( +fn wait_for_query( query: Q, - qcx: Qcx, + qcx: Q::Qcx, span: Span, key: Q::Key, - latch: QueryLatch, + latch: QueryLatch<::QueryInfo>, current: Option, ) -> (Q::Value, Option) where - Q: QueryDispatcher, - Qcx: QueryContext, + Q: QueryDispatcher, { // For parallel queries, we'll block and wait until the query running // in another thread has completed. Record how long we wait in the @@ -341,16 +339,15 @@ where } #[inline(never)] -fn try_execute_query( +fn try_execute_query( query: Q, - qcx: Qcx, + qcx: Q::Qcx, span: Span, key: Q::Key, dep_node: Option, ) -> (Q::Value, Option) where - Q: QueryDispatcher, - Qcx: QueryContext, + Q: QueryDispatcher, { let state = query.query_state(qcx); let key_hash = sharded::make_hash(&key); @@ -382,7 +379,7 @@ where // Drop the lock before we start executing the query drop(state_lock); - execute_job::<_, _, INCR>(query, qcx, state, key, key_hash, id, dep_node) + execute_job::(query, qcx, state, key, key_hash, id, dep_node) } Entry::Occupied(mut entry) => { match &mut entry.get_mut().1 { @@ -411,18 +408,17 @@ where } #[inline(always)] -fn execute_job( +fn execute_job( query: Q, - qcx: Qcx, - state: &QueryState, + qcx: Q::Qcx, + state: &QueryState::QueryInfo>, key: Q::Key, key_hash: u64, id: QueryJobId, dep_node: Option, ) -> (Q::Value, Option) where - Q: QueryDispatcher, - Qcx: QueryContext, + Q: QueryDispatcher, { // Use `JobOwner` so the query will be poisoned if executing it panics. let job_owner = JobOwner { state, key }; @@ -484,15 +480,14 @@ where // Fast path for when incr. comp. is off. #[inline(always)] -fn execute_job_non_incr( +fn execute_job_non_incr( query: Q, - qcx: Qcx, + qcx: Q::Qcx, key: Q::Key, job_id: QueryJobId, ) -> (Q::Value, DepNodeIndex) where - Q: QueryDispatcher, - Qcx: QueryContext, + Q: QueryDispatcher, { debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled()); @@ -521,17 +516,16 @@ where } #[inline(always)] -fn execute_job_incr( +fn execute_job_incr( query: Q, - qcx: Qcx, - dep_graph_data: &DepGraphData, + qcx: Q::Qcx, + dep_graph_data: &DepGraphData<::Deps>, key: Q::Key, mut dep_node_opt: Option, job_id: QueryJobId, ) -> (Q::Value, DepNodeIndex) where - Q: QueryDispatcher, - Qcx: QueryContext, + Q: QueryDispatcher, { if !query.anon() && !query.eval_always() { // `to_dep_node` is expensive for some `DepKind`s. @@ -577,16 +571,15 @@ where } #[inline(always)] -fn try_load_from_disk_and_cache_in_memory( +fn try_load_from_disk_and_cache_in_memory( query: Q, - dep_graph_data: &DepGraphData, - qcx: Qcx, + dep_graph_data: &DepGraphData<::Deps>, + qcx: Q::Qcx, key: &Q::Key, dep_node: &DepNode, ) -> Option<(Q::Value, DepNodeIndex)> where - Q: QueryDispatcher, - Qcx: QueryContext, + Q: QueryDispatcher, { // Note this function can be called concurrently from the same query // We must ensure that this is handled correctly. @@ -764,15 +757,14 @@ fn incremental_verify_ich_failed( /// /// Note: The optimization is only available during incr. comp. #[inline(never)] -fn ensure_must_run( +fn ensure_must_run( query: Q, - qcx: Qcx, + qcx: Q::Qcx, key: &Q::Key, check_cache: bool, ) -> (bool, Option) where - Q: QueryDispatcher, - Qcx: QueryContext, + Q: QueryDispatcher, { if query.eval_always() { return (true, None); @@ -817,27 +809,25 @@ pub enum QueryMode { } #[inline(always)] -pub fn get_query_non_incr(query: Q, qcx: Qcx, span: Span, key: Q::Key) -> Q::Value +pub fn get_query_non_incr(query: Q, qcx: Q::Qcx, span: Span, key: Q::Key) -> Q::Value where - Q: QueryDispatcher, - Qcx: QueryContext, + Q: QueryDispatcher, { debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled()); - ensure_sufficient_stack(|| try_execute_query::(query, qcx, span, key, None).0) + ensure_sufficient_stack(|| try_execute_query::(query, qcx, span, key, None).0) } #[inline(always)] -pub fn get_query_incr( +pub fn get_query_incr( query: Q, - qcx: Qcx, + qcx: Q::Qcx, span: Span, key: Q::Key, mode: QueryMode, ) -> Option where - Q: QueryDispatcher, - Qcx: QueryContext, + Q: QueryDispatcher, { debug_assert!(qcx.dep_context().dep_graph().is_fully_enabled()); @@ -851,19 +841,17 @@ where None }; - let (result, dep_node_index) = ensure_sufficient_stack(|| { - try_execute_query::<_, _, true>(query, qcx, span, key, dep_node) - }); + let (result, dep_node_index) = + ensure_sufficient_stack(|| try_execute_query::(query, qcx, span, key, dep_node)); if let Some(dep_node_index) = dep_node_index { qcx.dep_context().dep_graph().read_index(dep_node_index) } Some(result) } -pub fn force_query(query: Q, qcx: Qcx, key: Q::Key, dep_node: DepNode) +pub fn force_query(query: Q, qcx: Q::Qcx, key: Q::Key, dep_node: DepNode) where - Q: QueryDispatcher, - Qcx: QueryContext, + Q: QueryDispatcher, { // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. @@ -875,6 +863,6 @@ where debug_assert!(!query.anon()); ensure_sufficient_stack(|| { - try_execute_query::<_, _, true>(query, qcx, DUMMY_SP, key, Some(dep_node)) + try_execute_query::(query, qcx, DUMMY_SP, key, Some(dep_node)) }); } From 99591e6d427568ddfee8212ebe12d4300c111f16 Mon Sep 17 00:00:00 2001 From: sgasho Date: Sat, 24 Jan 2026 23:44:31 +0900 Subject: [PATCH 201/978] Fix -Zmir-enable-passes to detect unregistered enum names --- compiler/rustc_mir_transform/src/lib.rs | 30 +++++++++++++------ tests/ui/lint/invalid_value-polymorphic.rs | 2 +- ...s_validation.enum_not_in_pass_names.stderr | 8 +++++ tests/ui/mir/enable_passes_validation.rs | 9 ++++++ 4 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 tests/ui/mir/enable_passes_validation.enum_not_in_pass_names.stderr diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 2f8c6b876398..0e6a1a414e45 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -91,20 +91,32 @@ macro_rules! declare_passes { )+ )* - static PASS_NAMES: LazyLock> = LazyLock::new(|| [ + static PASS_NAMES: LazyLock> = LazyLock::new(|| { + let mut set = FxIndexSet::default(); // Fake marker pass - "PreCodegen", + set.insert("PreCodegen"); $( $( - stringify!($pass_name), - $( - $( - $mod_name::$pass_name::$ident.name(), - )* - )? + set.extend(pass_names!($mod_name : $pass_name $( { $($ident),* } )? )); )+ )* - ].into_iter().collect()); + set + }); + }; +} + +macro_rules! pass_names { + // pass groups: only pass names inside are considered pass_names + ($mod_name:ident : $pass_group:ident { $($pass_name:ident),* $(,)? }) => { + [ + $( + $mod_name::$pass_group::$pass_name.name(), + )* + ] + }; + // lone pass names: stringify the struct or enum name + ($mod_name:ident : $pass_name:ident) => { + [stringify!($pass_name)] }; } diff --git a/tests/ui/lint/invalid_value-polymorphic.rs b/tests/ui/lint/invalid_value-polymorphic.rs index 6a31ac17d96f..4ed8950d20fa 100644 --- a/tests/ui/lint/invalid_value-polymorphic.rs +++ b/tests/ui/lint/invalid_value-polymorphic.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --crate-type=lib -Zmir-enable-passes=+InstSimplify +//@ compile-flags: --crate-type=lib -Zmir-enable-passes=+InstSimplify-before-inline //@ build-pass #![feature(core_intrinsics)] diff --git a/tests/ui/mir/enable_passes_validation.enum_not_in_pass_names.stderr b/tests/ui/mir/enable_passes_validation.enum_not_in_pass_names.stderr new file mode 100644 index 000000000000..89229ebabe84 --- /dev/null +++ b/tests/ui/mir/enable_passes_validation.enum_not_in_pass_names.stderr @@ -0,0 +1,8 @@ +warning: MIR pass `SimplifyCfg` is unknown and will be ignored + +warning: MIR pass `SimplifyCfg` is unknown and will be ignored + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: 2 warnings emitted + diff --git a/tests/ui/mir/enable_passes_validation.rs b/tests/ui/mir/enable_passes_validation.rs index 99b1ba528b0c..d3d22b49ac7f 100644 --- a/tests/ui/mir/enable_passes_validation.rs +++ b/tests/ui/mir/enable_passes_validation.rs @@ -1,4 +1,5 @@ //@ revisions: empty unprefixed all_unknown all_known mixed +//@ revisions: enum_not_in_pass_names enum_in_pass_names //@[empty] compile-flags: -Zmir-enable-passes= @@ -13,6 +14,12 @@ //@[mixed] check-pass //@[mixed] compile-flags: -Zmir-enable-passes=+ThisPassDoesNotExist,+CheckAlignment +//@[enum_not_in_pass_names] check-pass +//@[enum_not_in_pass_names] compile-flags: -Zmir-enable-passes=+SimplifyCfg + +//@[enum_in_pass_names] check-pass +//@[enum_in_pass_names] compile-flags: -Zmir-enable-passes=+AddCallGuards + fn main() {} //[empty]~? ERROR incorrect value `` for unstable option `mir-enable-passes` @@ -23,3 +30,5 @@ fn main() {} //[all_unknown]~? WARN MIR pass `DoesNotExist` is unknown and will be ignored //[all_unknown]~? WARN MIR pass `ThisPass` is unknown and will be ignored //[all_unknown]~? WARN MIR pass `DoesNotExist` is unknown and will be ignored +//[enum_not_in_pass_names]~? WARN MIR pass `SimplifyCfg` is unknown and will be ignored +//[enum_not_in_pass_names]~? WARN MIR pass `SimplifyCfg` is unknown and will be ignored From 8238fa692a4a7a99ad8aca5b147b63b9ff17e80d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 29 Jan 2026 13:08:13 +1100 Subject: [PATCH 202/978] Remove or narrow some `typos.toml` allowlist entries --- typos.toml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/typos.toml b/typos.toml index 920234a9381b..7fbf129f9cc7 100644 --- a/typos.toml +++ b/typos.toml @@ -19,7 +19,6 @@ extend-exclude = [ arange = "arange" childs = "childs" clonable = "clonable" -Datas = "Datas" filetimes = "filetimes" leafs = "leafs" makro = "makro" @@ -28,7 +27,6 @@ moreso = "moreso" optin = "optin" publically = "publically" rplace = "rplace" -smove = "smove" splitted = "splitted" taits = "taits" targetting = "targetting" @@ -37,9 +35,6 @@ unstability = "unstability" unstalled = "unstalled" numer = "numer" -# this can be valid word, depends on dictionary edition -#matcheable = "matcheable" - [default.extend-identifiers] # An entry goes here if the typo is part of some existing ident # where you want to keep it, but don't want to allow @@ -63,6 +58,7 @@ Oppen = "Oppen" # typos treats this as two different camelcase words (`SETTIN` and `Gs`) # Tracked in: https://github.com/crate-ci/typos/issues/745 SETTINGs = "SETTINGs" +key_smove = "key_smove" # shifted move key, used by terminfo tolen = "tolen" [default] From e8bdcb084d74b1a3db48ba2b3d5a23999d57773d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 29 Jan 2026 12:55:26 +1100 Subject: [PATCH 203/978] Enforce alphabetical sorting in `typos.toml` and tweak comments --- src/tools/tidy/src/main.rs | 2 ++ typos.toml | 40 +++++++++++++++++++++++++------------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 94c24f11ed12..0d9a22556dfa 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -32,6 +32,7 @@ fn main() { let npm: PathBuf = env::args_os().nth(5).expect("need name/path of npm command").into(); let root_manifest = root_path.join("Cargo.toml"); + let typos_toml = root_path.join("typos.toml"); let src_path = root_path.join("src"); let tests_path = root_path.join("tests"); let library_path = root_path.join("library"); @@ -143,6 +144,7 @@ fn main() { check!(edition, &library_path); check!(alphabetical, &root_manifest); + check!(alphabetical, &typos_toml); check!(alphabetical, &src_path); check!(alphabetical, &tests_path); check!(alphabetical, &compiler_path); diff --git a/typos.toml b/typos.toml index 7fbf129f9cc7..a735187d1669 100644 --- a/typos.toml +++ b/typos.toml @@ -1,3 +1,6 @@ +# Config for the `typos` crate, used by `./x test tidy --extra-checks=spellcheck`. +# See also: https://github.com/crate-ci/typos/blob/v1.28.2/docs/reference.md + [files] extend-exclude = [ # exclude git (sub)modules and generated content @@ -13,9 +16,10 @@ extend-exclude = [ ] [default.extend-words] -# Add exclusions here, lines should be like `x = "x"`, where `x` is excluded word. +# Allowlist for words that look like typos but are not, or aren't worth fixing +# right now. Entries should look like `mipsel = "mipsel"`. # -# Also see docs: https://github.com/crate-ci/typos/blob/v1.28.2/docs/reference.md +# tidy-alphabetical-start arange = "arange" childs = "childs" clonable = "clonable" @@ -24,6 +28,7 @@ leafs = "leafs" makro = "makro" misformed = "misformed" moreso = "moreso" +numer = "numer" optin = "optin" publically = "publically" rplace = "rplace" @@ -33,33 +38,42 @@ targetting = "targetting" unparseable = "unparseable" unstability = "unstability" unstalled = "unstalled" -numer = "numer" +# tidy-alphabetical-end + +# Denylist to forbid misspelled words that aren't detected by the built-in +# dictionary. Entries should look like `mipsel = ""` or `mipsel = "misspell"`; +# the non-empty form can be automatically fixed by `--bless`. +# +# tidy-alphabetical-start +# tidy-alphabetical-end [default.extend-identifiers] -# An entry goes here if the typo is part of some existing ident -# where you want to keep it, but don't want to allow -# such typos everywhere. +# Allowlist for specific identifiers that should be permitted even though they +# appear to contain typos that would be forbidden in other identifiers. # -# I.e. you don't want (or can't) fix some constant name, like -# `DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME` but actually -# want to see `INVAILD` typo fixed in other places. -debug_aranges = "debug_aranges" +# For example, you might want to allow a specific constant like +# `DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME`, but still want to forbid +# the typo `INVAILD` in other places. +# +# tidy-alphabetical-start DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME = "DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME" -EnzymeTypeTreeShiftIndiciesEq = "EnzymeTypeTreeShiftIndiciesEq" -EnzymeTypeTreeShiftIndiciesEqFn = "EnzymeTypeTreeShiftIndiciesEqFn" -shift_indicies_eq = "shift_indicies_eq" ERRNO_ACCES = "ERRNO_ACCES" ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS = "ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS" ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC = "ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC" ERROR_FILENAME_EXCED_RANGE = "ERROR_FILENAME_EXCED_RANGE" ERROR_MCA_OCCURED = "ERROR_MCA_OCCURED" ERROR_REQ_NOT_ACCEP = "ERROR_REQ_NOT_ACCEP" +EnzymeTypeTreeShiftIndiciesEq = "EnzymeTypeTreeShiftIndiciesEq" +EnzymeTypeTreeShiftIndiciesEqFn = "EnzymeTypeTreeShiftIndiciesEqFn" Oppen = "Oppen" # typos treats this as two different camelcase words (`SETTIN` and `Gs`) # Tracked in: https://github.com/crate-ci/typos/issues/745 SETTINGs = "SETTINGs" +debug_aranges = "debug_aranges" key_smove = "key_smove" # shifted move key, used by terminfo +shift_indicies_eq = "shift_indicies_eq" tolen = "tolen" +# tidy-alphabetical-end [default] extend-ignore-words-re = [ From 38a60a63079923034699045ff27d1ec14c9d4c75 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 29 Jan 2026 13:28:10 +1100 Subject: [PATCH 204/978] Explain some allowlist entries in `typos.toml` --- typos.toml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/typos.toml b/typos.toml index a735187d1669..c65e2ba293e5 100644 --- a/typos.toml +++ b/typos.toml @@ -20,24 +20,24 @@ extend-exclude = [ # right now. Entries should look like `mipsel = "mipsel"`. # # tidy-alphabetical-start -arange = "arange" +arange = "arange" # short for A-range childs = "childs" clonable = "clonable" -filetimes = "filetimes" +filetimes = "filetimes" # short for "file times", not a typo for "lifetimes" leafs = "leafs" -makro = "makro" +makro = "makro" # deliberate misspelling to avoid `macro` keyword misformed = "misformed" moreso = "moreso" -numer = "numer" -optin = "optin" +numer = "numer" # short for numerator, not a typo for "number" +optin = "optin" # short for opt-in publically = "publically" -rplace = "rplace" +rplace = "rplace" # short for R-place splitted = "splitted" -taits = "taits" +taits = "taits" # lowercase for TAITs (type alias impl trait) targetting = "targetting" unparseable = "unparseable" unstability = "unstability" -unstalled = "unstalled" +unstalled = "unstalled" # short for un-stalled # tidy-alphabetical-end # Denylist to forbid misspelled words that aren't detected by the built-in @@ -65,14 +65,14 @@ ERROR_MCA_OCCURED = "ERROR_MCA_OCCURED" ERROR_REQ_NOT_ACCEP = "ERROR_REQ_NOT_ACCEP" EnzymeTypeTreeShiftIndiciesEq = "EnzymeTypeTreeShiftIndiciesEq" EnzymeTypeTreeShiftIndiciesEqFn = "EnzymeTypeTreeShiftIndiciesEqFn" -Oppen = "Oppen" +Oppen = "Oppen" # Derek C. Oppen, author of "Pretty Printing" (1979) # typos treats this as two different camelcase words (`SETTIN` and `Gs`) # Tracked in: https://github.com/crate-ci/typos/issues/745 SETTINGs = "SETTINGs" -debug_aranges = "debug_aranges" +debug_aranges = "debug_aranges" # debug A-ranges key_smove = "key_smove" # shifted move key, used by terminfo shift_indicies_eq = "shift_indicies_eq" -tolen = "tolen" +tolen = "tolen" # length of "to" buffer, used by `sendto` in Windows sockets # tidy-alphabetical-end [default] From a42bbe697f24adbb3683ea0479c9b78a04a50e2f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 29 Jan 2026 13:10:58 +1100 Subject: [PATCH 205/978] Fix some typos of "definition" --- compiler/rustc_resolve/src/build_reduced_graph.rs | 4 ++-- typos.toml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index e06ca59771e6..f0dffd8829da 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -60,7 +60,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - /// Create a name definitinon from the given components, and put it into the local module. + /// Create a name definition from the given components, and put it into the local module. fn define_local( &mut self, parent: Module<'ra>, @@ -76,7 +76,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.plant_decl_into_local_module(ident, orig_ident.span, ns, decl); } - /// Create a name definitinon from the given components, and put it into the extern module. + /// Create a name definition from the given components, and put it into the extern module. fn define_extern( &self, parent: Module<'ra>, diff --git a/typos.toml b/typos.toml index c65e2ba293e5..25083174cb8f 100644 --- a/typos.toml +++ b/typos.toml @@ -45,6 +45,7 @@ unstalled = "unstalled" # short for un-stalled # the non-empty form can be automatically fixed by `--bless`. # # tidy-alphabetical-start +definitinon = "definition" # tidy-alphabetical-end [default.extend-identifiers] From b235cc22acdde9be7a25c3b5828e9c5863a0b54f Mon Sep 17 00:00:00 2001 From: Adwin White Date: Thu, 7 Aug 2025 19:41:57 +0800 Subject: [PATCH 206/978] fix accidental type variable resolution in array coercion --- compiler/rustc_hir_typeck/src/coercion.rs | 23 +++++++++++++ compiler/rustc_hir_typeck/src/expr.rs | 13 ++++++- tests/ui/coercion/closure-in-array.rs | 7 ++++ tests/ui/coercion/closure-in-array.stderr | 14 ++++++++ tests/ui/coercion/coerce-many-with-ty-var.rs | 36 ++++++++++++++++++++ 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 tests/ui/coercion/closure-in-array.rs create mode 100644 tests/ui/coercion/closure-in-array.stderr create mode 100644 tests/ui/coercion/coerce-many-with-ty-var.rs diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 52ea6cdeaa0e..0e87b90dc6c1 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1365,6 +1365,7 @@ pub fn can_coerce<'tcx>( /// - WARNING: I don't believe this final type is guaranteed to be /// related to your initial `expected_ty` in any particular way, /// although it will typically be a subtype, so you should check it. +/// Check the note below for more details. /// - Invoking `complete()` may cause us to go and adjust the "adjustments" on /// previously coerced expressions. /// @@ -1378,6 +1379,28 @@ pub fn can_coerce<'tcx>( /// } /// let final_ty = coerce.complete(fcx); /// ``` +/// +/// NOTE: Why does the `expected_ty` participate in the LUB? +/// When coercing, each branch should use the following expectations for type inference: +/// - The branch can be coerced to the expected type of the match/if/whatever. +/// - The branch can be coercion lub'd with the types of the previous branches. +/// Ideally we'd have some sort of `Expectation::ParticipatesInCoerceLub(ongoing_lub_ty, final_ty)`, +/// but adding and using this feels very challenging. +/// What we instead do is to use the expected type of the match/if/whatever as +/// the initial coercion lub. This allows us to use the lub of "expected type of match" with +/// "types from previous branches" as the coercion target, which can contains both expectations. +/// +/// Two concerns with this approach: +/// - We may have incompatible `final_ty` if that lub is different from the expected +/// type of the match. However, in this case coercing the final type of the +/// `CoerceMany` to its expected type would have error'd anyways, so we don't care. +/// - We may constrain the `expected_ty` too early. For some branches with +/// type `a` and `b`, we end up with `(a lub expected_ty) lub b` instead of +/// `(a lub b) lub expected_ty`. They should be the same type. However, +/// `a lub expected_ty` may constrain inference variables in `expected_ty`. +/// In this case the difference does matter and we get actually incorrect results. +/// FIXME: Ideally we'd compute the final type without unnecessarily constraining +/// the expected type of the match when computing the types of its branches. pub(crate) struct CoerceMany<'tcx> { expected_ty: Ty<'tcx>, final_ty: Option>, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 885af3b909b8..5b40531f9462 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1670,11 +1670,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let coerce_to = expected .to_option(self) - .and_then(|uty| self.try_structurally_resolve_type(expr.span, uty).builtin_index()) + .and_then(|uty| { + self.try_structurally_resolve_type(expr.span, uty) + .builtin_index() + // Avoid using the original type variable as the coerce_to type, as it may resolve + // during the first coercion instead of being the LUB type. + .filter(|t| !self.try_structurally_resolve_type(expr.span, *t).is_ty_var()) + }) .unwrap_or_else(|| self.next_ty_var(expr.span)); let mut coerce = CoerceMany::with_capacity(coerce_to, args.len()); for e in args { + // FIXME: the element expectation should use + // `try_structurally_resolve_and_adjust_for_branches` just like in `if` and `match`. + // While that fixes nested coercion, it will break [some + // code like this](https://github.com/rust-lang/rust/pull/140283#issuecomment-2958776528). + // If we find a way to support recursive tuple coercion, this break can be avoided. let e_ty = self.check_expr_with_hint(e, coerce_to); let cause = self.misc(e.span); coerce.coerce(self, &cause, e, e_ty); diff --git a/tests/ui/coercion/closure-in-array.rs b/tests/ui/coercion/closure-in-array.rs new file mode 100644 index 000000000000..ca5c021c77a7 --- /dev/null +++ b/tests/ui/coercion/closure-in-array.rs @@ -0,0 +1,7 @@ +// Weakened closure sig inference by #140283. +fn foo usize, const N: usize>(x: [F; N]) {} + +fn main() { + foo([|s| s.len()]) + //~^ ERROR: type annotations needed +} diff --git a/tests/ui/coercion/closure-in-array.stderr b/tests/ui/coercion/closure-in-array.stderr new file mode 100644 index 000000000000..90cf590c09e7 --- /dev/null +++ b/tests/ui/coercion/closure-in-array.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/closure-in-array.rs:5:11 + | +LL | foo([|s| s.len()]) + | ^ - type must be known at this point + | +help: consider giving this closure parameter an explicit type + | +LL | foo([|s: /* Type */| s.len()]) + | ++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/coercion/coerce-many-with-ty-var.rs b/tests/ui/coercion/coerce-many-with-ty-var.rs new file mode 100644 index 000000000000..cbd16f58ea5b --- /dev/null +++ b/tests/ui/coercion/coerce-many-with-ty-var.rs @@ -0,0 +1,36 @@ +//@ run-pass +// Check that least upper bound coercions don't resolve type variable merely based on the first +// coercion. Check issue #136420. + +fn foo() {} +fn bar() {} + +fn infer(_: T) {} + +fn infer_array_element(_: [T; 2]) {} + +fn main() { + // Previously the element type's ty var will be unified with `foo`. + let _: [_; 2] = [foo, bar]; + infer_array_element([foo, bar]); + + let _ = if false { + foo + } else { + bar + }; + infer(if false { + foo + } else { + bar + }); + + let _ = match false { + true => foo, + false => bar, + }; + infer(match false { + true => foo, + false => bar, + }); +} From f5b53682a1b14b97b13f335110d8ad55f6c7fb9f Mon Sep 17 00:00:00 2001 From: Zen <250477360+ZenPZero@users.noreply.github.com> Date: Wed, 28 Jan 2026 23:00:39 -0500 Subject: [PATCH 207/978] Fix grammar --- library/std/src/env.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 5c068ad2471a..615b767a4ea5 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -728,7 +728,7 @@ pub fn temp_dir() -> PathBuf { /// /// You expected to safely execute the current executable, but you're /// instead executing something completely different. The code you -/// just executed run with your privileges. +/// just executed runs with your privileges. /// /// This sort of behavior has been known to [lead to privilege escalation] when /// used incorrectly. From a5052a093fa805edb5efdc512761e1cc8086f134 Mon Sep 17 00:00:00 2001 From: Andrew Zhogin Date: Mon, 6 Oct 2025 04:39:10 +0700 Subject: [PATCH 208/978] hir_owner_parent optimized to inlined call for non-incremental build --- compiler/rustc_middle/src/hir/mod.rs | 42 +++++++++++++++++--------- compiler/rustc_middle/src/query/mod.rs | 2 +- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index ba2d8febad7c..82f8eb4bbc4a 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -365,6 +365,33 @@ impl<'tcx> TyCtxt<'tcx> { } } } + + #[inline] + fn hir_owner_parent_impl(self, owner_id: OwnerId) -> HirId { + self.opt_local_parent(owner_id.def_id).map_or(CRATE_HIR_ID, |parent_def_id| { + let parent_owner_id = self.local_def_id_to_hir_id(parent_def_id).owner; + HirId { + owner: parent_owner_id, + local_id: self.hir_crate(()).owners[parent_owner_id.def_id] + .unwrap() + .parenting + .get(&owner_id.def_id) + .copied() + .unwrap_or(ItemLocalId::ZERO), + } + }) + } + + /// Optimization of `hir_owner_parent` query as an inlined function + /// in case of non-incremental build. The query itself renamed to `hir_owner_parent_q`. + #[inline] + pub fn hir_owner_parent(self, owner_id: OwnerId) -> HirId { + if self.dep_graph.is_fully_enabled() { + self.hir_owner_parent_q(owner_id) + } else { + self.hir_owner_parent_impl(owner_id) + } + } } /// Hashes computed by [`TyCtxt::hash_owner_nodes`] if necessary. @@ -386,20 +413,7 @@ pub fn provide(providers: &mut Providers) { }; providers.opt_hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners.get(id)?.as_owner().map(|i| &i.nodes); - providers.hir_owner_parent = |tcx, owner_id| { - tcx.opt_local_parent(owner_id.def_id).map_or(CRATE_HIR_ID, |parent_def_id| { - let parent_owner_id = tcx.local_def_id_to_hir_id(parent_def_id).owner; - HirId { - owner: parent_owner_id, - local_id: tcx.hir_crate(()).owners[parent_owner_id.def_id] - .unwrap() - .parenting - .get(&owner_id.def_id) - .copied() - .unwrap_or(ItemLocalId::ZERO), - } - }) - }; + providers.hir_owner_parent_q = |tcx, owner_id| tcx.hir_owner_parent_impl(owner_id); providers.hir_attr_map = |tcx, id| { tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs) }; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 9d17c998a8f2..0a4faa1b6247 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -266,7 +266,7 @@ rustc_queries! { /// /// This can be conveniently accessed by `tcx.hir_*` methods. /// Avoid calling this query directly. - query hir_owner_parent(key: hir::OwnerId) -> hir::HirId { + query hir_owner_parent_q(key: hir::OwnerId) -> hir::HirId { desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key) } } From 59c77c43d941dd621701d8e452928846af934497 Mon Sep 17 00:00:00 2001 From: Shunpoco Date: Sat, 17 Jan 2026 10:14:47 +0000 Subject: [PATCH 209/978] use clap on tidy Current tidy parses paths and options manually, and parsing is spreading multple files. This commit introduces a parser using clap to clean and centralize it. --- Cargo.lock | 9 +- src/tools/tidy/Cargo.toml | 1 + src/tools/tidy/src/alphabetical/tests.rs | 2 +- src/tools/tidy/src/arg_parser.rs | 92 +++++++++++++ src/tools/tidy/src/arg_parser/tests.rs | 162 +++++++++++++++++++++++ src/tools/tidy/src/diagnostics.rs | 12 +- src/tools/tidy/src/extra_checks/mod.rs | 12 +- src/tools/tidy/src/lib.rs | 1 + src/tools/tidy/src/main.rs | 39 +++--- 9 files changed, 284 insertions(+), 46 deletions(-) create mode 100644 src/tools/tidy/src/arg_parser.rs create mode 100644 src/tools/tidy/src/arg_parser/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 01300d56cff9..f279ad6cae9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -580,9 +580,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.51" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" +checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" dependencies = [ "clap_builder", "clap_derive", @@ -600,9 +600,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.51" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" +checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" dependencies = [ "anstream", "anstyle", @@ -5622,6 +5622,7 @@ version = "0.1.0" dependencies = [ "build_helper", "cargo_metadata 0.21.0", + "clap", "fluent-syntax", "globset", "ignore", diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index cbf27ea87a07..d5433080efc0 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -20,6 +20,7 @@ fluent-syntax = "0.12" similar = "2.5.0" toml = "0.7.8" tempfile = "3.15.0" +clap = "4.5.54" [features] build-metrics = ["dep:serde"] diff --git a/src/tools/tidy/src/alphabetical/tests.rs b/src/tools/tidy/src/alphabetical/tests.rs index 4a1d263f1a4f..5fa0dd751b64 100644 --- a/src/tools/tidy/src/alphabetical/tests.rs +++ b/src/tools/tidy/src/alphabetical/tests.rs @@ -37,7 +37,7 @@ fn bless_test(before: &str, after: &str) { let temp_path = tempfile::Builder::new().tempfile().unwrap().into_temp_path(); std::fs::write(&temp_path, before).unwrap(); - let tidy_ctx = TidyCtx::new(Path::new("/"), false, TidyFlags::new(&["--bless".to_owned()])); + let tidy_ctx = TidyCtx::new(Path::new("/"), false, TidyFlags::new(true)); let mut check = tidy_ctx.start_check("alphabetical-test"); check_lines(&temp_path, before, &tidy_ctx, &mut check); diff --git a/src/tools/tidy/src/arg_parser.rs b/src/tools/tidy/src/arg_parser.rs new file mode 100644 index 000000000000..ca7ee04da8fb --- /dev/null +++ b/src/tools/tidy/src/arg_parser.rs @@ -0,0 +1,92 @@ +use std::num::NonZeroUsize; +use std::path::PathBuf; + +use clap::{Arg, ArgAction, ArgMatches, Command, value_parser}; + +#[cfg(test)] +mod tests; + +#[derive(Debug, Clone)] +pub struct TidyArgParser { + pub root_path: PathBuf, + pub cargo: PathBuf, + pub output_directory: PathBuf, + pub concurrency: NonZeroUsize, + pub npm: PathBuf, + pub verbose: bool, + pub bless: bool, + pub extra_checks: Option>, + pub pos_args: Vec, +} + +impl TidyArgParser { + fn command() -> Command { + Command::new("rust-tidy") + .arg( + Arg::new("root_path") + .help("path of the root directory") + .required(true) + .value_parser(value_parser!(PathBuf)), + ) + .arg( + Arg::new("cargo") + .help("path of cargo") + .required(true) + .value_parser(value_parser!(PathBuf)), + ) + .arg( + Arg::new("output_directory") + .help("path of output directory") + .required(true) + .value_parser(value_parser!(PathBuf)), + ) + .arg(Arg::new("concurrency").required(true).value_parser(value_parser!(NonZeroUsize))) + .arg( + Arg::new("npm") + .help("path of npm") + .required(true) + .value_parser(value_parser!(PathBuf)), + ) + .arg(Arg::new("verbose").help("verbose").long("verbose").action(ArgAction::SetTrue)) + .arg(Arg::new("bless").help("bless").long("bless").action(ArgAction::SetTrue)) + .arg( + Arg::new("extra_checks") + .help("extra checks") + .long("extra-checks") + .value_delimiter(',') + .action(ArgAction::Append), + ) + .arg(Arg::new("pos_args").help("for extra checks. you can specify configs and target files for external check tools").action(ArgAction::Append).last(true)) + } + + fn build(matches: ArgMatches) -> Self { + let mut tidy_flags = Self { + root_path: matches.get_one::("root_path").unwrap().clone(), + cargo: matches.get_one::("cargo").unwrap().clone(), + output_directory: matches.get_one::("output_directory").unwrap().clone(), + concurrency: *matches.get_one::("concurrency").unwrap(), + npm: matches.get_one::("npm").unwrap().clone(), + verbose: *matches.get_one::("verbose").unwrap(), + bless: *matches.get_one::("bless").unwrap(), + extra_checks: None, + pos_args: vec![], + }; + + if let Some(extra_checks) = matches.get_many::("extra_checks") { + tidy_flags.extra_checks = Some(extra_checks.map(|s| s.to_string()).collect::>()); + } + + tidy_flags.pos_args = matches + .get_many::("pos_args") + .unwrap_or_default() + .map(|v| v.to_string()) + .collect::>(); + + tidy_flags + } + + pub fn parse() -> Self { + let matches = Self::command().get_matches(); + Self::build(matches) + } +} diff --git a/src/tools/tidy/src/arg_parser/tests.rs b/src/tools/tidy/src/arg_parser/tests.rs new file mode 100644 index 000000000000..856e80279e27 --- /dev/null +++ b/src/tools/tidy/src/arg_parser/tests.rs @@ -0,0 +1,162 @@ +use std::path::PathBuf; + +use crate::arg_parser::TidyArgParser; + +#[test] +fn test_tidy_parser() { + let args = vec![ + "rust-tidy", + "/home/user/rust", // Root dir + "/home/user/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo", // Cardo location + "/home/user/rust/build", // Build dir + "16", // Number of concurrency + "/home/user/rust/build/misc-tools/bin/yarn", // Yarn location + "--verbose", + "--bless", + "--extra-checks", + "if-installed:auto:js,auto:if-installed:py,if-installed:auto:cpp,if-installed:auto:spellcheck", + "--", // pos_args + "some-file", + "some-file2", + ]; + let cmd = TidyArgParser::command(); + let parsed_args = TidyArgParser::build(cmd.get_matches_from(args)); + + assert_eq!(parsed_args.root_path, PathBuf::from("/home/user/rust")); + assert_eq!( + parsed_args.cargo, + PathBuf::from("/home/user/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo") + ); + assert_eq!(parsed_args.output_directory, PathBuf::from("/home/user/rust/build")); + assert_eq!(parsed_args.concurrency.get(), 16); + assert_eq!(parsed_args.npm, PathBuf::from("/home/user/rust/build/misc-tools/bin/yarn")); + assert!(parsed_args.verbose); + assert!(parsed_args.bless); + assert_eq!( + parsed_args.extra_checks, + Some(vec![ + "if-installed:auto:js".to_string(), + "auto:if-installed:py".to_string(), + "if-installed:auto:cpp".to_string(), + "if-installed:auto:spellcheck".to_string(), + ]) + ); + assert_eq!(parsed_args.pos_args, vec!["some-file".to_string(), "some-file2".to_string()]); +} + +// The parser can take required args any order +#[test] +fn test_tidy_parser_any_order() { + let args = vec![ + "rust-tidy", + "--npm-path", + "yarn", + "--concurrency", + "16", + "--output-dir", + "/home/user/rust/build", + "--cargo-path", + "/home/user/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo", + "--root-path", + "/home/user/rust", + ]; + let cmd = TidyArgParser::command(); + let parsed_args = TidyArgParser::build(cmd.get_matches_from(args)); + + assert_eq!(parsed_args.root_path, PathBuf::from("/home/user/rust")); + assert_eq!( + parsed_args.cargo, + PathBuf::from("/home/user/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo") + ); + assert_eq!(parsed_args.output_directory, PathBuf::from("/home/user/rust/build")); + assert_eq!(parsed_args.concurrency.get(), 16); + assert_eq!(parsed_args.npm, PathBuf::from("yarn")); +} + +// --root-path is required +#[test] +fn test_tidy_parser_missing_root_path() { + let args = vec![ + "rust-tidy", + "--npm-path", + "yarn", + "--concurrency", + "16", + "--output-dir", + "/home/user/rust/build", + "--cargo-path", + "/home/user/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo", + ]; + let cmd = TidyArgParser::command(); + assert!(cmd.try_get_matches_from(args).is_err()); +} + +// --cargo-path is required +#[test] +fn test_tidy_parser_missing_cargo_path() { + let args = vec![ + "rust-tidy", + "--npm-path", + "yarn", + "--concurrency", + "16", + "--output-dir", + "/home/user/rust/build", + "--root-path", + "/home/user/rust", + ]; + let cmd = TidyArgParser::command(); + assert!(cmd.try_get_matches_from(args).is_err()); +} + +// --output-dir is required +#[test] +fn test_tidy_parser_missing_output_dir() { + let args = vec![ + "rust-tidy", + "--npm-path", + "yarn", + "--concurrency", + "16", + "--cargo-path", + "/home/user/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo", + "--root-path", + "/home/user/rust", + ]; + let cmd = TidyArgParser::command(); + assert!(cmd.try_get_matches_from(args).is_err()); +} + +// --concurrency is required +#[test] +fn test_tidy_parser_missing_concurrency() { + let args = vec![ + "rust-tidy", + "--npm-path", + "yarn", + "--output-dir", + "/home/user/rust/build", + "--cargo-path", + "/home/user/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo", + "--root-path", + "/home/user/rust", + ]; + let cmd = TidyArgParser::command(); + assert!(cmd.try_get_matches_from(args).is_err()); +} + +// --npm-path is required +#[test] +fn test_tidy_parser_missing_npm_path() { + let args = vec![ + "rust-tidy", + "--concurrency", + "16", + "--output-dir", + "/home/user/rust/build", + "--cargo-path", + "/home/user/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo", + ]; + let cmd = TidyArgParser::command(); + assert!(cmd.try_get_matches_from(args).is_err()); +} diff --git a/src/tools/tidy/src/diagnostics.rs b/src/tools/tidy/src/diagnostics.rs index 6f53f2fff1a4..4e6c316f5e18 100644 --- a/src/tools/tidy/src/diagnostics.rs +++ b/src/tools/tidy/src/diagnostics.rs @@ -14,16 +14,8 @@ pub struct TidyFlags { } impl TidyFlags { - pub fn new(cfg_args: &[String]) -> Self { - let mut flags = Self::default(); - - for arg in cfg_args { - match arg.as_str() { - "--bless" => flags.bless = true, - _ => continue, - } - } - flags + pub fn new(bless: bool) -> Self { + Self { bless } } } diff --git a/src/tools/tidy/src/extra_checks/mod.rs b/src/tools/tidy/src/extra_checks/mod.rs index 1c81a485608a..6272e00591d7 100644 --- a/src/tools/tidy/src/extra_checks/mod.rs +++ b/src/tools/tidy/src/extra_checks/mod.rs @@ -58,8 +58,8 @@ pub fn check( tools_path: &Path, npm: &Path, cargo: &Path, - extra_checks: Option<&str>, - pos_args: &[String], + extra_checks: Option>, + pos_args: Vec, tidy_ctx: TidyCtx, ) { let mut check = tidy_ctx.start_check("extra_checks"); @@ -88,8 +88,8 @@ fn check_impl( tools_path: &Path, npm: &Path, cargo: &Path, - extra_checks: Option<&str>, - pos_args: &[String], + extra_checks: Option>, + pos_args: Vec, tidy_ctx: &TidyCtx, ) -> Result<(), Error> { let show_diff = @@ -99,9 +99,7 @@ fn check_impl( // Split comma-separated args up let mut lint_args = match extra_checks { Some(s) => s - .strip_prefix("--extra-checks=") - .unwrap() - .split(',') + .iter() .map(|s| { if s == "spellcheck:fix" { eprintln!("warning: `spellcheck:fix` is no longer valid, use `--extra-checks=spellcheck --bless`"); diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 425f43e42b7f..19a9fa80d9f0 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -157,6 +157,7 @@ pub fn files_modified(ci_info: &CiInfo, pred: impl Fn(&str) -> bool) -> bool { } pub mod alphabetical; +pub mod arg_parser; pub mod bins; pub mod debug_artifacts; pub mod deps; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 94c24f11ed12..457fbe93e6d2 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -5,12 +5,10 @@ //! builders. The tidy checks can be executed with `./x.py test tidy`. use std::collections::VecDeque; -use std::num::NonZeroUsize; -use std::path::PathBuf; -use std::str::FromStr; use std::thread::{self, ScopedJoinHandle, scope}; use std::{env, process}; +use tidy::arg_parser::TidyArgParser; use tidy::diagnostics::{COLOR_ERROR, COLOR_SUCCESS, TidyCtx, TidyFlags, output_message}; use tidy::*; @@ -22,14 +20,13 @@ fn main() { env::set_var("RUSTC_BOOTSTRAP", "1"); } - let root_path: PathBuf = env::args_os().nth(1).expect("need path to root of repo").into(); - let cargo: PathBuf = env::args_os().nth(2).expect("need path to cargo").into(); - let output_directory: PathBuf = - env::args_os().nth(3).expect("need path to output directory").into(); - let concurrency: NonZeroUsize = - FromStr::from_str(&env::args().nth(4).expect("need concurrency")) - .expect("concurrency must be a number"); - let npm: PathBuf = env::args_os().nth(5).expect("need name/path of npm command").into(); + let parsed_args = TidyArgParser::parse(); + + let root_path = parsed_args.root_path; + let cargo = parsed_args.cargo; + let output_directory = parsed_args.output_directory; + let concurrency = parsed_args.concurrency.get(); + let npm = parsed_args.npm; let root_manifest = root_path.join("Cargo.toml"); let src_path = root_path.join("src"); @@ -40,17 +37,12 @@ fn main() { let tools_path = src_path.join("tools"); let crashes_path = tests_path.join("crashes"); - let args: Vec = env::args().skip(1).collect(); - let (cfg_args, pos_args) = match args.iter().position(|arg| arg == "--") { - Some(pos) => (&args[..pos], &args[pos + 1..]), - None => (&args[..], [].as_slice()), - }; - let verbose = cfg_args.iter().any(|s| *s == "--verbose"); - let extra_checks = - cfg_args.iter().find(|s| s.starts_with("--extra-checks=")).map(String::as_str); + let verbose = parsed_args.verbose; + let bless = parsed_args.bless; + let extra_checks = parsed_args.extra_checks; + let pos_args = parsed_args.pos_args; - let tidy_flags = TidyFlags::new(cfg_args); - let tidy_ctx = TidyCtx::new(&root_path, verbose, tidy_flags); + let tidy_ctx = TidyCtx::new(&root_path, verbose, TidyFlags::new(bless)); let ci_info = CiInfo::new(tidy_ctx.clone()); let drain_handles = |handles: &mut VecDeque>| { @@ -61,14 +53,13 @@ fn main() { } } - while handles.len() >= concurrency.get() { + while handles.len() >= concurrency { handles.pop_front().unwrap().join().unwrap(); } }; scope(|s| { - let mut handles: VecDeque> = - VecDeque::with_capacity(concurrency.get()); + let mut handles: VecDeque> = VecDeque::with_capacity(concurrency); macro_rules! check { ($p:ident) => { From 14858732330380e488ffb406d4a537bf133d90f9 Mon Sep 17 00:00:00 2001 From: Shunpoco Date: Sun, 25 Jan 2026 10:13:48 +0000 Subject: [PATCH 210/978] set long variants for required args Currently some required arguments (like path of the root dir) are ordered, but it causes an user (mainly bootstrap) needs to remember the order. This commit introduces long arguments (e.g., --root-path) for required args. --- src/bootstrap/src/core/build_steps/test.rs | 12 ++++++------ src/tools/tidy/src/arg_parser.rs | 14 ++++++++++++-- src/tools/tidy/src/arg_parser/tests.rs | 20 +++++++++++++------- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 52b38421eec2..ca70a7758d58 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1293,19 +1293,19 @@ impl Step for Tidy { /// for the `dev` or `nightly` channels. fn run(self, builder: &Builder<'_>) { let mut cmd = builder.tool_cmd(Tool::Tidy); - cmd.arg(&builder.src); - cmd.arg(&builder.initial_cargo); - cmd.arg(&builder.out); + cmd.arg(format!("--root-path={}", &builder.src.display())); + cmd.arg(format!("--cargo-path={}", &builder.initial_cargo.display())); + cmd.arg(format!("--output-dir={}", &builder.out.display())); // Tidy is heavily IO constrained. Still respect `-j`, but use a higher limit if `jobs` hasn't been configured. let jobs = builder.config.jobs.unwrap_or_else(|| { 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32 }); - cmd.arg(jobs.to_string()); + cmd.arg(format!("--concurrency={jobs}")); // pass the path to the yarn command used for installing js deps. if let Some(yarn) = &builder.config.yarn { - cmd.arg(yarn); + cmd.arg(format!("--npm-path={}", yarn.display())); } else { - cmd.arg("yarn"); + cmd.arg("--npm-path=yarn"); } if builder.is_verbose() { cmd.arg("--verbose"); diff --git a/src/tools/tidy/src/arg_parser.rs b/src/tools/tidy/src/arg_parser.rs index ca7ee04da8fb..8041f739308d 100644 --- a/src/tools/tidy/src/arg_parser.rs +++ b/src/tools/tidy/src/arg_parser.rs @@ -25,30 +25,40 @@ impl TidyArgParser { .arg( Arg::new("root_path") .help("path of the root directory") + .long("root-path") .required(true) .value_parser(value_parser!(PathBuf)), ) .arg( Arg::new("cargo") .help("path of cargo") + .long("cargo-path") .required(true) .value_parser(value_parser!(PathBuf)), ) .arg( Arg::new("output_directory") .help("path of output directory") + .long("output-dir") .required(true) .value_parser(value_parser!(PathBuf)), ) - .arg(Arg::new("concurrency").required(true).value_parser(value_parser!(NonZeroUsize))) + .arg( + Arg::new("concurrency") + .help("number of threads working concurrently") + .long("concurrency") + .required(true) + .value_parser(value_parser!(NonZeroUsize)), + ) .arg( Arg::new("npm") .help("path of npm") + .long("npm-path") .required(true) .value_parser(value_parser!(PathBuf)), ) .arg(Arg::new("verbose").help("verbose").long("verbose").action(ArgAction::SetTrue)) - .arg(Arg::new("bless").help("bless").long("bless").action(ArgAction::SetTrue)) + .arg(Arg::new("bless").help("target files are modified").long("bless").action(ArgAction::SetTrue)) .arg( Arg::new("extra_checks") .help("extra checks") diff --git a/src/tools/tidy/src/arg_parser/tests.rs b/src/tools/tidy/src/arg_parser/tests.rs index 856e80279e27..c5e7aed21c1a 100644 --- a/src/tools/tidy/src/arg_parser/tests.rs +++ b/src/tools/tidy/src/arg_parser/tests.rs @@ -2,15 +2,21 @@ use std::path::PathBuf; use crate::arg_parser::TidyArgParser; +// Test all arguments #[test] -fn test_tidy_parser() { +fn test_tidy_parser_full() { let args = vec![ "rust-tidy", - "/home/user/rust", // Root dir - "/home/user/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo", // Cardo location - "/home/user/rust/build", // Build dir - "16", // Number of concurrency - "/home/user/rust/build/misc-tools/bin/yarn", // Yarn location + "--root-path", + "/home/user/rust", + "--cargo-path", + "/home/user/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo", + "--output-dir", + "/home/user/rust/build", + "--concurrency", + "16", + "--npm-path", + "yarn", "--verbose", "--bless", "--extra-checks", @@ -29,7 +35,7 @@ fn test_tidy_parser() { ); assert_eq!(parsed_args.output_directory, PathBuf::from("/home/user/rust/build")); assert_eq!(parsed_args.concurrency.get(), 16); - assert_eq!(parsed_args.npm, PathBuf::from("/home/user/rust/build/misc-tools/bin/yarn")); + assert_eq!(parsed_args.npm, PathBuf::from("yarn")); assert!(parsed_args.verbose); assert!(parsed_args.bless); assert_eq!( From 4b22ee9fc5a208658d1fbfd2492ea3105f822e5d Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 22 Jan 2026 21:09:44 +0900 Subject: [PATCH 211/978] Tweak E0599 to consolidate unsatisfied trait bound messages --- .../rustc_hir_typeck/src/method/suggest.rs | 145 +++++++++++++++++- .../ui/proc-macro/quote/not-repeatable.stderr | 2 +- ...ssociated-item-unsatisfied-trait-bounds.rs | 9 ++ ...iated-item-unsatisfied-trait-bounds.stderr | 33 ++++ 4 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 tests/ui/traits/associated-item-unsatisfied-trait-bounds.rs create mode 100644 tests/ui/traits/associated-item-unsatisfied-trait-bounds.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 5673d044ad2c..b318f5bb25d2 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -13,7 +13,9 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; -use rustc_errors::{Applicability, Diag, MultiSpan, StashKey, pluralize, struct_span_code_err}; +use rustc_errors::{ + Applicability, Diag, MultiSpan, StashKey, listify, pluralize, struct_span_code_err, +}; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; @@ -50,6 +52,51 @@ use crate::errors::{self, CandidateTraitNote, NoAssociatedItem}; use crate::method::probe::UnsatisfiedPredicates; use crate::{Expectation, FnCtxt}; +/// Tracks trait bounds and detects duplicates between ref and non-ref versions of self types. +/// This is used to condense error messages when the same trait bound appears for both +/// `T` and `&T` (or `&mut T`). +struct TraitBoundDuplicateTracker { + trait_def_ids: FxIndexSet, + seen_ref: FxIndexSet, + seen_non_ref: FxIndexSet, + has_ref_dupes: bool, +} + +impl TraitBoundDuplicateTracker { + fn new() -> Self { + Self { + trait_def_ids: FxIndexSet::default(), + seen_ref: FxIndexSet::default(), + seen_non_ref: FxIndexSet::default(), + has_ref_dupes: false, + } + } + + /// Track a trait bound. `is_ref` indicates whether the self type is a reference. + fn track(&mut self, def_id: DefId, is_ref: bool) { + self.trait_def_ids.insert(def_id); + if is_ref { + if self.seen_non_ref.contains(&def_id) { + self.has_ref_dupes = true; + } + self.seen_ref.insert(def_id); + } else { + if self.seen_ref.contains(&def_id) { + self.has_ref_dupes = true; + } + self.seen_non_ref.insert(def_id); + } + } + + fn has_ref_dupes(&self) -> bool { + self.has_ref_dupes + } + + fn into_trait_def_ids(self) -> FxIndexSet { + self.trait_def_ids + } +} + impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool { self.autoderef(span, ty) @@ -1004,6 +1051,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_ident: Ident, item_kind: &str, bound_spans: SortedMap>, + unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>, ) { let mut ty_span = match rcvr_ty.kind() { ty::Param(param_type) => { @@ -1012,13 +1060,61 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Adt(def, _) if def.did().is_local() => Some(self.tcx.def_span(def.did())), _ => None, }; + let rcvr_ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path()); + let mut tracker = TraitBoundDuplicateTracker::new(); + for (predicate, _parent_pred, _cause) in unsatisfied_predicates { + if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = + predicate.kind().skip_binder() + && let self_ty = pred.trait_ref.self_ty() + && self_ty.peel_refs() == rcvr_ty + { + let is_ref = matches!(self_ty.kind(), ty::Ref(..)); + tracker.track(pred.trait_ref.def_id, is_ref); + } + } + let has_ref_dupes = tracker.has_ref_dupes(); + let mut missing_trait_names = tracker + .into_trait_def_ids() + .into_iter() + .map(|def_id| format!("`{}`", self.tcx.def_path_str(def_id))) + .collect::>(); + missing_trait_names.sort(); + let should_condense = + has_ref_dupes && missing_trait_names.len() > 1 && matches!(rcvr_ty.kind(), ty::Adt(..)); + let missing_trait_list = if should_condense { + Some(match missing_trait_names.as_slice() { + [only] => only.clone(), + [first, second] => format!("{first} or {second}"), + [rest @ .., last] => format!("{} or {last}", rest.join(", ")), + [] => String::new(), + }) + } else { + None + }; for (span, mut bounds) in bound_spans { if !self.tcx.sess.source_map().is_span_accessible(span) { continue; } bounds.sort(); bounds.dedup(); - let pre = if Some(span) == ty_span { + let is_ty_span = Some(span) == ty_span; + if is_ty_span && should_condense { + ty_span.take(); + let label = if let Some(missing_trait_list) = &missing_trait_list { + format!( + "{item_kind} `{item_ident}` not found for this {} because `{rcvr_ty_str}` doesn't implement {missing_trait_list}", + rcvr_ty.prefix_string(self.tcx) + ) + } else { + format!( + "{item_kind} `{item_ident}` not found for this {}", + rcvr_ty.prefix_string(self.tcx) + ) + }; + err.span_label(span, label); + continue; + } + let pre = if is_ty_span { ty_span.take(); format!( "{item_kind} `{item_ident}` not found for this {} because it ", @@ -1248,6 +1344,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_ident, item_kind, bound_spans, + unsatisfied_predicates, ); self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_ident, expected); @@ -1507,6 +1604,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bound_spans: &mut SortedMap>, ) { let tcx = self.tcx; + let rcvr_ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path()); let mut type_params = FxIndexMap::default(); // Pick out the list of unimplemented traits on the receiver. @@ -1798,6 +1896,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect(); spanned_predicates.sort_by_key(|(span, _)| *span); for (_, (primary_spans, span_labels, predicates)) in spanned_predicates { + let mut tracker = TraitBoundDuplicateTracker::new(); + let mut all_trait_bounds_for_rcvr = true; + for pred in &predicates { + match pred.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { + let self_ty = pred.trait_ref.self_ty(); + if self_ty.peel_refs() != rcvr_ty { + all_trait_bounds_for_rcvr = false; + break; + } + let is_ref = matches!(self_ty.kind(), ty::Ref(..)); + tracker.track(pred.trait_ref.def_id, is_ref); + } + _ => { + all_trait_bounds_for_rcvr = false; + break; + } + } + } + let has_ref_dupes = tracker.has_ref_dupes(); + let trait_def_ids = tracker.into_trait_def_ids(); let mut preds: Vec<_> = predicates .iter() .filter_map(|pred| format_pred(**pred)) @@ -1805,7 +1924,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect(); preds.sort(); preds.dedup(); - let msg = if let [pred] = &preds[..] { + let availability_note = if all_trait_bounds_for_rcvr + && has_ref_dupes + && trait_def_ids.len() > 1 + && matches!(rcvr_ty.kind(), ty::Adt(..)) + { + let mut trait_names = trait_def_ids + .into_iter() + .map(|def_id| format!("`{}`", tcx.def_path_str(def_id))) + .collect::>(); + trait_names.sort(); + listify(&trait_names, |name| name.to_string()).map(|traits| { + format!( + "for `{item_ident}` to be available, `{rcvr_ty_str}` must implement {traits}" + ) + }) + } else { + None + }; + let msg = if let Some(availability_note) = availability_note { + availability_note + } else if let [pred] = &preds[..] { format!("trait bound {pred} was not satisfied") } else { format!("the following trait bounds were not satisfied:\n{}", preds.join("\n"),) diff --git a/tests/ui/proc-macro/quote/not-repeatable.stderr b/tests/ui/proc-macro/quote/not-repeatable.stderr index 5943111efd58..6a867350a3b3 100644 --- a/tests/ui/proc-macro/quote/not-repeatable.stderr +++ b/tests/ui/proc-macro/quote/not-repeatable.stderr @@ -2,7 +2,7 @@ error[E0599]: the method `quote_into_iter` exists for struct `Ipv4Addr`, but its --> $DIR/not-repeatable.rs:11:13 | LL | struct Ipv4Addr; - | --------------- method `quote_into_iter` not found for this struct because it doesn't satisfy `Ipv4Addr: Iterator`, `Ipv4Addr: ToTokens`, `Ipv4Addr: proc_macro::ext::RepIteratorExt` or `Ipv4Addr: proc_macro::ext::RepToTokensExt` + | --------------- method `quote_into_iter` not found for this struct because `Ipv4Addr` doesn't implement `Iterator` or `ToTokens` ... LL | let _ = quote! { $($ip)* }; | ^^^^^^^^^^^^^^^^^^ method cannot be called on `Ipv4Addr` due to unsatisfied trait bounds diff --git a/tests/ui/traits/associated-item-unsatisfied-trait-bounds.rs b/tests/ui/traits/associated-item-unsatisfied-trait-bounds.rs new file mode 100644 index 000000000000..4fb4cd61ac51 --- /dev/null +++ b/tests/ui/traits/associated-item-unsatisfied-trait-bounds.rs @@ -0,0 +1,9 @@ +struct Foo; +trait Bar {} +trait Baz {} +trait Bat { fn bat(&self); } +impl Bat for T where T: 'static + Bar + Baz { fn bat(&self) { println!("generic bat"); } } + +pub fn main() { + Foo::bat(()); //~ ERROR E0599 +} diff --git a/tests/ui/traits/associated-item-unsatisfied-trait-bounds.stderr b/tests/ui/traits/associated-item-unsatisfied-trait-bounds.stderr new file mode 100644 index 000000000000..42969de715eb --- /dev/null +++ b/tests/ui/traits/associated-item-unsatisfied-trait-bounds.stderr @@ -0,0 +1,33 @@ +error[E0599]: the function or associated item `bat` exists for struct `Foo`, but its trait bounds were not satisfied + --> $DIR/associated-item-unsatisfied-trait-bounds.rs:8:10 + | +LL | struct Foo; + | ---------- function or associated item `bat` not found for this struct because `Foo` doesn't implement `Bar` or `Baz` +... +LL | Foo::bat(()); + | ^^^ function or associated item cannot be called on `Foo` due to unsatisfied trait bounds + | +note: for `bat` to be available, `Foo` must implement `Bar` and `Baz` + --> $DIR/associated-item-unsatisfied-trait-bounds.rs:5:38 + | +LL | impl Bat for T where T: 'static + Bar + Baz { fn bat(&self) { println!("generic bat"); } } + | --- - ^^^ ^^^ unsatisfied trait bound introduced here + | | + | unsatisfied trait bound introduced here +note: the traits `Bar` and `Baz` must be implemented + --> $DIR/associated-item-unsatisfied-trait-bounds.rs:2:1 + | +LL | trait Bar {} + | ^^^^^^^^^ +LL | trait Baz {} + | ^^^^^^^^^ + = help: items from traits can only be used if the trait is implemented and in scope +note: `Bat` defines an item `bat`, perhaps you need to implement it + --> $DIR/associated-item-unsatisfied-trait-bounds.rs:4:1 + | +LL | trait Bat { fn bat(&self); } + | ^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. From 4803644df98f09d0da1022e85e4820403c785fe1 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 29 Jan 2026 17:20:32 +0800 Subject: [PATCH 212/978] Fix false positive in unused_parens caused by break --- compiler/rustc_lint/src/unused.rs | 5 +++- ...nused-parens-labeled-break-issue-143256.rs | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lint/unused-parens-labeled-break-issue-143256.rs diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 506a16355e22..27ddd4fb5f28 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -794,7 +794,10 @@ trait UnusedDelimLint { ExprKind::Break(_label, None) => return false, ExprKind::Break(_label, Some(break_expr)) => { - return matches!(break_expr.kind, ExprKind::Block(..)); + // `if (break 'label i) { ... }` removing parens would make `i { ... }` + // be parsed as a struct literal, so keep parentheses if the break value + // ends with a path (which could be mistaken for a struct name). + return matches!(break_expr.kind, ExprKind::Block(..) | ExprKind::Path(..)); } ExprKind::Range(_lhs, Some(rhs), _limits) => { diff --git a/tests/ui/lint/unused-parens-labeled-break-issue-143256.rs b/tests/ui/lint/unused-parens-labeled-break-issue-143256.rs new file mode 100644 index 000000000000..8594e646f605 --- /dev/null +++ b/tests/ui/lint/unused-parens-labeled-break-issue-143256.rs @@ -0,0 +1,25 @@ +//@ check-pass +// testcase for https://github.com/rust-lang/rust/issues/143256 + +#![deny(unused_parens)] +#![allow(unreachable_code, unused_variables, dead_code)] + +fn foo() { + let _x = || 'outer: loop { + let inner = 'inner: loop { + let i = Default::default(); + // the parentheses here are necessary + if (break 'outer i) { + loop { + break 'inner 5i8; + } + } else if true { + break 'inner 6; + } + break 7; + }; + break inner < 8; + }; +} + +fn main() {} From e164dca633aa9dcc6f7929ac69be4f16e30d7ddd Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 29 Jan 2026 10:34:44 +0100 Subject: [PATCH 213/978] Don't expect specific instructions for _mm256_set_pd/_mm_set_ps These don't correspond to specific instructions and will produce different instructions on x86/x86_64 based on ABI details. --- library/stdarch/crates/core_arch/src/x86/avx.rs | 1 - library/stdarch/crates/core_arch/src/x86/sse.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx.rs b/library/stdarch/crates/core_arch/src/x86/avx.rs index 7b4b210bacf4..74fc2db13dcd 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx.rs @@ -2426,7 +2426,6 @@ pub const fn _mm256_setzero_si256() -> __m256i { #[inline] #[target_feature(enable = "avx")] // This intrinsic has no corresponding instruction. -#[cfg_attr(test, assert_instr(vinsertf128))] #[stable(feature = "simd_x86", since = "1.27.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_set_pd(a: f64, b: f64, c: f64, d: f64) -> __m256d { diff --git a/library/stdarch/crates/core_arch/src/x86/sse.rs b/library/stdarch/crates/core_arch/src/x86/sse.rs index b83274e60e72..2c4439a3f3a5 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse.rs @@ -968,7 +968,7 @@ pub const fn _mm_set_ps1(a: f32) -> __m128 { /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_set_ps) #[inline] #[target_feature(enable = "sse")] -#[cfg_attr(test, assert_instr(unpcklps))] +// This intrinsic has no corresponding instruction. #[stable(feature = "simd_x86", since = "1.27.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_set_ps(a: f32, b: f32, c: f32, d: f32) -> __m128 { From 293b61e4440234fddee48dba109d61d86f327b5c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 29 Jan 2026 11:07:06 +0100 Subject: [PATCH 214/978] Ignore non-yml files in generator Otherwise this picks up vim .swp files. --- library/stdarch/crates/stdarch-gen-arm/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/stdarch/crates/stdarch-gen-arm/src/main.rs b/library/stdarch/crates/stdarch-gen-arm/src/main.rs index 9bf7d0981deb..e14e2782485b 100644 --- a/library/stdarch/crates/stdarch-gen-arm/src/main.rs +++ b/library/stdarch/crates/stdarch-gen-arm/src/main.rs @@ -139,6 +139,7 @@ fn parse_args() -> Vec<(PathBuf, Option)> { .into_iter() .filter_map(Result::ok) .filter(|f| f.file_type().is_file()) + .filter(|f| f.file_name().to_string_lossy().ends_with(".yml")) .map(|f| (f.into_path(), out_dir.clone())) .collect() } From f5d594a309d31c83d55fd67d3178429c70b75d95 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 29 Jan 2026 11:21:11 +0100 Subject: [PATCH 215/978] Change lanes vcopy_lane tests to avoid zip2 --- .../core_arch/src/aarch64/neon/generated.rs | 78 +++++++++---------- .../spec/neon/aarch64.spec.yml | 8 +- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index 9507b71106dd..3d5d07ac1b4e 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -4092,7 +4092,7 @@ pub fn vcmlaq_rot90_laneq_f32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_f32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_f32( @@ -4113,7 +4113,7 @@ pub fn vcopy_lane_f32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_s8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { @@ -4137,7 +4137,7 @@ pub fn vcopy_lane_s8(a: int8x8_t, b: int8x8_ #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_s16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { @@ -4157,7 +4157,7 @@ pub fn vcopy_lane_s16(a: int16x4_t, b: int16 #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_s32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { @@ -4175,7 +4175,7 @@ pub fn vcopy_lane_s32(a: int32x2_t, b: int32 #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_u8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { @@ -4199,7 +4199,7 @@ pub fn vcopy_lane_u8(a: uint8x8_t, b: uint8x #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_u16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_u16( @@ -4222,7 +4222,7 @@ pub fn vcopy_lane_u16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_u32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_u32( @@ -4243,7 +4243,7 @@ pub fn vcopy_lane_u32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_p8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { @@ -4267,7 +4267,7 @@ pub fn vcopy_lane_p8(a: poly8x8_t, b: poly8x #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_lane_p16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_lane_p16( @@ -4290,7 +4290,7 @@ pub fn vcopy_lane_p16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_f32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_f32( @@ -4312,7 +4312,7 @@ pub fn vcopy_laneq_f32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_s8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_s8(a: int8x8_t, b: int8x16_t) -> int8x8_t { @@ -4338,7 +4338,7 @@ pub fn vcopy_laneq_s8(a: int8x8_t, b: int8x1 #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_s16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_s16( @@ -4362,7 +4362,7 @@ pub fn vcopy_laneq_s16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_s32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_s32( @@ -4384,7 +4384,7 @@ pub fn vcopy_laneq_s32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_u8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_u8( @@ -4413,7 +4413,7 @@ pub fn vcopy_laneq_u8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_u16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_u16( @@ -4437,7 +4437,7 @@ pub fn vcopy_laneq_u16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_u32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_u32( @@ -4459,7 +4459,7 @@ pub fn vcopy_laneq_u32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_p8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_p8( @@ -4488,7 +4488,7 @@ pub fn vcopy_laneq_p8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopy_laneq_p16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopy_laneq_p16( @@ -4624,7 +4624,7 @@ pub fn vcopyq_lane_p64( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_s8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_s8(a: int8x16_t, b: int8x8_t) -> int8x16_t { @@ -4994,7 +4994,7 @@ pub fn vcopyq_lane_s8(a: int8x16_t, b: int8x #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_s16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_s16( @@ -5022,7 +5022,7 @@ pub fn vcopyq_lane_s16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_s32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_s32( @@ -5046,7 +5046,7 @@ pub fn vcopyq_lane_s32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_u8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_u8( @@ -5419,7 +5419,7 @@ pub fn vcopyq_lane_u8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_u16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_u16( @@ -5447,7 +5447,7 @@ pub fn vcopyq_lane_u16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_u32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_u32( @@ -5471,7 +5471,7 @@ pub fn vcopyq_lane_u32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_p8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_p8( @@ -5844,7 +5844,7 @@ pub fn vcopyq_lane_p8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_lane_p16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_lane_p16( @@ -5872,7 +5872,7 @@ pub fn vcopyq_lane_p16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_f32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_f32( @@ -5895,7 +5895,7 @@ pub fn vcopyq_laneq_f32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_f64)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_f64( @@ -5916,7 +5916,7 @@ pub fn vcopyq_laneq_f64( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_s8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_s8( @@ -6287,7 +6287,7 @@ pub fn vcopyq_laneq_s8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_s16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_s16( @@ -6314,7 +6314,7 @@ pub fn vcopyq_laneq_s16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_s32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_s32( @@ -6337,7 +6337,7 @@ pub fn vcopyq_laneq_s32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_s64)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_s64( @@ -6358,7 +6358,7 @@ pub fn vcopyq_laneq_s64( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_u8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_u8( @@ -6729,7 +6729,7 @@ pub fn vcopyq_laneq_u8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_u16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_u16( @@ -6756,7 +6756,7 @@ pub fn vcopyq_laneq_u16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_u32)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_u32( @@ -6779,7 +6779,7 @@ pub fn vcopyq_laneq_u32( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_u64)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_u64( @@ -6800,7 +6800,7 @@ pub fn vcopyq_laneq_u64( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_p8)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_p8( @@ -7171,7 +7171,7 @@ pub fn vcopyq_laneq_p8( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_p16)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_p16( @@ -7198,7 +7198,7 @@ pub fn vcopyq_laneq_p16( #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vcopyq_laneq_p64)"] #[inline(always)] #[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] +#[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub fn vcopyq_laneq_p64( diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml index a9bc377924dd..a099c2c8d694 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml @@ -8958,7 +8958,7 @@ intrinsics: arguments: ["a: {neon_type[0]}", "b: {neon_type[1]}"] return_type: "{neon_type[2]}" attr: - - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 1']]}]] + - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 0']]}]] - FnCall: [rustc_legacy_const_generics, ['1', '3']] - FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] static_defs: ['const LANE1: i32, const LANE2: i32'] @@ -8983,7 +8983,7 @@ intrinsics: arguments: ["a: {neon_type[0]}", "b: {neon_type[1]}"] return_type: "{neon_type[2]}" attr: - - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 1']]}]] + - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 0']]}]] - FnCall: [rustc_legacy_const_generics, ['1', '3']] - FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] static_defs: ['const LANE1: i32, const LANE2: i32'] @@ -9008,7 +9008,7 @@ intrinsics: arguments: ["a: {neon_type[0]}", "b: {neon_type[1]}"] return_type: "{neon_type[2]}" attr: - - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 1']]}]] + - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 0']]}]] - FnCall: [rustc_legacy_const_generics, ['1', '3']] - FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] static_defs: ['const LANE1: i32, const LANE2: i32'] @@ -9037,7 +9037,7 @@ intrinsics: arguments: ["a: {neon_type[0]}", "b: {neon_type[1]}"] return_type: "{neon_type[2]}" attr: - - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 1']]}]] + - FnCall: [cfg_attr, [test, {FnCall: [assert_instr, [mov, 'LANE1 = 0', 'LANE2 = 0']]}]] - FnCall: [rustc_legacy_const_generics, ['1', '3']] - FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] static_defs: ['const LANE1: i32, const LANE2: i32'] From b500dd3f6b5af7e198a8a307d9eadcd8891dad26 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 29 Jan 2026 11:28:32 +0100 Subject: [PATCH 216/978] Adjust expected output for vrfin It actually generates vrfin now --- library/stdarch/crates/core_arch/src/powerpc/altivec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs index fb1a9d8ed9e2..0e238c532553 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs @@ -3249,7 +3249,7 @@ mod sealed { unsafe fn vec_round(self) -> Self; } - test_impl! { vec_vrfin(a: vector_float) -> vector_float [vrfin, xvrspic] } + test_impl! { vec_vrfin(a: vector_float) -> vector_float [vrfin, vrfin] } #[unstable(feature = "stdarch_powerpc", issue = "111145")] impl VectorRound for vector_float { From d4454e59d3021557aead4591dea0390bf9d8e68b Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 29 Jan 2026 11:47:21 +0100 Subject: [PATCH 217/978] add regression test --- tests/ui/layout/rigid-alias-no-params.rs | 30 +++++++++++++++++++ ...und-unsatisfied-item-bounds-mit-opt-ice.rs | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/ui/layout/rigid-alias-no-params.rs diff --git a/tests/ui/layout/rigid-alias-no-params.rs b/tests/ui/layout/rigid-alias-no-params.rs new file mode 100644 index 000000000000..bc2622eb7ca6 --- /dev/null +++ b/tests/ui/layout/rigid-alias-no-params.rs @@ -0,0 +1,30 @@ +//@ compile-flags: -O -Cdebug-assertions=on +//@ build-pass + +// A regression test for #151791. Computing the layout of +// `>::Archived` fails as the alias +// is still rigid as the where-bound in scope shadows the impl. +// +// This previously caused an incorrect error during MIR optimizations. + +struct ArchivedString; + +pub trait ArchiveWith<'a> { + type Archived; +} + +struct AsOwned; +impl ArchiveWith<'_> for AsOwned { + type Archived = ArchivedString; +} + +fn foo<'a>() +where + AsOwned: ArchiveWith<'a>, +{ + let _ = unsafe { &*std::ptr::dangling::<>::Archived>() }; +} + +fn main() { + foo(); +} diff --git a/tests/ui/where-clauses/projection-bound-unsatisfied-item-bounds-mit-opt-ice.rs b/tests/ui/where-clauses/projection-bound-unsatisfied-item-bounds-mit-opt-ice.rs index 80eec709eecb..9448c8a2f911 100644 --- a/tests/ui/where-clauses/projection-bound-unsatisfied-item-bounds-mit-opt-ice.rs +++ b/tests/ui/where-clauses/projection-bound-unsatisfied-item-bounds-mit-opt-ice.rs @@ -2,7 +2,7 @@ //@ build-pass // A regression test for #149081. The environment of `size` and `align` -// currently means that the item bound of`T::Assoc` doesn't hold. This can +// currently means that the item bound of `T::Assoc` doesn't hold. This can // result in normalization failures and ICE during MIR optimizations. // // This will no longer be an issue once #149283 is implemented. From 25c13655072475476f6ff3f26dc5cfda39db44d8 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 22 Dec 2025 14:45:08 +0000 Subject: [PATCH 218/978] Part 2 refactoring of moving placeholder types to `rustc_type_ir` --- .../src/diagnostics/bound_region_errors.rs | 4 +- .../src/region_infer/graphviz.rs | 2 +- .../rustc_borrowck/src/region_infer/values.rs | 10 +- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- .../src/type_check/relate_tys.rs | 14 +- .../src/check/compare_impl_item.rs | 6 +- .../src/collect/item_bounds.rs | 5 +- .../src/collect/resolve_bound_vars.rs | 48 +-- .../src/hir_ty_lowering/bounds.rs | 6 +- .../src/hir_ty_lowering/mod.rs | 6 +- .../src/infer/canonical/canonicalizer.rs | 6 +- compiler/rustc_infer/src/infer/mod.rs | 8 +- .../src/infer/outlives/test_type_match.rs | 4 +- .../src/infer/relate/higher_ranked.rs | 6 +- .../rustc_lint/src/impl_trait_overcaptures.rs | 2 +- .../src/middle/resolve_bound_vars.rs | 4 +- compiler/rustc_middle/src/query/erase.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 4 +- compiler/rustc_middle/src/ty/codec.rs | 6 +- compiler/rustc_middle/src/ty/consts.rs | 8 +- compiler/rustc_middle/src/ty/context.rs | 26 +- compiler/rustc_middle/src/ty/fold.rs | 49 ++- compiler/rustc_middle/src/ty/mod.rs | 104 +----- compiler/rustc_middle/src/ty/print/pretty.rs | 14 +- compiler/rustc_middle/src/ty/region.rs | 95 +---- .../rustc_middle/src/ty/structural_impls.rs | 28 +- compiler/rustc_middle/src/ty/sty.rs | 84 ++--- compiler/rustc_middle/src/ty/visit.rs | 14 +- .../src/canonical/canonicalizer.rs | 25 +- .../src/canonical/mod.rs | 4 +- .../src/placeholder.rs | 22 +- .../src/unstable/convert/internal.rs | 2 +- .../src/unstable/convert/stable/ty.rs | 10 +- .../src/unstable/internal_cx/mod.rs | 5 +- compiler/rustc_public/src/unstable/mod.rs | 5 +- .../nice_region_error/placeholder_relation.rs | 8 +- .../src/error_reporting/infer/region.rs | 2 +- .../src/traits/coherence.rs | 8 +- .../rustc_trait_selection/src/traits/mod.rs | 2 +- .../rustc_trait_selection/src/traits/util.rs | 12 +- compiler/rustc_ty_utils/src/ty.rs | 2 +- compiler/rustc_type_ir/src/binder.rs | 352 +++++++++++++++++- compiler/rustc_type_ir/src/canonical.rs | 6 +- compiler/rustc_type_ir/src/const_kind.rs | 4 +- compiler/rustc_type_ir/src/error.rs | 2 +- compiler/rustc_type_ir/src/inherent.rs | 74 +--- compiler/rustc_type_ir/src/interner.rs | 18 +- compiler/rustc_type_ir/src/outlives.rs | 2 +- compiler/rustc_type_ir/src/region_kind.rs | 10 +- compiler/rustc_type_ir/src/ty_kind.rs | 4 +- src/librustdoc/clean/mod.rs | 2 +- src/tools/clippy/clippy_utils/src/ty/mod.rs | 8 +- 52 files changed, 610 insertions(+), 546 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 254d28d243ff..6ed07cf9b1c8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -169,7 +169,7 @@ pub(crate) trait TypeOpInfo<'tcx> { let placeholder_region = ty::Region::new_placeholder( tcx, - ty::Placeholder::new(adjusted_universe.into(), placeholder.bound), + ty::PlaceholderRegion::new(adjusted_universe.into(), placeholder.bound), ); let error_region = @@ -179,7 +179,7 @@ pub(crate) trait TypeOpInfo<'tcx> { adjusted_universe.map(|adjusted| { ty::Region::new_placeholder( tcx, - ty::Placeholder::new(adjusted.into(), error_placeholder.bound), + ty::PlaceholderRegion::new(adjusted.into(), error_placeholder.bound), ) }) } else { diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs index 526e1850c2ef..ceb33d82deba 100644 --- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs +++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs @@ -52,7 +52,7 @@ fn render_region_vid<'tcx>( format!(" (for<{}>)", tcx.item_name(def_id)) } ty::BoundRegionKind::ClosureEnv | ty::BoundRegionKind::Anon => " (for<'_>)".to_string(), - ty::BoundRegionKind::NamedAnon(_) => { + ty::BoundRegionKind::NamedForPrinting(_) => { bug!("only used for pretty printing") } }, diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 0063af25d781..1dd3bc831f45 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -10,8 +10,8 @@ use rustc_middle::ty::{self, RegionVid}; use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; use tracing::debug; +use crate::BorrowIndex; use crate::polonius::LiveLoans; -use crate::{BorrowIndex, TyCtxt}; rustc_index::newtype_index! { /// A single integer representing a `ty::Placeholder`. @@ -420,18 +420,18 @@ impl ToElementIndex<'_> for RegionVid { impl<'tcx> ToElementIndex<'tcx> for ty::PlaceholderRegion<'tcx> { fn add_to_row(self, values: &mut RegionValues<'tcx, N>, row: N) -> bool where - Self: Into, ty::BoundRegion>>, + Self: Into>, { - let placeholder: ty::Placeholder, ty::BoundRegion> = self.into(); + let placeholder: ty::PlaceholderRegion<'tcx> = self.into(); let index = values.placeholder_indices.lookup_index(placeholder); values.placeholders.insert(row, index) } fn contained_in_row(self, values: &RegionValues<'tcx, N>, row: N) -> bool where - Self: Into, ty::BoundRegion>>, + Self: Into>, { - let placeholder: ty::Placeholder, ty::BoundRegion> = self.into(); + let placeholder: ty::PlaceholderRegion<'tcx> = self.into(); let index = values.placeholder_indices.lookup_index(placeholder); values.placeholders.contains(row, index) } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index d2464c7e99ee..e9dfea6043a3 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -772,7 +772,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ty::BoundRegionKind::Anon => sym::anon, ty::BoundRegionKind::Named(def_id) => tcx.item_name(def_id), ty::BoundRegionKind::ClosureEnv => sym::env, - ty::BoundRegionKind::NamedAnon(_) => { + ty::BoundRegionKind::NamedForPrinting(_) => { bug!("only used for pretty printing") } }; diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 045507ceb4b4..e2d684e12a81 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -174,7 +174,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { let infcx = self.type_checker.infcx; let mut lazy_universe = None; let delegate = FnMutDelegate { - regions: &mut |br: ty::BoundRegion| { + regions: &mut |br: ty::BoundRegion<'tcx>| { // The first time this closure is called, create a // new universe for the placeholders we will make // from here out. @@ -191,10 +191,10 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { placeholder_reg }, - types: &mut |_bound_ty: ty::BoundTy| { + types: &mut |_bound_ty: ty::BoundTy<'tcx>| { unreachable!("we only replace regions in nll_relate, not types") }, - consts: &mut |_bound_const: ty::BoundConst| { + consts: &mut |_bound_const: ty::BoundConst<'tcx>| { unreachable!("we only replace regions in nll_relate, not consts") }, }; @@ -218,7 +218,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { let infcx = self.type_checker.infcx; let mut reg_map = FxHashMap::default(); let delegate = FnMutDelegate { - regions: &mut |br: ty::BoundRegion| { + regions: &mut |br: ty::BoundRegion<'tcx>| { if let Some(ex_reg_var) = reg_map.get(&br) { *ex_reg_var } else { @@ -230,10 +230,10 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { ex_reg_var } }, - types: &mut |_bound_ty: ty::BoundTy| { + types: &mut |_bound_ty: ty::BoundTy<'tcx>| { unreachable!("we only replace regions in nll_relate, not types") }, - consts: &mut |_bound_const: ty::BoundConst| { + consts: &mut |_bound_const: ty::BoundConst<'tcx>| { unreachable!("we only replace regions in nll_relate, not consts") }, }; @@ -268,7 +268,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { ty::BoundRegionKind::Anon => sym::anon, ty::BoundRegionKind::Named(def_id) => self.type_checker.tcx().item_name(def_id), ty::BoundRegionKind::ClosureEnv => sym::env, - ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"), + ty::BoundRegionKind::NamedForPrinting(_) => bug!("only used for pretty printing"), }; if cfg!(debug_assertions) { 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 4534cfcf962e..dd7b03c9dac3 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -592,7 +592,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( ty, Ty::new_placeholder( tcx, - ty::Placeholder::new( + ty::PlaceholderType::new( universe, ty::BoundTy { var: idx, kind: ty::BoundTyKind::Anon }, ), @@ -2551,7 +2551,7 @@ fn param_env_with_gat_bounds<'tcx>( } }; - let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> = + let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind<'tcx>; 8]> = smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).own_params.len()); // Extend the impl's identity args with late-bound GAT vars let normalize_impl_ty_args = ty::GenericArgs::identity_for_item(tcx, container_id) @@ -2587,7 +2587,7 @@ fn param_env_with_gat_bounds<'tcx>( ty::Const::new_bound( tcx, ty::INNERMOST, - ty::BoundConst { var: ty::BoundVar::from_usize(bound_vars.len() - 1) }, + ty::BoundConst::new(ty::BoundVar::from_usize(bound_vars.len() - 1)), ) .into() } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 7025f7ac84b0..a01ee2d31a3d 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -241,7 +241,7 @@ struct MapAndCompressBoundVars<'tcx> { binder: ty::DebruijnIndex, /// List of bound vars that remain unsubstituted because they were not /// mentioned in the GAT's args. - still_bound_vars: Vec, + still_bound_vars: Vec>, /// Subtle invariant: If the `GenericArg` is bound, then it should be /// stored with the debruijn index of `INNERMOST` so it can be shifted /// correctly during substitution. @@ -330,7 +330,8 @@ impl<'tcx> TypeFolder> for MapAndCompressBoundVars<'tcx> { } else { let var = ty::BoundVar::from_usize(self.still_bound_vars.len()); self.still_bound_vars.push(ty::BoundVariableKind::Const); - let mapped = ty::Const::new_bound(self.tcx, ty::INNERMOST, ty::BoundConst { var }); + let mapped = + ty::Const::new_bound(self.tcx, ty::INNERMOST, ty::BoundConst::new(var)); self.mapping.insert(old_bound.var, mapped.into()); mapped }; 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 02443b577d38..26f79d374075 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -63,9 +63,9 @@ impl ResolvedArg { struct BoundVarContext<'a, 'tcx> { tcx: TyCtxt<'tcx>, - rbv: &'a mut ResolveBoundVars, + rbv: &'a mut ResolveBoundVars<'tcx>, disambiguator: &'a mut DisambiguatorState, - scope: ScopeRef<'a>, + scope: ScopeRef<'a, 'tcx>, opaque_capture_errors: RefCell>, } @@ -76,7 +76,7 @@ struct OpaqueHigherRankedLifetimeCaptureErrors { } #[derive(Debug)] -enum Scope<'a> { +enum Scope<'a, 'tcx> { /// Declares lifetimes, and each can be early-bound or late-bound. /// The `DebruijnIndex` of late-bound lifetimes starts at `1` and /// it should be shifted by the number of `Binder`s in between the @@ -94,7 +94,7 @@ enum Scope<'a> { /// to append to. hir_id: HirId, - s: ScopeRef<'a>, + s: ScopeRef<'a, 'tcx>, /// If this binder comes from a where clause, specify how it was created. /// This is used to diagnose inaccessible lifetimes in APIT: @@ -110,7 +110,7 @@ enum Scope<'a> { /// e.g., `(&T, fn(&T) -> &T);` becomes `(&'_ T, for<'a> fn(&'a T) -> &'a T)`. Body { id: hir::BodyId, - s: ScopeRef<'a>, + s: ScopeRef<'a, 'tcx>, }, /// Use a specific lifetime (if `Some`) or leave it unset (to be @@ -118,7 +118,7 @@ enum Scope<'a> { /// for the default choice of lifetime in a trait object type. ObjectLifetimeDefault { lifetime: Option, - s: ScopeRef<'a>, + s: ScopeRef<'a, 'tcx>, }, /// When we have nested trait refs, we concatenate late bound vars for inner @@ -126,12 +126,12 @@ enum Scope<'a> { /// lifetimes encountered when identifying the trait that an associated type /// is declared on. Supertrait { - bound_vars: Vec, - s: ScopeRef<'a>, + bound_vars: Vec>, + s: ScopeRef<'a, 'tcx>, }, TraitRefBoundary { - s: ScopeRef<'a>, + s: ScopeRef<'a, 'tcx>, }, /// Remap lifetimes that appear in opaque types to fresh lifetime parameters. Given: @@ -148,7 +148,7 @@ enum Scope<'a> { /// Mapping from each captured lifetime `'a` to the duplicate generic parameter `'b`. captures: &'a RefCell>, - s: ScopeRef<'a>, + s: ScopeRef<'a, 'tcx>, }, /// Disallows capturing late-bound vars from parent scopes. @@ -157,7 +157,7 @@ enum Scope<'a> { /// since we don't do something more correct like replacing any captured /// late-bound vars with early-bound params in the const's own generics. LateBoundary { - s: ScopeRef<'a>, + s: ScopeRef<'a, 'tcx>, what: &'static str, deny_late_regions: bool, }, @@ -167,7 +167,7 @@ enum Scope<'a> { }, } -impl<'a> Scope<'a> { +impl<'a, 'tcx> Scope<'a, 'tcx> { // A helper for debugging scopes without printing parent scopes fn debug_truncated(&self) -> impl fmt::Debug { fmt::from_fn(move |f| match self { @@ -227,7 +227,7 @@ enum BinderScopeType { Concatenating, } -type ScopeRef<'a> = &'a Scope<'a>; +type ScopeRef<'a, 'tcx> = &'a Scope<'a, 'tcx>; /// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`] pub(crate) fn provide(providers: &mut Providers) { @@ -253,7 +253,7 @@ pub(crate) fn provide(providers: &mut Providers) { /// You should not read the result of this query directly, but rather use /// `named_variable_map`, `late_bound_vars_map`, etc. #[instrument(level = "debug", skip(tcx))] -fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars { +fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars<'_> { let mut rbv = ResolveBoundVars::default(); let mut visitor = BoundVarContext { tcx, @@ -287,7 +287,7 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou rbv } -fn late_arg_as_bound_arg<'tcx>(param: &GenericParam<'tcx>) -> ty::BoundVariableKind { +fn late_arg_as_bound_arg<'tcx>(param: &GenericParam<'tcx>) -> ty::BoundVariableKind<'tcx> { let def_id = param.def_id.to_def_id(); match param.kind { GenericParamKind::Lifetime { .. } => { @@ -301,7 +301,9 @@ fn late_arg_as_bound_arg<'tcx>(param: &GenericParam<'tcx>) -> ty::BoundVariableK /// Turn a [`ty::GenericParamDef`] into a bound arg. Generally, this should only /// be used when turning early-bound vars into late-bound vars when lowering /// return type notation. -fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVariableKind { +fn generic_param_def_as_bound_arg<'tcx>( + param: &ty::GenericParamDef, +) -> ty::BoundVariableKind<'tcx> { match param.kind { ty::GenericParamDefKind::Lifetime => { ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(param.def_id)) @@ -329,7 +331,9 @@ fn opaque_captures_all_in_scope_lifetimes<'tcx>(opaque: &'tcx hir::OpaqueTy<'tcx impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { /// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref. - fn poly_trait_ref_binder_info(&mut self) -> (Vec, BinderScopeType) { + fn poly_trait_ref_binder_info( + &mut self, + ) -> (Vec>, BinderScopeType) { let mut scope = self.scope; let mut supertrait_bound_vars = vec![]; loop { @@ -364,7 +368,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { Scope::Binder { hir_id, .. } => { // Nested poly trait refs have the binders concatenated - let mut full_binders = + let mut full_binders: Vec> = self.rbv.late_bound_vars.get_mut_or_insert_default(hir_id.local_id).clone(); full_binders.extend(supertrait_bound_vars); break (full_binders, BinderScopeType::Concatenating); @@ -1094,7 +1098,7 @@ fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectL } impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { - fn with(&mut self, wrap_scope: Scope<'_>, f: F) + fn with(&mut self, wrap_scope: Scope<'_, 'tcx>, f: F) where F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>), { @@ -1115,7 +1119,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { *self.opaque_capture_errors.borrow_mut() = this.opaque_capture_errors.into_inner(); } - fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec) { + fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec>) { if let Some(old) = self.rbv.late_bound_vars.insert(hir_id.local_id, binder) { bug!( "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}", @@ -1931,7 +1935,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { def_id: DefId, assoc_ident: Ident, assoc_tag: ty::AssocTag, - ) -> Option<(Vec, &'tcx ty::AssocItem)> { + ) -> Option<(Vec>, &'tcx ty::AssocItem)> { let trait_defines_associated_item_named = |trait_def_id: DefId| { tcx.associated_items(trait_def_id).find_by_ident_and_kind( tcx, @@ -1942,7 +1946,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { }; use smallvec::{SmallVec, smallvec}; - let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind; 8]>); 8]> = + let mut stack: SmallVec<[(DefId, SmallVec<[ty::BoundVariableKind<'tcx>; 8]>); 8]> = smallvec![(def_id, smallvec![])]; let mut visited: FxHashSet = FxHashSet::default(); loop { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index d6441702b268..3515ce4ea939 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -362,7 +362,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { param_ty: Ty<'tcx>, hir_bounds: I, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, - bound_vars: &'tcx ty::List, + bound_vars: &'tcx ty::List>, predicate_filter: PredicateFilter, overlapping_assoc_constraints: OverlappingAsssocItemConstraints, ) where @@ -1000,7 +1000,9 @@ impl<'tcx> TypeVisitor> for GenericParamAndBoundVarCollector<'_, 't .delayed_bug(format!("unexpected bound region kind: {:?}", br.kind)); return ControlFlow::Break(guar); } - ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"), + ty::BoundRegionKind::NamedForPrinting(_) => { + bug!("only used for pretty printing") + } }); } _ => {} diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 867c588e302d..9f84f652698b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2310,7 +2310,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => ty::Const::new_bound( tcx, debruijn, - ty::BoundConst { var: ty::BoundVar::from_u32(index) }, + ty::BoundConst::new(ty::BoundVar::from_u32(index)), ), Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar), arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", path_hir_id), @@ -3196,8 +3196,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { #[instrument(level = "trace", skip(self, generate_err))] fn validate_late_bound_regions<'cx>( &'cx self, - constrained_regions: FxIndexSet, - referenced_regions: FxIndexSet, + constrained_regions: FxIndexSet>, + referenced_regions: FxIndexSet>, generate_err: impl Fn(&str) -> Diag<'cx>, ) { for br in referenced_regions.difference(&constrained_regions) { diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 23f6fee406a5..89ea6324d854 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -684,19 +684,19 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { CanonicalVarKind::Region(u) => CanonicalVarKind::Region(reverse_universe_map[&u]), CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]), CanonicalVarKind::PlaceholderTy(placeholder) => { - CanonicalVarKind::PlaceholderTy(ty::Placeholder::new( + CanonicalVarKind::PlaceholderTy(ty::PlaceholderType::new( reverse_universe_map[&placeholder.universe], placeholder.bound, )) } CanonicalVarKind::PlaceholderRegion(placeholder) => { - CanonicalVarKind::PlaceholderRegion(ty::Placeholder::new( + CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new( reverse_universe_map[&placeholder.universe], placeholder.bound, )) } CanonicalVarKind::PlaceholderConst(placeholder) => { - CanonicalVarKind::PlaceholderConst(ty::Placeholder::new( + CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst::new( reverse_universe_map[&placeholder.universe], placeholder.bound, )) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index c9ea420944e2..e15b25500bb5 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -447,7 +447,7 @@ pub enum RegionVariableOrigin<'tcx> { /// Region variables created when instantiating a binder with /// existential variables, e.g. when calling a function or method. - BoundRegion(Span, ty::BoundRegionKind, BoundRegionConversionTime), + BoundRegion(Span, ty::BoundRegionKind<'tcx>, BoundRegionConversionTime), UpvarRegion(ty::UpvarId, Span), @@ -1300,13 +1300,13 @@ impl<'tcx> InferCtxt<'tcx> { } impl<'tcx> BoundVarReplacerDelegate<'tcx> for ToFreshVars<'tcx> { - fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> { + fn replace_region(&mut self, br: ty::BoundRegion<'tcx>) -> ty::Region<'tcx> { self.args[br.var.index()].expect_region() } - fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { + fn replace_ty(&mut self, bt: ty::BoundTy<'tcx>) -> Ty<'tcx> { self.args[bt.var.index()].expect_ty() } - fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx> { + fn replace_const(&mut self, bc: ty::BoundConst<'tcx>) -> ty::Const<'tcx> { self.args[bc.var.index()].expect_const() } } 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 7be5daf61056..479daf67a8ba 100644 --- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs +++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs @@ -91,7 +91,7 @@ pub(super) fn can_match_erased_ty<'tcx>( struct MatchAgainstHigherRankedOutlives<'tcx> { tcx: TyCtxt<'tcx>, pattern_depth: ty::DebruijnIndex, - map: FxHashMap>, + map: FxHashMap, ty::Region<'tcx>>, } impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> { @@ -115,7 +115,7 @@ impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> { #[instrument(level = "trace", skip(self))] fn bind( &mut self, - br: ty::BoundRegion, + br: ty::BoundRegion<'tcx>, value: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { match self.map.entry(br) { diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index 7a0f70e979b8..324725a079bb 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -33,13 +33,13 @@ impl<'tcx> InferCtxt<'tcx> { let next_universe = self.create_next_universe(); let delegate = FnMutDelegate { - regions: &mut |br: ty::BoundRegion| { + regions: &mut |br: ty::BoundRegion<'tcx>| { ty::Region::new_placeholder(self.tcx, ty::PlaceholderRegion::new(next_universe, br)) }, - types: &mut |bound_ty: ty::BoundTy| { + types: &mut |bound_ty: ty::BoundTy<'tcx>| { Ty::new_placeholder(self.tcx, ty::PlaceholderType::new(next_universe, bound_ty)) }, - consts: &mut |bound_const: ty::BoundConst| { + consts: &mut |bound_const: ty::BoundConst<'tcx>| { ty::Const::new_placeholder( self.tcx, ty::PlaceholderConst::new(next_universe, bound_const), diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index f6c2e5946079..1cdc5e4a1b36 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -211,7 +211,7 @@ where // When we get into a binder, we need to add its own bound vars to the scope. let mut added = vec![]; for arg in t.bound_vars() { - let arg: ty::BoundVariableKind = arg; + let arg: ty::BoundVariableKind<'tcx> = arg; match arg { ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id)) | ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id)) => { diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs index 51a079e8bc12..d625e9ea08cc 100644 --- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs +++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs @@ -48,7 +48,7 @@ pub enum ObjectLifetimeDefault { /// Maps the id of each bound variable reference to the variable decl /// that it corresponds to. #[derive(Debug, Default, HashStable)] -pub struct ResolveBoundVars { +pub struct ResolveBoundVars<'tcx> { // Maps from every use of a named (not anonymous) bound var to a // `ResolvedArg` describing how that variable is bound. pub defs: SortedMap, @@ -59,7 +59,7 @@ pub struct ResolveBoundVars { // - closures // - trait refs // - bound types (like `T` in `for<'a> T<'a>: Foo`) - pub late_bound_vars: SortedMap>, + pub late_bound_vars: SortedMap>>, // List captured variables for each opaque type. pub opaque_captured_lifetimes: LocalDefIdMap>, diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 940cc30c17e6..afda0da48611 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -346,7 +346,6 @@ trivial! { rustc_middle::ty::AssocContainer, rustc_middle::ty::Asyncness, rustc_middle::ty::AsyncDestructor, - rustc_middle::ty::BoundVariableKind, rustc_middle::ty::AnonConstKind, rustc_middle::ty::Destructor, rustc_middle::ty::fast_reject::SimplifiedType, @@ -415,6 +414,7 @@ tcx_lifetime! { rustc_middle::ty::ConstConditions, rustc_middle::ty::inhabitedness::InhabitedPredicate, rustc_middle::ty::Instance, + rustc_middle::ty::BoundVariableKind, rustc_middle::ty::InstanceKind, rustc_middle::ty::layout::FnAbiError, rustc_middle::ty::layout::LayoutError, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 2f83f3078e89..1a60cc2530d8 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2116,7 +2116,7 @@ rustc_queries! { /// Does lifetime resolution on items. Importantly, we can't resolve /// lifetimes directly on things like trait methods, because of trait params. /// See `rustc_resolve::late::lifetimes` for details. - query resolve_bound_vars(owner_id: hir::OwnerId) -> &'tcx ResolveBoundVars { + query resolve_bound_vars(owner_id: hir::OwnerId) -> &'tcx ResolveBoundVars<'tcx> { arena_cache desc { |tcx| "resolving lifetimes for `{}`", tcx.def_path_str(owner_id) } } @@ -2145,7 +2145,7 @@ rustc_queries! { separate_provide_extern } query late_bound_vars_map(owner_id: hir::OwnerId) - -> &'tcx SortedMap> { + -> &'tcx SortedMap>> { desc { |tcx| "looking up late bound vars inside `{}`", tcx.def_path_str(owner_id) } } /// For an opaque type, return the list of (captured lifetime, inner generic param). diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 75b1317e022b..4856df3a6222 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -427,11 +427,11 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [Spanned } } -impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List { +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List> { fn decode(decoder: &mut D) -> &'tcx Self { let len = decoder.read_usize(); decoder.interner().mk_bound_variable_kinds_from_iter( - (0..len).map::(|_| Decodable::decode(decoder)), + (0..len).map::, _>(|_| Decodable::decode(decoder)), ) } } @@ -495,7 +495,7 @@ impl_decodable_via_ref! { &'tcx ty::List>, &'tcx traits::ImplSource<'tcx, ()>, &'tcx mir::Body<'tcx>, - &'tcx ty::List, + &'tcx ty::List>, &'tcx ty::List>, &'tcx ty::ListWithCachedTypeInfo>, } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index da3caf0bb210..5581ad5669aa 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -94,7 +94,7 @@ impl<'tcx> Const<'tcx> { pub fn new_bound( tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, - bound_const: ty::BoundConst, + bound_const: ty::BoundConst<'tcx>, ) -> Const<'tcx> { Const::new(tcx, ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_const)) } @@ -103,7 +103,7 @@ impl<'tcx> Const<'tcx> { pub fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: ty::BoundVar) -> Const<'tcx> { Const::new( tcx, - ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, ty::BoundConst { var }), + ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, ty::BoundConst::new(var)), ) } @@ -183,13 +183,13 @@ impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { fn new_bound( interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, - bound_const: ty::BoundConst, + bound_const: ty::BoundConst<'tcx>, ) -> Self { Const::new_bound(interner, debruijn, bound_const) } fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { - Const::new_bound(tcx, debruijn, ty::BoundConst { var }) + Const::new_bound(tcx, debruijn, ty::BoundConst::new(var)) } fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: rustc_type_ir::BoundVar) -> Self { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f015d0edc56c..a6960523f6cf 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -108,9 +108,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>]; type GenericArg = ty::GenericArg<'tcx>; type Term = ty::Term<'tcx>; - type BoundVarKinds = &'tcx List; + type BoundVarKinds = &'tcx List>; - type BoundVarKind = ty::BoundVariableKind; type PredefinedOpaques = solve::PredefinedOpaques<'tcx>; fn mk_predefined_opaques_in_body( @@ -144,10 +143,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type FnInputTys = &'tcx [Ty<'tcx>]; type ParamTy = ParamTy; - type BoundTy = ty::BoundTy; type Symbol = Symbol; - type PlaceholderTy = ty::PlaceholderType<'tcx>; type ErrorGuaranteed = ErrorGuaranteed; type BoundExistentialPredicates = &'tcx List>; @@ -157,10 +154,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type Safety = hir::Safety; type Abi = ExternAbi; type Const = ty::Const<'tcx>; - type PlaceholderConst = ty::PlaceholderConst<'tcx>; type ParamConst = ty::ParamConst; - type BoundConst = ty::BoundConst; type ValueConst = ty::Value<'tcx>; type ExprConst = ty::Expr<'tcx>; type ValTree = ty::ValTree<'tcx>; @@ -169,8 +164,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type Region = Region<'tcx>; type EarlyParamRegion = ty::EarlyParamRegion; type LateParamRegion = ty::LateParamRegion; - type BoundRegion = ty::BoundRegion; - type PlaceholderRegion = ty::PlaceholderRegion<'tcx>; type RegionAssumptions = &'tcx ty::List>; @@ -776,6 +769,13 @@ impl<'tcx> Interner for TyCtxt<'tcx> { ) -> (QueryResult<'tcx>, &'tcx inspect::Probe>) { self.evaluate_root_goal_for_proof_tree_raw(canonical_goal) } + + fn item_name(self, id: DefId) -> Symbol { + let id = id.into_query_param(); + self.opt_item_name(id).unwrap_or_else(|| { + bug!("item_name: no name for {:?}", self.def_path(id)); + }) + } } macro_rules! bidirectional_lang_item_map { @@ -938,7 +938,7 @@ pub struct CtxtInterners<'tcx> { const_: InternedSet<'tcx, WithCachedTypeInfo>>, pat: InternedSet<'tcx, PatternKind<'tcx>>, const_allocation: InternedSet<'tcx, Allocation>, - bound_variable_kinds: InternedSet<'tcx, List>, + bound_variable_kinds: InternedSet<'tcx, List>>, layout: InternedSet<'tcx, LayoutData>, adt_def: InternedSet<'tcx, AdtDefData>, external_constraints: InternedSet<'tcx, ExternalConstraintsData>>, @@ -2530,7 +2530,7 @@ nop_list_lift! { type_lists; Ty<'a> => Ty<'tcx> } nop_list_lift! { poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx> } -nop_list_lift! { bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind } +nop_list_lift! { bound_variable_kinds; ty::BoundVariableKind<'a> => ty::BoundVariableKind<'tcx> } // This is the impl for `&'a GenericArgs<'a>`. nop_list_lift! { args; GenericArg<'a> => GenericArg<'tcx> } @@ -2817,7 +2817,7 @@ slice_interners!( poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>), projs: pub mk_projs(ProjectionKind), place_elems: pub mk_place_elems(PlaceElem<'tcx>), - bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind), + bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind<'tcx>), fields: pub mk_fields(FieldIdx), local_def_ids: intern_local_def_ids(LocalDefId), captures: intern_captures(&'tcx ty::CapturedPlace<'tcx>), @@ -3242,7 +3242,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn mk_bound_variable_kinds_from_iter(self, iter: I) -> T::Output where I: Iterator, - T: CollectAndApply>, + T: CollectAndApply, &'tcx List>>, { T::collect_and_apply(iter, |xs| self.mk_bound_variable_kinds(xs)) } @@ -3362,7 +3362,7 @@ impl<'tcx> TyCtxt<'tcx> { self.is_late_bound_map(id.owner).is_some_and(|set| set.contains(&id.local_id)) } - pub fn late_bound_vars(self, id: HirId) -> &'tcx List { + pub fn late_bound_vars(self, id: HirId) -> &'tcx List> { self.mk_bound_variable_kinds( &self .late_bound_vars_map(id.owner) diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index ee29afcff638..3d9148d6ed7b 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -3,7 +3,7 @@ use rustc_hir::def_id::DefId; use rustc_type_ir::data_structures::DelayedMap; use crate::ty::{ - self, Binder, BoundConst, BoundTy, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + self, Binder, BoundTy, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; @@ -58,28 +58,28 @@ where /// gets mapped to the same result. `BoundVarReplacer` caches by using /// a `DelayedMap` which does not cache the first few types it encounters. pub trait BoundVarReplacerDelegate<'tcx> { - fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx>; - fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx>; - fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx>; + fn replace_region(&mut self, br: ty::BoundRegion<'tcx>) -> ty::Region<'tcx>; + fn replace_ty(&mut self, bt: ty::BoundTy<'tcx>) -> Ty<'tcx>; + fn replace_const(&mut self, bc: ty::BoundConst<'tcx>) -> ty::Const<'tcx>; } /// A simple delegate taking 3 mutable functions. The used functions must /// always return the same result for each bound variable, no matter how /// frequently they are called. pub struct FnMutDelegate<'a, 'tcx> { - pub regions: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a), - pub types: &'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a), - pub consts: &'a mut (dyn FnMut(ty::BoundConst) -> ty::Const<'tcx> + 'a), + pub regions: &'a mut (dyn FnMut(ty::BoundRegion<'tcx>) -> ty::Region<'tcx> + 'a), + pub types: &'a mut (dyn FnMut(ty::BoundTy<'tcx>) -> Ty<'tcx> + 'a), + pub consts: &'a mut (dyn FnMut(ty::BoundConst<'tcx>) -> ty::Const<'tcx> + 'a), } impl<'a, 'tcx> BoundVarReplacerDelegate<'tcx> for FnMutDelegate<'a, 'tcx> { - fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> { + fn replace_region(&mut self, br: ty::BoundRegion<'tcx>) -> ty::Region<'tcx> { (self.regions)(br) } - fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { + fn replace_ty(&mut self, bt: ty::BoundTy<'tcx>) -> Ty<'tcx> { (self.types)(bt) } - fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx> { + fn replace_const(&mut self, bc: ty::BoundConst<'tcx>) -> ty::Const<'tcx> { (self.consts)(bc) } } @@ -207,13 +207,14 @@ impl<'tcx> TyCtxt<'tcx> { self, value: Binder<'tcx, T>, mut fld_r: F, - ) -> (T, FxIndexMap>) + ) -> (T, FxIndexMap, ty::Region<'tcx>>) where - F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, + F: FnMut(ty::BoundRegion<'tcx>) -> ty::Region<'tcx>, T: TypeFoldable>, { let mut region_map = FxIndexMap::default(); - let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br)); + let real_fld_r = + |br: ty::BoundRegion<'tcx>| *region_map.entry(br).or_insert_with(|| fld_r(br)); let value = self.instantiate_bound_regions_uncached(value, real_fld_r); (value, region_map) } @@ -224,7 +225,7 @@ impl<'tcx> TyCtxt<'tcx> { mut replace_regions: F, ) -> T where - F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, + F: FnMut(ty::BoundRegion<'tcx>) -> ty::Region<'tcx>, T: TypeFoldable>, { let value = value.skip_binder(); @@ -292,14 +293,14 @@ impl<'tcx> TyCtxt<'tcx> { self.replace_escaping_bound_vars_uncached( value, FnMutDelegate { - regions: &mut |r: ty::BoundRegion| { + regions: &mut |r: ty::BoundRegion<'tcx>| { ty::Region::new_bound( self, ty::INNERMOST, ty::BoundRegion { var: shift_bv(r.var), kind: r.kind }, ) }, - types: &mut |t: ty::BoundTy| { + types: &mut |t: ty::BoundTy<'tcx>| { Ty::new_bound( self, ty::INNERMOST, @@ -307,11 +308,7 @@ impl<'tcx> TyCtxt<'tcx> { ) }, consts: &mut |c| { - ty::Const::new_bound( - self, - ty::INNERMOST, - ty::BoundConst { var: shift_bv(c.var) }, - ) + ty::Const::new_bound(self, ty::INNERMOST, ty::BoundConst::new(shift_bv(c.var))) }, }, ) @@ -333,10 +330,10 @@ impl<'tcx> TyCtxt<'tcx> { { struct Anonymize<'a, 'tcx> { tcx: TyCtxt<'tcx>, - map: &'a mut FxIndexMap, + map: &'a mut FxIndexMap>, } impl<'tcx> BoundVarReplacerDelegate<'tcx> for Anonymize<'_, 'tcx> { - fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> { + fn replace_region(&mut self, br: ty::BoundRegion<'tcx>) -> ty::Region<'tcx> { let entry = self.map.entry(br.var); let index = entry.index(); let var = ty::BoundVar::from_usize(index); @@ -346,7 +343,7 @@ impl<'tcx> TyCtxt<'tcx> { let br = ty::BoundRegion { var, kind }; ty::Region::new_bound(self.tcx, ty::INNERMOST, br) } - fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { + fn replace_ty(&mut self, bt: ty::BoundTy<'tcx>) -> Ty<'tcx> { let entry = self.map.entry(bt.var); let index = entry.index(); let var = ty::BoundVar::from_usize(index); @@ -355,12 +352,12 @@ impl<'tcx> TyCtxt<'tcx> { .expect_ty(); Ty::new_bound(self.tcx, ty::INNERMOST, BoundTy { var, kind }) } - fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx> { + fn replace_const(&mut self, bc: ty::BoundConst<'tcx>) -> ty::Const<'tcx> { let entry = self.map.entry(bc.var); let index = entry.index(); let var = ty::BoundVar::from_usize(index); let () = entry.or_insert_with(|| ty::BoundVariableKind::Const).expect_const(); - ty::Const::new_bound(self.tcx, ty::INNERMOST, BoundConst { var }) + ty::Const::new_bound(self.tcx, ty::INNERMOST, ty::BoundConst::new(var)) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ce713dcf42f5..3e3c9e27186a 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -97,13 +97,13 @@ pub use self::predicate::{ RegionOutlivesPredicate, SubtypePredicate, TraitPredicate, TraitRef, TypeOutlivesPredicate, }; pub use self::region::{ - BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, - RegionKind, RegionVid, + EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, RegionKind, RegionVid, }; pub use self::sty::{ - AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, - CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst, - ParamTy, PolyFnSig, TyKind, TypeAndMut, TypingMode, UpvarArgs, + AliasTy, Article, Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, + BoundVariableKind, CanonicalPolyFnSig, CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, + InlineConstArgsParts, ParamConst, ParamTy, PlaceholderConst, PlaceholderRegion, + PlaceholderType, PolyFnSig, TyKind, TypeAndMut, TypingMode, UpvarArgs, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ @@ -914,100 +914,6 @@ impl<'tcx> DefinitionSiteHiddenType<'tcx> { } } -pub type PlaceholderRegion<'tcx> = ty::Placeholder, BoundRegion>; - -impl<'tcx> rustc_type_ir::inherent::PlaceholderLike> for PlaceholderRegion<'tcx> { - type Bound = BoundRegion; - - fn universe(self) -> UniverseIndex { - self.universe - } - - fn var(self) -> BoundVar { - self.bound.var - } - - fn with_updated_universe(self, ui: UniverseIndex) -> Self { - ty::Placeholder::new(ui, self.bound) - } - - fn new(ui: UniverseIndex, bound: BoundRegion) -> Self { - ty::Placeholder::new(ui, bound) - } - - fn new_anon(ui: UniverseIndex, var: BoundVar) -> Self { - ty::Placeholder::new(ui, BoundRegion { var, kind: BoundRegionKind::Anon }) - } -} - -pub type PlaceholderType<'tcx> = ty::Placeholder, BoundTy>; - -impl<'tcx> rustc_type_ir::inherent::PlaceholderLike> for PlaceholderType<'tcx> { - type Bound = BoundTy; - - fn universe(self) -> UniverseIndex { - self.universe - } - - fn var(self) -> BoundVar { - self.bound.var - } - - fn with_updated_universe(self, ui: UniverseIndex) -> Self { - ty::Placeholder::new(ui, self.bound) - } - - fn new(ui: UniverseIndex, bound: BoundTy) -> Self { - ty::Placeholder::new(ui, bound) - } - - fn new_anon(ui: UniverseIndex, var: BoundVar) -> Self { - ty::Placeholder::new(ui, BoundTy { var, kind: BoundTyKind::Anon }) - } -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] -#[derive(TyEncodable, TyDecodable)] -pub struct BoundConst { - pub var: BoundVar, -} - -impl<'tcx> rustc_type_ir::inherent::BoundVarLike> for BoundConst { - fn var(self) -> BoundVar { - self.var - } - - fn assert_eq(self, var: ty::BoundVariableKind) { - var.expect_const() - } -} - -pub type PlaceholderConst<'tcx> = ty::Placeholder, BoundConst>; - -impl<'tcx> rustc_type_ir::inherent::PlaceholderLike> for PlaceholderConst<'tcx> { - type Bound = BoundConst; - - fn universe(self) -> UniverseIndex { - self.universe - } - - fn var(self) -> BoundVar { - self.bound.var - } - - fn with_updated_universe(self, ui: UniverseIndex) -> Self { - ty::Placeholder::new(ui, self.bound) - } - - fn new(ui: UniverseIndex, bound: BoundConst) -> Self { - ty::Placeholder::new(ui, bound) - } - - fn new_anon(ui: UniverseIndex, var: BoundVar) -> Self { - ty::Placeholder::new(ui, BoundConst { var }) - } -} - pub type Clauses<'tcx> = &'tcx ListWithCachedTypeInfo>; impl<'tcx> rustc_type_ir::Flags for Clauses<'tcx> { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index de13c4f836a5..724be7b15ff2 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -199,7 +199,7 @@ pub struct RegionHighlightMode<'tcx> { /// This is used when you have a signature like `fn foo(x: &u32, /// y: &'a u32)` and we want to give a name to the region of the /// reference `x`. - highlight_bound_region: Option<(ty::BoundRegionKind, usize)>, + highlight_bound_region: Option<(ty::BoundRegionKind<'tcx>, usize)>, } impl<'tcx> RegionHighlightMode<'tcx> { @@ -248,7 +248,7 @@ impl<'tcx> RegionHighlightMode<'tcx> { /// Highlight the given bound region. /// We can only highlight one bound region at a time. See /// the field `highlight_bound_region` for more detailed notes. - pub fn highlighting_bound_region(&mut self, br: ty::BoundRegionKind, number: usize) { + pub fn highlighting_bound_region(&mut self, br: ty::BoundRegionKind<'tcx>, number: usize) { assert!(self.highlight_bound_region.is_none()); self.highlight_bound_region = Some((br, number)); } @@ -2641,12 +2641,12 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { struct RegionFolder<'a, 'tcx> { tcx: TyCtxt<'tcx>, current_index: ty::DebruijnIndex, - region_map: UnordMap>, + region_map: UnordMap, ty::Region<'tcx>>, name: &'a mut ( dyn FnMut( Option, // Debruijn index of the folded late-bound region ty::DebruijnIndex, // Index corresponding to binder level - ty::BoundRegion, + ty::BoundRegion<'tcx>, ) -> ty::Region<'tcx> + 'a ), @@ -2719,7 +2719,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { &mut self, value: &ty::Binder<'tcx, T>, mode: WrapBinderMode, - ) -> Result<(T, UnordMap>), fmt::Error> + ) -> Result<(T, UnordMap, ty::Region<'tcx>>), fmt::Error> where T: TypeFoldable>, { @@ -2812,12 +2812,12 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { // see issue #102392. let mut name = |lifetime_idx: Option, binder_level_idx: ty::DebruijnIndex, - br: ty::BoundRegion| { + br: ty::BoundRegion<'tcx>| { let (name, kind) = if let Some(name) = br.kind.get_name(tcx) { (name, br.kind) } else { let name = next_name(self); - (name, ty::BoundRegionKind::NamedAnon(name)) + (name, ty::BoundRegionKind::NamedForPrinting(name)) }; if let Some(lt_idx) = lifetime_idx { diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 61994d928dec..a497501ef19d 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -50,7 +50,7 @@ impl<'tcx> Region<'tcx> { pub fn new_bound( tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, - bound_region: ty::BoundRegion, + bound_region: ty::BoundRegion<'tcx>, ) -> Region<'tcx> { // Use a pre-interned one when possible. if let ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon } = bound_region @@ -160,7 +160,7 @@ impl<'tcx> rustc_type_ir::inherent::Region> for Region<'tcx> { fn new_bound( interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, - var: ty::BoundRegion, + var: ty::BoundRegion<'tcx>, ) -> Self { Region::new_bound(interner, debruijn, var) } @@ -388,7 +388,7 @@ pub struct LateParamRegion { pub kind: LateParamRegionKind, } -/// When liberating bound regions, we map their [`BoundRegionKind`] +/// When liberating bound regions, we map their [`ty::BoundRegionKind`] /// to this as we need to track the index of anonymous regions. We /// otherwise end up liberating multiple bound regions to the same /// late-bound region. @@ -397,7 +397,7 @@ pub struct LateParamRegion { pub enum LateParamRegionKind { /// An anonymous region parameter for a given fn (&T) /// - /// Unlike [`BoundRegionKind::Anon`], this tracks the index of the + /// Unlike [`ty::BoundRegionKind::Anon`], this tracks the index of the /// liberated bound region. /// /// We should ideally never liberate anonymous regions, but do so for the @@ -418,12 +418,14 @@ pub enum LateParamRegionKind { } impl LateParamRegionKind { - pub fn from_bound(var: BoundVar, br: BoundRegionKind) -> LateParamRegionKind { + pub fn from_bound(var: BoundVar, br: ty::BoundRegionKind<'_>) -> LateParamRegionKind { match br { - BoundRegionKind::Anon => LateParamRegionKind::Anon(var.as_u32()), - BoundRegionKind::Named(def_id) => LateParamRegionKind::Named(def_id), - BoundRegionKind::ClosureEnv => LateParamRegionKind::ClosureEnv, - BoundRegionKind::NamedAnon(name) => LateParamRegionKind::NamedAnon(var.as_u32(), name), + ty::BoundRegionKind::Anon => LateParamRegionKind::Anon(var.as_u32()), + ty::BoundRegionKind::Named(def_id) => LateParamRegionKind::Named(def_id), + ty::BoundRegionKind::ClosureEnv => LateParamRegionKind::ClosureEnv, + ty::BoundRegionKind::NamedForPrinting(name) => { + LateParamRegionKind::NamedAnon(var.as_u32(), name) + } } } @@ -450,81 +452,6 @@ impl LateParamRegionKind { } } -#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Copy)] -#[derive(HashStable)] -pub enum BoundRegionKind { - /// An anonymous region parameter for a given fn (&T) - Anon, - - /// An anonymous region parameter with a `Symbol` name. - /// - /// Used to give late-bound regions names for things like pretty printing. - NamedAnon(Symbol), - - /// Late-bound regions that appear in the AST. - Named(DefId), - - /// Anonymous region for the implicit env pointer parameter - /// to a closure - ClosureEnv, -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable)] -pub struct BoundRegion { - pub var: BoundVar, - pub kind: BoundRegionKind, -} - -impl<'tcx> rustc_type_ir::inherent::BoundVarLike> for BoundRegion { - fn var(self) -> BoundVar { - self.var - } - - fn assert_eq(self, var: ty::BoundVariableKind) { - assert_eq!(self.kind, var.expect_region()) - } -} - -impl core::fmt::Debug for BoundRegion { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self.kind { - BoundRegionKind::Anon => write!(f, "{:?}", self.var), - BoundRegionKind::ClosureEnv => write!(f, "{:?}.Env", self.var), - BoundRegionKind::Named(def) => { - write!(f, "{:?}.Named({:?})", self.var, def) - } - BoundRegionKind::NamedAnon(symbol) => { - write!(f, "{:?}.NamedAnon({:?})", self.var, symbol) - } - } - } -} - -impl BoundRegionKind { - pub fn is_named(&self, tcx: TyCtxt<'_>) -> bool { - self.get_name(tcx).is_some() - } - - pub fn get_name(&self, tcx: TyCtxt<'_>) -> Option { - match *self { - BoundRegionKind::Named(def_id) => { - let name = tcx.item_name(def_id); - if name != kw::UnderscoreLifetime { Some(name) } else { None } - } - BoundRegionKind::NamedAnon(name) => Some(name), - _ => None, - } - } - - pub fn get_id(&self) -> Option { - match *self { - BoundRegionKind::Named(id) => Some(id), - _ => None, - } - } -} - // Some types are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 314d2ba39632..8707b03e4b8f 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -65,21 +65,6 @@ impl<'tcx> fmt::Debug for ty::adjustment::PatAdjustment<'tcx> { } } -impl fmt::Debug for ty::BoundRegionKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - ty::BoundRegionKind::Anon => write!(f, "BrAnon"), - ty::BoundRegionKind::NamedAnon(name) => { - write!(f, "BrNamedAnon({name})") - } - ty::BoundRegionKind::Named(did) => { - write!(f, "BrNamed({did:?})") - } - ty::BoundRegionKind::ClosureEnv => write!(f, "BrEnv"), - } - } -} - impl fmt::Debug for ty::LateParamRegion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "ReLateParam({:?}, {:?})", self.scope, self.kind) @@ -175,15 +160,6 @@ impl<'tcx> fmt::Debug for ty::Const<'tcx> { } } -impl fmt::Debug for ty::BoundTy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.kind { - ty::BoundTyKind::Anon => write!(f, "{:?}", self.var), - ty::BoundTyKind::Param(def_id) => write!(f, "{def_id:?}"), - } - } -} - impl<'tcx> fmt::Debug for GenericArg<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.kind() { @@ -255,7 +231,8 @@ TrivialTypeTraversalImpls! { crate::ty::AdtKind, crate::ty::AssocItem, crate::ty::AssocKind, - crate::ty::BoundRegion, + crate::ty::BoundRegion<'tcx>, + crate::ty::BoundTy<'tcx>, crate::ty::ScalarInt, crate::ty::UserTypeAnnotationIndex, crate::ty::abstract_const::NotConstEvaluatable, @@ -284,7 +261,6 @@ TrivialTypeTraversalImpls! { TrivialTypeTraversalAndLiftImpls! { // tidy-alphabetical-start crate::mir::RuntimeChecks, - crate::ty::BoundTy, crate::ty::ParamTy, crate::ty::instance::ReifyReason, rustc_hir::def_id::DefId, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index b0b5a783b00e..4c5bd85e6b72 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -13,7 +13,7 @@ use rustc_hir as hir; use rustc_hir::LangItem; use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, extension}; -use rustc_span::{DUMMY_SP, Span, Symbol, sym}; +use rustc_span::{DUMMY_SP, Span, Symbol, kw, sym}; use rustc_type_ir::TyKind::*; use rustc_type_ir::solve::SizedTraitKind; use rustc_type_ir::walk::TypeWalker; @@ -26,8 +26,8 @@ use crate::infer::canonical::Canonical; use crate::traits::ObligationCause; use crate::ty::InferTy::*; use crate::ty::{ - self, AdtDef, BoundRegionKind, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv, - Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy, + self, AdtDef, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv, Region, Ty, + TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy, }; // Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here @@ -40,6 +40,15 @@ pub type Binder<'tcx, T> = ir::Binder, T>; pub type EarlyBinder<'tcx, T> = ir::EarlyBinder, T>; pub type TypingMode<'tcx> = ir::TypingMode>; pub type Placeholder<'tcx, T> = ir::Placeholder, T>; +pub type PlaceholderRegion<'tcx> = ir::PlaceholderRegion>; +pub type PlaceholderType<'tcx> = ir::PlaceholderType>; +pub type PlaceholderConst<'tcx> = ir::PlaceholderConst>; +pub type BoundTy<'tcx> = ir::BoundTy>; +pub type BoundConst<'tcx> = ir::BoundConst>; +pub type BoundRegion<'tcx> = ir::BoundRegion>; +pub type BoundVariableKind<'tcx> = ir::BoundVariableKind>; +pub type BoundRegionKind<'tcx> = ir::BoundRegionKind>; +pub type BoundTyKind<'tcx> = ir::BoundTyKind>; pub trait Article { fn article(&self) -> &'static str; @@ -257,37 +266,6 @@ impl<'tcx> InlineConstArgs<'tcx> { } } -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable)] -pub enum BoundVariableKind { - Ty(BoundTyKind), - Region(BoundRegionKind), - Const, -} - -impl BoundVariableKind { - pub fn expect_region(self) -> BoundRegionKind { - match self { - BoundVariableKind::Region(lt) => lt, - _ => bug!("expected a region, but found another kind"), - } - } - - pub fn expect_ty(self) -> BoundTyKind { - match self { - BoundVariableKind::Ty(ty) => ty, - _ => bug!("expected a type, but found another kind"), - } - } - - pub fn expect_const(self) { - match self { - BoundVariableKind::Const => (), - _ => bug!("expected a const, but found another kind"), - } - } -} - pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>; pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<'tcx, FnSig<'tcx>>>; @@ -381,30 +359,6 @@ impl ParamConst { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable)] -pub struct BoundTy { - pub var: BoundVar, - pub kind: BoundTyKind, -} - -impl<'tcx> rustc_type_ir::inherent::BoundVarLike> for BoundTy { - fn var(self) -> BoundVar { - self.var - } - - fn assert_eq(self, var: ty::BoundVariableKind) { - assert_eq!(self.kind, var.expect_ty()) - } -} - -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable)] -pub enum BoundTyKind { - Anon, - Param(DefId), -} - /// Constructors for `Ty` impl<'tcx> Ty<'tcx> { /// Avoid using this in favour of more specific `new_*` methods, where possible. @@ -479,7 +433,7 @@ impl<'tcx> Ty<'tcx> { pub fn new_bound( tcx: TyCtxt<'tcx>, index: ty::DebruijnIndex, - bound_ty: ty::BoundTy, + bound_ty: ty::BoundTy<'tcx>, ) -> Ty<'tcx> { // Use a pre-interned one when possible. if let ty::BoundTy { var, kind: ty::BoundTyKind::Anon } = bound_ty @@ -961,7 +915,11 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { Ty::new_placeholder(tcx, placeholder) } - fn new_bound(interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundTy) -> Self { + fn new_bound( + interner: TyCtxt<'tcx>, + debruijn: ty::DebruijnIndex, + var: ty::BoundTy<'tcx>, + ) -> Self { Ty::new_bound(interner, debruijn, var) } @@ -2135,6 +2093,12 @@ impl<'tcx> rustc_type_ir::inherent::Tys> for &'tcx ty::List rustc_type_ir::inherent::Symbol> for Symbol { + fn is_kw_underscore_lifetime(self) -> bool { + self == kw::UnderscoreLifetime + } +} + // Some types are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index e84ac56b31df..8f79f8e3564e 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -113,7 +113,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn collect_constrained_late_bound_regions( self, value: Binder<'tcx, T>, - ) -> FxIndexSet + ) -> FxIndexSet> where T: TypeFoldable>, { @@ -124,7 +124,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn collect_referenced_late_bound_regions( self, value: Binder<'tcx, T>, - ) -> FxIndexSet + ) -> FxIndexSet> where T: TypeFoldable>, { @@ -135,7 +135,7 @@ impl<'tcx> TyCtxt<'tcx> { self, value: Binder<'tcx, T>, just_constrained: bool, - ) -> FxIndexSet + ) -> FxIndexSet> where T: TypeFoldable>, { @@ -149,9 +149,9 @@ impl<'tcx> TyCtxt<'tcx> { /// Collects all the late-bound regions at the innermost binding level /// into a hash set. -struct LateBoundRegionsCollector { +struct LateBoundRegionsCollector<'tcx> { current_index: ty::DebruijnIndex, - regions: FxIndexSet, + regions: FxIndexSet>, /// `true` if we only want regions that are known to be /// "constrained" when you equate this type with another type. In @@ -163,13 +163,13 @@ struct LateBoundRegionsCollector { just_constrained: bool, } -impl LateBoundRegionsCollector { +impl LateBoundRegionsCollector<'_> { fn new(just_constrained: bool) -> Self { Self { current_index: ty::INNERMOST, regions: Default::default(), just_constrained } } } -impl<'tcx> TypeVisitor> for LateBoundRegionsCollector { +impl<'tcx> TypeVisitor> for LateBoundRegionsCollector<'tcx> { fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) { self.current_index.shift_in(1); t.super_visit_with(self); diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index 61a2dcd226b7..ce2be24adc58 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -3,7 +3,8 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::solve::{Goal, QueryInput}; use rustc_type_ir::{ self as ty, Canonical, CanonicalParamEnvCacheEntry, CanonicalVarKind, Flags, InferCtxtLike, - Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, + Interner, PlaceholderConst, PlaceholderType, TypeFlags, TypeFoldable, TypeFolder, + TypeSuperFoldable, TypeVisitableExt, }; use crate::delegate::SolverDelegate; @@ -357,13 +358,13 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { }, ty::Placeholder(placeholder) => match self.canonicalize_mode { CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderTy( - PlaceholderLike::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()), + PlaceholderType::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()), ), CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder), }, ty::Param(_) => match self.canonicalize_mode { CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderTy( - PlaceholderLike::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()), + PlaceholderType::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()), ), CanonicalizeMode::Response { .. } => panic!("param ty in response: {t:?}"), }, @@ -513,17 +514,23 @@ impl, I: Interner> TypeFolder for Canonicaliz ty::InferConst::Fresh(_) => todo!(), }, ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderConst( - PlaceholderLike::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()), - ), + CanonicalizeMode::Input { .. } => { + CanonicalVarKind::PlaceholderConst(PlaceholderConst::new_anon( + ty::UniverseIndex::ROOT, + self.variables.len().into(), + )) + } CanonicalizeMode::Response { .. } => { CanonicalVarKind::PlaceholderConst(placeholder) } }, ty::ConstKind::Param(_) => match self.canonicalize_mode { - CanonicalizeMode::Input { .. } => CanonicalVarKind::PlaceholderConst( - PlaceholderLike::new_anon(ty::UniverseIndex::ROOT, self.variables.len().into()), - ), + CanonicalizeMode::Input { .. } => { + CanonicalVarKind::PlaceholderConst(PlaceholderConst::new_anon( + ty::UniverseIndex::ROOT, + self.variables.len().into(), + )) + } CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"), }, // FIXME: See comment above -- we could fold the region separately or something. diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index 96fea09013a1..1f64f09fe787 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -177,9 +177,9 @@ where } } ty::GenericArgKind::Const(c) => { - if let ty::ConstKind::Bound(index_kind, bv) = c.kind() { + if let ty::ConstKind::Bound(index_kind, bc) = c.kind() { assert!(matches!(index_kind, ty::BoundVarIndexKind::Canonical)); - opt_values[bv.var()] = Some(*original_value); + opt_values[bc.var()] = Some(*original_value); } } } diff --git a/compiler/rustc_next_trait_solver/src/placeholder.rs b/compiler/rustc_next_trait_solver/src/placeholder.rs index c8016759f239..31fce0601697 100644 --- a/compiler/rustc_next_trait_solver/src/placeholder.rs +++ b/compiler/rustc_next_trait_solver/src/placeholder.rs @@ -3,8 +3,8 @@ use core::panic; use rustc_type_ir::data_structures::IndexMap; use rustc_type_ir::inherent::*; use rustc_type_ir::{ - self as ty, InferCtxtLike, Interner, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, + self as ty, InferCtxtLike, Interner, PlaceholderConst, PlaceholderRegion, PlaceholderType, + TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; pub struct BoundVarReplacer<'a, Infcx, I = ::Interner> @@ -16,9 +16,9 @@ where // These three maps track the bound variable that were replaced by placeholders. It might be // nice to remove these since we already have the `kind` in the placeholder; we really just need // the `var` (but we *could* bring that into scope if we were to track them as we pass them). - mapped_regions: IndexMap, - mapped_types: IndexMap, - mapped_consts: IndexMap, + mapped_regions: IndexMap, ty::BoundRegion>, + mapped_types: IndexMap, ty::BoundTy>, + mapped_consts: IndexMap, ty::BoundConst>, // 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, @@ -40,9 +40,9 @@ where value: T, ) -> ( T, - IndexMap, - IndexMap, - IndexMap, + IndexMap, ty::BoundRegion>, + IndexMap, ty::BoundTy>, + IndexMap, ty::BoundConst>, ) { let mut replacer = BoundVarReplacer { infcx, @@ -103,7 +103,7 @@ where if debruijn >= self.current_index => { let universe = self.universe_for(debruijn); - let p = PlaceholderLike::new(universe, br); + let p = PlaceholderRegion::new(universe, br); self.mapped_regions.insert(p, br); Region::new_placeholder(self.cx(), p) } @@ -126,7 +126,7 @@ where if debruijn >= self.current_index => { let universe = self.universe_for(debruijn); - let p = PlaceholderLike::new(universe, bound_ty); + let p = PlaceholderType::new(universe, bound_ty); self.mapped_types.insert(p, bound_ty); Ty::new_placeholder(self.cx(), p) } @@ -150,7 +150,7 @@ where if debruijn >= self.current_index => { let universe = self.universe_for(debruijn); - let p = PlaceholderLike::new(universe, bound_const); + let p = PlaceholderConst::new(universe, bound_const); self.mapped_consts.insert(p, bound_const); Const::new_placeholder(self.cx(), p) } diff --git a/compiler/rustc_public/src/unstable/convert/internal.rs b/compiler/rustc_public/src/unstable/convert/internal.rs index 73a3fed111b3..8594f6510041 100644 --- a/compiler/rustc_public/src/unstable/convert/internal.rs +++ b/compiler/rustc_public/src/unstable/convert/internal.rs @@ -433,7 +433,7 @@ where } impl RustcInternal for BoundVariableKind { - type T<'tcx> = rustc_ty::BoundVariableKind; + type T<'tcx> = rustc_ty::BoundVariableKind<'tcx>; fn internal<'tcx>( &self, diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index cee144122c0e..70cdae43126c 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -271,7 +271,7 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> { } } -impl<'tcx> Stable<'tcx> for ty::BoundTyKind { +impl<'tcx> Stable<'tcx> for ty::BoundTyKind<'tcx> { type T = crate::ty::BoundTyKind; fn stable<'cx>( @@ -290,7 +290,7 @@ impl<'tcx> Stable<'tcx> for ty::BoundTyKind { } } -impl<'tcx> Stable<'tcx> for ty::BoundRegionKind { +impl<'tcx> Stable<'tcx> for ty::BoundRegionKind<'tcx> { type T = crate::ty::BoundRegionKind; fn stable<'cx>( @@ -307,12 +307,12 @@ impl<'tcx> Stable<'tcx> for ty::BoundRegionKind { cx.tcx.item_name(*def_id).to_string(), ), ty::BoundRegionKind::ClosureEnv => BoundRegionKind::BrEnv, - ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"), + ty::BoundRegionKind::NamedForPrinting(_) => bug!("only used for pretty printing"), } } } -impl<'tcx> Stable<'tcx> for ty::BoundVariableKind { +impl<'tcx> Stable<'tcx> for ty::BoundVariableKind<'tcx> { type T = crate::ty::BoundVariableKind; fn stable<'cx>( @@ -546,7 +546,7 @@ impl<'tcx> Stable<'tcx> for ty::ParamTy { } } -impl<'tcx> Stable<'tcx> for ty::BoundTy { +impl<'tcx> Stable<'tcx> for ty::BoundTy<'tcx> { type T = crate::ty::BoundTy; fn stable<'cx>( &self, diff --git a/compiler/rustc_public/src/unstable/internal_cx/mod.rs b/compiler/rustc_public/src/unstable/internal_cx/mod.rs index 601ca4fb5cfd..4da86b9442f1 100644 --- a/compiler/rustc_public/src/unstable/internal_cx/mod.rs +++ b/compiler/rustc_public/src/unstable/internal_cx/mod.rs @@ -78,7 +78,10 @@ impl<'tcx> InternalCx<'tcx> for TyCtxt<'tcx> { fn mk_bound_variable_kinds_from_iter(self, iter: I) -> T::Output where I: Iterator, - T: ty::CollectAndApply>, + T: ty::CollectAndApply< + ty::BoundVariableKind<'tcx>, + &'tcx List>, + >, { TyCtxt::mk_bound_variable_kinds_from_iter(self, iter) } diff --git a/compiler/rustc_public/src/unstable/mod.rs b/compiler/rustc_public/src/unstable/mod.rs index 2b69fb5408cf..583493c23d66 100644 --- a/compiler/rustc_public/src/unstable/mod.rs +++ b/compiler/rustc_public/src/unstable/mod.rs @@ -47,7 +47,10 @@ pub trait InternalCx<'tcx>: Copy + Clone { fn mk_bound_variable_kinds_from_iter(self, iter: I) -> T::Output where I: Iterator, - T: ty::CollectAndApply>; + T: ty::CollectAndApply< + ty::BoundVariableKind<'tcx>, + &'tcx List>, + >; fn mk_place_elems(self, v: &[mir::PlaceElem<'tcx>]) -> &'tcx List>; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs index 3bab09bc587f..05a1e3fe95dd 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs @@ -34,14 +34,18 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { (Some(self.tcx().def_span(def_id)), Some(self.tcx().item_name(def_id))) } ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => (None, None), - ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"), + ty::BoundRegionKind::NamedForPrinting(_) => { + bug!("only used for pretty printing") + } }; let (sup_span, sup_symbol) = match *sup_name { ty::BoundRegionKind::Named(def_id) => { (Some(self.tcx().def_span(def_id)), Some(self.tcx().item_name(def_id))) } ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => (None, None), - ty::BoundRegionKind::NamedAnon(_) => bug!("only used for pretty printing"), + ty::BoundRegionKind::NamedForPrinting(_) => { + bug!("only used for pretty printing") + } }; let diag = match (sub_span, sup_span, sub_symbol, sup_symbol) { (Some(sub_span), Some(sup_span), Some(sub_symbol), Some(sup_symbol)) => { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index fdaf2d619dd5..b11461cd0e32 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -1052,7 +1052,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } fn report_inference_failure(&self, var_origin: RegionVariableOrigin<'tcx>) -> Diag<'_> { - let br_string = |br: ty::BoundRegionKind| { + let br_string = |br: ty::BoundRegionKind<'tcx>| { let mut s = match br { ty::BoundRegionKind::Named(def_id) => self.tcx.item_name(def_id).to_string(), _ => String::new(), diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 2aae5f2cde1e..9f59f6c59250 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -566,7 +566,7 @@ fn plug_infer_with_placeholders<'tcx>( ty, Ty::new_placeholder( self.infcx.tcx, - ty::Placeholder::new( + ty::PlaceholderType::new( self.universe, ty::BoundTy { var: self.next_var(), kind: ty::BoundTyKind::Anon }, ), @@ -592,9 +592,9 @@ fn plug_infer_with_placeholders<'tcx>( ct, ty::Const::new_placeholder( self.infcx.tcx, - ty::Placeholder::new( + ty::PlaceholderConst::new( self.universe, - ty::BoundConst { var: self.next_var() }, + ty::BoundConst::new(self.next_var()), ), ), ) @@ -623,7 +623,7 @@ fn plug_infer_with_placeholders<'tcx>( r, ty::Region::new_placeholder( self.infcx.tcx, - ty::Placeholder::new( + ty::PlaceholderRegion::new( self.universe, ty::BoundRegion { var: self.next_var(), diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 5839a8c2e295..4e027a301cc8 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -772,7 +772,7 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>( self.idx += 1; ty::Const::new_placeholder( self.tcx, - ty::PlaceholderConst::new(ty::UniverseIndex::ROOT, ty::BoundConst { var: idx }), + ty::PlaceholderConst::new(ty::UniverseIndex::ROOT, ty::BoundConst::new(idx)), ) } else { c.super_fold_with(self) diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 19ccf6a55bf1..c3f46aa51c73 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -220,9 +220,9 @@ pub fn with_replaced_escaping_bound_vars< /// The inverse of [`BoundVarReplacer`]: replaces placeholders with the bound vars from which they came. pub struct PlaceholderReplacer<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, - mapped_regions: FxIndexMap, ty::BoundRegion>, - mapped_types: FxIndexMap, ty::BoundTy>, - mapped_consts: FxIndexMap, ty::BoundConst>, + mapped_regions: FxIndexMap, ty::BoundRegion<'tcx>>, + mapped_types: FxIndexMap, ty::BoundTy<'tcx>>, + mapped_consts: FxIndexMap, ty::BoundConst<'tcx>>, universe_indices: &'a [Option], current_index: ty::DebruijnIndex, } @@ -230,9 +230,9 @@ pub struct PlaceholderReplacer<'a, 'tcx> { impl<'a, 'tcx> PlaceholderReplacer<'a, 'tcx> { pub fn replace_placeholders>>( infcx: &'a InferCtxt<'tcx>, - mapped_regions: FxIndexMap, ty::BoundRegion>, - mapped_types: FxIndexMap, ty::BoundTy>, - mapped_consts: FxIndexMap, ty::BoundConst>, + mapped_regions: FxIndexMap, ty::BoundRegion<'tcx>>, + mapped_types: FxIndexMap, ty::BoundTy<'tcx>>, + mapped_consts: FxIndexMap, ty::BoundConst<'tcx>>, universe_indices: &'a [Option], value: T, ) -> T { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index bb25a14ef744..d6a29aba22b9 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -210,7 +210,7 @@ struct ImplTraitInTraitFinder<'a, 'tcx> { tcx: TyCtxt<'tcx>, predicates: &'a mut Vec>, fn_def_id: DefId, - bound_vars: &'tcx ty::List, + bound_vars: &'tcx ty::List>, seen: FxHashSet, depth: ty::DebruijnIndex, } diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index b5c9080154ce..fc8b39f7c01f 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -1,11 +1,14 @@ use std::fmt; +use std::hash::Hash; use std::marker::PhantomData; use std::ops::{ControlFlow, Deref}; use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; -use rustc_type_ir_macros::{GenericTypeVisitable, TypeFoldable_Generic, TypeVisitable_Generic}; +use rustc_type_ir_macros::{ + GenericTypeVisitable, Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic, +}; use tracing::instrument; use crate::data_structures::SsoHashSet; @@ -23,8 +26,11 @@ use crate::{self as ty, DebruijnIndex, Interner, UniverseIndex}; /// for more details. /// /// `Decodable` and `Encodable` are implemented for `Binder` using the `impl_binder_encode_decode!` macro. -#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, T)] +// FIXME(derive-where#136): Need to use separate `derive_where` for +// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd` +// impls from incorrectly relying on `T: Copy` and `T: Ord`. #[derive_where(Copy; I: Interner, T: Copy)] +#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, T)] #[derive(GenericTypeVisitable)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub struct Binder { @@ -359,9 +365,12 @@ impl TypeVisitor for ValidateBoundVars { /// `instantiate`. /// /// See for more details. -#[derive_where(Clone, PartialEq, Ord, Hash, Debug; I: Interner, T)] -#[derive_where(PartialOrd; I: Interner, T: Ord)] +// FIXME(derive-where#136): Need to use separate `derive_where` for +// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd` +// impls from incorrectly relying on `T: Copy` and `T: Ord`. +#[derive_where(Ord; I: Interner, T: Ord)] #[derive_where(Copy; I: Interner, T: Copy)] +#[derive_where(Clone, PartialOrd, PartialEq, Hash, Debug; I: Interner, T)] #[derive(GenericTypeVisitable)] #[cfg_attr( feature = "nightly", @@ -955,11 +964,12 @@ pub enum BoundVarIndexKind { /// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are /// identified by both a universe, as well as a name residing within that universe. Distinct bound /// regions/types/consts within the same universe simply have an unknown relationship to one -/// another. -#[derive_where(Clone, PartialEq, Ord, Hash; I: Interner, T)] -#[derive_where(PartialOrd; I: Interner, T: Ord)] -#[derive_where(Copy; I: Interner, T: Copy, T)] -#[derive_where(Eq; T)] +// FIXME(derive-where#136): Need to use separate `derive_where` for +// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd` +// impls from incorrectly relying on `T: Copy` and `T: Ord`. +#[derive_where(Ord; I: Interner, T: Ord)] +#[derive_where(Copy; I: Interner, T: Copy)] +#[derive_where(Clone, PartialOrd, PartialEq, Eq, Hash; I: Interner, T)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr( feature = "nightly", @@ -973,12 +983,6 @@ pub struct Placeholder { _tcx: PhantomData I>, } -impl Placeholder { - pub fn new(universe: UniverseIndex, bound: T) -> Self { - Placeholder { universe, bound, _tcx: PhantomData } - } -} - impl fmt::Debug for ty::Placeholder { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.universe == ty::UniverseIndex::ROOT { @@ -1003,3 +1007,321 @@ where }) } } + +#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)] +#[derive(Lift_Generic)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] + +pub enum BoundRegionKind { + /// An anonymous region parameter for a given fn (&T) + Anon, + + /// An anonymous region parameter with a `Symbol` name. + /// + /// Used to give late-bound regions names for things like pretty printing. + NamedForPrinting(I::Symbol), + + /// Late-bound regions that appear in the AST. + Named(I::DefId), + + /// Anonymous region for the implicit env pointer parameter + /// to a closure + ClosureEnv, +} + +impl fmt::Debug for ty::BoundRegionKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + ty::BoundRegionKind::Anon => write!(f, "BrAnon"), + ty::BoundRegionKind::NamedForPrinting(name) => { + write!(f, "BrNamedForPrinting({:?})", name) + } + ty::BoundRegionKind::Named(did) => { + write!(f, "BrNamed({did:?})") + } + ty::BoundRegionKind::ClosureEnv => write!(f, "BrEnv"), + } + } +} + +impl BoundRegionKind { + pub fn is_named(&self, tcx: I) -> bool { + self.get_name(tcx).is_some() + } + + pub fn get_name(&self, tcx: I) -> Option { + match *self { + ty::BoundRegionKind::Named(def_id) => { + let name = tcx.item_name(def_id); + if name.is_kw_underscore_lifetime() { None } else { Some(name) } + } + ty::BoundRegionKind::NamedForPrinting(name) => Some(name), + _ => None, + } + } + + pub fn get_id(&self) -> Option { + match *self { + ty::BoundRegionKind::Named(id) => Some(id), + _ => None, + } + } +} + +#[derive_where(Clone, Copy, PartialEq, Eq, Debug, Hash; I: Interner)] +#[derive(Lift_Generic)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] +pub enum BoundTyKind { + Anon, + Param(I::DefId), +} + +#[derive_where(Clone, Copy, PartialEq, Eq, Debug, Hash; I: Interner)] +#[derive(Lift_Generic)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] +pub enum BoundVariableKind { + Ty(BoundTyKind), + Region(BoundRegionKind), + Const, +} + +impl BoundVariableKind { + pub fn expect_region(self) -> BoundRegionKind { + match self { + BoundVariableKind::Region(lt) => lt, + _ => panic!("expected a region, but found another kind"), + } + } + + pub fn expect_ty(self) -> BoundTyKind { + match self { + BoundVariableKind::Ty(ty) => ty, + _ => panic!("expected a type, but found another kind"), + } + } + + pub fn expect_const(self) { + match self { + BoundVariableKind::Const => (), + _ => panic!("expected a const, but found another kind"), + } + } +} + +#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, HashStable_NoContext, Decodable_NoContext) +)] +pub struct BoundRegion { + pub var: ty::BoundVar, + pub kind: BoundRegionKind, +} + +impl core::fmt::Debug for BoundRegion { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.kind { + BoundRegionKind::Anon => write!(f, "{:?}", self.var), + BoundRegionKind::ClosureEnv => write!(f, "{:?}.Env", self.var), + BoundRegionKind::Named(def) => { + write!(f, "{:?}.Named({:?})", self.var, def) + } + BoundRegionKind::NamedForPrinting(symbol) => { + write!(f, "{:?}.NamedAnon({:?})", self.var, symbol) + } + } + } +} + +impl BoundRegion { + pub fn var(self) -> ty::BoundVar { + self.var + } + + pub fn assert_eq(self, var: BoundVariableKind) { + assert_eq!(self.kind, var.expect_region()) + } +} + +pub type PlaceholderRegion = ty::Placeholder>; + +impl PlaceholderRegion { + pub fn universe(self) -> UniverseIndex { + self.universe + } + + pub fn var(self) -> ty::BoundVar { + self.bound.var() + } + + pub fn with_updated_universe(self, ui: UniverseIndex) -> Self { + Self { universe: ui, bound: self.bound, _tcx: PhantomData } + } + + pub fn new(ui: UniverseIndex, bound: BoundRegion) -> Self { + Self { universe: ui, bound, _tcx: PhantomData } + } + + pub fn new_anon(ui: UniverseIndex, var: ty::BoundVar) -> Self { + let bound = BoundRegion { var, kind: BoundRegionKind::Anon }; + Self { universe: ui, bound, _tcx: PhantomData } + } +} + +#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] +pub struct BoundTy { + pub var: ty::BoundVar, + pub kind: BoundTyKind, +} + +impl Lift for BoundTy +where + BoundTyKind: Lift>, +{ + type Lifted = BoundTy; + + fn lift_to_interner(self, cx: U) -> Option { + Some(BoundTy { var: self.var, kind: self.kind.lift_to_interner(cx)? }) + } +} + +impl fmt::Debug for ty::BoundTy { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.kind { + ty::BoundTyKind::Anon => write!(f, "{:?}", self.var), + ty::BoundTyKind::Param(def_id) => write!(f, "{def_id:?}"), + } + } +} + +impl BoundTy { + pub fn var(self) -> ty::BoundVar { + self.var + } + + pub fn assert_eq(self, var: BoundVariableKind) { + assert_eq!(self.kind, var.expect_ty()) + } +} + +pub type PlaceholderType = ty::Placeholder>; + +impl PlaceholderType { + pub fn universe(self) -> UniverseIndex { + self.universe + } + + pub fn var(self) -> ty::BoundVar { + self.bound.var + } + + pub fn with_updated_universe(self, ui: UniverseIndex) -> Self { + Self { universe: ui, bound: self.bound, _tcx: PhantomData } + } + + pub fn new(ui: UniverseIndex, bound: BoundTy) -> Self { + Self { universe: ui, bound, _tcx: PhantomData } + } + + pub fn new_anon(ui: UniverseIndex, var: ty::BoundVar) -> Self { + let bound = BoundTy { var, kind: BoundTyKind::Anon }; + Self { universe: ui, bound, _tcx: PhantomData } + } +} + +#[derive_where(Clone, Copy, PartialEq, Debug, Eq, Hash; I: Interner)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] +pub struct BoundConst { + pub var: ty::BoundVar, + #[derive_where(skip(Debug))] + pub _tcx: PhantomData I>, +} + +impl BoundConst { + pub fn var(self) -> ty::BoundVar { + self.var + } + + pub fn assert_eq(self, var: BoundVariableKind) { + var.expect_const() + } + + pub fn new(var: ty::BoundVar) -> Self { + Self { var, _tcx: PhantomData } + } +} + +pub type PlaceholderConst = ty::Placeholder>; + +impl PlaceholderConst { + pub fn universe(self) -> UniverseIndex { + self.universe + } + + pub fn var(self) -> ty::BoundVar { + self.bound.var + } + + pub fn with_updated_universe(self, ui: UniverseIndex) -> Self { + Self { universe: ui, bound: self.bound, _tcx: PhantomData } + } + + pub fn new(ui: UniverseIndex, bound: BoundConst) -> Self { + Self { universe: ui, bound, _tcx: PhantomData } + } + + pub fn new_anon(ui: UniverseIndex, var: ty::BoundVar) -> Self { + let bound = BoundConst::new(var); + Self { universe: ui, bound, _tcx: PhantomData } + } + + pub fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty { + let mut candidates = env.caller_bounds().iter().filter_map(|clause| { + // `ConstArgHasType` are never desugared to be higher ranked. + match clause.kind().skip_binder() { + ty::ClauseKind::ConstArgHasType(placeholder_ct, ty) => { + assert!(!(placeholder_ct, ty).has_escaping_bound_vars()); + + match placeholder_ct.kind() { + ty::ConstKind::Placeholder(placeholder_ct) if placeholder_ct == self => { + Some(ty) + } + _ => None, + } + } + _ => None, + } + }); + + // N.B. it may be tempting to fix ICEs by making this function return + // `Option>` instead of `Ty<'tcx>`; however, this is generally + // considered to be a bandaid solution, since it hides more important + // underlying issues with how we construct generics and predicates of + // items. It's advised to fix the underlying issue rather than trying + // to modify this function. + let ty = candidates.next().unwrap_or_else(|| { + panic!("cannot find `{self:?}` in param-env: {env:#?}"); + }); + assert!( + candidates.next().is_none(), + "did not expect duplicate `ConstParamHasTy` for `{self:?}` in param-env: {env:#?}" + ); + ty + } +} diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 12d222258b0c..8e7414674c6e 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -108,7 +108,7 @@ pub enum CanonicalVarKind { Float, /// A "placeholder" that represents "any type". - PlaceholderTy(I::PlaceholderTy), + PlaceholderTy(ty::PlaceholderType), /// Region variable `'?R`. Region(UniverseIndex), @@ -116,13 +116,13 @@ pub enum CanonicalVarKind { /// A "placeholder" that represents "any region". Created when you /// are solving a goal like `for<'a> T: Foo<'a>` to represent the /// bound region `'a`. - PlaceholderRegion(I::PlaceholderRegion), + PlaceholderRegion(ty::PlaceholderRegion), /// Some kind of const inference variable. Const(UniverseIndex), /// A "placeholder" that represents "any const". - PlaceholderConst(I::PlaceholderConst), + PlaceholderConst(ty::PlaceholderConst), } impl Eq for CanonicalVarKind {} diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 5b136ae03121..b215230ea443 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -26,10 +26,10 @@ pub enum ConstKind { Infer(InferConst), /// Bound const variable, used only when preparing a trait query. - Bound(BoundVarIndexKind, I::BoundConst), + Bound(BoundVarIndexKind, ty::BoundConst), /// A placeholder const - universally quantified higher-ranked const. - Placeholder(I::PlaceholderConst), + Placeholder(ty::PlaceholderConst), /// An unnormalized const item such as an anon const or assoc const or free const item. /// Right now anything other than anon consts does not actually work properly but this diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs index 502622aa50ca..eba4c7c6644a 100644 --- a/compiler/rustc_type_ir/src/error.rs +++ b/compiler/rustc_type_ir/src/error.rs @@ -33,7 +33,7 @@ pub enum TypeError { ArgCount, RegionsDoesNotOutlive(I::Region, I::Region), - RegionsInsufficientlyPolymorphic(I::BoundRegion, I::Region), + RegionsInsufficientlyPolymorphic(ty::BoundRegion, I::Region), RegionsPlaceholderMismatch, Sorts(ExpectedFound), diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 4323b1ca6469..89cb236d38c6 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -12,7 +12,7 @@ use crate::elaborate::Elaboratable; use crate::fold::{TypeFoldable, TypeSuperFoldable}; use crate::relate::Relate; use crate::solve::{AdtDestructorKind, SizedTraitKind}; -use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt}; +use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{self as ty, CollectAndApply, Interner, UpcastFrom}; pub trait Ty>: @@ -42,9 +42,9 @@ pub trait Ty>: fn new_param(interner: I, param: I::ParamTy) -> Self; - fn new_placeholder(interner: I, param: I::PlaceholderTy) -> Self; + fn new_placeholder(interner: I, param: ty::PlaceholderType) -> Self; - fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundTy) -> Self; + fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundTy) -> Self; fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self; @@ -228,7 +228,7 @@ pub trait Region>: + Flags + Relate { - fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundRegion) -> Self; + fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundRegion) -> Self; fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self; @@ -236,7 +236,7 @@ pub trait Region>: fn new_static(interner: I) -> Self; - fn new_placeholder(interner: I, var: I::PlaceholderRegion) -> Self; + fn new_placeholder(interner: I, var: ty::PlaceholderRegion) -> Self; fn is_bound(self) -> bool { matches!(self.kind(), ty::ReBound(..)) @@ -260,13 +260,13 @@ pub trait Const>: fn new_var(interner: I, var: ty::ConstVid) -> Self; - fn new_bound(interner: I, debruijn: ty::DebruijnIndex, bound_const: I::BoundConst) -> Self; + fn new_bound(interner: I, debruijn: ty::DebruijnIndex, bound_const: ty::BoundConst) -> Self; fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self; fn new_canonical_bound(interner: I, var: ty::BoundVar) -> Self; - fn new_placeholder(interner: I, param: I::PlaceholderConst) -> Self; + fn new_placeholder(interner: I, param: ty::PlaceholderConst) -> Self; fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst) -> Self; @@ -543,68 +543,12 @@ pub trait Clauses>: { } -/// Common capabilities of placeholder kinds -pub trait PlaceholderLike: Copy + Debug + Hash + Eq { - fn universe(self) -> ty::UniverseIndex; - fn var(self) -> ty::BoundVar; - - type Bound: BoundVarLike; - fn new(ui: ty::UniverseIndex, bound: Self::Bound) -> Self; - fn new_anon(ui: ty::UniverseIndex, var: ty::BoundVar) -> Self; - fn with_updated_universe(self, ui: ty::UniverseIndex) -> Self; -} - -pub trait PlaceholderConst: PlaceholderLike { - fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty; -} -impl PlaceholderConst for I::PlaceholderConst { - fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty { - let mut candidates = env.caller_bounds().iter().filter_map(|clause| { - // `ConstArgHasType` are never desugared to be higher ranked. - match clause.kind().skip_binder() { - ty::ClauseKind::ConstArgHasType(placeholder_ct, ty) => { - assert!(!(placeholder_ct, ty).has_escaping_bound_vars()); - - match placeholder_ct.kind() { - ty::ConstKind::Placeholder(placeholder_ct) if placeholder_ct == self => { - Some(ty) - } - _ => None, - } - } - _ => None, - } - }); - - // N.B. it may be tempting to fix ICEs by making this function return - // `Option>` instead of `Ty<'tcx>`; however, this is generally - // considered to be a bandaid solution, since it hides more important - // underlying issues with how we construct generics and predicates of - // items. It's advised to fix the underlying issue rather than trying - // to modify this function. - let ty = candidates.next().unwrap_or_else(|| { - panic!("cannot find `{self:?}` in param-env: {env:#?}"); - }); - assert!( - candidates.next().is_none(), - "did not expect duplicate `ConstParamHasTy` for `{self:?}` in param-env: {env:#?}" - ); - ty - } -} - pub trait IntoKind { type Kind; fn kind(self) -> Self::Kind; } -pub trait BoundVarLike: Copy + Debug + Hash + Eq { - fn var(self) -> ty::BoundVar; - - fn assert_eq(self, var: I::BoundVarKind); -} - pub trait ParamLike: Copy + Debug + Hash + Eq { fn index(self) -> u32; } @@ -768,3 +712,7 @@ impl<'a, S: SliceLike> SliceLike for &'a S { (*self).as_slice() } } + +pub trait Symbol: Copy + Hash + PartialEq + Eq + Debug { + fn is_kw_underscore_lifetime(self) -> bool; +} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 0ab27a65c687..59ae6733fb84 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -61,8 +61,12 @@ pub trait Interner: type GenericArg: GenericArg; type Term: Term; - type BoundVarKinds: Copy + Debug + Hash + Eq + SliceLike + Default; - type BoundVarKind: Copy + Debug + Hash + Eq; + type BoundVarKinds: Copy + + Debug + + Hash + + Eq + + SliceLike> + + Default; type PredefinedOpaques: Copy + Debug @@ -120,9 +124,7 @@ pub trait Interner: type Tys: Tys; type FnInputTys: Copy + Debug + Hash + Eq + SliceLike + TypeVisitable; type ParamTy: ParamLike; - type BoundTy: BoundVarLike; - type PlaceholderTy: PlaceholderLike; - type Symbol: Copy + Hash + PartialEq + Eq + Debug; + type Symbol: Symbol; // Things stored inside of tys type ErrorGuaranteed: Copy + Debug + Hash + Eq; @@ -149,8 +151,6 @@ pub trait Interner: // Kinds of consts type Const: Const; type ParamConst: Copy + Debug + Hash + Eq + ParamLike; - type BoundConst: BoundVarLike; - type PlaceholderConst: PlaceholderConst; type ValueConst: ValueConst; type ExprConst: ExprConst; type ValTree: ValTree; @@ -160,8 +160,6 @@ pub trait Interner: type Region: Region; type EarlyParamRegion: ParamLike; type LateParamRegion: Copy + Debug + Hash + Eq; - type BoundRegion: BoundVarLike; - type PlaceholderRegion: PlaceholderLike; type RegionAssumptions: Copy + Debug @@ -411,6 +409,8 @@ pub trait Interner: self, canonical_goal: CanonicalInput, ) -> (QueryResult, Self::Probe); + + fn item_name(self, item_index: Self::DefId) -> Self::Symbol; } /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index c7dccea6adc1..300e5c0b4695 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -14,7 +14,7 @@ use crate::{self as ty, Interner}; pub enum Component { Region(I::Region), Param(I::ParamTy), - Placeholder(I::PlaceholderTy), + Placeholder(ty::PlaceholderType), UnresolvedInferenceVariable(ty::InferTy), // Projections like `T::Foo` are tricky because a constraint like diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 9acf9ff8557e..e08c274f9f14 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -8,7 +8,7 @@ use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContex use rustc_type_ir_macros::GenericTypeVisitable; use self::RegionKind::*; -use crate::{BoundVarIndexKind, Interner}; +use crate::{BoundRegion, BoundVarIndexKind, Interner, PlaceholderRegion}; rustc_index::newtype_index! { /// A **region** **v**ariable **ID**. @@ -149,7 +149,7 @@ pub enum RegionKind { /// 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(BoundVarIndexKind, I::BoundRegion), + ReBound(BoundVarIndexKind, BoundRegion), /// Late-bound function parameters are represented using a `ReBound`. When /// inside of a function, we convert these bound variables to placeholder @@ -170,7 +170,7 @@ pub enum RegionKind { /// Should not exist outside of type inference. /// /// Used when instantiating a `forall` binder via `infcx.enter_forall`. - RePlaceholder(I::PlaceholderRegion), + RePlaceholder(PlaceholderRegion), /// Erased region, used by trait selection, in MIR and during codegen. ReErased, @@ -214,9 +214,9 @@ impl fmt::Debug for RegionKind { impl HashStable for RegionKind where I::EarlyParamRegion: HashStable, - I::BoundRegion: HashStable, I::LateParamRegion: HashStable, - I::PlaceholderRegion: HashStable, + I::DefId: HashStable, + I::Symbol: HashStable, { #[inline] fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 498797bef653..7cb71387e868 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -233,7 +233,7 @@ pub enum TyKind { /// /// [1]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html /// [2]: https://rustc-dev-guide.rust-lang.org/traits/canonical-queries.html - Bound(BoundVarIndexKind, I::BoundTy), + Bound(BoundVarIndexKind, ty::BoundTy), /// A placeholder type, used during higher ranked subtyping to instantiate /// bound variables. @@ -243,7 +243,7 @@ pub enum TyKind { /// to the bound variable's index from the binder from which it was instantiated), /// and `U` is the universe index in which it is instantiated, or totally omitted /// if the universe index is zero. - Placeholder(I::PlaceholderTy), + Placeholder(ty::PlaceholderType), /// A type variable used during type checking. /// diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9d6038367419..1c9154238657 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3178,7 +3178,7 @@ fn clean_assoc_item_constraint<'tcx>( } fn clean_bound_vars<'tcx>( - bound_vars: &ty::List, + bound_vars: &ty::List>, cx: &mut DocContext<'tcx>, ) -> Vec { bound_vars diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 2926a329ce16..0f11df98fc17 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -782,15 +782,15 @@ pub fn is_c_void(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { } } -pub fn for_each_top_level_late_bound_region( - ty: Ty<'_>, - f: impl FnMut(BoundRegion) -> ControlFlow, +pub fn for_each_top_level_late_bound_region<'cx, B>( + ty: Ty<'cx>, + f: impl FnMut(BoundRegion<'cx>) -> ControlFlow, ) -> ControlFlow { struct V { index: u32, f: F, } - impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow> TypeVisitor> for V { + impl<'tcx, B, F: FnMut(BoundRegion<'tcx>) -> ControlFlow> TypeVisitor> for V { type Result = ControlFlow; fn visit_region(&mut self, r: Region<'tcx>) -> Self::Result { if let RegionKind::ReBound(BoundVarIndexKind::Bound(idx), bound) = r.kind() From f992358ab772ba146732024975802648eb7a490b Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 22 Dec 2025 14:45:08 +0000 Subject: [PATCH 219/978] Part 2 refactoring of moving placeholder types to `rustc_type_ir` --- clippy_utils/src/ty/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index 2926a329ce16..0f11df98fc17 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -782,15 +782,15 @@ pub fn is_c_void(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { } } -pub fn for_each_top_level_late_bound_region( - ty: Ty<'_>, - f: impl FnMut(BoundRegion) -> ControlFlow, +pub fn for_each_top_level_late_bound_region<'cx, B>( + ty: Ty<'cx>, + f: impl FnMut(BoundRegion<'cx>) -> ControlFlow, ) -> ControlFlow { struct V { index: u32, f: F, } - impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow> TypeVisitor> for V { + impl<'tcx, B, F: FnMut(BoundRegion<'tcx>) -> ControlFlow> TypeVisitor> for V { type Result = ControlFlow; fn visit_region(&mut self, r: Region<'tcx>) -> Self::Result { if let RegionKind::ReBound(BoundVarIndexKind::Bound(idx), bound) = r.kind() From a333f6f93c5fe34d59e24af1269b528c6b608596 Mon Sep 17 00:00:00 2001 From: "Andrew V. Teylu" Date: Thu, 29 Jan 2026 12:04:30 +0000 Subject: [PATCH 220/978] Fix missing syntax context in lifetime hygiene debug output `-Zunpretty=expanded,hygiene` was not printing the syntax context for lifetimes. For example, two macro-generated lifetimes `'a` with different hygiene would both print as `/* 2538 */` instead of `/* 2538#0 */` and `/* 2538#1 */`, making it impossible to distinguish them. This was fixed by changing `print_lifetime` to call `ann_post()` with the full `Ident`, matching how regular identifiers are handled in `print_ident`. --- compiler/rustc_ast_pretty/src/pprust/state.rs | 3 +- tests/ui/hygiene/unpretty-debug-lifetimes.rs | 18 +++++++++++ .../hygiene/unpretty-debug-lifetimes.stdout | 31 +++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 tests/ui/hygiene/unpretty-debug-lifetimes.rs create mode 100644 tests/ui/hygiene/unpretty-debug-lifetimes.stdout diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index e50e31c226fd..c8874ed99dca 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1961,7 +1961,8 @@ impl<'a> State<'a> { } fn print_lifetime(&mut self, lifetime: ast::Lifetime) { - self.print_name(lifetime.ident.name) + self.word(lifetime.ident.name.to_string()); + self.ann_post(lifetime.ident) } fn print_lifetime_bounds(&mut self, bounds: &ast::GenericBounds) { diff --git a/tests/ui/hygiene/unpretty-debug-lifetimes.rs b/tests/ui/hygiene/unpretty-debug-lifetimes.rs new file mode 100644 index 000000000000..ee8be21b60d0 --- /dev/null +++ b/tests/ui/hygiene/unpretty-debug-lifetimes.rs @@ -0,0 +1,18 @@ +//@ check-pass +//@ compile-flags: -Zunpretty=expanded,hygiene + +// Regression test for lifetime hygiene annotations in -Zunpretty=expanded,hygiene +// Previously, lifetimes were missing the #N syntax context suffix. + +// Don't break whenever Symbol numbering changes +//@ normalize-stdout: "\d+#" -> "0#" + +#![feature(decl_macro)] +#![feature(no_core)] +#![no_core] + +macro lifetime_hygiene($f:ident<$a:lifetime>) { + fn $f<$a, 'a>() {} +} + +lifetime_hygiene!(f<'a>); diff --git a/tests/ui/hygiene/unpretty-debug-lifetimes.stdout b/tests/ui/hygiene/unpretty-debug-lifetimes.stdout new file mode 100644 index 000000000000..28a5c70a02d7 --- /dev/null +++ b/tests/ui/hygiene/unpretty-debug-lifetimes.stdout @@ -0,0 +1,31 @@ +//@ check-pass +//@ compile-flags: -Zunpretty=expanded,hygiene + +// Regression test for lifetime hygiene annotations in -Zunpretty=expanded,hygiene +// Previously, lifetimes were missing the #N syntax context suffix. + +// Don't break whenever Symbol numbering changes +//@ normalize-stdout: "\d+#" -> "0#" + +#![feature /* 0#0 */(decl_macro)] +#![feature /* 0#0 */(no_core)] +#![no_core /* 0#0 */] + +macro lifetime_hygiene + /* + 0#0 + */ { + ($f:ident<$a:lifetime>) => { fn $f<$a, 'a>() {} } +} +fn f /* 0#0 */<'a /* 0#0 */, 'a /* 0#1 */>() {} + + +/* +Expansions: +crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root +crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "lifetime_hygiene") + +SyntaxContexts: +#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) +#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) +*/ From 21c99d3ad9ca533a2c4fe2a6bff19b7f74fd07f5 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 29 Jan 2026 18:00:33 +1100 Subject: [PATCH 221/978] Fix some typos of "similarity" --- compiler/rustc_arena/src/lib.rs | 4 ++-- typos.toml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 5e81ec28ee35..cc18cf38ef4c 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -208,7 +208,7 @@ impl TypedArena { &self, iter: impl IntoIterator>, ) -> Result<&mut [T], E> { - // Despite the similarlty with `DroplessArena`, we cannot reuse their fast case. The reason + // Despite the similarity with `DroplessArena`, we cannot reuse their fast case. The reason // is subtle: these arenas are reentrant. In other words, `iter` may very well be holding a // reference to `self` and adding elements to the arena during iteration. // @@ -584,7 +584,7 @@ impl DroplessArena { &self, iter: impl IntoIterator>, ) -> Result<&mut [T], E> { - // Despite the similarlty with `alloc_from_iter`, we cannot reuse their fast case, as we + // Despite the similarity with `alloc_from_iter`, we cannot reuse their fast case, as we // cannot know the minimum length of the iterator in this case. assert!(size_of::() != 0); diff --git a/typos.toml b/typos.toml index 25083174cb8f..e486a7c1722c 100644 --- a/typos.toml +++ b/typos.toml @@ -46,6 +46,7 @@ unstalled = "unstalled" # short for un-stalled # # tidy-alphabetical-start definitinon = "definition" +similarlty = "similarity" # tidy-alphabetical-end [default.extend-identifiers] From 363d3ac4382e3f46a7472bed796aebc34f76deab Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 29 Jan 2026 18:05:40 +1100 Subject: [PATCH 222/978] Document a safety condition for `TypedArena::alloc_raw_slice` --- compiler/rustc_arena/src/lib.rs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index cc18cf38ef4c..524baf5b07fe 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -172,8 +172,22 @@ impl TypedArena { available_bytes >= additional_bytes } + /// Allocates storage for `len >= 1` values in this arena, and returns a + /// raw pointer to the first value's storage. + /// + /// # Safety + /// + /// Caller must initialize each of the `len` slots to a droppable value + /// before the arena is dropped. + /// + /// In practice, this typically means that the caller must be able to + /// raw-copy `len` already-initialized values into the slice without any + /// possibility of panicking. + /// + /// FIXME(Zalathar): This is *very* fragile; perhaps we need a different + /// approach to arena-allocating slices of droppable values. #[inline] - fn alloc_raw_slice(&self, len: usize) -> *mut T { + unsafe fn alloc_raw_slice(&self, len: usize) -> *mut T { assert!(size_of::() != 0); assert!(len != 0); @@ -229,9 +243,15 @@ impl TypedArena { } // Move the content to the arena by copying and then forgetting it. let len = vec.len(); - let start_ptr = self.alloc_raw_slice(len); + + // SAFETY: After allocating raw storage for exactly `len` values, we + // must fully initialize the storage without panicking, and we must + // also prevent the stale values in the vec from being dropped. Ok(unsafe { + let start_ptr = self.alloc_raw_slice(len); + // Initialize the newly-allocated storage without panicking. vec.as_ptr().copy_to_nonoverlapping(start_ptr, len); + // Prevent the stale values in the vec from being dropped. vec.set_len(0); slice::from_raw_parts_mut(start_ptr, len) }) From db74048b9a8bb6cc5092da218552a464cd1dcb52 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 23 Jan 2026 17:02:30 +1100 Subject: [PATCH 223/978] Rename, clarify, and document code for "erasing" query values --- compiler/rustc_middle/src/query/erase.rs | 288 ++++++++++++-------- compiler/rustc_middle/src/query/inner.rs | 20 +- compiler/rustc_middle/src/query/mod.rs | 1 - compiler/rustc_middle/src/query/plumbing.rs | 27 +- compiler/rustc_query_impl/src/lib.rs | 1 - compiler/rustc_query_impl/src/plumbing.rs | 18 +- 6 files changed, 206 insertions(+), 149 deletions(-) diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 940cc30c17e6..090bcaf45c73 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -1,3 +1,10 @@ +//! To improve compile times and code size for the compiler itself, query +//! values are "erased" in some contexts (e.g. inside in-memory cache types), +//! to reduce the number of generic instantiations created during codegen. +//! +//! See for some bootstrap-time +//! and performance benchmarks. + use std::ffi::OsStr; use std::intrinsics::transmute_unchecked; use std::mem::MaybeUninit; @@ -14,138 +21,169 @@ use crate::ty::adjustment::CoerceUnsizedInfo; use crate::ty::{self, Ty, TyCtxt}; use crate::{mir, traits}; +/// Internal implementation detail of [`Erased`]. #[derive(Copy, Clone)] -pub struct Erased { - // We use `MaybeUninit` here so we can store any value - // in `data` since we aren't actually storing a `T`. - data: MaybeUninit, +pub struct ErasedData { + /// We use `MaybeUninit` here to make sure it's legal to store a transmuted + /// value that isn't actually of type `Storage`. + data: MaybeUninit, } -pub trait EraseType: Copy { - type Result: Copy; +/// Trait for types that can be erased into [`Erased`]. +/// +/// Erasing and unerasing values is performed by [`erase_val`] and [`restore_val`]. +/// +/// FIXME: This whole trait could potentially be replaced by `T: Copy` and the +/// storage type `[u8; size_of::()]` when support for that is more mature. +pub trait Erasable: Copy { + /// Storage type to used for erased values of this type. + /// Should be `[u8; N]`, where N is equal to `size_of::`. + /// + /// [`ErasedData`] wraps this storage type in `MaybeUninit` to ensure that + /// transmutes to/from erased storage are well-defined. + type Storage: Copy; } -// Allow `type_alias_bounds` since compilation will fail without `EraseType`. -#[allow(type_alias_bounds)] -pub type Erase = Erased; +/// A value of `T` that has been "erased" into some opaque storage type. +/// +/// This is helpful for reducing the number of concrete instantiations needed +/// during codegen when building the compiler. +/// +/// Using an opaque type alias allows the type checker to enforce that +/// `Erased` and `Erased` are still distinct types, while allowing +/// monomorphization to see that they might actually use the same storage type. +pub type Erased = ErasedData; +/// Erases a value of type `T` into `Erased`. +/// +/// `Erased` and `Erased` are type-checked as distinct types, but codegen +/// can see whether they actually have the same storage type. +/// +/// FIXME: This might have soundness issues with erasable types that don't +/// implement the same auto-traits as `[u8; _]`; see +/// #[inline(always)] -#[define_opaque(Erase)] -pub fn erase(src: T) -> Erase { +#[define_opaque(Erased)] +pub fn erase_val(value: T) -> Erased { // Ensure the sizes match const { - if size_of::() != size_of::() { - panic!("size of T must match erased type T::Result") + if size_of::() != size_of::() { + panic!("size of T must match erased type ::Storage") } }; - Erased::<::Result> { + ErasedData::<::Storage> { // `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 + // (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. + // `Erasable: 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_unchecked::>(src) }, + data: unsafe { transmute_unchecked::>(value) }, } } -/// Restores an erased value. +/// Restores an erased value to its real type. +/// +/// This relies on the fact that `Erased` and `Erased` are type-checked +/// as distinct types, even if they use the same storage type. #[inline(always)] -#[define_opaque(Erase)] -pub fn restore(value: Erase) -> T { - let value: Erased<::Result> = value; - // See comment in `erase` for why we use `transmute_unchecked`. +#[define_opaque(Erased)] +pub fn restore_val(erased_value: Erased) -> T { + let ErasedData { data }: ErasedData<::Storage> = erased_value; + // See comment in `erase_val` 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_unchecked::, T>(value.data) } + // SAFETY: Due to the use of impl Trait in `Erased` the only way to safely create an instance + // of `Erased` is to call `erase_val`, so we know that `erased_value.data` is a valid instance + // of `T` of the right size. + unsafe { transmute_unchecked::, T>(data) } } -impl EraseType for &'_ T { - type Result = [u8; size_of::<&'static ()>()]; +// FIXME(#151565): Using `T: ?Sized` here should let us remove the separate +// impls for fat reference types. +impl Erasable for &'_ T { + type Storage = [u8; size_of::<&'static ()>()]; } -impl EraseType for &'_ [T] { - type Result = [u8; size_of::<&'static [()]>()]; +impl Erasable for &'_ [T] { + type Storage = [u8; size_of::<&'static [()]>()]; } -impl EraseType for &'_ OsStr { - type Result = [u8; size_of::<&'static OsStr>()]; +impl Erasable for &'_ OsStr { + type Storage = [u8; size_of::<&'static OsStr>()]; } -impl EraseType for &'_ ty::List { - type Result = [u8; size_of::<&'static ty::List<()>>()]; +impl Erasable for &'_ ty::List { + type Storage = [u8; size_of::<&'static ty::List<()>>()]; } -impl EraseType for &'_ ty::ListWithCachedTypeInfo { - type Result = [u8; size_of::<&'static ty::ListWithCachedTypeInfo<()>>()]; +impl Erasable for &'_ ty::ListWithCachedTypeInfo { + type Storage = [u8; size_of::<&'static ty::ListWithCachedTypeInfo<()>>()]; } -impl EraseType for &'_ rustc_index::IndexSlice { - type Result = [u8; size_of::<&'static rustc_index::IndexSlice>()]; +impl Erasable for &'_ rustc_index::IndexSlice { + type Storage = [u8; size_of::<&'static rustc_index::IndexSlice>()]; } -impl EraseType for Result<&'_ T, traits::query::NoSolution> { - type Result = [u8; size_of::>()]; +impl Erasable for Result<&'_ T, traits::query::NoSolution> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Result<&'_ [T], traits::query::NoSolution> { - type Result = [u8; size_of::>()]; +impl Erasable for Result<&'_ [T], traits::query::NoSolution> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Result<&'_ T, rustc_errors::ErrorGuaranteed> { - type Result = [u8; size_of::>()]; +impl Erasable for Result<&'_ T, rustc_errors::ErrorGuaranteed> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Result<&'_ [T], rustc_errors::ErrorGuaranteed> { - type Result = [u8; size_of::>()]; +impl Erasable for Result<&'_ [T], rustc_errors::ErrorGuaranteed> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Result<&'_ T, traits::CodegenObligationError> { - type Result = [u8; size_of::>()]; +impl Erasable for Result<&'_ T, traits::CodegenObligationError> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Result<&'_ T, &'_ ty::layout::FnAbiError<'_>> { - type Result = [u8; size_of::>>()]; +impl Erasable for Result<&'_ T, &'_ ty::layout::FnAbiError<'_>> { + type Storage = [u8; size_of::>>()]; } -impl EraseType for Result<(&'_ T, crate::thir::ExprId), rustc_errors::ErrorGuaranteed> { - type Result = [u8; size_of::< +impl Erasable for Result<(&'_ T, crate::thir::ExprId), rustc_errors::ErrorGuaranteed> { + type Storage = [u8; size_of::< Result<(&'static (), crate::thir::ExprId), rustc_errors::ErrorGuaranteed>, >()]; } -impl EraseType for Result>, rustc_errors::ErrorGuaranteed> { - type Result = +impl Erasable for Result>, rustc_errors::ErrorGuaranteed> { + type Storage = [u8; size_of::>, rustc_errors::ErrorGuaranteed>>()]; } -impl EraseType for Result { - type Result = [u8; size_of::>()]; +impl Erasable for Result { + type Storage = [u8; size_of::>()]; } -impl EraseType +impl Erasable for Result>>, rustc_errors::ErrorGuaranteed> { - type Result = [u8; size_of::< + type Storage = [u8; size_of::< Result>>, rustc_errors::ErrorGuaranteed>, >()]; } -impl EraseType for Result, traits::query::NoSolution> { - type Result = [u8; size_of::, traits::query::NoSolution>>()]; +impl Erasable for Result, traits::query::NoSolution> { + type Storage = [u8; size_of::, traits::query::NoSolution>>()]; } -impl EraseType for Result> { - type Result = [u8; size_of::>>()]; +impl Erasable for Result> { + type Storage = [u8; size_of::>>()]; } -impl EraseType for Result>, &ty::layout::LayoutError<'_>> { - type Result = [u8; size_of::< +impl Erasable for Result>, &ty::layout::LayoutError<'_>> { + type Storage = [u8; size_of::< Result< rustc_abi::TyAndLayout<'static, Ty<'static>>, &'static ty::layout::LayoutError<'static>, @@ -153,35 +191,36 @@ impl EraseType for Result>, &ty::layout::Layou >()]; } -impl EraseType for Result, mir::interpret::ErrorHandled> { - type Result = [u8; size_of::, mir::interpret::ErrorHandled>>()]; +impl Erasable for Result, mir::interpret::ErrorHandled> { + type Storage = + [u8; size_of::, mir::interpret::ErrorHandled>>()]; } -impl EraseType for Result { - type Result = [u8; size_of::>()]; +impl Erasable for Result { + type Storage = [u8; size_of::>()]; } -impl EraseType for Option<(mir::ConstValue, Ty<'_>)> { - type Result = [u8; size_of::)>>()]; +impl Erasable for Option<(mir::ConstValue, Ty<'_>)> { + type Storage = [u8; size_of::)>>()]; } -impl EraseType for EvalToValTreeResult<'_> { - type Result = [u8; size_of::>()]; +impl Erasable for EvalToValTreeResult<'_> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Result<&'_ ty::List>, ty::util::AlwaysRequiresDrop> { - type Result = +impl Erasable for Result<&'_ ty::List>, ty::util::AlwaysRequiresDrop> { + type Storage = [u8; size_of::>, ty::util::AlwaysRequiresDrop>>()]; } -impl EraseType for Result>, CyclePlaceholder> { - type Result = [u8; size_of::>, CyclePlaceholder>>()]; +impl Erasable for Result>, CyclePlaceholder> { + type Storage = [u8; size_of::>, CyclePlaceholder>>()]; } -impl EraseType +impl Erasable for Result<(&'_ [Spanned>], &'_ [Spanned>]), NormalizationErrorInMono> { - type Result = [u8; size_of::< + type Storage = [u8; size_of::< Result< (&'static [Spanned>], &'static [Spanned>]), NormalizationErrorInMono, @@ -189,86 +228,89 @@ impl EraseType >()]; } -impl EraseType for Result<&'_ TokenStream, ()> { - type Result = [u8; size_of::>()]; +impl Erasable for Result<&'_ TokenStream, ()> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Option<&'_ T> { - type Result = [u8; size_of::>()]; +impl Erasable for Option<&'_ T> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Option<&'_ [T]> { - type Result = [u8; size_of::>()]; +impl Erasable for Option<&'_ [T]> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Option<&'_ OsStr> { - type Result = [u8; size_of::>()]; +impl Erasable for Option<&'_ OsStr> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Option> { - type Result = [u8; size_of::>>()]; +impl Erasable for Option> { + type Storage = [u8; size_of::>>()]; } -impl EraseType for ty::ImplTraitHeader<'_> { - type Result = [u8; size_of::>()]; +impl Erasable for ty::ImplTraitHeader<'_> { + type Storage = [u8; size_of::>()]; } -impl EraseType for Option>> { - type Result = [u8; size_of::>>>()]; +impl Erasable for Option>> { + type Storage = [u8; size_of::>>>()]; } -impl EraseType for rustc_hir::MaybeOwner<'_> { - type Result = [u8; size_of::>()]; +impl Erasable for rustc_hir::MaybeOwner<'_> { + type Storage = [u8; size_of::>()]; } -impl EraseType for ty::EarlyBinder<'_, T> { - type Result = T::Result; +impl Erasable for ty::EarlyBinder<'_, T> { + type Storage = T::Storage; } -impl EraseType for ty::Binder<'_, ty::FnSig<'_>> { - type Result = [u8; size_of::>>()]; +impl Erasable for ty::Binder<'_, ty::FnSig<'_>> { + type Storage = [u8; size_of::>>()]; } -impl EraseType for ty::Binder<'_, ty::CoroutineWitnessTypes>> { - type Result = +impl Erasable for ty::Binder<'_, ty::CoroutineWitnessTypes>> { + type Storage = [u8; size_of::>>>()]; } -impl EraseType for ty::Binder<'_, &'_ ty::List>> { - type Result = [u8; size_of::>>>()]; +impl Erasable for ty::Binder<'_, &'_ ty::List>> { + type Storage = [u8; size_of::>>>()]; } -impl EraseType for (&'_ T0, &'_ T1) { - type Result = [u8; size_of::<(&'static (), &'static ())>()]; +impl Erasable for (&'_ T0, &'_ T1) { + type Storage = [u8; size_of::<(&'static (), &'static ())>()]; } -impl EraseType for (solve::QueryResult<'_>, &'_ T0) { - type Result = [u8; size_of::<(solve::QueryResult<'static>, &'static ())>()]; +impl Erasable for (solve::QueryResult<'_>, &'_ T0) { + type Storage = [u8; size_of::<(solve::QueryResult<'static>, &'static ())>()]; } -impl EraseType for (&'_ T0, &'_ [T1]) { - type Result = [u8; size_of::<(&'static (), &'static [()])>()]; +impl Erasable for (&'_ T0, &'_ [T1]) { + type Storage = [u8; size_of::<(&'static (), &'static [()])>()]; } -impl EraseType for (&'_ [T0], &'_ [T1]) { - type Result = [u8; size_of::<(&'static [()], &'static [()])>()]; +impl Erasable for (&'_ [T0], &'_ [T1]) { + type Storage = [u8; size_of::<(&'static [()], &'static [()])>()]; } -impl EraseType for (&'_ T0, Result<(), ErrorGuaranteed>) { - type Result = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()]; +impl Erasable for (&'_ T0, Result<(), ErrorGuaranteed>) { + type Storage = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()]; } -macro_rules! trivial { +macro_rules! impl_erasable_for_simple_types { ($($ty:ty),+ $(,)?) => { $( - impl EraseType for $ty { - type Result = [u8; size_of::<$ty>()]; + impl Erasable for $ty { + type Storage = [u8; size_of::<$ty>()]; } )* } } -trivial! { +// For concrete types with no lifetimes, the erased storage for `Foo` is +// `[u8; size_of::()]`. +impl_erasable_for_simple_types! { + // FIXME(#151565): Add `tidy-alphabetical-{start,end}` and sort this. (), bool, Option<(rustc_span::def_id::DefId, rustc_session::config::EntryFnType)>, @@ -378,17 +420,23 @@ trivial! { usize, } -macro_rules! tcx_lifetime { +macro_rules! impl_erasable_for_single_lifetime_types { ($($($fake_path:ident)::+),+ $(,)?) => { $( - impl<'tcx> EraseType for $($fake_path)::+<'tcx> { - type Result = [u8; size_of::<$($fake_path)::+<'static>>()]; + impl<'tcx> Erasable for $($fake_path)::+<'tcx> { + type Storage = [u8; size_of::<$($fake_path)::+<'static>>()]; } )* } } -tcx_lifetime! { +// For types containing a single lifetime and no other generics, e.g. +// `Foo<'tcx>`, the erased storage is `[u8; size_of::>()]`. +// +// FIXME(#151565): Some of the hand-written impls above that only use one +// lifetime can probably be migrated here. +impl_erasable_for_single_lifetime_types! { + // FIXME(#151565): Add `tidy-alphabetical-{start,end}` and sort this. rustc_middle::middle::exported_symbols::ExportedSymbol, rustc_middle::mir::Const, rustc_middle::mir::DestructuredConstant, diff --git a/compiler/rustc_middle/src/query/inner.rs b/compiler/rustc_middle/src/query/inner.rs index ee828ae55f7a..e41d23f82f12 100644 --- a/compiler/rustc_middle/src/query/inner.rs +++ b/compiler/rustc_middle/src/query/inner.rs @@ -11,7 +11,7 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use crate::dep_graph; use crate::query::IntoQueryParam; -use crate::query::erase::{self, Erase, EraseType}; +use crate::query::erase::{self, Erasable, Erased}; use crate::ty::TyCtxt; /// Shared implementation of `tcx.$query(..)` and `tcx.at(span).$query(..)` @@ -63,15 +63,15 @@ pub(crate) fn query_ensure_error_guaranteed<'tcx, Cache, T>( check_cache: bool, ) -> Result<(), ErrorGuaranteed> where - Cache: QueryCache>>, - Result: EraseType, + Cache: QueryCache>>, + Result: Erasable, { let key = key.into_query_param(); if let Some(res) = try_get_cached(tcx, query_cache, &key) { - erase::restore(res).map(drop) + erase::restore_val(res).map(drop) } else { execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache }) - .map(erase::restore) + .map(erase::restore_val) .map(|res| res.map(drop)) // Either we actually executed the query, which means we got a full `Result`, // or we can just assume the query succeeded, because it was green in the @@ -90,17 +90,17 @@ pub(crate) fn query_feed<'tcx, Cache, Value>( hasher: Option, &Value) -> Fingerprint>, cache: &Cache, key: Cache::Key, - erased: Erase, + erased: Erased, ) where - Cache: QueryCache>, + Cache: QueryCache>, Cache::Key: DepNodeParams>, - Value: EraseType + Debug, + Value: Erasable + Debug, { - let value = erase::restore::(erased); + let value = erase::restore_val::(erased); match try_get_cached(tcx, cache, &key) { Some(old) => { - let old = erase::restore::(old); + let old = erase::restore_val::(old); if let Some(hasher) = hasher { let (value_hash, old_hash): (Fingerprint, Fingerprint) = tcx .with_stable_hashing_context(|mut hcx| { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 901a023c4f30..ae94c154015b 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -121,7 +121,6 @@ use crate::mir::interpret::{ use crate::mir::mono::{ CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions, NormalizationErrorInMono, }; -use crate::query::erase::{Erase, erase, restore}; use crate::query::plumbing::CyclePlaceholder; use crate::traits::query::{ CanonicalAliasGoal, CanonicalDropckOutlivesGoal, CanonicalImpliedOutlivesBoundsGoal, diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 0e536352563f..7b85dac41aef 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -266,6 +266,7 @@ macro_rules! define_callbacks { pub mod queries { $(pub mod $name { use super::super::*; + use $crate::query::erase::{self, Erased}; pub type Key<'tcx> = $($K)*; pub type Value<'tcx> = $V; @@ -288,29 +289,33 @@ macro_rules! define_callbacks { #[inline(always)] pub fn provided_to_erased<'tcx>( _tcx: TyCtxt<'tcx>, - value: ProvidedValue<'tcx>, - ) -> Erase> { - erase(query_if_arena!([$($modifiers)*] + provided_value: ProvidedValue<'tcx>, + ) -> Erased> { + // Store the provided value in an arena and get a reference + // to it, for queries with `arena_cache`. + let value: Value<'tcx> = query_if_arena!([$($modifiers)*] { use $crate::query::arena_cached::ArenaCached; if mem::needs_drop::<<$V as ArenaCached<'tcx>>::Allocated>() { <$V as ArenaCached>::alloc_in_arena( |v| _tcx.query_system.arenas.$name.alloc(v), - value, + provided_value, ) } else { <$V as ArenaCached>::alloc_in_arena( |v| _tcx.arena.dropless.alloc(v), - value, + provided_value, ) } } - (value) - )) + // Otherwise, the provided value is the value. + (provided_value) + ); + erase::erase_val(value) } - pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache>; + pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache>; // Ensure that keys grow no larger than 88 bytes by accident. // Increase this limit if necessary, but do try to keep the size low if possible @@ -411,7 +416,9 @@ macro_rules! define_callbacks { #[inline(always)] pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V { - restore::<$V>(crate::query::inner::query_get_at( + use $crate::query::{erase, inner}; + + erase::restore_val::<$V>(inner::query_get_at( self.tcx, self.tcx.query_system.fns.engine.$name, &self.tcx.query_system.caches.$name, @@ -480,7 +487,7 @@ macro_rules! define_callbacks { Span, queries::$name::Key<'tcx>, QueryMode, - ) -> Option>,)* + ) -> Option<$crate::query::erase::Erased<$V>>,)* } }; } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index d6310b62b275..382b8750a1ce 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -10,7 +10,6 @@ use rustc_data_structures::stable_hasher::HashStable; use rustc_data_structures::sync::AtomicU64; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::{self, DepKind, DepKindVTable, DepNodeIndex}; -use rustc_middle::query::erase::{Erase, erase, restore}; use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; use rustc_middle::query::plumbing::{QuerySystem, QuerySystemFns, QueryVTable}; use rustc_middle::query::{ diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 0223981fd55d..c71352c3fd20 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -281,7 +281,10 @@ macro_rules! feedable { macro_rules! hash_result { ([][$V:ty]) => {{ - Some(|hcx, result| dep_graph::hash_result(hcx, &restore::<$V>(*result))) + Some(|hcx, result| { + let result = ::rustc_middle::query::erase::restore_val::<$V>(*result); + ::rustc_query_system::dep_graph::hash_result(hcx, &result) + }) }}; ([(no_hash) $($rest:tt)*][$V:ty]) => {{ None @@ -597,6 +600,7 @@ macro_rules! define_queries { pub(crate) mod query_impl { $(pub(crate) mod $name { use super::super::*; use std::marker::PhantomData; + use ::rustc_middle::query::erase::{self, Erased}; pub(crate) mod get_query_incr { use super::*; @@ -609,7 +613,7 @@ macro_rules! define_queries { span: Span, key: queries::$name::Key<'tcx>, mode: QueryMode, - ) -> Option>> { + ) -> Option>> { #[cfg(debug_assertions)] let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); get_query_incr( @@ -631,7 +635,7 @@ macro_rules! define_queries { span: Span, key: queries::$name::Key<'tcx>, __mode: QueryMode, - ) -> Option>> { + ) -> Option>> { Some(get_query_non_incr( QueryType::query_dispatcher(tcx), QueryCtxt::new(tcx), @@ -652,7 +656,7 @@ macro_rules! define_queries { query_state: std::mem::offset_of!(QueryStates<'tcx>, $name), query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name), cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key), - execute_query: |tcx, key| erase(tcx.$name(key)), + execute_query: |tcx, key| erase::erase_val(tcx.$name(key)), compute: |tcx, key| { #[cfg(debug_assertions)] let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); @@ -690,7 +694,7 @@ macro_rules! define_queries { }), value_from_cycle_error: |tcx, cycle, guar| { let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle, guar); - erase(result) + erase::erase_val(result) }, loadable_from_disk: |_tcx, _key, _index| { should_ever_cache_on_disk!([$($modifiers)*] { @@ -701,7 +705,7 @@ macro_rules! define_queries { }) }, hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]), - format_value: |value| format!("{:?}", restore::>(*value)), + format_value: |value| format!("{:?}", erase::restore_val::>(*value)), } } @@ -731,7 +735,7 @@ macro_rules! define_queries { #[inline(always)] fn restore_val(value: ::Value) -> Self::UnerasedValue { - restore::>(value) + erase::restore_val::>(value) } } From d3bffef0391f299f9ff96628f88f4e9a40b8a07c Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 29 Jan 2026 15:25:15 +0200 Subject: [PATCH 224/978] bump to latest mdbook https://github.com/rust-lang/mdBook/blob/master/CHANGELOG.md --- src/doc/rustc-dev-guide/.github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/.github/workflows/ci.yml b/src/doc/rustc-dev-guide/.github/workflows/ci.yml index f2f2f7ed1485..bdb70f215f83 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/ci.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: if: github.repository == 'rust-lang/rustc-dev-guide' runs-on: ubuntu-latest env: - MDBOOK_VERSION: 0.5.1 + MDBOOK_VERSION: 0.5.2 MDBOOK_LINKCHECK2_VERSION: 0.11.0 MDBOOK_MERMAID_VERSION: 0.17.0 MDBOOK_OUTPUT__LINKCHECK__FOLLOW_WEB_LINKS: ${{ github.event_name != 'pull_request' }} From 989568a79fbe7c3ed8974107b503a1adc5cfdf30 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 15 Jan 2026 20:53:30 +0300 Subject: [PATCH 225/978] privacy: Fix privacy lints in RPITITs --- compiler/rustc_privacy/src/lib.rs | 40 ++-- tests/ui/privacy/private-in-public-warn.rs | 9 + .../ui/privacy/private-in-public-warn.stderr | 218 +++++++++++++----- tests/ui/privacy/pub-priv-dep/pub-priv1.rs | 3 + .../ui/privacy/pub-priv-dep/pub-priv1.stderr | 82 ++++--- 5 files changed, 239 insertions(+), 113 deletions(-) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 8656ec6e39ae..d4d0727dc479 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1,5 +1,6 @@ // tidy-alphabetical-start #![feature(associated_type_defaults)] +#![feature(default_field_values)] #![feature(try_blocks)] // tidy-alphabetical-end @@ -29,8 +30,8 @@ use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, use rustc_middle::query::Providers; use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{ - self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, - TypeVisitor, + self, AssocContainer, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, + TypeVisitable, TypeVisitor, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint; @@ -1353,9 +1354,9 @@ struct SearchInterfaceForPrivateItemsVisitor<'tcx> { /// The visitor checks that each component type is at least this visible. required_visibility: ty::Visibility, required_effective_vis: Option, - in_assoc_ty: bool, - in_primary_interface: bool, - skip_assoc_tys: bool, + hard_error: bool = false, + in_primary_interface: bool = true, + skip_assoc_tys: bool = false, } impl SearchInterfaceForPrivateItemsVisitor<'_> { @@ -1427,7 +1428,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { }; let vis = self.tcx.local_visibility(local_def_id); - if self.in_assoc_ty && !vis.is_at_least(self.required_visibility, self.tcx) { + if self.hard_error && !vis.is_at_least(self.required_visibility, self.tcx) { let vis_descr = match vis { ty::Visibility::Public => "public", ty::Visibility::Restricted(vis_def_id) => { @@ -1544,9 +1545,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { item_def_id: def_id, required_visibility, required_effective_vis, - in_assoc_ty: false, - in_primary_interface: true, - skip_assoc_tys: false, + .. } } @@ -1589,11 +1588,15 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { ty::AssocKind::Type { .. } => (item.defaultness(self.tcx).has_value(), true), }; - check.in_assoc_ty = is_assoc_ty; + check.hard_error = is_assoc_ty && !item.is_impl_trait_in_trait(); check.generics().predicates(); if check_ty { check.ty(); } + if is_assoc_ty && item.container == AssocContainer::Trait { + check.hard_error = false; + check.bounds(); + } } fn get(&self, def_id: LocalDefId) -> Option { @@ -1625,20 +1628,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { self.check(def_id, item_visibility, effective_vis).generics().predicates(); for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() { - if assoc_item.is_impl_trait_in_trait() { - continue; - } - self.check_assoc_item(assoc_item, item_visibility, effective_vis); - - if assoc_item.is_type() { - self.check( - assoc_item.def_id.expect_local(), - item_visibility, - effective_vis, - ) - .bounds(); - } } } DefKind::TraitAlias => { @@ -1712,10 +1702,6 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { } for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() { - if assoc_item.is_impl_trait_in_trait() { - continue; - } - let impl_item_vis = if !of_trait { min(tcx.local_visibility(assoc_item.def_id.expect_local()), impl_vis, tcx) } else { diff --git a/tests/ui/privacy/private-in-public-warn.rs b/tests/ui/privacy/private-in-public-warn.rs index f79e4641312e..9f2958e88298 100644 --- a/tests/ui/privacy/private-in-public-warn.rs +++ b/tests/ui/privacy/private-in-public-warn.rs @@ -49,7 +49,10 @@ mod traits { fn f(arg: T) {} //~^ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::f` fn g() -> impl PrivTr; + //~^ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::g::{anon_assoc#0}` fn h() -> impl PrivTr {} + //~^ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::h::{anon_assoc#0}` + //~| ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::h::{anon_assoc#0}` } impl Pub {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Pub` impl PubTr for Pub {} // OK, trait impl predicates @@ -89,7 +92,13 @@ mod generics { pub trait Tr5 { fn required() -> impl PrivTr>; + //~^ ERROR trait `generics::PrivTr>` is more private than the item `Tr5::required::{anon_assoc#0}` + //~| ERROR type `generics::Priv<()>` is more private than the item `Tr5::required::{anon_assoc#0}` fn provided() -> impl PrivTr> {} + //~^ ERROR trait `generics::PrivTr>` is more private than the item `Tr5::provided::{anon_assoc#0}` + //~| ERROR type `generics::Priv<()>` is more private than the item `Tr5::provided::{anon_assoc#0}` + //~| ERROR trait `generics::PrivTr>` is more private than the item `Tr5::provided::{anon_assoc#0}` + //~| ERROR type `generics::Priv<()>` is more private than the item `Tr5::provided::{anon_assoc#0}` } } diff --git a/tests/ui/privacy/private-in-public-warn.stderr b/tests/ui/privacy/private-in-public-warn.stderr index edcffaf6b70a..7ec023b9f89f 100644 --- a/tests/ui/privacy/private-in-public-warn.stderr +++ b/tests/ui/privacy/private-in-public-warn.stderr @@ -194,8 +194,44 @@ note: but trait `traits::PrivTr` is only usable at visibility `pub(self)` LL | trait PrivTr {} | ^^^^^^^^^^^^ +error: trait `traits::PrivTr` is more private than the item `traits::Tr3::g::{anon_assoc#0}` + --> $DIR/private-in-public-warn.rs:51:19 + | +LL | fn g() -> impl PrivTr; + | ^^^^^^^^^^^ opaque type `traits::Tr3::g::{anon_assoc#0}` is reachable at visibility `pub(crate)` + | +note: but trait `traits::PrivTr` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:37:5 + | +LL | trait PrivTr {} + | ^^^^^^^^^^^^ + +error: trait `traits::PrivTr` is more private than the item `traits::Tr3::h::{anon_assoc#0}` + --> $DIR/private-in-public-warn.rs:53:19 + | +LL | fn h() -> impl PrivTr {} + | ^^^^^^^^^^^ opaque type `traits::Tr3::h::{anon_assoc#0}` is reachable at visibility `pub(crate)` + | +note: but trait `traits::PrivTr` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:37:5 + | +LL | trait PrivTr {} + | ^^^^^^^^^^^^ + +error: trait `traits::PrivTr` is more private than the item `traits::Tr3::h::{anon_assoc#0}` + --> $DIR/private-in-public-warn.rs:53:19 + | +LL | fn h() -> impl PrivTr {} + | ^^^^^^^^^^^ opaque type `traits::Tr3::h::{anon_assoc#0}` is reachable at visibility `pub(crate)` + | +note: but trait `traits::PrivTr` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:37:5 + | +LL | trait PrivTr {} + | ^^^^^^^^^^^^ + error: trait `traits::PrivTr` is more private than the item `traits::Pub` - --> $DIR/private-in-public-warn.rs:54:5 + --> $DIR/private-in-public-warn.rs:57:5 | LL | impl Pub {} | ^^^^^^^^^^^^^^^^^^^^^^ implementation `traits::Pub` is reachable at visibility `pub(crate)` @@ -207,103 +243,175 @@ LL | trait PrivTr {} | ^^^^^^^^^^^^ error: trait `traits_where::PrivTr` is more private than the item `traits_where::Alias` - --> $DIR/private-in-public-warn.rs:63:5 + --> $DIR/private-in-public-warn.rs:66:5 | LL | pub type Alias where T: PrivTr = T; | ^^^^^^^^^^^^^^^^^ type alias `traits_where::Alias` is reachable at visibility `pub(crate)` | note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:59:5 + --> $DIR/private-in-public-warn.rs:62:5 | LL | trait PrivTr {} | ^^^^^^^^^^^^ error: trait `traits_where::PrivTr` is more private than the item `traits_where::Tr2` - --> $DIR/private-in-public-warn.rs:66:5 + --> $DIR/private-in-public-warn.rs:69:5 | LL | pub trait Tr2 where T: PrivTr {} | ^^^^^^^^^^^^^^^^ trait `traits_where::Tr2` is reachable at visibility `pub(crate)` | note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:59:5 + --> $DIR/private-in-public-warn.rs:62:5 | LL | trait PrivTr {} | ^^^^^^^^^^^^ error: trait `traits_where::PrivTr` is more private than the item `traits_where::Tr3::f` - --> $DIR/private-in-public-warn.rs:69:9 + --> $DIR/private-in-public-warn.rs:72:9 | LL | fn f(arg: T) where T: PrivTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated function `traits_where::Tr3::f` is reachable at visibility `pub(crate)` | note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:59:5 + --> $DIR/private-in-public-warn.rs:62:5 | LL | trait PrivTr {} | ^^^^^^^^^^^^ error: trait `traits_where::PrivTr` is more private than the item `traits_where::Pub` - --> $DIR/private-in-public-warn.rs:72:5 + --> $DIR/private-in-public-warn.rs:75:5 | LL | impl Pub where T: PrivTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation `traits_where::Pub` is reachable at visibility `pub(crate)` | note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:59:5 + --> $DIR/private-in-public-warn.rs:62:5 | LL | trait PrivTr {} | ^^^^^^^^^^^^ error: trait `generics::PrivTr` is more private than the item `generics::Tr1` - --> $DIR/private-in-public-warn.rs:84:5 + --> $DIR/private-in-public-warn.rs:87:5 | LL | pub trait Tr1: PrivTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `generics::Tr1` is reachable at visibility `pub(crate)` | note: but trait `generics::PrivTr` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:80:5 + --> $DIR/private-in-public-warn.rs:83:5 | LL | trait PrivTr {} | ^^^^^^^^^^^^^^^ error: type `generics::Priv` is more private than the item `generics::Tr2` - --> $DIR/private-in-public-warn.rs:86:5 + --> $DIR/private-in-public-warn.rs:89:5 | LL | pub trait Tr2: PubTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `generics::Tr2` is reachable at visibility `pub(crate)` | note: but type `generics::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:78:5 + --> $DIR/private-in-public-warn.rs:81:5 | LL | struct Priv(T); | ^^^^^^^^^^^^^^^^^^^ error: type `generics::Priv` is more private than the item `generics::Tr3` - --> $DIR/private-in-public-warn.rs:87:5 + --> $DIR/private-in-public-warn.rs:90:5 | LL | pub trait Tr3: PubTr<[Priv; 1]> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `generics::Tr3` is reachable at visibility `pub(crate)` | note: but type `generics::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:78:5 + --> $DIR/private-in-public-warn.rs:81:5 | LL | struct Priv(T); | ^^^^^^^^^^^^^^^^^^^ error: type `generics::Priv` is more private than the item `Tr4` - --> $DIR/private-in-public-warn.rs:88:5 + --> $DIR/private-in-public-warn.rs:91:5 | LL | pub trait Tr4: PubTr> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `Tr4` is reachable at visibility `pub(crate)` | note: but type `generics::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:78:5 + --> $DIR/private-in-public-warn.rs:81:5 + | +LL | struct Priv(T); + | ^^^^^^^^^^^^^^^^^^^ + +error: trait `generics::PrivTr>` is more private than the item `Tr5::required::{anon_assoc#0}` + --> $DIR/private-in-public-warn.rs:94:26 + | +LL | fn required() -> impl PrivTr>; + | ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::required::{anon_assoc#0}` is reachable at visibility `pub(crate)` + | +note: but trait `generics::PrivTr>` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:83:5 + | +LL | trait PrivTr {} + | ^^^^^^^^^^^^^^^ + +error: type `generics::Priv<()>` is more private than the item `Tr5::required::{anon_assoc#0}` + --> $DIR/private-in-public-warn.rs:94:26 + | +LL | fn required() -> impl PrivTr>; + | ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::required::{anon_assoc#0}` is reachable at visibility `pub(crate)` + | +note: but type `generics::Priv<()>` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:81:5 + | +LL | struct Priv(T); + | ^^^^^^^^^^^^^^^^^^^ + +error: trait `generics::PrivTr>` is more private than the item `Tr5::provided::{anon_assoc#0}` + --> $DIR/private-in-public-warn.rs:97:26 + | +LL | fn provided() -> impl PrivTr> {} + | ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::provided::{anon_assoc#0}` is reachable at visibility `pub(crate)` + | +note: but trait `generics::PrivTr>` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:83:5 + | +LL | trait PrivTr {} + | ^^^^^^^^^^^^^^^ + +error: type `generics::Priv<()>` is more private than the item `Tr5::provided::{anon_assoc#0}` + --> $DIR/private-in-public-warn.rs:97:26 + | +LL | fn provided() -> impl PrivTr> {} + | ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::provided::{anon_assoc#0}` is reachable at visibility `pub(crate)` + | +note: but type `generics::Priv<()>` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:81:5 + | +LL | struct Priv(T); + | ^^^^^^^^^^^^^^^^^^^ + +error: trait `generics::PrivTr>` is more private than the item `Tr5::provided::{anon_assoc#0}` + --> $DIR/private-in-public-warn.rs:97:26 + | +LL | fn provided() -> impl PrivTr> {} + | ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::provided::{anon_assoc#0}` is reachable at visibility `pub(crate)` + | +note: but trait `generics::PrivTr>` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:83:5 + | +LL | trait PrivTr {} + | ^^^^^^^^^^^^^^^ + +error: type `generics::Priv<()>` is more private than the item `Tr5::provided::{anon_assoc#0}` + --> $DIR/private-in-public-warn.rs:97:26 + | +LL | fn provided() -> impl PrivTr> {} + | ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::provided::{anon_assoc#0}` is reachable at visibility `pub(crate)` + | +note: but type `generics::Priv<()>` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:81:5 | LL | struct Priv(T); | ^^^^^^^^^^^^^^^^^^^ error[E0446]: private type `impls::Priv` in public interface - --> $DIR/private-in-public-warn.rs:119:9 + --> $DIR/private-in-public-warn.rs:128:9 | LL | struct Priv; | ----------- `impls::Priv` declared as private @@ -312,44 +420,17 @@ LL | type Alias = Priv; | ^^^^^^^^^^ can't leak private type error: type `aliases_pub::Priv` is more private than the item `aliases_pub::::f` - --> $DIR/private-in-public-warn.rs:190:9 + --> $DIR/private-in-public-warn.rs:199:9 | LL | pub fn f(arg: Priv) {} | ^^^^^^^^^^^^^^^^^^^ associated function `aliases_pub::::f` is reachable at visibility `pub(crate)` | note: but type `aliases_pub::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:163:5 + --> $DIR/private-in-public-warn.rs:172:5 | LL | struct Priv; | ^^^^^^^^^^^ -error[E0446]: private type `aliases_pub::Priv` in public interface - --> $DIR/private-in-public-warn.rs:193:9 - | -LL | struct Priv; - | ----------- `aliases_pub::Priv` declared as private -... -LL | type Check = Priv; - | ^^^^^^^^^^ can't leak private type - -error[E0446]: private type `aliases_pub::Priv` in public interface - --> $DIR/private-in-public-warn.rs:196:9 - | -LL | struct Priv; - | ----------- `aliases_pub::Priv` declared as private -... -LL | type Check = Priv; - | ^^^^^^^^^^ can't leak private type - -error[E0446]: private type `aliases_pub::Priv` in public interface - --> $DIR/private-in-public-warn.rs:199:9 - | -LL | struct Priv; - | ----------- `aliases_pub::Priv` declared as private -... -LL | type Check = Priv; - | ^^^^^^^^^^ can't leak private type - error[E0446]: private type `aliases_pub::Priv` in public interface --> $DIR/private-in-public-warn.rs:202:9 | @@ -359,38 +440,65 @@ LL | struct Priv; LL | type Check = Priv; | ^^^^^^^^^^ can't leak private type +error[E0446]: private type `aliases_pub::Priv` in public interface + --> $DIR/private-in-public-warn.rs:205:9 + | +LL | struct Priv; + | ----------- `aliases_pub::Priv` declared as private +... +LL | type Check = Priv; + | ^^^^^^^^^^ can't leak private type + +error[E0446]: private type `aliases_pub::Priv` in public interface + --> $DIR/private-in-public-warn.rs:208:9 + | +LL | struct Priv; + | ----------- `aliases_pub::Priv` declared as private +... +LL | type Check = Priv; + | ^^^^^^^^^^ can't leak private type + +error[E0446]: private type `aliases_pub::Priv` in public interface + --> $DIR/private-in-public-warn.rs:211:9 + | +LL | struct Priv; + | ----------- `aliases_pub::Priv` declared as private +... +LL | type Check = Priv; + | ^^^^^^^^^^ can't leak private type + error: trait `PrivTr1` is more private than the item `aliases_priv::Tr1` - --> $DIR/private-in-public-warn.rs:232:5 + --> $DIR/private-in-public-warn.rs:241:5 | LL | pub trait Tr1: PrivUseAliasTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `aliases_priv::Tr1` is reachable at visibility `pub(crate)` | note: but trait `PrivTr1` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:218:5 + --> $DIR/private-in-public-warn.rs:227:5 | LL | trait PrivTr1 { | ^^^^^^^^^^^^^^^^^^^^^ error: trait `PrivTr1` is more private than the item `aliases_priv::Tr2` - --> $DIR/private-in-public-warn.rs:234:5 + --> $DIR/private-in-public-warn.rs:243:5 | LL | pub trait Tr2: PrivUseAliasTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `aliases_priv::Tr2` is reachable at visibility `pub(crate)` | note: but trait `PrivTr1` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:218:5 + --> $DIR/private-in-public-warn.rs:227:5 | LL | trait PrivTr1 { | ^^^^^^^^^^^^^^^^^^^^^ error: type `Priv2` is more private than the item `aliases_priv::Tr2` - --> $DIR/private-in-public-warn.rs:234:5 + --> $DIR/private-in-public-warn.rs:243:5 | LL | pub trait Tr2: PrivUseAliasTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `aliases_priv::Tr2` is reachable at visibility `pub(crate)` | note: but type `Priv2` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:216:5 + --> $DIR/private-in-public-warn.rs:225:5 | LL | struct Priv2; | ^^^^^^^^^^^^ @@ -410,7 +518,7 @@ LL | pub type Alias = T; = note: `#[warn(type_alias_bounds)]` on by default warning: where clauses on type aliases are not enforced - --> $DIR/private-in-public-warn.rs:63:29 + --> $DIR/private-in-public-warn.rs:66:29 | LL | pub type Alias where T: PrivTr = T; | ------^^^^^^^^^ @@ -422,6 +530,6 @@ LL | pub type Alias where T: PrivTr = T; see issue #112792 for more information = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics -error: aborting due to 34 previous errors; 2 warnings emitted +error: aborting due to 43 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs index eae0f9756a10..9093b0808fdb 100644 --- a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs +++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs @@ -74,8 +74,11 @@ pub trait MyPubTrait { //~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface fn required_impl_trait() -> impl OtherTrait; + //~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface fn provided_impl_trait() -> impl OtherTrait { OtherType } + //~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface + //~| ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface fn required_concrete() -> OtherType; //~^ ERROR type `OtherType` from private dependency 'priv_dep' in public interface diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr index e66db53f65dd..61c948c2817a 100644 --- a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr +++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr @@ -11,55 +11,55 @@ LL | #![deny(exported_private_dependencies)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: macro `m` from private dependency 'priv_dep' is re-exported - --> $DIR/pub-priv1.rs:156:9 + --> $DIR/pub-priv1.rs:159:9 | LL | pub use priv_dep::m; | ^^^^^^^^^^^ error: macro `fn_like` from private dependency 'pm' is re-exported - --> $DIR/pub-priv1.rs:158:9 + --> $DIR/pub-priv1.rs:161:9 | LL | pub use pm::fn_like; | ^^^^^^^^^^^ error: derive macro `PmDerive` from private dependency 'pm' is re-exported - --> $DIR/pub-priv1.rs:160:9 + --> $DIR/pub-priv1.rs:163:9 | LL | pub use pm::PmDerive; | ^^^^^^^^^^^^ error: attribute macro `pm_attr` from private dependency 'pm' is re-exported - --> $DIR/pub-priv1.rs:162:9 + --> $DIR/pub-priv1.rs:165:9 | LL | pub use pm::pm_attr; | ^^^^^^^^^^^ error: variant `V1` from private dependency 'priv_dep' is re-exported - --> $DIR/pub-priv1.rs:165:9 + --> $DIR/pub-priv1.rs:168:9 | LL | pub use priv_dep::E::V1; | ^^^^^^^^^^^^^^^ error: type alias `Unit` from private dependency 'priv_dep' is re-exported - --> $DIR/pub-priv1.rs:168:9 + --> $DIR/pub-priv1.rs:171:9 | LL | pub use priv_dep::Unit; | ^^^^^^^^^^^^^^ error: type alias `PubPub` from private dependency 'priv_dep' is re-exported - --> $DIR/pub-priv1.rs:170:9 + --> $DIR/pub-priv1.rs:173:9 | LL | pub use priv_dep::PubPub; | ^^^^^^^^^^^^^^^^ error: type alias `PubPriv` from private dependency 'priv_dep' is re-exported - --> $DIR/pub-priv1.rs:172:9 + --> $DIR/pub-priv1.rs:175:9 | LL | pub use priv_dep::PubPriv; | ^^^^^^^^^^^^^^^^^ error: struct `Renamed` from private dependency 'priv_dep' is re-exported - --> $DIR/pub-priv1.rs:174:9 + --> $DIR/pub-priv1.rs:177:9 | LL | pub use priv_dep::OtherType as Renamed; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -124,92 +124,112 @@ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface LL | type Foo: OtherTrait; | ^^^^^^^^^^^^^^^^^^^^ +error: trait `OtherTrait` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:76:33 + | +LL | fn required_impl_trait() -> impl OtherTrait; + | ^^^^^^^^^^^^^^^ + +error: trait `OtherTrait` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:79:33 + | +LL | fn provided_impl_trait() -> impl OtherTrait { OtherType } + | ^^^^^^^^^^^^^^^ + +error: trait `OtherTrait` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:79:33 + | +LL | fn provided_impl_trait() -> impl OtherTrait { OtherType } + | ^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:80:5 + --> $DIR/pub-priv1.rs:83:5 | LL | fn required_concrete() -> OtherType; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:83:5 + --> $DIR/pub-priv1.rs:86:5 | LL | fn provided_concrete() -> OtherType { OtherType } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:87:1 + --> $DIR/pub-priv1.rs:90:1 | LL | pub trait WithSuperTrait: OtherTrait {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:96:5 + --> $DIR/pub-priv1.rs:99:5 | LL | type X = OtherType; | ^^^^^^ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:100:1 + --> $DIR/pub-priv1.rs:103:1 | LL | pub fn in_bounds(x: T) { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:103:1 + --> $DIR/pub-priv1.rs:106:1 | LL | pub fn private_return_impl_trait() -> impl OtherTrait { OtherType } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:106:1 + --> $DIR/pub-priv1.rs:109:1 | LL | pub fn private_return() -> OtherType { OtherType } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:109:1 + --> $DIR/pub-priv1.rs:112:1 | LL | pub fn private_in_generic() -> std::num::Saturating { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:112:1 + --> $DIR/pub-priv1.rs:115:1 | LL | pub static STATIC: OtherType = OtherType; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:115:1 + --> $DIR/pub-priv1.rs:118:1 | LL | pub const CONST: OtherType = OtherType; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:118:1 + --> $DIR/pub-priv1.rs:121:1 | LL | pub type Alias = OtherType; | ^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:121:1 + --> $DIR/pub-priv1.rs:124:1 | LL | pub type AliasOfAlias = priv_dep::PubPub; | ^^^^^^^^^^^^^^^^^^^^^ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:126:1 + --> $DIR/pub-priv1.rs:129:1 | LL | impl OtherTrait for PublicWithPrivateImpl {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:131:1 + --> $DIR/pub-priv1.rs:134:1 | LL | impl PubTraitOnPrivate for OtherType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:131:1 + --> $DIR/pub-priv1.rs:134:1 | LL | impl PubTraitOnPrivate for OtherType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,25 +237,25 @@ LL | impl PubTraitOnPrivate for OtherType {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:137:1 + --> $DIR/pub-priv1.rs:140:1 | LL | impl From for PublicWithStdImpl { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:139:5 + --> $DIR/pub-priv1.rs:142:5 | LL | fn from(val: OtherType) -> Self { Self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:143:1 + --> $DIR/pub-priv1.rs:146:1 | LL | impl From for OtherType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:143:1 + --> $DIR/pub-priv1.rs:146:1 | LL | impl From for OtherType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -243,18 +263,18 @@ LL | impl From for OtherType { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:146:5 + --> $DIR/pub-priv1.rs:149:5 | LL | fn from(val: PublicWithStdImpl) -> Self { Self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:146:5 + --> $DIR/pub-priv1.rs:149:5 | LL | fn from(val: PublicWithStdImpl) -> Self { Self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 41 previous errors +error: aborting due to 44 previous errors From 1ce89c04490746ba07f55413d7f511675e638bab Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 16 Jan 2026 20:51:41 +0300 Subject: [PATCH 226/978] privacy: Close one more hole in associated type visiting --- compiler/rustc_privacy/src/lib.rs | 26 ++-- tests/ui/privacy/private-in-public-warn.rs | 3 + .../ui/privacy/private-in-public-warn.stderr | 138 +++++++++++------- tests/ui/privacy/pub-priv-dep/pub-priv1.rs | 1 + .../ui/privacy/pub-priv-dep/pub-priv1.stderr | 74 +++++----- 5 files changed, 148 insertions(+), 94 deletions(-) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index d4d0727dc479..a8046e705732 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -312,6 +312,18 @@ where } } +fn assoc_has_type_of(tcx: TyCtxt<'_>, item: &ty::AssocItem) -> bool { + if let ty::AssocKind::Type { data: ty::AssocTypeData::Normal(..) } = item.kind + && let hir::Node::TraitItem(item) = + tcx.hir_node(tcx.local_def_id_to_hir_id(item.def_id.expect_local())) + && let hir::TraitItemKind::Type(_, None) = item.kind + { + false + } else { + true + } +} + fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility { if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 } } @@ -680,10 +692,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { let tcx = self.tcx; let mut reach = self.reach(def_id, item_ev); reach.generics().predicates(); - - if assoc_item.is_type() && !assoc_item.defaultness(tcx).has_value() { - // No type to visit. - } else { + if assoc_has_type_of(tcx, assoc_item) { reach.ty(); } } @@ -1583,14 +1592,11 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { ) { let mut check = self.check(item.def_id.expect_local(), vis, effective_vis); - let (check_ty, is_assoc_ty) = match item.kind { - ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => (true, false), - ty::AssocKind::Type { .. } => (item.defaultness(self.tcx).has_value(), true), - }; - + let is_assoc_ty = item.is_type(); check.hard_error = is_assoc_ty && !item.is_impl_trait_in_trait(); check.generics().predicates(); - if check_ty { + if assoc_has_type_of(self.tcx, item) { + check.hard_error = check.hard_error && item.defaultness(self.tcx).has_value(); check.ty(); } if is_assoc_ty && item.container == AssocContainer::Trait { diff --git a/tests/ui/privacy/private-in-public-warn.rs b/tests/ui/privacy/private-in-public-warn.rs index 9f2958e88298..6a0ac2b9ade7 100644 --- a/tests/ui/privacy/private-in-public-warn.rs +++ b/tests/ui/privacy/private-in-public-warn.rs @@ -50,6 +50,7 @@ mod traits { //~^ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::f` fn g() -> impl PrivTr; //~^ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::g::{anon_assoc#0}` + //~| ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::g::{anon_assoc#0}` fn h() -> impl PrivTr {} //~^ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::h::{anon_assoc#0}` //~| ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::h::{anon_assoc#0}` @@ -94,6 +95,8 @@ mod generics { fn required() -> impl PrivTr>; //~^ ERROR trait `generics::PrivTr>` is more private than the item `Tr5::required::{anon_assoc#0}` //~| ERROR type `generics::Priv<()>` is more private than the item `Tr5::required::{anon_assoc#0}` + //~| ERROR trait `generics::PrivTr>` is more private than the item `Tr5::required::{anon_assoc#0}` + //~| ERROR type `generics::Priv<()>` is more private than the item `Tr5::required::{anon_assoc#0}` fn provided() -> impl PrivTr> {} //~^ ERROR trait `generics::PrivTr>` is more private than the item `Tr5::provided::{anon_assoc#0}` //~| ERROR type `generics::Priv<()>` is more private than the item `Tr5::provided::{anon_assoc#0}` diff --git a/tests/ui/privacy/private-in-public-warn.stderr b/tests/ui/privacy/private-in-public-warn.stderr index 7ec023b9f89f..1fa415e27c16 100644 --- a/tests/ui/privacy/private-in-public-warn.stderr +++ b/tests/ui/privacy/private-in-public-warn.stderr @@ -206,8 +206,20 @@ note: but trait `traits::PrivTr` is only usable at visibility `pub(self)` LL | trait PrivTr {} | ^^^^^^^^^^^^ +error: trait `traits::PrivTr` is more private than the item `traits::Tr3::g::{anon_assoc#0}` + --> $DIR/private-in-public-warn.rs:51:19 + | +LL | fn g() -> impl PrivTr; + | ^^^^^^^^^^^ opaque type `traits::Tr3::g::{anon_assoc#0}` is reachable at visibility `pub(crate)` + | +note: but trait `traits::PrivTr` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:37:5 + | +LL | trait PrivTr {} + | ^^^^^^^^^^^^ + error: trait `traits::PrivTr` is more private than the item `traits::Tr3::h::{anon_assoc#0}` - --> $DIR/private-in-public-warn.rs:53:19 + --> $DIR/private-in-public-warn.rs:54:19 | LL | fn h() -> impl PrivTr {} | ^^^^^^^^^^^ opaque type `traits::Tr3::h::{anon_assoc#0}` is reachable at visibility `pub(crate)` @@ -219,7 +231,7 @@ LL | trait PrivTr {} | ^^^^^^^^^^^^ error: trait `traits::PrivTr` is more private than the item `traits::Tr3::h::{anon_assoc#0}` - --> $DIR/private-in-public-warn.rs:53:19 + --> $DIR/private-in-public-warn.rs:54:19 | LL | fn h() -> impl PrivTr {} | ^^^^^^^^^^^ opaque type `traits::Tr3::h::{anon_assoc#0}` is reachable at visibility `pub(crate)` @@ -231,7 +243,7 @@ LL | trait PrivTr {} | ^^^^^^^^^^^^ error: trait `traits::PrivTr` is more private than the item `traits::Pub` - --> $DIR/private-in-public-warn.rs:57:5 + --> $DIR/private-in-public-warn.rs:58:5 | LL | impl Pub {} | ^^^^^^^^^^^^^^^^^^^^^^ implementation `traits::Pub` is reachable at visibility `pub(crate)` @@ -243,175 +255,199 @@ LL | trait PrivTr {} | ^^^^^^^^^^^^ error: trait `traits_where::PrivTr` is more private than the item `traits_where::Alias` - --> $DIR/private-in-public-warn.rs:66:5 + --> $DIR/private-in-public-warn.rs:67:5 | LL | pub type Alias where T: PrivTr = T; | ^^^^^^^^^^^^^^^^^ type alias `traits_where::Alias` is reachable at visibility `pub(crate)` | note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:62:5 + --> $DIR/private-in-public-warn.rs:63:5 | LL | trait PrivTr {} | ^^^^^^^^^^^^ error: trait `traits_where::PrivTr` is more private than the item `traits_where::Tr2` - --> $DIR/private-in-public-warn.rs:69:5 + --> $DIR/private-in-public-warn.rs:70:5 | LL | pub trait Tr2 where T: PrivTr {} | ^^^^^^^^^^^^^^^^ trait `traits_where::Tr2` is reachable at visibility `pub(crate)` | note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:62:5 + --> $DIR/private-in-public-warn.rs:63:5 | LL | trait PrivTr {} | ^^^^^^^^^^^^ error: trait `traits_where::PrivTr` is more private than the item `traits_where::Tr3::f` - --> $DIR/private-in-public-warn.rs:72:9 + --> $DIR/private-in-public-warn.rs:73:9 | LL | fn f(arg: T) where T: PrivTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated function `traits_where::Tr3::f` is reachable at visibility `pub(crate)` | note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:62:5 + --> $DIR/private-in-public-warn.rs:63:5 | LL | trait PrivTr {} | ^^^^^^^^^^^^ error: trait `traits_where::PrivTr` is more private than the item `traits_where::Pub` - --> $DIR/private-in-public-warn.rs:75:5 + --> $DIR/private-in-public-warn.rs:76:5 | LL | impl Pub where T: PrivTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation `traits_where::Pub` is reachable at visibility `pub(crate)` | note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:62:5 + --> $DIR/private-in-public-warn.rs:63:5 | LL | trait PrivTr {} | ^^^^^^^^^^^^ error: trait `generics::PrivTr` is more private than the item `generics::Tr1` - --> $DIR/private-in-public-warn.rs:87:5 + --> $DIR/private-in-public-warn.rs:88:5 | LL | pub trait Tr1: PrivTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `generics::Tr1` is reachable at visibility `pub(crate)` | note: but trait `generics::PrivTr` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:83:5 + --> $DIR/private-in-public-warn.rs:84:5 | LL | trait PrivTr {} | ^^^^^^^^^^^^^^^ error: type `generics::Priv` is more private than the item `generics::Tr2` - --> $DIR/private-in-public-warn.rs:89:5 + --> $DIR/private-in-public-warn.rs:90:5 | LL | pub trait Tr2: PubTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `generics::Tr2` is reachable at visibility `pub(crate)` | note: but type `generics::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:81:5 + --> $DIR/private-in-public-warn.rs:82:5 | LL | struct Priv(T); | ^^^^^^^^^^^^^^^^^^^ error: type `generics::Priv` is more private than the item `generics::Tr3` - --> $DIR/private-in-public-warn.rs:90:5 + --> $DIR/private-in-public-warn.rs:91:5 | LL | pub trait Tr3: PubTr<[Priv; 1]> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `generics::Tr3` is reachable at visibility `pub(crate)` | note: but type `generics::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:81:5 + --> $DIR/private-in-public-warn.rs:82:5 | LL | struct Priv(T); | ^^^^^^^^^^^^^^^^^^^ error: type `generics::Priv` is more private than the item `Tr4` - --> $DIR/private-in-public-warn.rs:91:5 + --> $DIR/private-in-public-warn.rs:92:5 | LL | pub trait Tr4: PubTr> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `Tr4` is reachable at visibility `pub(crate)` | note: but type `generics::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:81:5 + --> $DIR/private-in-public-warn.rs:82:5 | LL | struct Priv(T); | ^^^^^^^^^^^^^^^^^^^ error: trait `generics::PrivTr>` is more private than the item `Tr5::required::{anon_assoc#0}` - --> $DIR/private-in-public-warn.rs:94:26 + --> $DIR/private-in-public-warn.rs:95:26 | LL | fn required() -> impl PrivTr>; | ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::required::{anon_assoc#0}` is reachable at visibility `pub(crate)` | note: but trait `generics::PrivTr>` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:83:5 + --> $DIR/private-in-public-warn.rs:84:5 | LL | trait PrivTr {} | ^^^^^^^^^^^^^^^ error: type `generics::Priv<()>` is more private than the item `Tr5::required::{anon_assoc#0}` - --> $DIR/private-in-public-warn.rs:94:26 + --> $DIR/private-in-public-warn.rs:95:26 | LL | fn required() -> impl PrivTr>; | ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::required::{anon_assoc#0}` is reachable at visibility `pub(crate)` | note: but type `generics::Priv<()>` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:81:5 + --> $DIR/private-in-public-warn.rs:82:5 + | +LL | struct Priv(T); + | ^^^^^^^^^^^^^^^^^^^ + +error: trait `generics::PrivTr>` is more private than the item `Tr5::required::{anon_assoc#0}` + --> $DIR/private-in-public-warn.rs:95:26 + | +LL | fn required() -> impl PrivTr>; + | ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::required::{anon_assoc#0}` is reachable at visibility `pub(crate)` + | +note: but trait `generics::PrivTr>` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:84:5 + | +LL | trait PrivTr {} + | ^^^^^^^^^^^^^^^ + +error: type `generics::Priv<()>` is more private than the item `Tr5::required::{anon_assoc#0}` + --> $DIR/private-in-public-warn.rs:95:26 + | +LL | fn required() -> impl PrivTr>; + | ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::required::{anon_assoc#0}` is reachable at visibility `pub(crate)` + | +note: but type `generics::Priv<()>` is only usable at visibility `pub(self)` + --> $DIR/private-in-public-warn.rs:82:5 | LL | struct Priv(T); | ^^^^^^^^^^^^^^^^^^^ error: trait `generics::PrivTr>` is more private than the item `Tr5::provided::{anon_assoc#0}` - --> $DIR/private-in-public-warn.rs:97:26 + --> $DIR/private-in-public-warn.rs:100:26 | LL | fn provided() -> impl PrivTr> {} | ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::provided::{anon_assoc#0}` is reachable at visibility `pub(crate)` | note: but trait `generics::PrivTr>` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:83:5 + --> $DIR/private-in-public-warn.rs:84:5 | LL | trait PrivTr {} | ^^^^^^^^^^^^^^^ error: type `generics::Priv<()>` is more private than the item `Tr5::provided::{anon_assoc#0}` - --> $DIR/private-in-public-warn.rs:97:26 + --> $DIR/private-in-public-warn.rs:100:26 | LL | fn provided() -> impl PrivTr> {} | ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::provided::{anon_assoc#0}` is reachable at visibility `pub(crate)` | note: but type `generics::Priv<()>` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:81:5 + --> $DIR/private-in-public-warn.rs:82:5 | LL | struct Priv(T); | ^^^^^^^^^^^^^^^^^^^ error: trait `generics::PrivTr>` is more private than the item `Tr5::provided::{anon_assoc#0}` - --> $DIR/private-in-public-warn.rs:97:26 + --> $DIR/private-in-public-warn.rs:100:26 | LL | fn provided() -> impl PrivTr> {} | ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::provided::{anon_assoc#0}` is reachable at visibility `pub(crate)` | note: but trait `generics::PrivTr>` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:83:5 + --> $DIR/private-in-public-warn.rs:84:5 | LL | trait PrivTr {} | ^^^^^^^^^^^^^^^ error: type `generics::Priv<()>` is more private than the item `Tr5::provided::{anon_assoc#0}` - --> $DIR/private-in-public-warn.rs:97:26 + --> $DIR/private-in-public-warn.rs:100:26 | LL | fn provided() -> impl PrivTr> {} | ^^^^^^^^^^^^^^^^^^^^^ opaque type `Tr5::provided::{anon_assoc#0}` is reachable at visibility `pub(crate)` | note: but type `generics::Priv<()>` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:81:5 + --> $DIR/private-in-public-warn.rs:82:5 | LL | struct Priv(T); | ^^^^^^^^^^^^^^^^^^^ error[E0446]: private type `impls::Priv` in public interface - --> $DIR/private-in-public-warn.rs:128:9 + --> $DIR/private-in-public-warn.rs:131:9 | LL | struct Priv; | ----------- `impls::Priv` declared as private @@ -420,26 +456,17 @@ LL | type Alias = Priv; | ^^^^^^^^^^ can't leak private type error: type `aliases_pub::Priv` is more private than the item `aliases_pub::::f` - --> $DIR/private-in-public-warn.rs:199:9 + --> $DIR/private-in-public-warn.rs:202:9 | LL | pub fn f(arg: Priv) {} | ^^^^^^^^^^^^^^^^^^^ associated function `aliases_pub::::f` is reachable at visibility `pub(crate)` | note: but type `aliases_pub::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:172:5 + --> $DIR/private-in-public-warn.rs:175:5 | LL | struct Priv; | ^^^^^^^^^^^ -error[E0446]: private type `aliases_pub::Priv` in public interface - --> $DIR/private-in-public-warn.rs:202:9 - | -LL | struct Priv; - | ----------- `aliases_pub::Priv` declared as private -... -LL | type Check = Priv; - | ^^^^^^^^^^ can't leak private type - error[E0446]: private type `aliases_pub::Priv` in public interface --> $DIR/private-in-public-warn.rs:205:9 | @@ -467,38 +494,47 @@ LL | struct Priv; LL | type Check = Priv; | ^^^^^^^^^^ can't leak private type +error[E0446]: private type `aliases_pub::Priv` in public interface + --> $DIR/private-in-public-warn.rs:214:9 + | +LL | struct Priv; + | ----------- `aliases_pub::Priv` declared as private +... +LL | type Check = Priv; + | ^^^^^^^^^^ can't leak private type + error: trait `PrivTr1` is more private than the item `aliases_priv::Tr1` - --> $DIR/private-in-public-warn.rs:241:5 + --> $DIR/private-in-public-warn.rs:244:5 | LL | pub trait Tr1: PrivUseAliasTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `aliases_priv::Tr1` is reachable at visibility `pub(crate)` | note: but trait `PrivTr1` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:227:5 + --> $DIR/private-in-public-warn.rs:230:5 | LL | trait PrivTr1 { | ^^^^^^^^^^^^^^^^^^^^^ error: trait `PrivTr1` is more private than the item `aliases_priv::Tr2` - --> $DIR/private-in-public-warn.rs:243:5 + --> $DIR/private-in-public-warn.rs:246:5 | LL | pub trait Tr2: PrivUseAliasTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `aliases_priv::Tr2` is reachable at visibility `pub(crate)` | note: but trait `PrivTr1` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:227:5 + --> $DIR/private-in-public-warn.rs:230:5 | LL | trait PrivTr1 { | ^^^^^^^^^^^^^^^^^^^^^ error: type `Priv2` is more private than the item `aliases_priv::Tr2` - --> $DIR/private-in-public-warn.rs:243:5 + --> $DIR/private-in-public-warn.rs:246:5 | LL | pub trait Tr2: PrivUseAliasTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `aliases_priv::Tr2` is reachable at visibility `pub(crate)` | note: but type `Priv2` is only usable at visibility `pub(self)` - --> $DIR/private-in-public-warn.rs:225:5 + --> $DIR/private-in-public-warn.rs:228:5 | LL | struct Priv2; | ^^^^^^^^^^^^ @@ -518,7 +554,7 @@ LL | pub type Alias = T; = note: `#[warn(type_alias_bounds)]` on by default warning: where clauses on type aliases are not enforced - --> $DIR/private-in-public-warn.rs:66:29 + --> $DIR/private-in-public-warn.rs:67:29 | LL | pub type Alias where T: PrivTr = T; | ------^^^^^^^^^ @@ -530,6 +566,6 @@ LL | pub type Alias where T: PrivTr = T; see issue #112792 for more information = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics -error: aborting due to 43 previous errors; 2 warnings emitted +error: aborting due to 46 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs index 9093b0808fdb..ae86be19cf96 100644 --- a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs +++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs @@ -75,6 +75,7 @@ pub trait MyPubTrait { fn required_impl_trait() -> impl OtherTrait; //~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface + //~| ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface fn provided_impl_trait() -> impl OtherTrait { OtherType } //~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr index 61c948c2817a..609dbd77f9c1 100644 --- a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr +++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr @@ -11,55 +11,55 @@ LL | #![deny(exported_private_dependencies)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: macro `m` from private dependency 'priv_dep' is re-exported - --> $DIR/pub-priv1.rs:159:9 + --> $DIR/pub-priv1.rs:160:9 | LL | pub use priv_dep::m; | ^^^^^^^^^^^ error: macro `fn_like` from private dependency 'pm' is re-exported - --> $DIR/pub-priv1.rs:161:9 + --> $DIR/pub-priv1.rs:162:9 | LL | pub use pm::fn_like; | ^^^^^^^^^^^ error: derive macro `PmDerive` from private dependency 'pm' is re-exported - --> $DIR/pub-priv1.rs:163:9 + --> $DIR/pub-priv1.rs:164:9 | LL | pub use pm::PmDerive; | ^^^^^^^^^^^^ error: attribute macro `pm_attr` from private dependency 'pm' is re-exported - --> $DIR/pub-priv1.rs:165:9 + --> $DIR/pub-priv1.rs:166:9 | LL | pub use pm::pm_attr; | ^^^^^^^^^^^ error: variant `V1` from private dependency 'priv_dep' is re-exported - --> $DIR/pub-priv1.rs:168:9 + --> $DIR/pub-priv1.rs:169:9 | LL | pub use priv_dep::E::V1; | ^^^^^^^^^^^^^^^ error: type alias `Unit` from private dependency 'priv_dep' is re-exported - --> $DIR/pub-priv1.rs:171:9 + --> $DIR/pub-priv1.rs:172:9 | LL | pub use priv_dep::Unit; | ^^^^^^^^^^^^^^ error: type alias `PubPub` from private dependency 'priv_dep' is re-exported - --> $DIR/pub-priv1.rs:173:9 + --> $DIR/pub-priv1.rs:174:9 | LL | pub use priv_dep::PubPub; | ^^^^^^^^^^^^^^^^ error: type alias `PubPriv` from private dependency 'priv_dep' is re-exported - --> $DIR/pub-priv1.rs:175:9 + --> $DIR/pub-priv1.rs:176:9 | LL | pub use priv_dep::PubPriv; | ^^^^^^^^^^^^^^^^^ error: struct `Renamed` from private dependency 'priv_dep' is re-exported - --> $DIR/pub-priv1.rs:177:9 + --> $DIR/pub-priv1.rs:178:9 | LL | pub use priv_dep::OtherType as Renamed; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -131,13 +131,21 @@ LL | fn required_impl_trait() -> impl OtherTrait; | ^^^^^^^^^^^^^^^ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:79:33 + --> $DIR/pub-priv1.rs:76:33 + | +LL | fn required_impl_trait() -> impl OtherTrait; + | ^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: trait `OtherTrait` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:80:33 | LL | fn provided_impl_trait() -> impl OtherTrait { OtherType } | ^^^^^^^^^^^^^^^ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:79:33 + --> $DIR/pub-priv1.rs:80:33 | LL | fn provided_impl_trait() -> impl OtherTrait { OtherType } | ^^^^^^^^^^^^^^^ @@ -145,91 +153,91 @@ LL | fn provided_impl_trait() -> impl OtherTrait { OtherType } = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:83:5 + --> $DIR/pub-priv1.rs:84:5 | LL | fn required_concrete() -> OtherType; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:86:5 + --> $DIR/pub-priv1.rs:87:5 | LL | fn provided_concrete() -> OtherType { OtherType } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:90:1 + --> $DIR/pub-priv1.rs:91:1 | LL | pub trait WithSuperTrait: OtherTrait {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:99:5 + --> $DIR/pub-priv1.rs:100:5 | LL | type X = OtherType; | ^^^^^^ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:103:1 + --> $DIR/pub-priv1.rs:104:1 | LL | pub fn in_bounds(x: T) { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:106:1 + --> $DIR/pub-priv1.rs:107:1 | LL | pub fn private_return_impl_trait() -> impl OtherTrait { OtherType } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:109:1 + --> $DIR/pub-priv1.rs:110:1 | LL | pub fn private_return() -> OtherType { OtherType } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:112:1 + --> $DIR/pub-priv1.rs:113:1 | LL | pub fn private_in_generic() -> std::num::Saturating { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:115:1 + --> $DIR/pub-priv1.rs:116:1 | LL | pub static STATIC: OtherType = OtherType; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:118:1 + --> $DIR/pub-priv1.rs:119:1 | LL | pub const CONST: OtherType = OtherType; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:121:1 + --> $DIR/pub-priv1.rs:122:1 | LL | pub type Alias = OtherType; | ^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:124:1 + --> $DIR/pub-priv1.rs:125:1 | LL | pub type AliasOfAlias = priv_dep::PubPub; | ^^^^^^^^^^^^^^^^^^^^^ error: trait `OtherTrait` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:129:1 + --> $DIR/pub-priv1.rs:130:1 | LL | impl OtherTrait for PublicWithPrivateImpl {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:134:1 + --> $DIR/pub-priv1.rs:135:1 | LL | impl PubTraitOnPrivate for OtherType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:134:1 + --> $DIR/pub-priv1.rs:135:1 | LL | impl PubTraitOnPrivate for OtherType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -237,25 +245,25 @@ LL | impl PubTraitOnPrivate for OtherType {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:140:1 + --> $DIR/pub-priv1.rs:141:1 | LL | impl From for PublicWithStdImpl { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:142:5 + --> $DIR/pub-priv1.rs:143:5 | LL | fn from(val: OtherType) -> Self { Self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:146:1 + --> $DIR/pub-priv1.rs:147:1 | LL | impl From for OtherType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:146:1 + --> $DIR/pub-priv1.rs:147:1 | LL | impl From for OtherType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -263,18 +271,18 @@ LL | impl From for OtherType { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:149:5 + --> $DIR/pub-priv1.rs:150:5 | LL | fn from(val: PublicWithStdImpl) -> Self { Self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:149:5 + --> $DIR/pub-priv1.rs:150:5 | LL | fn from(val: PublicWithStdImpl) -> Self { Self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 44 previous errors +error: aborting due to 45 previous errors From 88f2e79b77879ea87a28c28b0f5a111721c4b27a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 18 Jan 2026 14:32:52 +0300 Subject: [PATCH 227/978] Add test case from issue 151284 --- .../missing-mir-priv-bounds-extern.rs | 40 +++++++++++++++++++ tests/ui/privacy/missing-mir-priv-bounds.rs | 26 ++++++++++++ .../ui/privacy/missing-mir-priv-bounds.stderr | 10 +++++ 3 files changed, 76 insertions(+) create mode 100644 tests/ui/privacy/auxiliary/missing-mir-priv-bounds-extern.rs create mode 100644 tests/ui/privacy/missing-mir-priv-bounds.rs create mode 100644 tests/ui/privacy/missing-mir-priv-bounds.stderr diff --git a/tests/ui/privacy/auxiliary/missing-mir-priv-bounds-extern.rs b/tests/ui/privacy/auxiliary/missing-mir-priv-bounds-extern.rs new file mode 100644 index 000000000000..4cb7bfcc6a3f --- /dev/null +++ b/tests/ui/privacy/auxiliary/missing-mir-priv-bounds-extern.rs @@ -0,0 +1,40 @@ +pub trait ToPriv { + type AssocPriv; +} + +pub trait PubTr { + #[expect(private_bounds)] + type Assoc: ToPriv; +} + +struct Dummy; +struct DummyToPriv; +impl PubTr for Dummy { + type Assoc = DummyToPriv; +} +impl ToPriv for DummyToPriv { + type AssocPriv = Priv; +} + +pub fn get_dummy() -> impl PubTr { + Dummy +} + +struct Priv; + +pub trait GetUnreachable { + type Assoc; +} + +mod m { + pub struct Unreachable; + + impl Unreachable { + #[expect(dead_code)] + pub fn generic() {} + } + + impl crate::GetUnreachable for crate::Priv { + type Assoc = Unreachable; + } +} diff --git a/tests/ui/privacy/missing-mir-priv-bounds.rs b/tests/ui/privacy/missing-mir-priv-bounds.rs new file mode 100644 index 000000000000..07783a2ef858 --- /dev/null +++ b/tests/ui/privacy/missing-mir-priv-bounds.rs @@ -0,0 +1,26 @@ +// Test case from issue #151284. +// A private associated type bound allows to leak another private type and result in missing MIR. + +//@ build-fail +//@ aux-crate:dep=missing-mir-priv-bounds-extern.rs + +extern crate dep; +use dep::{GetUnreachable, PubTr, ToPriv, get_dummy}; + +fn main() { + wut(get_dummy()); +} + +fn wut(_: T) { + ::AccessAssoc::generic::(); +} + +trait Access: PubTr { + type AccessAssoc; +} + +impl Access for T { + type AccessAssoc = <::AssocPriv as GetUnreachable>::Assoc; +} + +//~? ERROR missing optimized MIR diff --git a/tests/ui/privacy/missing-mir-priv-bounds.stderr b/tests/ui/privacy/missing-mir-priv-bounds.stderr new file mode 100644 index 000000000000..68eca33332cb --- /dev/null +++ b/tests/ui/privacy/missing-mir-priv-bounds.stderr @@ -0,0 +1,10 @@ +error: missing optimized MIR for `dep::m::Unreachable::generic::` in the crate `missing_mir_priv_bounds_extern` + | +note: missing optimized MIR for this item (was the crate `missing_mir_priv_bounds_extern` compiled with `--emit=metadata`?) + --> $DIR/auxiliary/missing-mir-priv-bounds-extern.rs:34:9 + | +LL | pub fn generic() {} + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From 7b5a4d865381345b9f273a08315075426e5511d5 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 18 Jan 2026 15:01:51 +0300 Subject: [PATCH 228/978] privacy: Synchronize PrivateItemsInPublicInterfacesChecker and EmbargoVisitor --- compiler/rustc_privacy/src/lib.rs | 53 +++++++++---------- .../duplicate-bound-err.stderr | 24 ++++----- .../ui/delegation/unsupported.current.stderr | 6 +-- tests/ui/delegation/unsupported.next.stderr | 2 +- .../ui/lint/lint-stability-deprecated.stderr | 20 +++---- tests/ui/lint/lint-stability.stderr | 18 +++---- 6 files changed, 59 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index a8046e705732..7c3312291198 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -652,6 +652,19 @@ impl<'tcx> EmbargoVisitor<'tcx> { } impl<'tcx> EmbargoVisitor<'tcx> { + fn check_assoc_item(&mut self, item: &ty::AssocItem, item_ev: EffectiveVisibility) { + let def_id = item.def_id.expect_local(); + let tcx = self.tcx; + let mut reach = self.reach(def_id, item_ev); + reach.generics().predicates(); + if assoc_has_type_of(tcx, item) { + reach.ty(); + } + if item.is_type() && item.container == AssocContainer::Trait { + reach.bounds(); + } + } + fn check_def_id(&mut self, owner_id: OwnerId) { // Update levels of nested things and mark all items // in interfaces of reachable items as reachable. @@ -682,19 +695,10 @@ impl<'tcx> EmbargoVisitor<'tcx> { self.reach(owner_id.def_id, item_ev).generics().predicates(); for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() { - if assoc_item.is_impl_trait_in_trait() { - continue; - } - let def_id = assoc_item.def_id.expect_local(); self.update(def_id, item_ev, Level::Reachable); - let tcx = self.tcx; - let mut reach = self.reach(def_id, item_ev); - reach.generics().predicates(); - if assoc_has_type_of(tcx, assoc_item) { - reach.ty(); - } + self.check_assoc_item(assoc_item, item_ev); } } } @@ -732,17 +736,13 @@ impl<'tcx> EmbargoVisitor<'tcx> { } for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() { - if assoc_item.is_impl_trait_in_trait() { - continue; - } - let def_id = assoc_item.def_id.expect_local(); let max_vis = if of_trait { None } else { Some(self.tcx.local_visibility(def_id)) }; self.update_eff_vis(def_id, item_ev, max_vis, Level::Direct); if let Some(impl_item_ev) = self.get(def_id) { - self.reach(def_id, impl_item_ev).generics().predicates().ty(); + self.check_assoc_item(assoc_item, impl_item_ev); } } } @@ -834,7 +834,12 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> { } fn predicates(&mut self) -> &mut Self { - self.visit_predicates(self.ev.tcx.predicates_of(self.item_def_id)); + self.visit_predicates(self.ev.tcx.explicit_predicates_of(self.item_def_id)); + self + } + + fn bounds(&mut self) -> &mut Self { + self.visit_clauses(self.ev.tcx.explicit_item_bounds(self.item_def_id).skip_binder()); self } @@ -1372,17 +1377,11 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { fn generics(&mut self) -> &mut Self { self.in_primary_interface = true; for param in &self.tcx.generics_of(self.item_def_id).own_params { - match param.kind { - GenericParamDefKind::Lifetime => {} - GenericParamDefKind::Type { has_default, .. } => { - if has_default { - let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity()); - } - } - // FIXME(generic_const_exprs): May want to look inside const here - GenericParamDefKind::Const { .. } => { - let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity()); - } + if let GenericParamDefKind::Const { .. } = param.kind { + let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity()); + } + if let Some(default) = param.default_value(self.tcx) { + let _ = self.visit(default.instantiate_identity()); } } self diff --git a/tests/ui/associated-type-bounds/duplicate-bound-err.stderr b/tests/ui/associated-type-bounds/duplicate-bound-err.stderr index 80db2cdb933f..695bb8ad6066 100644 --- a/tests/ui/associated-type-bounds/duplicate-bound-err.stderr +++ b/tests/ui/associated-type-bounds/duplicate-bound-err.stderr @@ -108,6 +108,18 @@ LL | fn foo() -> impl Iterator { LL | [2u32].into_iter() | ------------------ return type was inferred to be `std::array::IntoIter` here +error[E0271]: expected `impl Iterator` to be an iterator that yields `i32`, but it yields `u32` + --> $DIR/duplicate-bound-err.rs:111:17 + | +LL | fn foo() -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` + | +note: required by a bound in `Trait3::foo::{anon_assoc#0}` + --> $DIR/duplicate-bound-err.rs:107:31 + | +LL | fn foo() -> impl Iterator; + | ^^^^^^^^^^ required by this bound in `Trait3::foo::{anon_assoc#0}` + error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified --> $DIR/duplicate-bound-err.rs:87:42 | @@ -158,18 +170,6 @@ LL | type MustFail4 = dyn Trait2; | | | `ASSOC` bound here first -error[E0271]: expected `impl Iterator` to be an iterator that yields `i32`, but it yields `u32` - --> $DIR/duplicate-bound-err.rs:111:17 - | -LL | fn foo() -> impl Iterator { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` - | -note: required by a bound in `Trait3::foo::{anon_assoc#0}` - --> $DIR/duplicate-bound-err.rs:107:31 - | -LL | fn foo() -> impl Iterator; - | ^^^^^^^^^^ required by this bound in `Trait3::foo::{anon_assoc#0}` - error[E0271]: expected `Empty` to be an iterator that yields `i32`, but it yields `u32` --> $DIR/duplicate-bound-err.rs:119:16 | diff --git a/tests/ui/delegation/unsupported.current.stderr b/tests/ui/delegation/unsupported.current.stderr index 2bb0633621f2..9bc2eec068fe 100644 --- a/tests/ui/delegation/unsupported.current.stderr +++ b/tests/ui/delegation/unsupported.current.stderr @@ -29,11 +29,7 @@ note: ...which requires comparing an impl and trait method signature, inferring LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ = note: ...which again requires computing type of `opaque::::opaque_ret::{anon_assoc#0}`, completing the cycle -note: cycle used when checking assoc item `opaque::::opaque_ret` is compatible with trait definition - --> $DIR/unsupported.rs:33:24 - | -LL | reuse ToReuse::opaque_ret; - | ^^^^^^^^^^ + = note: cycle used when checking effective visibilities = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error[E0283]: type annotations needed diff --git a/tests/ui/delegation/unsupported.next.stderr b/tests/ui/delegation/unsupported.next.stderr index 1665d1f39d6d..08bc49513bad 100644 --- a/tests/ui/delegation/unsupported.next.stderr +++ b/tests/ui/delegation/unsupported.next.stderr @@ -25,7 +25,7 @@ note: ...which requires comparing an impl and trait method signature, inferring LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ = note: ...which again requires computing type of `opaque::::opaque_ret::{anon_assoc#0}`, completing the cycle - = note: cycle used when computing implied outlives bounds for `::opaque_ret::{anon_assoc#0}` (hack disabled = false) + = note: cycle used when checking effective visibilities = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error[E0283]: type annotations needed diff --git a/tests/ui/lint/lint-stability-deprecated.stderr b/tests/ui/lint/lint-stability-deprecated.stderr index bda4ee82d1fc..ce0bc36f6292 100644 --- a/tests/ui/lint/lint-stability-deprecated.stderr +++ b/tests/ui/lint/lint-stability-deprecated.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:97:48 +warning: use of deprecated function `lint_stability::deprecated`: text + --> $DIR/lint-stability-deprecated.rs:24:9 | -LL | struct S2(T::TypeDeprecated); - | ^^^^^^^^^^^^^^^^^ +LL | deprecated(); + | ^^^^^^^^^^ | note: the lint level is defined here --> $DIR/lint-stability-deprecated.rs:6:9 @@ -10,12 +10,6 @@ note: the lint level is defined here LL | #![warn(deprecated)] | ^^^^^^^^^^ -warning: use of deprecated function `lint_stability::deprecated`: text - --> $DIR/lint-stability-deprecated.rs:24:9 - | -LL | deprecated(); - | ^^^^^^^^^^ - warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text --> $DIR/lint-stability-deprecated.rs:29:16 | @@ -322,6 +316,12 @@ warning: use of deprecated function `this_crate::MethodTester::test_method_body: LL | fn_in_body(); | ^^^^^^^^^^ +warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text + --> $DIR/lint-stability-deprecated.rs:97:48 + | +LL | struct S2(T::TypeDeprecated); + | ^^^^^^^^^^^^^^^^^ + warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text --> $DIR/lint-stability-deprecated.rs:101:13 | diff --git a/tests/ui/lint/lint-stability.stderr b/tests/ui/lint/lint-stability.stderr index 249f3ccaa542..fd57908a77b5 100644 --- a/tests/ui/lint/lint-stability.stderr +++ b/tests/ui/lint/lint-stability.stderr @@ -1,12 +1,3 @@ -error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/lint-stability.rs:88:48 - | -LL | struct S1(T::TypeUnstable); - | ^^^^^^^^^^^^^^^ - | - = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:17:5 | @@ -376,6 +367,15 @@ LL | let _ = Unstable::StableVariant; = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0658]: use of unstable library feature `unstable_test_feature` + --> $DIR/lint-stability.rs:88:48 + | +LL | struct S1(T::TypeUnstable); + | ^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0658]: use of unstable library feature `unstable_test_feature` --> $DIR/lint-stability.rs:92:13 | From 7c9d14993643fff92b8cf1351422b76e468d6a27 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 29 Jan 2026 16:44:05 +0300 Subject: [PATCH 229/978] Add 2 more test cases from 151284 and 151479 --- .../missing-mir-priv-bounds-extern-2.rs | 46 +++++++++++++++++++ .../missing-mir-priv-bounds-extern-3.rs | 35 ++++++++++++++ tests/ui/privacy/missing-mir-priv-bounds-2.rs | 29 ++++++++++++ .../privacy/missing-mir-priv-bounds-2.stderr | 10 ++++ tests/ui/privacy/missing-mir-priv-bounds-3.rs | 30 ++++++++++++ .../privacy/missing-mir-priv-bounds-3.stderr | 10 ++++ 6 files changed, 160 insertions(+) create mode 100644 tests/ui/privacy/auxiliary/missing-mir-priv-bounds-extern-2.rs create mode 100644 tests/ui/privacy/auxiliary/missing-mir-priv-bounds-extern-3.rs create mode 100644 tests/ui/privacy/missing-mir-priv-bounds-2.rs create mode 100644 tests/ui/privacy/missing-mir-priv-bounds-2.stderr create mode 100644 tests/ui/privacy/missing-mir-priv-bounds-3.rs create mode 100644 tests/ui/privacy/missing-mir-priv-bounds-3.stderr diff --git a/tests/ui/privacy/auxiliary/missing-mir-priv-bounds-extern-2.rs b/tests/ui/privacy/auxiliary/missing-mir-priv-bounds-extern-2.rs new file mode 100644 index 000000000000..38e3cdded5f2 --- /dev/null +++ b/tests/ui/privacy/auxiliary/missing-mir-priv-bounds-extern-2.rs @@ -0,0 +1,46 @@ +// Doesn't involve `impl Trait` unlike missing-mir-priv-bounds-extern.rs + +pub trait ToPriv { + type AssocPriv; +} + +pub trait PubTr { + #[expect(private_bounds)] + type Assoc: ToPriv; +} + +// Dummy and DummyToPriv are only used in call_handler +struct Dummy; +struct DummyToPriv; +impl PubTr for Dummy { + type Assoc = DummyToPriv; +} +impl ToPriv for DummyToPriv { + type AssocPriv = Priv; +} + +pub trait PubTrHandler { + fn handle(); +} +pub fn call_handler() { + T::handle::(); +} + +struct Priv; + +pub trait GetUnreachable { + type Assoc; +} + +mod m { + pub struct Unreachable; + + impl Unreachable { + #[expect(dead_code)] + pub fn generic() {} + } + + impl crate::GetUnreachable for crate::Priv { + type Assoc = Unreachable; + } +} diff --git a/tests/ui/privacy/auxiliary/missing-mir-priv-bounds-extern-3.rs b/tests/ui/privacy/auxiliary/missing-mir-priv-bounds-extern-3.rs new file mode 100644 index 000000000000..807abe2c4ad8 --- /dev/null +++ b/tests/ui/privacy/auxiliary/missing-mir-priv-bounds-extern-3.rs @@ -0,0 +1,35 @@ +struct Priv; + +pub trait Super { + type AssocSuper: GetUnreachable; +} +#[expect(private_bounds)] +pub trait Sub: Super {} + +// This Dummy type is only used in call_handler +struct Dummy; +impl Super for Dummy { + type AssocSuper = Priv; +} +impl Sub for Dummy {} + +pub trait SubHandler { + fn handle(); +} +pub fn call_handler() { + ::handle::(); +} + +pub trait GetUnreachable { + type Assoc; +} +mod m { + pub struct Unreachable; + impl Unreachable { + #[expect(dead_code)] + pub fn generic() {} + } + impl crate::GetUnreachable for crate::Priv { + type Assoc = Unreachable; + } +} diff --git a/tests/ui/privacy/missing-mir-priv-bounds-2.rs b/tests/ui/privacy/missing-mir-priv-bounds-2.rs new file mode 100644 index 000000000000..7676fdb4af4b --- /dev/null +++ b/tests/ui/privacy/missing-mir-priv-bounds-2.rs @@ -0,0 +1,29 @@ +// Test case from issue #151284. +// A private associated type bound allows to leak another private type and result in missing MIR. + +//@ build-fail +//@ aux-crate:dep=missing-mir-priv-bounds-extern-2.rs + +extern crate dep; +use dep::{GetUnreachable, PubTr, PubTrHandler, ToPriv, call_handler}; + +fn main() { + call_handler::(); +} + +struct Handler; +impl PubTrHandler for Handler { + fn handle() { + ::AccessAssoc::generic::(); + } +} + +trait Access: PubTr { + type AccessAssoc; +} + +impl Access for T { + type AccessAssoc = <::AssocPriv as GetUnreachable>::Assoc; +} + +//~? ERROR missing optimized MIR diff --git a/tests/ui/privacy/missing-mir-priv-bounds-2.stderr b/tests/ui/privacy/missing-mir-priv-bounds-2.stderr new file mode 100644 index 000000000000..29a10eb1223b --- /dev/null +++ b/tests/ui/privacy/missing-mir-priv-bounds-2.stderr @@ -0,0 +1,10 @@ +error: missing optimized MIR for `dep::m::Unreachable::generic::` in the crate `missing_mir_priv_bounds_extern_2` + | +note: missing optimized MIR for this item (was the crate `missing_mir_priv_bounds_extern_2` compiled with `--emit=metadata`?) + --> $DIR/auxiliary/missing-mir-priv-bounds-extern-2.rs:40:9 + | +LL | pub fn generic() {} + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/privacy/missing-mir-priv-bounds-3.rs b/tests/ui/privacy/missing-mir-priv-bounds-3.rs new file mode 100644 index 000000000000..1d277265451e --- /dev/null +++ b/tests/ui/privacy/missing-mir-priv-bounds-3.rs @@ -0,0 +1,30 @@ +// Test case from issue #151479. +// A private associated type bound allows to leak another private type and result in missing MIR. + +//@ build-fail +//@ aux-crate:dep=missing-mir-priv-bounds-extern-3.rs + +extern crate dep; +use dep::{GetUnreachable, Sub, SubHandler, Super, call_handler}; + +fn main() { + call_handler::(); +} + +struct Handler; +impl SubHandler for Handler { + fn handle() { + ::AccessAssoc::generic::(); + } +} + +// Without this indirection, Handler::handle notices that +// it's mentioning dep::Priv. +trait Access: Super { + type AccessAssoc; +} +impl Access for T { + type AccessAssoc = <::AssocSuper as GetUnreachable>::Assoc; +} + +//~? ERROR missing optimized MIR diff --git a/tests/ui/privacy/missing-mir-priv-bounds-3.stderr b/tests/ui/privacy/missing-mir-priv-bounds-3.stderr new file mode 100644 index 000000000000..ef464de08cb9 --- /dev/null +++ b/tests/ui/privacy/missing-mir-priv-bounds-3.stderr @@ -0,0 +1,10 @@ +error: missing optimized MIR for `dep::m::Unreachable::generic::` in the crate `missing_mir_priv_bounds_extern_3` + | +note: missing optimized MIR for this item (was the crate `missing_mir_priv_bounds_extern_3` compiled with `--emit=metadata`?) + --> $DIR/auxiliary/missing-mir-priv-bounds-extern-3.rs:30:9 + | +LL | pub fn generic() {} + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From 02bd3e86c0ed79e6293d83082f60d78a3c56550a Mon Sep 17 00:00:00 2001 From: Jamie Hill-Daniel Date: Thu, 29 Jan 2026 14:52:09 +0000 Subject: [PATCH 230/978] Use `Rustc` prefix for `rustc` attrs in `AttributeKind` --- .../src/attributes/allow_unstable.rs | 2 +- .../src/attributes/codegen_attrs.rs | 4 +- .../src/attributes/confusables.rs | 2 +- .../src/attributes/dummy.rs | 2 +- .../src/attributes/link_attrs.rs | 2 +- .../src/attributes/lint_helpers.rs | 6 +- .../src/attributes/stability.rs | 6 +- .../src/attributes/traits.rs | 20 ++- .../src/attributes/transparency.rs | 2 +- .../rustc_codegen_ssa/src/codegen_attrs.rs | 6 +- .../rustc_const_eval/src/check_consts/mod.rs | 2 +- compiler/rustc_expand/src/base.rs | 7 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 2 +- .../rustc_hir/src/attrs/data_structures.rs | 149 +++++++++--------- .../rustc_hir/src/attrs/encode_cross_crate.rs | 42 ++--- .../rustc_hir_analysis/src/check/check.rs | 5 +- .../src/coherence/inherent_impls.rs | 4 +- compiler/rustc_hir_analysis/src/collect.rs | 25 +-- .../rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_lint/src/dangling.rs | 2 +- compiler/rustc_lint/src/pass_by_value.rs | 7 +- compiler/rustc_passes/src/check_attr.rs | 42 ++--- compiler/rustc_passes/src/lib_features.rs | 4 +- compiler/rustc_passes/src/stability.rs | 16 +- compiler/rustc_privacy/src/lib.rs | 2 +- 25 files changed, 187 insertions(+), 176 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index 7323db06a8f1..d825d770fa35 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -57,7 +57,7 @@ impl CombineAttributeParser for AllowConstFnUnstableParser { const PATH: &[Symbol] = &[sym::rustc_allow_const_fn_unstable]; type Item = Symbol; const CONVERT: ConvertFn = - |items, first_span| AttributeKind::AllowConstFnUnstable(items, first_span); + |items, first_span| AttributeKind::RustcAllowConstFnUnstable(items, first_span); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 063fa12d3896..485307622291 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -181,7 +181,7 @@ impl SingleAttributeParser for ObjcClassParser { cx.emit_err(NullOnObjcClass { span: nv.value_span }); return None; } - Some(AttributeKind::ObjcClass { classname, span: cx.attr_span }) + Some(AttributeKind::RustcObjcClass { classname, span: cx.attr_span }) } } @@ -213,7 +213,7 @@ impl SingleAttributeParser for ObjcSelectorParser { cx.emit_err(NullOnObjcSelector { span: nv.value_span }); return None; } - Some(AttributeKind::ObjcSelector { methname, span: cx.attr_span }) + Some(AttributeKind::RustcObjcSelector { methname, span: cx.attr_span }) } } diff --git a/compiler/rustc_attr_parsing/src/attributes/confusables.rs b/compiler/rustc_attr_parsing/src/attributes/confusables.rs index 0b7ac989346a..1897fed1e250 100644 --- a/compiler/rustc_attr_parsing/src/attributes/confusables.rs +++ b/compiler/rustc_attr_parsing/src/attributes/confusables.rs @@ -43,7 +43,7 @@ impl AttributeParser for ConfusablesParser { return None; } - Some(AttributeKind::Confusables { + Some(AttributeKind::RustcConfusables { symbols: self.confusables, first_span: self.first_span.unwrap(), }) diff --git a/compiler/rustc_attr_parsing/src/attributes/dummy.rs b/compiler/rustc_attr_parsing/src/attributes/dummy.rs index 0a7d95f31799..9f97af48afa0 100644 --- a/compiler/rustc_attr_parsing/src/attributes/dummy.rs +++ b/compiler/rustc_attr_parsing/src/attributes/dummy.rs @@ -16,6 +16,6 @@ impl SingleAttributeParser for DummyParser { const TEMPLATE: AttributeTemplate = template!(Word); // Anything, really fn convert(_: &mut AcceptContext<'_, '_, S>, _: &ArgParser) -> Option { - Some(AttributeKind::Dummy) + Some(AttributeKind::RustcDummy) } } diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index a636b449ca56..548f53a986b8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -529,7 +529,7 @@ impl NoArgsAttributeParser for StdInternalSymbolParser { Allow(Target::Static), Allow(Target::ForeignStatic), ]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::StdInternalSymbol; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcStdInternalSymbol; } pub(crate) struct LinkOrdinalParser; diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs index 8ca5f0f7228e..60e83a6083ed 100644 --- a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs +++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs @@ -11,7 +11,7 @@ impl NoArgsAttributeParser for AsPtrParser { Allow(Target::Method(MethodKind::Trait { body: true })), Allow(Target::Method(MethodKind::TraitImpl)), ]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::AsPtr; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcAsPtr; } pub(crate) struct PubTransparentParser; @@ -23,7 +23,7 @@ impl NoArgsAttributeParser for PubTransparentParser { Allow(Target::Enum), Allow(Target::Union), ]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::PubTransparent; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPubTransparent; } pub(crate) struct PassByValueParser; @@ -35,7 +35,7 @@ impl NoArgsAttributeParser for PassByValueParser { Allow(Target::Enum), Allow(Target::TyAlias), ]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::PassByValue; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPassByValue; } pub(crate) struct RustcShouldNotBeCalledOnConstItems; diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 8d27e2e276dd..1f01cadcb43e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -173,7 +173,7 @@ impl AttributeParser for BodyStabilityParser { fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option { let (stability, span) = self.stability?; - Some(AttributeKind::BodyStability { stability, span }) + Some(AttributeKind::RustcBodyStability { stability, span }) } } @@ -185,7 +185,7 @@ impl NoArgsAttributeParser for ConstStabilityIndirectParser { Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), ]); - const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ConstStabilityIndirect; + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcConstStabilityIndirect; } #[derive(Default)] @@ -258,7 +258,7 @@ impl AttributeParser for ConstStabilityParser { let (stability, span) = self.stability?; - Some(AttributeKind::ConstStability { stability, span }) + Some(AttributeKind::RustcConstStability { stability, span }) } } diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs index c0db5b4d442a..bfea02e789a0 100644 --- a/compiler/rustc_attr_parsing/src/attributes/traits.rs +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -50,7 +50,11 @@ impl SingleAttributeParser for SkipDuringMethodDispatchParser { cx.duplicate_key(arg.span(), key); } } - Some(AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: cx.attr_span }) + Some(AttributeKind::RustcSkipDuringMethodDispatch { + array, + boxed_slice, + span: cx.attr_span, + }) } } @@ -59,7 +63,7 @@ impl NoArgsAttributeParser for ParenSugarParser { const PATH: &[Symbol] = &[sym::rustc_paren_sugar]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::ParenSugar; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcParenSugar; } pub(crate) struct TypeConstParser; @@ -91,7 +95,7 @@ impl NoArgsAttributeParser for DenyExplicitImplParser { const PATH: &[Symbol] = &[sym::rustc_deny_explicit_impl]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::DenyExplicitImpl; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDenyExplicitImpl; } pub(crate) struct DynIncompatibleTraitParser; @@ -99,7 +103,7 @@ impl NoArgsAttributeParser for DynIncompatibleTraitParser { const PATH: &[Symbol] = &[sym::rustc_dyn_incompatible_trait]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::DynIncompatibleTrait; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDynIncompatibleTrait; } // Specialization @@ -109,7 +113,7 @@ impl NoArgsAttributeParser for SpecializationTraitParser { const PATH: &[Symbol] = &[sym::rustc_specialization_trait]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::SpecializationTrait; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcSpecializationTrait; } pub(crate) struct UnsafeSpecializationMarkerParser; @@ -117,7 +121,7 @@ impl NoArgsAttributeParser for UnsafeSpecializationMarkerParser { const PATH: &[Symbol] = &[sym::rustc_unsafe_specialization_marker]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::UnsafeSpecializationMarker; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcUnsafeSpecializationMarker; } // Coherence @@ -127,7 +131,7 @@ impl NoArgsAttributeParser for CoinductiveParser { const PATH: &[Symbol] = &[sym::rustc_coinductive]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::Coinductive; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcCoinductive; } pub(crate) struct AllowIncoherentImplParser; @@ -136,7 +140,7 @@ impl NoArgsAttributeParser for AllowIncoherentImplParser { const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Method(MethodKind::Inherent))]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::AllowIncoherentImpl; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcAllowIncoherentImpl; } pub(crate) struct FundamentalParser; diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs index 5b8b3cd151eb..7fa4487b7c69 100644 --- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs +++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs @@ -32,6 +32,6 @@ impl SingleAttributeParser for TransparencyParser { } None => None, } - .map(AttributeKind::MacroTransparency) + .map(AttributeKind::RustcMacroTransparency) } } diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 4cb390e7d569..9ecb7ab9fd45 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -189,7 +189,7 @@ fn process_builtin_attrs( }, AttributeKind::FfiConst(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST, AttributeKind::FfiPure(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE, - AttributeKind::StdInternalSymbol(_) => { + AttributeKind::RustcStdInternalSymbol(_) => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL } AttributeKind::Linkage(linkage, span) => { @@ -217,10 +217,10 @@ fn process_builtin_attrs( AttributeKind::Sanitize { span, .. } => { interesting_spans.sanitize = Some(*span); } - AttributeKind::ObjcClass { classname, .. } => { + AttributeKind::RustcObjcClass { classname, .. } => { codegen_fn_attrs.objc_class = Some(*classname); } - AttributeKind::ObjcSelector { methname, .. } => { + AttributeKind::RustcObjcSelector { methname, .. } => { codegen_fn_attrs.objc_selector = Some(*methname); } AttributeKind::EiiForeignItem => { diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs index e9824400ab7a..1adba200caaf 100644 --- a/compiler/rustc_const_eval/src/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/check_consts/mod.rs @@ -83,7 +83,7 @@ pub fn rustc_allow_const_fn_unstable( ) -> bool { let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id)); - find_attr!(attrs, AttributeKind::AllowConstFnUnstable(syms, _) if syms.contains(&feature_gate)) + find_attr!(attrs, AttributeKind::RustcAllowConstFnUnstable(syms, _) if syms.contains(&feature_gate)) } /// Returns `true` if the given `def_id` (trait or function) is "safe to expose on stable". diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 653f2071d898..6b3c7fe97932 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -963,13 +963,16 @@ impl SyntaxExtension { let stability = find_attr!(attrs, AttributeKind::Stability { stability, .. } => *stability); // FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem - if let Some(sp) = find_attr!(attrs, AttributeKind::ConstStability { span, .. } => *span) { + if let Some(sp) = + find_attr!(attrs, AttributeKind::RustcConstStability { span, .. } => *span) + { sess.dcx().emit_err(errors::MacroConstStability { span: sp, head_span: sess.source_map().guess_head_span(span), }); } - if let Some(sp) = find_attr!(attrs, AttributeKind::BodyStability{ span, .. } => *span) { + if let Some(sp) = find_attr!(attrs, AttributeKind::RustcBodyStability{ span, .. } => *span) + { sess.dcx().emit_err(errors::MacroBodyStability { span: sp, head_span: sess.source_map().guess_head_span(span), diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 8d2cc23f9763..7cd96211de50 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -819,7 +819,7 @@ pub fn compile_declarative_macro( } assert!(!kinds.is_empty()); - let transparency = find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x) + let transparency = find_attr!(attrs, AttributeKind::RustcMacroTransparency(x) => *x) .unwrap_or(Transparency::fallback(macro_rules)); if let Some(guar) = guar { diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 8a7dee15d4f4..ef9ee4b6fb2d 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -746,31 +746,15 @@ pub enum AttributeKind { // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity Align { align: Align, span: Span }, - /// Represents `#[rustc_allow_const_fn_unstable]`. - AllowConstFnUnstable(ThinVec, Span), - - /// Represents `#[rustc_allow_incoherent_impl]`. - AllowIncoherentImpl(Span), - /// Represents `#[allow_internal_unsafe]`. AllowInternalUnsafe(Span), /// Represents `#[allow_internal_unstable]`. AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span), - /// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint). - AsPtr(Span), - /// Represents `#[automatically_derived]` AutomaticallyDerived(Span), - /// Represents `#[rustc_default_body_unstable]`. - BodyStability { - stability: DefaultBodyStability, - /// Span of the `#[rustc_default_body_unstable(...)]` attribute - span: Span, - }, - /// Represents the trace attribute of `#[cfg_attr]` CfgAttrTrace, @@ -780,9 +764,6 @@ pub enum AttributeKind { /// Represents `#[cfi_encoding]` CfiEncoding { encoding: Symbol }, - /// Represents `#[rustc_coinductive]`. - Coinductive(Span), - /// Represents `#[cold]`. Cold(Span), @@ -792,26 +773,9 @@ pub enum AttributeKind { /// Represents `#[compiler_builtins]`. CompilerBuiltins, - /// Represents `#[rustc_confusables]`. - Confusables { - symbols: ThinVec, - // FIXME(jdonszelmann): remove when target validation code is moved - first_span: Span, - }, - /// Represents `#[const_continue]`. ConstContinue(Span), - /// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`. - ConstStability { - stability: PartialConstStability, - /// Span of the `#[rustc_const_stable(...)]` or `#[rustc_const_unstable(...)]` attribute - span: Span, - }, - - /// Represents `#[rustc_const_stable_indirect]`. - ConstStabilityIndirect, - /// Represents `#[coroutine]`. Coroutine(Span), @@ -830,9 +794,6 @@ pub enum AttributeKind { /// Represents `#[debugger_visualizer]`. DebuggerVisualizer(ThinVec), - /// Represents `#[rustc_deny_explicit_impl]`. - DenyExplicitImpl(Span), - /// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute). Deprecation { deprecation: Deprecation, span: Span }, @@ -848,12 +809,6 @@ pub enum AttributeKind { /// i.e. doc comments. DocComment { style: AttrStyle, kind: DocFragmentKind, span: Span, comment: Symbol }, - /// Represents `#[rustc_dummy]`. - Dummy, - - /// Represents `#[rustc_dyn_incompatible_trait]`. - DynIncompatibleTrait(Span), - /// Implementation detail of `#[eii]` EiiDeclaration(EiiDecl), @@ -920,9 +875,6 @@ pub enum AttributeKind { /// Represents [`#[macro_export]`](https://doc.rust-lang.org/reference/macros-by-example.html#r-macro.decl.scope.path). MacroExport { span: Span, local_inner_macros: bool }, - /// Represents `#[rustc_macro_transparency]`. - MacroTransparency(Transparency), - /// Represents `#[macro_use]`. MacroUse { span: Span, arguments: MacroUseArgs }, @@ -978,24 +930,12 @@ pub enum AttributeKind { /// Represents `#[non_exhaustive]` NonExhaustive(Span), - /// Represents `#[rustc_objc_class]` - ObjcClass { classname: Symbol, span: Span }, - - /// Represents `#[rustc_objc_selector]` - ObjcSelector { methname: Symbol, span: Span }, - /// Represents `#[optimize(size|speed)]` Optimize(OptimizeAttr, Span), /// Represents `#[panic_runtime]` PanicRuntime, - /// Represents `#[rustc_paren_sugar]`. - ParenSugar(Span), - - /// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint). - PassByValue(Span), - /// Represents `#[patchable_function_entry]` PatchableFunctionEntry { prefix: u8, entry: u8 }, @@ -1023,9 +963,6 @@ pub enum AttributeKind { /// Represents `#[profiler_runtime]` ProfilerRuntime, - /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint). - PubTransparent(Span), - /// Represents [`#[recursion_limit]`](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute) RecursionLimit { attr_span: Span, limit_span: Span, limit: Limit }, @@ -1041,15 +978,55 @@ pub enum AttributeKind { /// Represents `#[rustc_allocator_zeroed_variant]` RustcAllocatorZeroedVariant { name: Symbol }, + /// Represents `#[rustc_allow_const_fn_unstable]`. + RustcAllowConstFnUnstable(ThinVec, Span), + + /// Represents `#[rustc_allow_incoherent_impl]`. + RustcAllowIncoherentImpl(Span), + + /// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint). + RustcAsPtr(Span), + + /// Represents `#[rustc_default_body_unstable]`. + RustcBodyStability { + stability: DefaultBodyStability, + /// Span of the `#[rustc_default_body_unstable(...)]` attribute + span: Span, + }, /// Represents `#[rustc_builtin_macro]`. RustcBuiltinMacro { builtin_name: Option, helper_attrs: ThinVec, span: Span }, /// Represents `#[rustc_coherence_is_core]` RustcCoherenceIsCore(Span), + /// Represents `#[rustc_coinductive]`. + RustcCoinductive(Span), + + /// Represents `#[rustc_confusables]`. + RustcConfusables { + symbols: ThinVec, + // FIXME(jdonszelmann): remove when target validation code is moved + first_span: Span, + }, + /// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`. + RustcConstStability { + stability: PartialConstStability, + /// Span of the `#[rustc_const_stable(...)]` or `#[rustc_const_unstable(...)]` attribute + span: Span, + }, + + /// Represents `#[rustc_const_stable_indirect]`. + RustcConstStabilityIndirect, + /// Represents `#[rustc_deallocator]` RustcDeallocator, + /// Represents `#[rustc_deny_explicit_impl]`. + RustcDenyExplicitImpl(Span), + + /// Represents `#[rustc_dummy]`. + RustcDummy, + /// Represents `#[rustc_dump_def_parents]` RustcDumpDefParents, @@ -1065,6 +1042,9 @@ pub enum AttributeKind { /// Represents `#[rustc_dump_vtable]` RustcDumpVtable(Span), + /// Represents `#[rustc_dyn_incompatible_trait]`. + RustcDynIncompatibleTrait(Span), + /// Represents `#[rustc_has_incoherent_inherent_impls]` RustcHasIncoherentInherentImpls, @@ -1089,6 +1069,9 @@ pub enum AttributeKind { /// Represents `#[rustc_lint_untracked_query_information]` RustcLintUntrackedQueryInformation, + /// Represents `#[rustc_macro_transparency]`. + RustcMacroTransparency(Transparency), + /// Represents `#[rustc_main]`. RustcMain, @@ -1104,15 +1087,30 @@ pub enum AttributeKind { /// Represents `#[rustc_nounwind]` RustcNounwind, + /// Represents `#[rustc_objc_class]` + RustcObjcClass { classname: Symbol, span: Span }, + + /// Represents `#[rustc_objc_selector]` + RustcObjcSelector { methname: Symbol, span: Span }, + /// Represents `#[rustc_object_lifetime_default]`. RustcObjectLifetimeDefault, /// Represents `#[rustc_offload_kernel]` RustcOffloadKernel, + /// Represents `#[rustc_paren_sugar]`. + RustcParenSugar(Span), + + /// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint). + RustcPassByValue(Span), + /// Represents `#[rustc_pass_indirectly_in_non_rustic_abis]` RustcPassIndirectlyInNonRusticAbis(Span), + /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint). + RustcPubTransparent(Span), + /// Represents `#[rustc_reallocator]` RustcReallocator, @@ -1130,6 +1128,18 @@ pub enum AttributeKind { /// Represents `#[rustc_simd_monomorphize_lane_limit = "N"]`. RustcSimdMonomorphizeLaneLimit(Limit), + /// Represents `#[rustc_skip_during_method_dispatch]`. + RustcSkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span }, + + /// Represents `#[rustc_specialization_trait]`. + RustcSpecializationTrait(Span), + + /// Represents `#[rustc_std_internal_symbol]`. + RustcStdInternalSymbol(Span), + + /// Represents `#[rustc_unsafe_specialization_marker]`. + RustcUnsafeSpecializationMarker(Span), + /// Represents `#[rustc_variance]` RustcVariance, @@ -1151,22 +1161,12 @@ pub enum AttributeKind { /// Represents `#[should_panic]` ShouldPanic { reason: Option, span: Span }, - /// Represents `#[rustc_skip_during_method_dispatch]`. - SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span }, - - /// Represents `#[rustc_specialization_trait]`. - SpecializationTrait(Span), - /// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`. Stability { stability: Stability, /// Span of the attribute. span: Span, }, - - /// Represents `#[rustc_std_internal_symbol]`. - StdInternalSymbol(Span), - /// Represents `#[target_feature(enable = "...")]` and /// `#[unsafe(force_target_feature(enable = "...")]`. TargetFeature { features: ThinVec<(Symbol, Span)>, attr_span: Span, was_forced: bool }, @@ -1183,9 +1183,6 @@ pub enum AttributeKind { /// Represents `#[type_length_limit]` TypeLengthLimit { attr_span: Span, limit_span: Span, limit: Limit }, - /// Represents `#[rustc_unsafe_specialization_marker]`. - UnsafeSpecializationMarker(Span), - /// Represents `#[unstable_feature_bound]`. UnstableFeatureBound(ThinVec<(Symbol, Span)>), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 356575416ade..631b07ff1da2 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -19,37 +19,26 @@ impl AttributeKind { match self { // tidy-alphabetical-start Align { .. } => No, - AllowConstFnUnstable(..) => No, - AllowIncoherentImpl(..) => No, AllowInternalUnsafe(..) => Yes, AllowInternalUnstable(..) => Yes, - AsPtr(..) => Yes, AutomaticallyDerived(..) => Yes, - BodyStability { .. } => No, CfgAttrTrace => Yes, CfgTrace(..) => Yes, CfiEncoding { .. } => Yes, - Coinductive(..) => No, Cold(..) => No, CollapseDebugInfo(..) => Yes, CompilerBuiltins => No, - Confusables { .. } => Yes, ConstContinue(..) => No, - ConstStability { .. } => Yes, - ConstStabilityIndirect => No, Coroutine(..) => No, Coverage(..) => No, CrateName { .. } => No, CrateType(_) => No, CustomMir(_, _, _) => Yes, DebuggerVisualizer(..) => No, - DenyExplicitImpl(..) => No, Deprecation { .. } => Yes, DoNotRecommend { .. } => Yes, Doc(_) => Yes, DocComment { .. } => Yes, - Dummy => No, - DynIncompatibleTrait(..) => No, EiiDeclaration(_) => Yes, EiiForeignItem => No, EiiImpls(..) => No, @@ -69,7 +58,6 @@ impl AttributeKind { LoopMatch(..) => No, MacroEscape(..) => No, MacroExport { .. } => Yes, - MacroTransparency(..) => Yes, MacroUse { .. } => No, Marker(..) => No, MayDangle(..) => No, @@ -87,12 +75,8 @@ impl AttributeKind { NoMangle(..) => Yes, // Needed for rustdoc NoStd(..) => No, NonExhaustive(..) => Yes, // Needed for rustdoc - ObjcClass { .. } => No, - ObjcSelector { .. } => No, Optimize(..) => No, PanicRuntime => No, - ParenSugar(..) => No, - PassByValue(..) => Yes, PatchableFunctionEntry { .. } => Yes, Path(..) => No, PatternComplexityLimit { .. } => No, @@ -102,20 +86,30 @@ impl AttributeKind { ProcMacroAttribute(..) => No, ProcMacroDerive { .. } => No, ProfilerRuntime => No, - PubTransparent(..) => Yes, RecursionLimit { .. } => No, Repr { .. } => No, RustcAllocator => No, RustcAllocatorZeroed => No, RustcAllocatorZeroedVariant { .. } => Yes, + RustcAllowConstFnUnstable(..) => No, + RustcAllowIncoherentImpl(..) => No, + RustcAsPtr(..) => Yes, + RustcBodyStability { .. } => No, RustcBuiltinMacro { .. } => Yes, RustcCoherenceIsCore(..) => No, + RustcCoinductive(..) => No, + RustcConfusables { .. } => Yes, + RustcConstStability { .. } => Yes, + RustcConstStabilityIndirect => No, RustcDeallocator => No, + RustcDenyExplicitImpl(..) => No, + RustcDummy => No, RustcDumpDefParents => No, RustcDumpItemBounds => No, RustcDumpPredicates => No, RustcDumpUserArgs => No, RustcDumpVtable(..) => No, + RustcDynIncompatibleTrait(..) => No, RustcHasIncoherentInherentImpls => Yes, RustcLayoutScalarValidRangeEnd(..) => Yes, RustcLayoutScalarValidRangeStart(..) => Yes, @@ -124,32 +118,38 @@ impl AttributeKind { RustcLintOptTy => Yes, RustcLintQueryInstability => Yes, RustcLintUntrackedQueryInformation => Yes, + RustcMacroTransparency(..) => Yes, RustcMain => No, RustcMustImplementOneOf { .. } => No, RustcNeverReturnsNullPointer => Yes, RustcNoImplicitAutorefs => Yes, RustcNounwind => No, + RustcObjcClass { .. } => No, + RustcObjcSelector { .. } => No, RustcObjectLifetimeDefault => No, RustcOffloadKernel => Yes, + RustcParenSugar(..) => No, + RustcPassByValue(..) => Yes, RustcPassIndirectlyInNonRusticAbis(..) => No, + RustcPubTransparent(..) => Yes, RustcReallocator => No, RustcScalableVector { .. } => Yes, RustcShouldNotBeCalledOnConstItems(..) => Yes, RustcSimdMonomorphizeLaneLimit(..) => Yes, // Affects layout computation, which needs to work cross-crate + RustcSkipDuringMethodDispatch { .. } => No, + RustcSpecializationTrait(..) => No, + RustcStdInternalSymbol(..) => No, + RustcUnsafeSpecializationMarker(..) => No, RustcVariance => No, RustcVarianceOfOpaques => No, Sanitize { .. } => No, ShouldPanic { .. } => No, - SkipDuringMethodDispatch { .. } => No, - SpecializationTrait(..) => No, Stability { .. } => Yes, - StdInternalSymbol(..) => No, TargetFeature { .. } => No, ThreadLocal => No, TrackCaller(..) => Yes, TypeConst(..) => Yes, TypeLengthLimit { .. } => No, - UnsafeSpecializationMarker(..) => No, UnstableFeatureBound(..) => No, Used { .. } => No, WindowsSubsystem(..) => No, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index f2b06e1cde71..c00122bce559 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1701,7 +1701,10 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) ty::Array(ty, _) => check_unsuited(tcx, typing_env, *ty), ty::Adt(def, args) => { if !def.did().is_local() - && !find_attr!(tcx.get_all_attrs(def.did()), AttributeKind::PubTransparent(_)) + && !find_attr!( + tcx.get_all_attrs(def.did()), + AttributeKind::RustcPubTransparent(_) + ) { let non_exhaustive = def.is_variant_list_non_exhaustive() || def.variants().iter().any(ty::VariantDef::is_field_list_non_exhaustive); diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index fe47f3258846..edaf33e493c0 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -91,7 +91,7 @@ impl<'tcx> InherentCollect<'tcx> { for &impl_item in items { if !find_attr!( self.tcx.get_all_attrs(impl_item), - AttributeKind::AllowIncoherentImpl(_) + AttributeKind::RustcAllowIncoherentImpl(_) ) { let impl_span = self.tcx.def_span(impl_def_id); return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideRelevant { @@ -125,7 +125,7 @@ impl<'tcx> InherentCollect<'tcx> { for &impl_item in items { if !find_attr!( self.tcx.get_all_attrs(impl_item), - AttributeKind::AllowIncoherentImpl(_) + AttributeKind::RustcAllowIncoherentImpl(_) ) { let span = self.tcx.def_span(impl_def_id); return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsidePrimitive { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index dd399f9d90de..f50aff187f25 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -889,7 +889,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { let attrs = tcx.get_all_attrs(def_id); - let paren_sugar = find_attr!(attrs, AttributeKind::ParenSugar(_)); + let paren_sugar = find_attr!(attrs, AttributeKind::RustcParenSugar(_)); if paren_sugar && !tcx.features().unboxed_closures() { tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span }); } @@ -897,22 +897,23 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { // Only regular traits can be marker. let is_marker = !is_alias && find_attr!(attrs, AttributeKind::Marker(_)); - let rustc_coinductive = find_attr!(attrs, AttributeKind::Coinductive(_)); + let rustc_coinductive = find_attr!(attrs, AttributeKind::RustcCoinductive(_)); let is_fundamental = find_attr!(attrs, AttributeKind::Fundamental); let [skip_array_during_method_dispatch, skip_boxed_slice_during_method_dispatch] = find_attr!( attrs, - AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: _ } => [*array, *boxed_slice] + AttributeKind::RustcSkipDuringMethodDispatch { array, boxed_slice, span: _ } => [*array, *boxed_slice] ) .unwrap_or([false; 2]); - let specialization_kind = if find_attr!(attrs, AttributeKind::UnsafeSpecializationMarker(_)) { - ty::trait_def::TraitSpecializationKind::Marker - } else if find_attr!(attrs, AttributeKind::SpecializationTrait(_)) { - ty::trait_def::TraitSpecializationKind::AlwaysApplicable - } else { - ty::trait_def::TraitSpecializationKind::None - }; + let specialization_kind = + if find_attr!(attrs, AttributeKind::RustcUnsafeSpecializationMarker(_)) { + ty::trait_def::TraitSpecializationKind::Marker + } else if find_attr!(attrs, AttributeKind::RustcSpecializationTrait(_)) { + ty::trait_def::TraitSpecializationKind::AlwaysApplicable + } else { + ty::trait_def::TraitSpecializationKind::None + }; let must_implement_one_of = find_attr!( attrs, @@ -923,9 +924,9 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { .collect::>() ); - let deny_explicit_impl = find_attr!(attrs, AttributeKind::DenyExplicitImpl(_)); + let deny_explicit_impl = find_attr!(attrs, AttributeKind::RustcDenyExplicitImpl(_)); let force_dyn_incompatible = - find_attr!(attrs, AttributeKind::DynIncompatibleTrait(span) => *span); + find_attr!(attrs, AttributeKind::RustcDynIncompatibleTrait(span) => *span); ty::TraitDef { def_id: def_id.to_def_id(), diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 5673d044ad2c..c6241c6a3992 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2103,7 +2103,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for inherent_method in self.tcx.associated_items(inherent_impl_did).in_definition_order() { - if let Some(candidates) = find_attr!(self.tcx.get_all_attrs(inherent_method.def_id), AttributeKind::Confusables{symbols, ..} => symbols) + if let Some(candidates) = find_attr!(self.tcx.get_all_attrs(inherent_method.def_id), AttributeKind::RustcConfusables{symbols, ..} => symbols) && candidates.contains(&item_name.name) && inherent_method.is_fn() { diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs index af4457f4314b..71ea801a408e 100644 --- a/compiler/rustc_lint/src/dangling.rs +++ b/compiler/rustc_lint/src/dangling.rs @@ -268,7 +268,7 @@ fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) { && let ty = cx.typeck_results().expr_ty(receiver) && owns_allocation(cx.tcx, ty) && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) - && find_attr!(cx.tcx.get_all_attrs(fn_id), AttributeKind::AsPtr(_)) + && find_attr!(cx.tcx.get_all_attrs(fn_id), AttributeKind::RustcAsPtr(_)) { // FIXME: use `emit_node_lint` when `#[primary_span]` is added. cx.tcx.emit_node_span_lint( diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index f4a506d50a41..3823c9aa1861 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -44,7 +44,7 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option + if find_attr!(cx.tcx.get_all_attrs(def_id), AttributeKind::RustcPassByValue(_)) => { let name = cx.tcx.item_ident(def_id); let path_segment = path.segments.last().unwrap(); @@ -52,7 +52,10 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option { if let ty::Adt(adt, args) = cx.tcx.type_of(did).instantiate_identity().kind() { - if find_attr!(cx.tcx.get_all_attrs(adt.did()), AttributeKind::PassByValue(_)) { + if find_attr!( + cx.tcx.get_all_attrs(adt.did()), + AttributeKind::RustcPassByValue(_) + ) { return Some(cx.tcx.def_path_str_with_args(adt.did(), args)); } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index cdd141f9233e..541870607b63 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -150,7 +150,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { span: attr_span, stability: Stability { level, feature }, } - | AttributeKind::ConstStability { + | AttributeKind::RustcConstStability { span: attr_span, stability: PartialConstStability { level, feature, .. }, }, @@ -168,7 +168,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::AllowInternalUnsafe(attr_span) | AttributeKind::AllowInternalUnstable(.., attr_span)) => { self.check_macro_only_attr(*attr_span, span, target, attrs) } - Attribute::Parsed(AttributeKind::AllowConstFnUnstable(_, first_span)) => { + Attribute::Parsed(AttributeKind::RustcAllowConstFnUnstable(_, first_span)) => { self.check_rustc_allow_const_fn_unstable(hir_id, *first_span, span, target) } Attribute::Parsed(AttributeKind::Deprecation {span: attr_span, .. }) => { @@ -180,7 +180,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::RustcObjectLifetimeDefault) => { self.check_object_lifetime_default(hir_id); } - &Attribute::Parsed(AttributeKind::PubTransparent(attr_span)) => { + &Attribute::Parsed(AttributeKind::RustcPubTransparent(attr_span)) => { self.check_rustc_pub_transparent(attr_span, span, attrs) } Attribute::Parsed(AttributeKind::Align { align, span: attr_span }) => { @@ -226,29 +226,21 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::DoNotRecommend{attr_span}) => {self.check_do_not_recommend(*attr_span, hir_id, target, item)}, Attribute::Parsed( // tidy-alphabetical-start - AttributeKind::AllowIncoherentImpl(..) - | AttributeKind::AsPtr(..) + AttributeKind::RustcAllowIncoherentImpl(..) | AttributeKind::AutomaticallyDerived(..) - | AttributeKind::BodyStability { .. } | AttributeKind::CfgAttrTrace | AttributeKind::CfgTrace(..) | AttributeKind::CfiEncoding { .. } - | AttributeKind::Coinductive(..) | AttributeKind::Cold(..) | AttributeKind::CollapseDebugInfo(..) | AttributeKind::CompilerBuiltins - | AttributeKind::Confusables { .. } - | AttributeKind::ConstStabilityIndirect | AttributeKind::Coroutine(..) | AttributeKind::Coverage (..) | AttributeKind::CrateName { .. } | AttributeKind::CrateType(..) | AttributeKind::DebuggerVisualizer(..) - | AttributeKind::DenyExplicitImpl(..) // `#[doc]` is actually a lot more than just doc comments, so is checked below | AttributeKind::DocComment {..} - | AttributeKind::Dummy - | AttributeKind::DynIncompatibleTrait(..) | AttributeKind::EiiDeclaration { .. } | AttributeKind::EiiForeignItem | AttributeKind::ExportName { .. } @@ -262,7 +254,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::LinkSection { .. } | AttributeKind::Linkage(..) | AttributeKind::MacroEscape( .. ) - | AttributeKind::MacroTransparency(_) | AttributeKind::MacroUse { .. } | AttributeKind::Marker(..) | AttributeKind::MoveSizeLimit { .. } @@ -277,12 +268,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::NoMain | AttributeKind::NoMangle(..) | AttributeKind::NoStd { .. } - | AttributeKind::ObjcClass { .. } - | AttributeKind::ObjcSelector { .. } | AttributeKind::Optimize(..) | AttributeKind::PanicRuntime - | AttributeKind::ParenSugar(..) - | AttributeKind::PassByValue (..) | AttributeKind::PatchableFunctionEntry { .. } | AttributeKind::Path(..) | AttributeKind::PatternComplexityLimit { .. } @@ -295,14 +282,22 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcAllocator | AttributeKind::RustcAllocatorZeroed | AttributeKind::RustcAllocatorZeroedVariant { .. } + | AttributeKind::RustcAsPtr(..) + | AttributeKind::RustcBodyStability { .. } | AttributeKind::RustcBuiltinMacro { .. } | AttributeKind::RustcCoherenceIsCore(..) + | AttributeKind::RustcCoinductive(..) + | AttributeKind::RustcConfusables { .. } + | AttributeKind::RustcConstStabilityIndirect | AttributeKind::RustcDeallocator + | AttributeKind::RustcDenyExplicitImpl(..) + | AttributeKind::RustcDummy | AttributeKind::RustcDumpDefParents | AttributeKind::RustcDumpItemBounds | AttributeKind::RustcDumpPredicates | AttributeKind::RustcDumpUserArgs | AttributeKind::RustcDumpVtable(..) + | AttributeKind::RustcDynIncompatibleTrait(..) | AttributeKind::RustcHasIncoherentInherentImpls | AttributeKind::RustcLayoutScalarValidRangeEnd(..) | AttributeKind::RustcLayoutScalarValidRangeStart(..) @@ -310,26 +305,31 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcLintOptTy | AttributeKind::RustcLintQueryInstability | AttributeKind::RustcLintUntrackedQueryInformation + | AttributeKind::RustcMacroTransparency(_) | AttributeKind::RustcMain | AttributeKind::RustcNeverReturnsNullPointer | AttributeKind::RustcNoImplicitAutorefs | AttributeKind::RustcNounwind + | AttributeKind::RustcObjcClass { .. } + | AttributeKind::RustcObjcSelector { .. } | AttributeKind::RustcOffloadKernel + | AttributeKind::RustcParenSugar(..) + | AttributeKind::RustcPassByValue (..) | AttributeKind::RustcPassIndirectlyInNonRusticAbis(..) | AttributeKind::RustcReallocator | AttributeKind::RustcScalableVector { .. } | AttributeKind::RustcShouldNotBeCalledOnConstItems(..) | AttributeKind::RustcSimdMonomorphizeLaneLimit(..) + | AttributeKind::RustcSkipDuringMethodDispatch { .. } + | AttributeKind::RustcSpecializationTrait(..) + | AttributeKind::RustcStdInternalSymbol (..) + | AttributeKind::RustcUnsafeSpecializationMarker(..) | AttributeKind::RustcVariance | AttributeKind::RustcVarianceOfOpaques | AttributeKind::ShouldPanic { .. } - | AttributeKind::SkipDuringMethodDispatch { .. } - | AttributeKind::SpecializationTrait(..) - | AttributeKind::StdInternalSymbol (..) | AttributeKind::ThreadLocal | AttributeKind::TypeConst{..} | AttributeKind::TypeLengthLimit { .. } - | AttributeKind::UnsafeSpecializationMarker(..) | AttributeKind::UnstableFeatureBound(..) | AttributeKind::Used { .. } | AttributeKind::WindowsSubsystem(..) diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index 8d0ef88610af..1f92643815fd 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -30,10 +30,10 @@ impl<'tcx> LibFeatureCollector<'tcx> { Attribute::Parsed(AttributeKind::Stability { stability, span }) => { (stability.feature, stability.level, *span) } - Attribute::Parsed(AttributeKind::ConstStability { stability, span }) => { + Attribute::Parsed(AttributeKind::RustcConstStability { stability, span }) => { (stability.feature, stability.level, *span) } - Attribute::Parsed(AttributeKind::BodyStability { stability, span }) => { + Attribute::Parsed(AttributeKind::RustcBodyStability { stability, span }) => { (stability.feature, stability.level, *span) } _ => return None, diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 9d94c4cc6225..657b362d5ca1 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -197,7 +197,7 @@ fn lookup_default_body_stability( let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id)); // FIXME: check that this item can have body stability - find_attr!(attrs, AttributeKind::BodyStability { stability, .. } => *stability) + find_attr!(attrs, AttributeKind::RustcBodyStability { stability, .. } => *stability) } #[instrument(level = "debug", skip(tcx))] @@ -214,7 +214,7 @@ fn lookup_const_stability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option, def_id: LocalDefId) -> Option *stability); + find_attr!(attrs, AttributeKind::RustcConstStability { stability, span: _ } => *stability); // After checking the immediate attributes, get rid of the span and compute implied // const stability: inherit feature gate from regular stability. @@ -393,7 +393,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { if let Some(fn_sig) = fn_sig && !fn_sig.header.is_const() && const_stab.is_some() - && find_attr_span!(ConstStability).is_some() + && find_attr_span!(RustcConstStability).is_some() { self.tcx.dcx().emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span }); } @@ -403,7 +403,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { && let Some(fn_sig) = fn_sig && const_stab.is_const_stable() && !stab.is_some_and(|s| s.is_stable()) - && let Some(const_span) = find_attr_span!(ConstStability) + && let Some(const_span) = find_attr_span!(RustcConstStability) { self.tcx .dcx() @@ -413,7 +413,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { if let Some(stab) = &const_stab && stab.is_const_stable() && stab.const_stable_indirect - && let Some(span) = find_attr_span!(ConstStability) + && let Some(span) = find_attr_span!(RustcConstStability) { self.tcx.dcx().emit_err(errors::RustcConstStableIndirectPairing { span }); } @@ -602,7 +602,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { let stab = find_attr!(attrs, AttributeKind::Stability{stability, span} => (*stability, *span)); // FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem - let const_stab = find_attr!(attrs, AttributeKind::ConstStability{stability, ..} => *stability); + let const_stab = find_attr!(attrs, AttributeKind::RustcConstStability{stability, ..} => *stability); let unstable_feature_stab = find_attr!(attrs, AttributeKind::UnstableFeatureBound(i) => i) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 8656ec6e39ae..73446ddcf7e4 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -497,7 +497,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { let hir_id = self.tcx.local_def_id_to_hir_id(local_def_id); let attrs = self.tcx.hir_attrs(hir_id); - if find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x) + if find_attr!(attrs, AttributeKind::RustcMacroTransparency(x) => *x) .unwrap_or(Transparency::fallback(md.macro_rules)) != Transparency::Opaque { From 87f75df0b80b038daf307f56e0dde73b8514d195 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 29 Jan 2026 23:10:46 +0800 Subject: [PATCH 231/978] Fix unused lint error in macro --- compiler/rustc_lint/src/unused.rs | 21 ++++++++++++++----- .../lint-unsed-in-macro-issue-151269.rs | 15 +++++++++++++ .../lint-unsed-in-macro-issue-151269.stderr | 19 +++++++++++++++++ 3 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 tests/ui/lint/unused/lint-unsed-in-macro-issue-151269.rs create mode 100644 tests/ui/lint/unused/lint-unsed-in-macro-issue-151269.stderr diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 506a16355e22..5516298c5e85 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -539,10 +539,19 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ); } MustUsePath::Def(span, def_id, reason) => { - let span = span.find_ancestor_not_from_macro().unwrap_or(*span); + let ancenstor_span = span.find_ancestor_not_from_macro().unwrap_or(*span); + let is_redundant_let_ignore = cx + .sess() + .source_map() + .span_to_prev_source(ancenstor_span) + .ok() + .map(|prev| prev.trim_end().ends_with("let _ =")) + .unwrap_or(false); + let suggestion_span = + if is_redundant_let_ignore { *span } else { ancenstor_span }; cx.emit_span_lint( UNUSED_MUST_USE, - span, + ancenstor_span, UnusedDef { pre: descr_pre, post: descr_post, @@ -551,11 +560,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { note: *reason, suggestion: (!is_inner).then_some(if expr_is_from_block { UnusedDefSuggestion::BlockTailExpr { - before_span: span.shrink_to_lo(), - after_span: span.shrink_to_hi(), + before_span: suggestion_span.shrink_to_lo(), + after_span: suggestion_span.shrink_to_hi(), } } else { - UnusedDefSuggestion::NormalExpr { span: span.shrink_to_lo() } + UnusedDefSuggestion::NormalExpr { + span: suggestion_span.shrink_to_lo(), + } }), }, ); diff --git a/tests/ui/lint/unused/lint-unsed-in-macro-issue-151269.rs b/tests/ui/lint/unused/lint-unsed-in-macro-issue-151269.rs new file mode 100644 index 000000000000..65b8a22d383a --- /dev/null +++ b/tests/ui/lint/unused/lint-unsed-in-macro-issue-151269.rs @@ -0,0 +1,15 @@ +#![deny(unused_must_use)] + +fn error() -> Result<(), ()> { + Err(()) +} + +macro_rules! foo { + () => {{ + error(); + }}; +} + +fn main() { + let _ = foo!(); //~ ERROR unused `Result` that must be used +} diff --git a/tests/ui/lint/unused/lint-unsed-in-macro-issue-151269.stderr b/tests/ui/lint/unused/lint-unsed-in-macro-issue-151269.stderr new file mode 100644 index 000000000000..12cedf58974b --- /dev/null +++ b/tests/ui/lint/unused/lint-unsed-in-macro-issue-151269.stderr @@ -0,0 +1,19 @@ +error: unused `Result` that must be used + --> $DIR/lint-unsed-in-macro-issue-151269.rs:14:13 + | +LL | let _ = foo!(); + | ^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled +note: the lint level is defined here + --> $DIR/lint-unsed-in-macro-issue-151269.rs:1:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = error(); + | +++++++ + +error: aborting due to 1 previous error + From 9928723bffc9b3dae673462a78b97077a0bde200 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Thu, 29 Jan 2026 10:20:34 -0500 Subject: [PATCH 232/978] Implement `BinaryHeap::pop_if()` --- .../alloc/src/collections/binary_heap/mod.rs | 26 +++++++++++++++++++ library/alloctests/lib.rs | 1 + .../tests/collections/binary_heap.rs | 12 +++++++++ 3 files changed, 39 insertions(+) diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 5710b2a3a91d..65c8d5213f16 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -649,6 +649,32 @@ impl BinaryHeap { }) } + /// Removes and returns the greatest item from the binary heap if the predicate + /// returns `true`, or [`None`] if the predicate returns false or the heap + /// is empty (the predicate will not be called in that case). + /// + /// # Examples + /// + /// ``` + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::from([1, 2]); + /// let pred = |x: &i32| *x % 2 == 0; + /// + /// assert_eq!(heap.pop_if(pred), Some(2)); + /// assert_eq!(heap, BinaryHeap::from([1])); + /// assert_eq!(heap.pop_if(pred), None); + /// assert_eq!(heap, BinaryHeap::from([1])); + /// ``` + /// + /// # Time complexity + /// + /// The worst case cost of `pop_if` on a heap containing *n* elements is *O*(log(*n*)). + #[unstable(feature = "binary_heap_pop_if", issue = "151828")] + pub fn pop_if(&mut self, predicate: impl FnOnce(&T) -> bool) -> Option { + let first = self.data.first()?; + if predicate(first) { self.pop() } else { None } + } + /// Pushes an item onto the binary heap. /// /// # Examples diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index fe14480102e3..9806c59ce0e1 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -17,6 +17,7 @@ #![feature(allocator_api)] #![feature(array_into_iter_constructors)] #![feature(assert_matches)] +#![feature(binary_heap_pop_if)] #![feature(box_vec_non_null)] #![feature(char_internals)] #![feature(const_alloc_error)] diff --git a/library/alloctests/tests/collections/binary_heap.rs b/library/alloctests/tests/collections/binary_heap.rs index 95f4c3e614f5..1b6afec7f355 100644 --- a/library/alloctests/tests/collections/binary_heap.rs +++ b/library/alloctests/tests/collections/binary_heap.rs @@ -136,6 +136,18 @@ fn test_peek_and_pop() { } } +#[test] +fn test_pop_if() { + let data = vec![9, 8, 7, 6, 5, 4, 3, 2, 1, 0]; + let mut sorted = data.clone(); + sorted.sort(); + let mut heap = BinaryHeap::from(data); + while let Some(popped) = heap.pop_if(|x| *x > 2) { + assert_eq!(popped, sorted.pop().unwrap()); + } + assert_eq!(heap.into_sorted_vec(), vec![1, 2]); +} + #[test] fn test_peek_mut() { let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; From cf6625648ea97bb4951596c7b7c6038051c86113 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 28 Jan 2026 21:58:29 +0100 Subject: [PATCH 233/978] Update `askama` to `0.15.4` --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 43d6c82b34cb..8f5ef9ca2f8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ walkdir = "2.3" filetime = "0.2.9" itertools = "0.12" pulldown-cmark = { version = "0.11", default-features = false, features = ["html"] } -askama = { version = "0.15.2", default-features = false, features = ["alloc", "config", "derive"] } +askama = { version = "0.15.4", default-features = false, features = ["alloc", "config", "derive"] } [dev-dependencies.toml] version = "0.9.7" From b226583d9454d11ff141d258cd194256168842ac Mon Sep 17 00:00:00 2001 From: Jamie Hill-Daniel Date: Thu, 29 Jan 2026 15:51:43 +0000 Subject: [PATCH 234/978] Treat unions as 'data types' in attr parsing diagnostics --- .../rustc_attr_parsing/src/target_checking.rs | 2 +- tests/ui/attributes/attr-on-mac-call.stderr | 6 +- .../deprecated-expr-precedence.stderr | 2 +- .../ui/deprecation/deprecation-sanity.stderr | 2 +- ...issue-43106-gating-of-builtin-attrs.stderr | 10 +-- tests/ui/lint/fn_must_use.stderr | 2 +- .../lint/must_not_suspend/other_items.stderr | 2 +- tests/ui/lint/must_not_suspend/return.stderr | 2 +- .../unused/unused_attributes-must_use.stderr | 44 +++++------ tests/ui/pin-ergonomics/pin_v2-attr.stderr | 76 +++++++++---------- .../invalid-attribute.stderr | 2 +- .../param-attrs-builtin-attrs.stderr | 16 ++-- .../unsupported_attribute.stderr | 4 +- 13 files changed, 85 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index 79aa06e9475c..fb005477f0fa 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -205,7 +205,7 @@ pub(crate) fn allowed_targets_applied( ]; const IMPL_LIKE: &[Target] = &[Target::Impl { of_trait: false }, Target::Impl { of_trait: true }]; - const ADT_LIKE: &[Target] = &[Target::Struct, Target::Enum]; + const ADT_LIKE: &[Target] = &[Target::Struct, Target::Enum, Target::Union]; let mut added_fake_targets = Vec::new(); filter_targets( diff --git a/tests/ui/attributes/attr-on-mac-call.stderr b/tests/ui/attributes/attr-on-mac-call.stderr index 1aeec463c71c..3bb50f2d6f65 100644 --- a/tests/ui/attributes/attr-on-mac-call.stderr +++ b/tests/ui/attributes/attr-on-mac-call.stderr @@ -55,7 +55,7 @@ LL | #[deprecated] | ^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, unions, and use statements + = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements warning: `#[inline]` attribute cannot be used on macro calls --> $DIR/attr-on-mac-call.rs:24:5 @@ -136,7 +136,7 @@ LL | #[deprecated] | ^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, unions, and use statements + = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements warning: `#[automatically_derived]` attribute cannot be used on macro calls --> $DIR/attr-on-mac-call.rs:51:5 @@ -163,7 +163,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits warning: `#[no_implicit_prelude]` attribute cannot be used on macro calls --> $DIR/attr-on-mac-call.rs:60:5 diff --git a/tests/ui/deprecation/deprecated-expr-precedence.stderr b/tests/ui/deprecation/deprecated-expr-precedence.stderr index c3124cf86ef4..bd575e6b6276 100644 --- a/tests/ui/deprecation/deprecated-expr-precedence.stderr +++ b/tests/ui/deprecation/deprecated-expr-precedence.stderr @@ -5,7 +5,7 @@ LL | #[deprecated] 0 | ^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, unions, and use statements + = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements = note: requested on the command line with `-W unused-attributes` error[E0308]: mismatched types diff --git a/tests/ui/deprecation/deprecation-sanity.stderr b/tests/ui/deprecation/deprecation-sanity.stderr index a4dc9f23d3d2..427d14d89c19 100644 --- a/tests/ui/deprecation/deprecation-sanity.stderr +++ b/tests/ui/deprecation/deprecation-sanity.stderr @@ -83,7 +83,7 @@ LL | #[deprecated = "hello"] | ^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, unions, and use statements + = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements = note: `#[deny(useless_deprecated)]` on by default error: aborting due to 10 previous errors diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index fd90fe4c837b..d69daf45b352 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -1055,7 +1055,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits warning: `#[must_use]` attribute cannot be used on modules --> $DIR/issue-43106-gating-of-builtin-attrs.rs:766:17 @@ -1064,7 +1064,7 @@ LL | mod inner { #![must_use] } | ^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits warning: `#[must_use]` attribute cannot be used on type aliases --> $DIR/issue-43106-gating-of-builtin-attrs.rs:775:5 @@ -1073,7 +1073,7 @@ LL | #[must_use] type T = S; | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits warning: `#[must_use]` attribute cannot be used on inherent impl blocks --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:5 @@ -1082,7 +1082,7 @@ LL | #[must_use] impl S { } | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![windows_subsystem]` --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:1 @@ -1635,7 +1635,7 @@ LL | #![must_use] | ^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits warning: 175 warnings emitted diff --git a/tests/ui/lint/fn_must_use.stderr b/tests/ui/lint/fn_must_use.stderr index 0e8da873e7c3..bdf4eb6de4a5 100644 --- a/tests/ui/lint/fn_must_use.stderr +++ b/tests/ui/lint/fn_must_use.stderr @@ -5,7 +5,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, foreign functions, functions, inherent methods, provided trait methods, required trait methods, traits, and unions + = help: `#[must_use]` can be applied to data types, foreign functions, functions, inherent methods, provided trait methods, required trait methods, and traits = note: requested on the command line with `-W unused-attributes` warning: unused return value of `need_to_use_this_value` that must be used diff --git a/tests/ui/lint/must_not_suspend/other_items.stderr b/tests/ui/lint/must_not_suspend/other_items.stderr index 999a9d2fb3dc..289230b027ad 100644 --- a/tests/ui/lint/must_not_suspend/other_items.stderr +++ b/tests/ui/lint/must_not_suspend/other_items.stderr @@ -4,7 +4,7 @@ error: `#[must_not_suspend]` attribute cannot be used on modules LL | #[must_not_suspend] | ^^^^^^^^^^^^^^^^^^^ | - = help: `#[must_not_suspend]` can be applied to data types, traits, and unions + = help: `#[must_not_suspend]` can be applied to data types and traits error: aborting due to 1 previous error diff --git a/tests/ui/lint/must_not_suspend/return.stderr b/tests/ui/lint/must_not_suspend/return.stderr index 1a81b1a39f0c..b041491128e1 100644 --- a/tests/ui/lint/must_not_suspend/return.stderr +++ b/tests/ui/lint/must_not_suspend/return.stderr @@ -4,7 +4,7 @@ error: `#[must_not_suspend]` attribute cannot be used on functions LL | #[must_not_suspend] | ^^^^^^^^^^^^^^^^^^^ | - = help: `#[must_not_suspend]` can be applied to data types, traits, and unions + = help: `#[must_not_suspend]` can be applied to data types and traits error: aborting due to 1 previous error diff --git a/tests/ui/lint/unused/unused_attributes-must_use.stderr b/tests/ui/lint/unused/unused_attributes-must_use.stderr index 3192c0994548..3fc340b5188f 100644 --- a/tests/ui/lint/unused/unused_attributes-must_use.stderr +++ b/tests/ui/lint/unused/unused_attributes-must_use.stderr @@ -5,7 +5,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits note: the lint level is defined here --> $DIR/unused_attributes-must_use.rs:4:9 | @@ -19,7 +19,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on modules --> $DIR/unused_attributes-must_use.rs:11:1 @@ -28,7 +28,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on use statements --> $DIR/unused_attributes-must_use.rs:15:1 @@ -37,7 +37,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on constants --> $DIR/unused_attributes-must_use.rs:19:1 @@ -46,7 +46,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on statics --> $DIR/unused_attributes-must_use.rs:22:1 @@ -55,7 +55,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on inherent impl blocks --> $DIR/unused_attributes-must_use.rs:40:1 @@ -64,7 +64,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on foreign modules --> $DIR/unused_attributes-must_use.rs:55:1 @@ -73,7 +73,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on foreign statics --> $DIR/unused_attributes-must_use.rs:59:5 @@ -82,7 +82,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on type aliases --> $DIR/unused_attributes-must_use.rs:73:1 @@ -91,7 +91,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on type parameters --> $DIR/unused_attributes-must_use.rs:77:8 @@ -100,7 +100,7 @@ LL | fn qux<#[must_use] T>(_: T) {} | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on associated consts --> $DIR/unused_attributes-must_use.rs:82:5 @@ -109,7 +109,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on associated types --> $DIR/unused_attributes-must_use.rs:85:5 @@ -118,7 +118,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on trait impl blocks --> $DIR/unused_attributes-must_use.rs:95:1 @@ -127,7 +127,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on trait methods in impl blocks --> $DIR/unused_attributes-must_use.rs:100:5 @@ -136,7 +136,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, foreign functions, functions, inherent methods, provided trait methods, required trait methods, traits, and unions + = help: `#[must_use]` can be applied to data types, foreign functions, functions, inherent methods, provided trait methods, required trait methods, and traits error: `#[must_use]` attribute cannot be used on trait aliases --> $DIR/unused_attributes-must_use.rs:107:1 @@ -145,7 +145,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on macro defs --> $DIR/unused_attributes-must_use.rs:111:1 @@ -154,7 +154,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on statements --> $DIR/unused_attributes-must_use.rs:120:5 @@ -163,7 +163,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on closures --> $DIR/unused_attributes-must_use.rs:125:13 @@ -172,7 +172,7 @@ LL | let x = #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, foreign functions, functions, methods, traits, and unions + = help: `#[must_use]` can be applied to data types, foreign functions, functions, methods, and traits error: `#[must_use]` attribute cannot be used on match arms --> $DIR/unused_attributes-must_use.rs:148:9 @@ -181,7 +181,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on struct fields --> $DIR/unused_attributes-must_use.rs:157:28 @@ -190,7 +190,7 @@ LL | let s = PatternField { #[must_use] foo: 123 }; | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: `#[must_use]` attribute cannot be used on pattern fields --> $DIR/unused_attributes-must_use.rs:159:24 @@ -199,7 +199,7 @@ LL | let PatternField { #[must_use] foo } = s; | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits error: unused `X` that must be used --> $DIR/unused_attributes-must_use.rs:130:5 diff --git a/tests/ui/pin-ergonomics/pin_v2-attr.stderr b/tests/ui/pin-ergonomics/pin_v2-attr.stderr index c297afa87a73..8f8a9f3b3a19 100644 --- a/tests/ui/pin-ergonomics/pin_v2-attr.stderr +++ b/tests/ui/pin-ergonomics/pin_v2-attr.stderr @@ -4,7 +4,7 @@ error: `#[pin_v2]` attribute cannot be used on macro calls LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters --> $DIR/pin_v2-attr.rs:84:12 @@ -18,7 +18,7 @@ error: `#[pin_v2]` attribute cannot be used on crates LL | #![pin_v2] | ^^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on type parameters --> $DIR/pin_v2-attr.rs:27:10 @@ -26,7 +26,7 @@ error: `#[pin_v2]` attribute cannot be used on type parameters LL | enum Foo<#[pin_v2] T, #[pin_v2] U = ()> { | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on type parameters --> $DIR/pin_v2-attr.rs:27:23 @@ -34,7 +34,7 @@ error: `#[pin_v2]` attribute cannot be used on type parameters LL | enum Foo<#[pin_v2] T, #[pin_v2] U = ()> { | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on enum variants --> $DIR/pin_v2-attr.rs:30:5 @@ -42,7 +42,7 @@ error: `#[pin_v2]` attribute cannot be used on enum variants LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on struct fields --> $DIR/pin_v2-attr.rs:32:18 @@ -50,7 +50,7 @@ error: `#[pin_v2]` attribute cannot be used on struct fields LL | TupleVariant(#[pin_v2] T), | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on struct fields --> $DIR/pin_v2-attr.rs:34:9 @@ -58,7 +58,7 @@ error: `#[pin_v2]` attribute cannot be used on struct fields LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on traits --> $DIR/pin_v2-attr.rs:39:1 @@ -66,7 +66,7 @@ error: `#[pin_v2]` attribute cannot be used on traits LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on associated consts --> $DIR/pin_v2-attr.rs:41:5 @@ -74,7 +74,7 @@ error: `#[pin_v2]` attribute cannot be used on associated consts LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on associated types --> $DIR/pin_v2-attr.rs:43:5 @@ -82,7 +82,7 @@ error: `#[pin_v2]` attribute cannot be used on associated types LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on required trait methods --> $DIR/pin_v2-attr.rs:46:5 @@ -90,7 +90,7 @@ error: `#[pin_v2]` attribute cannot be used on required trait methods LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on provided trait methods --> $DIR/pin_v2-attr.rs:48:5 @@ -98,7 +98,7 @@ error: `#[pin_v2]` attribute cannot be used on provided trait methods LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on trait aliases --> $DIR/pin_v2-attr.rs:52:1 @@ -106,7 +106,7 @@ error: `#[pin_v2]` attribute cannot be used on trait aliases LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on inherent impl blocks --> $DIR/pin_v2-attr.rs:55:1 @@ -114,7 +114,7 @@ error: `#[pin_v2]` attribute cannot be used on inherent impl blocks LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on delegations --> $DIR/pin_v2-attr.rs:58:5 @@ -122,7 +122,7 @@ error: `#[pin_v2]` attribute cannot be used on delegations LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on inherent methods --> $DIR/pin_v2-attr.rs:61:5 @@ -130,7 +130,7 @@ error: `#[pin_v2]` attribute cannot be used on inherent methods LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on trait impl blocks --> $DIR/pin_v2-attr.rs:65:1 @@ -138,7 +138,7 @@ error: `#[pin_v2]` attribute cannot be used on trait impl blocks LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on trait methods in impl blocks --> $DIR/pin_v2-attr.rs:67:5 @@ -146,7 +146,7 @@ error: `#[pin_v2]` attribute cannot be used on trait methods in impl blocks LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on extern crates --> $DIR/pin_v2-attr.rs:71:1 @@ -154,7 +154,7 @@ error: `#[pin_v2]` attribute cannot be used on extern crates LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on use statements --> $DIR/pin_v2-attr.rs:74:1 @@ -162,7 +162,7 @@ error: `#[pin_v2]` attribute cannot be used on use statements LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on statics --> $DIR/pin_v2-attr.rs:77:1 @@ -170,7 +170,7 @@ error: `#[pin_v2]` attribute cannot be used on statics LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on constants --> $DIR/pin_v2-attr.rs:80:1 @@ -178,7 +178,7 @@ error: `#[pin_v2]` attribute cannot be used on constants LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on functions --> $DIR/pin_v2-attr.rs:83:1 @@ -186,7 +186,7 @@ error: `#[pin_v2]` attribute cannot be used on functions LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on function params --> $DIR/pin_v2-attr.rs:84:12 @@ -194,7 +194,7 @@ error: `#[pin_v2]` attribute cannot be used on function params LL | fn f(#[pin_v2] param: Foo) | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on closures --> $DIR/pin_v2-attr.rs:92:5 @@ -202,7 +202,7 @@ error: `#[pin_v2]` attribute cannot be used on closures LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on expressions --> $DIR/pin_v2-attr.rs:94:5 @@ -210,7 +210,7 @@ error: `#[pin_v2]` attribute cannot be used on expressions LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on struct fields --> $DIR/pin_v2-attr.rs:98:9 @@ -218,7 +218,7 @@ error: `#[pin_v2]` attribute cannot be used on struct fields LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on statements --> $DIR/pin_v2-attr.rs:96:5 @@ -226,7 +226,7 @@ error: `#[pin_v2]` attribute cannot be used on statements LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on match arms --> $DIR/pin_v2-attr.rs:102:9 @@ -234,7 +234,7 @@ error: `#[pin_v2]` attribute cannot be used on match arms LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on pattern fields --> $DIR/pin_v2-attr.rs:106:13 @@ -242,7 +242,7 @@ error: `#[pin_v2]` attribute cannot be used on pattern fields LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on where predicates --> $DIR/pin_v2-attr.rs:88:5 @@ -250,7 +250,7 @@ error: `#[pin_v2]` attribute cannot be used on where predicates LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on modules --> $DIR/pin_v2-attr.rs:112:1 @@ -258,7 +258,7 @@ error: `#[pin_v2]` attribute cannot be used on modules LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on foreign modules --> $DIR/pin_v2-attr.rs:115:1 @@ -266,7 +266,7 @@ error: `#[pin_v2]` attribute cannot be used on foreign modules LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on foreign types --> $DIR/pin_v2-attr.rs:117:5 @@ -274,7 +274,7 @@ error: `#[pin_v2]` attribute cannot be used on foreign types LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on foreign statics --> $DIR/pin_v2-attr.rs:120:5 @@ -282,7 +282,7 @@ error: `#[pin_v2]` attribute cannot be used on foreign statics LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on foreign functions --> $DIR/pin_v2-attr.rs:123:5 @@ -290,7 +290,7 @@ error: `#[pin_v2]` attribute cannot be used on foreign functions LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on type aliases --> $DIR/pin_v2-attr.rs:127:1 @@ -298,7 +298,7 @@ error: `#[pin_v2]` attribute cannot be used on type aliases LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: `#[pin_v2]` attribute cannot be used on macro defs --> $DIR/pin_v2-attr.rs:130:1 @@ -306,7 +306,7 @@ error: `#[pin_v2]` attribute cannot be used on macro defs LL | #[pin_v2] | ^^^^^^^^^ | - = help: `#[pin_v2]` can be applied to data types and unions + = help: `#[pin_v2]` can only be applied to data types error: aborting due to 39 previous errors diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr index 98e8f1235e6b..d711c3f2eb12 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr @@ -21,7 +21,7 @@ error: `#[non_exhaustive]` attribute cannot be used on unions LL | #[non_exhaustive] | ^^^^^^^^^^^^^^^^^ | - = help: `#[non_exhaustive]` can be applied to data types and enum variants + = help: `#[non_exhaustive]` can be applied to enum variants, enums, and structs error: aborting due to 3 previous errors diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr index cc08307a18d0..c234cb31bc56 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr +++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr @@ -389,7 +389,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits = note: requested on the command line with `-W unused-attributes` warning: `#[no_mangle]` attribute cannot be used on function params @@ -408,7 +408,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits warning: `#[no_mangle]` attribute cannot be used on function params --> $DIR/param-attrs-builtin-attrs.rs:70:9 @@ -426,7 +426,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits warning: `#[no_mangle]` attribute cannot be used on function params --> $DIR/param-attrs-builtin-attrs.rs:89:9 @@ -444,7 +444,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits warning: `#[no_mangle]` attribute cannot be used on function params --> $DIR/param-attrs-builtin-attrs.rs:114:9 @@ -462,7 +462,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits warning: `#[no_mangle]` attribute cannot be used on function params --> $DIR/param-attrs-builtin-attrs.rs:137:9 @@ -480,7 +480,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits warning: `#[no_mangle]` attribute cannot be used on function params --> $DIR/param-attrs-builtin-attrs.rs:156:9 @@ -498,7 +498,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits warning: `#[no_mangle]` attribute cannot be used on function params --> $DIR/param-attrs-builtin-attrs.rs:180:9 @@ -516,7 +516,7 @@ LL | #[must_use] | ^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = help: `#[must_use]` can be applied to data types, functions, and traits warning: `#[no_mangle]` attribute cannot be used on function params --> $DIR/param-attrs-builtin-attrs.rs:201:9 diff --git a/tests/ui/where-clauses/unsupported_attribute.stderr b/tests/ui/where-clauses/unsupported_attribute.stderr index 9ebc14c40a14..e69eff976c3f 100644 --- a/tests/ui/where-clauses/unsupported_attribute.stderr +++ b/tests/ui/where-clauses/unsupported_attribute.stderr @@ -64,7 +64,7 @@ error: `#[deprecated]` attribute cannot be used on where predicates LL | #[deprecated] T: Trait, | ^^^^^^^^^^^^^ | - = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, unions, and use statements + = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements error: `#[deprecated]` attribute cannot be used on where predicates --> $DIR/unsupported_attribute.rs:25:5 @@ -72,7 +72,7 @@ error: `#[deprecated]` attribute cannot be used on where predicates LL | #[deprecated] 'a: 'static, | ^^^^^^^^^^^^^ | - = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, unions, and use statements + = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, and use statements error: `#[automatically_derived]` attribute cannot be used on where predicates --> $DIR/unsupported_attribute.rs:26:5 From 63973953621c9f1aa84ceae6887d1ce818a4d98a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 29 Jan 2026 17:08:19 +0100 Subject: [PATCH 235/978] Update `askama` version to `0.15.4` --- Cargo.lock | 16 ++++++++-------- src/ci/citool/Cargo.toml | 2 +- src/librustdoc/Cargo.toml | 2 +- src/tools/generate-copyright/Cargo.toml | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 35ad4472e6a3..6be4565374af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -184,9 +184,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "askama" -version = "0.15.3" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a800c6f7c005e5bcb76ff0b9e61c9e54ad379ce4e83a88ed14ff487a73776d" +checksum = "08e1676b346cadfec169374f949d7490fd80a24193d37d2afce0c047cf695e57" dependencies = [ "askama_macros", "itoa", @@ -197,9 +197,9 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.15.3" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cb7657165bac49b5c533850e7cd67c1c60059aefc31088f89aa431c8a90d5d9" +checksum = "7661ff56517787343f376f75db037426facd7c8d3049cef8911f1e75016f3a37" dependencies = [ "askama_parser", "basic-toml", @@ -214,18 +214,18 @@ dependencies = [ [[package]] name = "askama_macros" -version = "0.15.3" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55eacd3e54d32483cd10d0a881a0f28a40f3a763704ac9b8693edc39d7321c7" +checksum = "713ee4dbfd1eb719c2dab859465b01fa1d21cb566684614a713a6b7a99a4e47b" dependencies = [ "askama_derive", ] [[package]] name = "askama_parser" -version = "0.15.3" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c3df8886ab5acdcd76eee93b3e2df1ef734251438b5b942b5fea22c50d2a0f" +checksum = "1d62d674238a526418b30c0def480d5beadb9d8964e7f38d635b03bf639c704c" dependencies = [ "rustc-hash 2.1.1", "serde", diff --git a/src/ci/citool/Cargo.toml b/src/ci/citool/Cargo.toml index c2a926b3eaef..0b1f2fe79bf7 100644 --- a/src/ci/citool/Cargo.toml +++ b/src/ci/citool/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] anyhow = "1" -askama = "0.15.3" +askama = "0.15.4" clap = { version = "4.5", features = ["derive"] } csv = "1" diff = "0.1" diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index efc44a8a2d51..033d3ecdd03d 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -10,7 +10,7 @@ path = "lib.rs" [dependencies] # tidy-alphabetical-start arrayvec = { version = "0.7", default-features = false } -askama = { version = "0.15.3", default-features = false, features = ["alloc", "config", "derive"] } +askama = { version = "0.15.4", default-features = false, features = ["alloc", "config", "derive"] } base64 = "0.21.7" indexmap = { version = "2", features = ["serde"] } itertools = "0.12" diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml index 965f7f992e75..17b5c727964f 100644 --- a/src/tools/generate-copyright/Cargo.toml +++ b/src/tools/generate-copyright/Cargo.toml @@ -8,7 +8,7 @@ description = "Produces a manifest of all the copyrighted materials in the Rust [dependencies] anyhow = "1.0.65" -askama = "0.15.3" +askama = "0.15.4" cargo_metadata = "0.21" serde = { version = "1.0.147", features = ["derive"] } serde_json = "1.0.85" From 959595fb45ac706b1a2c4e7774f69d18ae6441f3 Mon Sep 17 00:00:00 2001 From: IonicMC Date: Thu, 29 Jan 2026 20:26:06 +0200 Subject: [PATCH 236/978] Fix typo for Maybe dangling docs Boxe's -> Box's --- library/core/src/mem/maybe_dangling.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/mem/maybe_dangling.rs b/library/core/src/mem/maybe_dangling.rs index 3c5437757e97..a5f77e667f97 100644 --- a/library/core/src/mem/maybe_dangling.rs +++ b/library/core/src/mem/maybe_dangling.rs @@ -29,7 +29,7 @@ use crate::{mem, ptr}; /// mem::forget(boxed); // <-- this is UB! /// ``` /// -/// Even though the `Box`e's destructor is not run (and thus we don't have a double free bug), this +/// Even though the `Box`'s destructor is not run (and thus we don't have a double free bug), this /// code is still UB. This is because when moving `boxed` into `forget`, its validity invariants /// are asserted, causing UB since the `Box` is dangling. The safety comment is as such wrong, as /// moving the `boxed` variable as part of the `forget` call *is* a use. From c943cd9b8cd07b06d8be37e9c309fb3c96f6d795 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 29 Jan 2026 20:43:03 +0200 Subject: [PATCH 237/978] fix redirects --- src/doc/rustc-dev-guide/book.toml | 42 +++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/doc/rustc-dev-guide/book.toml b/src/doc/rustc-dev-guide/book.toml index 18ca2c85a617..5712a364f760 100644 --- a/src/doc/rustc-dev-guide/book.toml +++ b/src/doc/rustc-dev-guide/book.toml @@ -58,19 +58,19 @@ warning-policy = "error" [output.html.redirect] "/borrow_check.html" = "borrow-check.html" -"/borrow_check/drop_check.html" = "borrow-check/drop-check.html" -"/borrow_check/moves_and_initialization.html" = "borrow-check/moves-and-initialization.html" -"/borrow_check/moves_and_initialization/move_paths.html" = "borrow-check/moves-and-initialization/move-paths.html" -"/borrow_check/opaque-types-region-inference-restrictions.html" = "borrow-check/opaque-types-region-inference-restrictions.html" -"/borrow_check/region_inference.html" = "borrow-check/region-inference.html" -"/borrow_check/region_inference/closure_constraints.html" = "borrow-check/region-inference/closure-constraints.html" -"/borrow_check/region_inference/constraint_propagation.html" = "borrow-check/region-inference/constraint-propagation.html" -"/borrow_check/region_inference/error_reporting.html" = "borrow-check/region-inference/error-reporting.html" -"/borrow_check/region_inference/lifetime_parameters.html" = "borrow-check/region-inference/lifetime-parameters.html" -"/borrow_check/region_inference/member_constraints.html" = "borrow-check/region-inference/member-constraints.html" -"/borrow_check/region_inference/placeholders_and_universes.html" = "borrow-check/region-inference/placeholders-and-universes.html" -"/borrow_check/two_phase_borrows.html" = "borrow-check/two-phase-borrows.html" -"/borrow_check/type_check.html" = "borrow-check/type-check.html" +"/borrow_check/drop_check.html" = "/borrow-check/drop-check.html" +"/borrow_check/moves_and_initialization.html" = "/borrow-check/moves-and-initialization.html" +"/borrow_check/moves_and_initialization/move_paths.html" = "/borrow-check/moves-and-initialization/move-paths.html" +"/borrow_check/opaque-types-region-inference-restrictions.html" = "/borrow-check/opaque-types-region-inference-restrictions.html" +"/borrow_check/region_inference.html" = "/borrow-check/region-inference.html" +"/borrow_check/region_inference/closure_constraints.html" = "/borrow-check/region-inference/closure-constraints.html" +"/borrow_check/region_inference/constraint_propagation.html" = "/borrow-check/region-inference/constraint-propagation.html" +"/borrow_check/region_inference/error_reporting.html" = "/borrow-check/region-inference/error-reporting.html" +"/borrow_check/region_inference/lifetime_parameters.html" = "/borrow-check/region-inference/lifetime-parameters.html" +"/borrow_check/region_inference/member_constraints.html" = "/borrow-check/region-inference/member-constraints.html" +"/borrow_check/region_inference/placeholders_and_universes.html" = "/borrow-check/region-inference/placeholders-and-universes.html" +"/borrow_check/two_phase_borrows.html" = "/borrow-check/two-phase-borrows.html" +"/borrow_check/type_check.html" = "/borrow-check/type-check.html" "/compiletest.html" = "tests/compiletest.html" "/diagnostics/diagnostic-codes.html" = "error-codes.html" "/diagnostics/sessiondiagnostic.html" = "diagnostic-structs.html" @@ -78,18 +78,18 @@ warning-policy = "error" "/generic_parameters_summary.html" = "generic-parameters-summary.html" "/implementing_new_features.html" = "implementing-new-features.html" "/miri.html" = "const-eval/interpret.html" -"/profiling/with_perf.html" = "profiling/with-perf.html" -"/profiling/with_rustc_perf.html" = "profiling/with-rustc-perf.html" -"/profiling/wpa_profiling.html" = "profiling/wpa-profiling.html" +"/profiling/with_perf.html" = "with-perf.html" +"/profiling/with_rustc_perf.html" = "with-rustc-perf.html" +"/profiling/wpa_profiling.html" = "wpa-profiling.html" "/stabilization_guide.html" = "stabilization-guide.html" "/stabilization_report_template.html" = "stabilization-report-template.html" "/tests/fuchsia.html" = "ecosystem-test-jobs/fuchsia.html" "/tests/headers.html" = "directives.html" "/tests/integration.html" = "ecosystem.html" "/tests/rust-for-linux.html" = "ecosystem-test-jobs/rust-for-linux.html" -"/ty_module/binders.html" = "ty-module/binders.html" -"/ty_module/early_binder.html" = "ty-module/early-binder.html" -"/ty_module/generic_arguments.html" = "ty-module/generic-arguments.html" -"/ty_module/instantiating_binders.html" = "ty-module/instantiating-binders.html" -"/ty_module/param_ty_const_regions.html" = "ty-module/param-ty-const-regions.html" +"/ty_module/binders.html" = "/ty-module/binders.html" +"/ty_module/early_binder.html" = "/ty-module/early-binder.html" +"/ty_module/generic_arguments.html" = "/ty-module/generic-arguments.html" +"/ty_module/instantiating_binders.html" = "/ty-module/instantiating-binders.html" +"/ty_module/param_ty_const_regions.html" = "/ty-module/param-ty-const-regions.html" "/typing_parameter_envs.html" = "typing-parameter-envs.html" From f0bb4e649ff171d2dae737562503b801e62aa0a6 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Thu, 29 Jan 2026 18:52:52 +0000 Subject: [PATCH 238/978] Prepare for merging from rust-lang/rust This updates the rust-version file to 370143facfb348ad3b29749c0393402d76b280c3. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index c8a3b401a6e1..795271ee0ef0 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -0462e8f7e51f20692b02d68efee68bb28a6f4457 +370143facfb348ad3b29749c0393402d76b280c3 From b128539624b5ebb98e8eaa6a217ca199821abe36 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 29 Jan 2026 20:57:08 +0200 Subject: [PATCH 239/978] sembr src/tracing.md --- src/doc/rustc-dev-guide/src/tracing.md | 81 ++++++++++++++------------ 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tracing.md b/src/doc/rustc-dev-guide/src/tracing.md index 1005ad2c2346..33f9387355ac 100644 --- a/src/doc/rustc-dev-guide/src/tracing.md +++ b/src/doc/rustc-dev-guide/src/tracing.md @@ -1,14 +1,15 @@ # Using tracing to debug the compiler The compiler has a lot of [`debug!`] (or `trace!`) calls, which print out logging information -at many points. These are very useful to at least narrow down the location of +at many points. +These are very useful to at least narrow down the location of a bug if not to find it entirely, or just to orient yourself as to why the compiler is doing a particular thing. [`debug!`]: https://docs.rs/tracing/0.1/tracing/macro.debug.html -To see the logs, you need to set the `RUSTC_LOG` environment variable to your -log filter. The full syntax of the log filters can be found in the [rustdoc +To see the logs, you need to set the `RUSTC_LOG` environment variable to your log filter. +The full syntax of the log filters can be found in the [rustdoc of `tracing-subscriber`](https://docs.rs/tracing-subscriber/0.2.24/tracing_subscriber/filter/struct.EnvFilter.html#directives). ## Function level filters @@ -47,69 +48,74 @@ RUSTC_LOG=rustc_borrowck[do_mir_borrowck] ### I don't want all calls If you are compiling libcore, you likely don't want *all* borrowck dumps, but only one -for a specific function. You can filter function calls by their arguments by regexing them. +for a specific function. +You can filter function calls by their arguments by regexing them. ``` RUSTC_LOG=[do_mir_borrowck{id=\.\*from_utf8_unchecked\.\*}] ``` -will only give you the logs of borrowchecking `from_utf8_unchecked`. Note that you will -still get a short message per ignored `do_mir_borrowck`, but none of the things inside those -calls. This helps you in looking through the calls that are happening and helps you adjust +will only give you the logs of borrowchecking `from_utf8_unchecked`. +Note that you will +still get a short message per ignored `do_mir_borrowck`, but none of the things inside those calls. +This helps you in looking through the calls that are happening and helps you adjust your regex if you mistyped it. ## Query level filters Every [query](query.md) is automatically tagged with a logging span so that -you can display all log messages during the execution of the query. For -example, if you want to log everything during type checking: +you can display all log messages during the execution of the query. +For example, if you want to log everything during type checking: ``` RUSTC_LOG=[typeck] ``` The query arguments are included as a tracing field which means that you can -filter on the debug display of the arguments. For example, the `typeck` query -has an argument `key: LocalDefId` of what is being checked. You can use a -regex to match on that `LocalDefId` to log type checking for a specific +filter on the debug display of the arguments. +For example, the `typeck` query has an argument `key: LocalDefId` of what is being checked. +You can use a regex to match on that `LocalDefId` to log type checking for a specific function: ``` RUSTC_LOG=[typeck{key=.*name_of_item.*}] ``` -Different queries have different arguments. You can find a list of queries and -their arguments in +Different queries have different arguments. +You can find a list of queries and their arguments in [`rustc_middle/src/query/mod.rs`](https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_middle/src/query/mod.rs#L18). ## Broad module level filters You can also use filters similar to the `log` crate's filters, which will enable -everything within a specific module. This is often too verbose and too unstructured, +everything within a specific module. +This is often too verbose and too unstructured, so it is recommended to use function level filters. Your log filter can be just `debug` to get all `debug!` output and higher (e.g., it will also include `info!`), or `path::to::module` to get *all* output (which will include `trace!`) from a particular module, or -`path::to::module=debug` to get `debug!` output and higher from a particular -module. +`path::to::module=debug` to get `debug!` output and higher from a particular module. For example, to get the `debug!` output and higher for a specific module, you can run the compiler with `RUSTC_LOG=path::to::module=debug rustc my-file.rs`. All `debug!` output will then appear in standard error. -Note that you can use a partial path and the filter will still work. For -example, if you want to see `info!` output from only +Note that you can use a partial path and the filter will still work. +For example, if you want to see `info!` output from only `rustdoc::passes::collect_intra_doc_links`, you could use `RUSTDOC_LOG=rustdoc::passes::collect_intra_doc_links=info` *or* you could use `RUSTDOC_LOG=rustdoc::passes::collect_intra=info`. -If you are developing rustdoc, use `RUSTDOC_LOG` instead. If you are developing -Miri, use `MIRI_LOG` instead. You get the idea :) +If you are developing rustdoc, use `RUSTDOC_LOG` instead. +If you are developing Miri, use `MIRI_LOG` instead. +You get the idea :) See the [`tracing`] crate's docs, and specifically the docs for [`debug!`] to -see the full syntax you can use. (Note: unlike the compiler, the [`tracing`] -crate and its examples use the `RUSTC_LOG` environment variable. rustc, rustdoc, +see the full syntax you can use. +(Note: unlike the compiler, the [`tracing`] +crate and its examples use the `RUSTC_LOG` environment variable. +rustc, rustdoc, and other tools set custom environment variables.) **Note that unless you use a very strict filter, the logger will emit a lot of @@ -157,18 +163,20 @@ $ RUSTDOC_LOG=rustdoc=debug rustdoc +stage1 my-file.rs ## Log colors By default, rustc (and other tools, like rustdoc and Miri) will be smart about -when to use ANSI colors in the log output. If they are outputting to a terminal, +when to use ANSI colors in the log output. +If they are outputting to a terminal, they will use colors, and if they are outputting to a file or being piped -somewhere else, they will not. However, it's hard to read log output in your +somewhere else, they will not. +However, it's hard to read log output in your terminal unless you have a very strict filter, so you may want to pipe the -output to a pager like `less`. But then there won't be any colors, which makes -it hard to pick out what you're looking for! +output to a pager like `less`. +But then there won't be any colors, which makes it hard to pick out what you're looking for! You can override whether to have colors in log output with the `RUSTC_LOG_COLOR` environment variable (or `RUSTDOC_LOG_COLOR` for rustdoc, or `MIRI_LOG_COLOR` for Miri, etc.). There are three options: `auto` (the default), `always`, and -`never`. So, if you want to enable colors when piping to `less`, use something -similar to this command: +`never`. +So, if you want to enable colors when piping to `less`, use something similar to this command: ```bash # The `-R` switch tells less to print ANSI colors without escaping them. @@ -176,8 +184,8 @@ $ RUSTC_LOG=debug RUSTC_LOG_COLOR=always rustc +stage1 ... | less -R ``` Note that `MIRI_LOG_COLOR` will only color logs that come from Miri, not logs -from rustc functions that Miri calls. Use `RUSTC_LOG_COLOR` to color logs from -rustc. +from rustc functions that Miri calls. +Use `RUSTC_LOG_COLOR` to color logs from rustc. ## How to keep or remove `debug!` and `trace!` calls from the resulting binary @@ -186,8 +194,7 @@ calls to `debug!` and `trace!` are only included in the program if `rust.debug-logging=true` is turned on in bootstrap.toml (it is turned off by default), so if you don't see `DEBUG` logs, especially if you run the compiler with `RUSTC_LOG=rustc rustc some.rs` and only see -`INFO` logs, make sure that `debug-logging=true` is turned on in your -bootstrap.toml. +`INFO` logs, make sure that `debug-logging=true` is turned on in your bootstrap.toml. ## Logging etiquette and conventions @@ -196,8 +203,8 @@ about the performance of adding "unnecessary" calls to `debug!` and leaving them commit - they won't slow down the performance of what we ship. That said, there can also be excessive tracing calls, especially -when they are redundant with other calls nearby or in functions called from -here. There is no perfect balance to hit here, and is left to the reviewer's +when they are redundant with other calls nearby or in functions called from here. +There is no perfect balance to hit here, and is left to the reviewer's discretion to decide whether to let you leave `debug!` statements in or whether to ask you to remove them before merging. @@ -219,8 +226,8 @@ debug!(x = ?random_operation(tcx)); ``` Then if someone runs a debug `rustc` with `RUSTC_LOG=rustc::foo`, then -`random_operation()` will run. `RUSTC_LOG` filters that do not enable this -debug statement will not execute `random_operation`. +`random_operation()` will run. +`RUSTC_LOG` filters that do not enable this debug statement will not execute `random_operation`. This means that you should not put anything too expensive or likely to crash there - that would annoy anyone who wants to use logging for that module. From 481d49de092f245ee2186f8eccdab5ed8b461c47 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 29 Jan 2026 21:08:19 +0200 Subject: [PATCH 240/978] missing word --- src/doc/rustc-dev-guide/src/tracing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tracing.md b/src/doc/rustc-dev-guide/src/tracing.md index 33f9387355ac..75bce30d3af1 100644 --- a/src/doc/rustc-dev-guide/src/tracing.md +++ b/src/doc/rustc-dev-guide/src/tracing.md @@ -204,7 +204,7 @@ commit - they won't slow down the performance of what we ship. That said, there can also be excessive tracing calls, especially when they are redundant with other calls nearby or in functions called from here. -There is no perfect balance to hit here, and is left to the reviewer's +There is no perfect balance to hit here, and it is left to the reviewer's discretion to decide whether to let you leave `debug!` statements in or whether to ask you to remove them before merging. From c4718ea1d92ddabc90fc2aac2d7d556a7fcef815 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 29 Jan 2026 21:08:37 +0200 Subject: [PATCH 241/978] missing pause --- src/doc/rustc-dev-guide/src/tracing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tracing.md b/src/doc/rustc-dev-guide/src/tracing.md index 75bce30d3af1..28c0bcc737ca 100644 --- a/src/doc/rustc-dev-guide/src/tracing.md +++ b/src/doc/rustc-dev-guide/src/tracing.md @@ -205,7 +205,7 @@ commit - they won't slow down the performance of what we ship. That said, there can also be excessive tracing calls, especially when they are redundant with other calls nearby or in functions called from here. There is no perfect balance to hit here, and it is left to the reviewer's -discretion to decide whether to let you leave `debug!` statements in or whether to ask +discretion to decide whether to let you leave `debug!` statements in, or whether to ask you to remove them before merging. It may be preferable to use `trace!` over `debug!` for very noisy logs. From 4264da6869bfbd8a314990dcf567389ab0e416af Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 29 Jan 2026 01:27:22 -0800 Subject: [PATCH 242/978] Add `shift_{left,right}` on slices cc tracking issue 151772 --- library/core/src/slice/mod.rs | 213 +++++++++++++++++++++++++++++++ library/coretests/tests/lib.rs | 1 + library/coretests/tests/slice.rs | 38 ++++++ 3 files changed, 252 insertions(+) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 3e1eeba4e92e..e449ceadf19d 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3939,6 +3939,219 @@ impl [T] { } } + /// Moves the elements of this slice `N` places to the left, returning the ones + /// that "fall off" the front, and putting `inserted` at the end. + /// + /// Equivalently, you can think of concatenating `self` and `inserted` into one + /// long sequence, then returning the left-most `N` items and the rest into `self`: + /// + /// ```text + /// self (before) inserted + /// vvvvvvvvvvvvvvv vvv + /// [1, 2, 3, 4, 5] [9] + /// ↙ ↙ ↙ ↙ ↙ ↙ + /// [1] [2, 3, 4, 5, 9] + /// ^^^ ^^^^^^^^^^^^^^^ + /// returned self (after) + /// ``` + /// + /// See also [`Self::shift_right`] and compare [`Self::rotate_left`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_shift)] + /// + /// // Same as the diagram above + /// let mut a = [1, 2, 3, 4, 5]; + /// let inserted = [9]; + /// let returned = a.shift_left(inserted); + /// assert_eq!(returned, [1]); + /// assert_eq!(a, [2, 3, 4, 5, 9]); + /// + /// // You can shift multiple items at a time + /// let mut a = *b"Hello world"; + /// assert_eq!(a.shift_left(*b" peace"), *b"Hello "); + /// assert_eq!(a, *b"world peace"); + /// + /// // The name comes from this operation's similarity to bitshifts + /// let mut a: u8 = 0b10010110; + /// a <<= 3; + /// assert_eq!(a, 0b10110000_u8); + /// let mut a: [_; 8] = [1, 0, 0, 1, 0, 1, 1, 0]; + /// a.shift_left([0; 3]); + /// assert_eq!(a, [1, 0, 1, 1, 0, 0, 0, 0]); + /// + /// // Remember you can sub-slice to affect less that the whole slice. + /// // For example, this is similar to `.remove(1)` + `.insert(4, 'Z')` + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// assert_eq!(a[1..=4].shift_left(['Z']), ['b']); + /// assert_eq!(a, ['a', 'c', 'd', 'e', 'Z', 'f']); + /// + /// // If the size matches it's equivalent to `mem::replace` + /// let mut a = [1, 2, 3]; + /// assert_eq!(a.shift_left([7, 8, 9]), [1, 2, 3]); + /// assert_eq!(a, [7, 8, 9]); + /// + /// // Some of the "inserted" elements end up returned if the slice is too short + /// let mut a = []; + /// assert_eq!(a.shift_left([1, 2, 3]), [1, 2, 3]); + /// let mut a = [9]; + /// assert_eq!(a.shift_left([1, 2, 3]), [9, 1, 2]); + /// assert_eq!(a, [3]); + /// ``` + #[unstable(feature = "slice_shift", issue = "151772")] + pub const fn shift_left(&mut self, inserted: [T; N]) -> [T; N] { + if let Some(shift) = self.len().checked_sub(N) { + // SAFETY: Having just checked that the inserted/returned arrays are + // shorter than (or the same length as) the slice: + // 1. The read for the items to return is in-bounds + // 2. We can `memmove` the slice over to cover the items we're returning + // to ensure those aren't double-dropped + // 3. Then we write (in-bounds for the same reason as the read) the + // inserted items atop the items of the slice that we just duplicated + // + // And none of this can panic, so there's no risk of intermediate unwinds. + unsafe { + let ptr = self.as_mut_ptr(); + let returned = ptr.cast_array::().read(); + ptr.copy_from(ptr.add(N), shift); + ptr.add(shift).cast_array::().write(inserted); + returned + } + } else { + // SAFETY: Having checked that the slice is strictly shorter than the + // inserted/returned arrays, it means we'll be copying the whole slice + // into the returned array, but that's not enough on its own. We also + // need to copy some of the inserted array into the returned array, + // with the rest going into the slice. Because `&mut` is exclusive + // and we own both `inserted` and `returned`, they're all disjoint + // allocations from each other as we can use `nonoverlapping` copies. + // + // We avoid double-frees by `ManuallyDrop`ing the inserted items, + // since we always copy them to other locations that will drop them + // instead. Plus nothing in here can panic -- it's just memcpy three + // times -- so there's no intermediate unwinds to worry about. + unsafe { + let len = self.len(); + let slice = self.as_mut_ptr(); + let inserted = mem::ManuallyDrop::new(inserted); + let inserted = (&raw const inserted).cast::(); + + let mut returned = MaybeUninit::<[T; N]>::uninit(); + let ptr = returned.as_mut_ptr().cast::(); + ptr.copy_from_nonoverlapping(slice, len); + ptr.add(len).copy_from_nonoverlapping(inserted, N - len); + slice.copy_from_nonoverlapping(inserted.add(N - len), len); + returned.assume_init() + } + } + } + + /// Moves the elements of this slice `N` places to the right, returning the ones + /// that "fall off" the back, and putting `inserted` at the beginning. + /// + /// Equivalently, you can think of concatenating `inserted` and `self` into one + /// long sequence, then returning the right-most `N` items and the rest into `self`: + /// + /// ```text + /// inserted self (before) + /// vvv vvvvvvvvvvvvvvv + /// [0] [5, 6, 7, 8, 9] + /// ↘ ↘ ↘ ↘ ↘ ↘ + /// [0, 5, 6, 7, 8] [9] + /// ^^^^^^^^^^^^^^^ ^^^ + /// self (after) returned + /// ``` + /// + /// See also [`Self::shift_left`] and compare [`Self::rotate_right`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_shift)] + /// + /// // Same as the diagram above + /// let mut a = [5, 6, 7, 8, 9]; + /// let inserted = [0]; + /// let returned = a.shift_right(inserted); + /// assert_eq!(returned, [9]); + /// assert_eq!(a, [0, 5, 6, 7, 8]); + /// + /// // The name comes from this operation's similarity to bitshifts + /// let mut a: u8 = 0b10010110; + /// a >>= 3; + /// assert_eq!(a, 0b00010010_u8); + /// let mut a: [_; 8] = [1, 0, 0, 1, 0, 1, 1, 0]; + /// a.shift_right([0; 3]); + /// assert_eq!(a, [0, 0, 0, 1, 0, 0, 1, 0]); + /// + /// // Remember you can sub-slice to affect less that the whole slice. + /// // For example, this is similar to `.remove(4)` + `.insert(1, 'Z')` + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// assert_eq!(a[1..=4].shift_right(['Z']), ['e']); + /// assert_eq!(a, ['a', 'Z', 'b', 'c', 'd', 'f']); + /// + /// // If the size matches it's equivalent to `mem::replace` + /// let mut a = [1, 2, 3]; + /// assert_eq!(a.shift_right([7, 8, 9]), [1, 2, 3]); + /// assert_eq!(a, [7, 8, 9]); + /// + /// // Some of the "inserted" elements end up returned if the slice is too short + /// let mut a = []; + /// assert_eq!(a.shift_right([1, 2, 3]), [1, 2, 3]); + /// let mut a = [9]; + /// assert_eq!(a.shift_right([1, 2, 3]), [2, 3, 9]); + /// assert_eq!(a, [1]); + /// ``` + #[unstable(feature = "slice_shift", issue = "151772")] + pub const fn shift_right(&mut self, inserted: [T; N]) -> [T; N] { + if let Some(shift) = self.len().checked_sub(N) { + // SAFETY: Having just checked that the inserted/returned arrays are + // shorter than (or the same length as) the slice: + // 1. The read for the items to return is in-bounds + // 2. We can `memmove` the slice over to cover the items we're returning + // to ensure those aren't double-dropped + // 3. Then we write (in-bounds for the same reason as the read) the + // inserted items atop the items of the slice that we just duplicated + // + // And none of this can panic, so there's no risk of intermediate unwinds. + unsafe { + let ptr = self.as_mut_ptr(); + let returned = ptr.add(shift).cast_array::().read(); + ptr.add(N).copy_from(ptr, shift); + ptr.cast_array::().write(inserted); + returned + } + } else { + // SAFETY: Having checked that the slice is strictly shorter than the + // inserted/returned arrays, it means we'll be copying the whole slice + // into the returned array, but that's not enough on its own. We also + // need to copy some of the inserted array into the returned array, + // with the rest going into the slice. Because `&mut` is exclusive + // and we own both `inserted` and `returned`, they're all disjoint + // allocations from each other as we can use `nonoverlapping` copies. + // + // We avoid double-frees by `ManuallyDrop`ing the inserted items, + // since we always copy them to other locations that will drop them + // instead. Plus nothing in here can panic -- it's just memcpy three + // times -- so there's no intermediate unwinds to worry about. + unsafe { + let len = self.len(); + let slice = self.as_mut_ptr(); + let inserted = mem::ManuallyDrop::new(inserted); + let inserted = (&raw const inserted).cast::(); + + let mut returned = MaybeUninit::<[T; N]>::uninit(); + let ptr = returned.as_mut_ptr().cast::(); + ptr.add(N - len).copy_from_nonoverlapping(slice, len); + ptr.copy_from_nonoverlapping(inserted.add(len), N - len); + slice.copy_from_nonoverlapping(inserted, len); + returned.assume_init() + } + } + } + /// Fills `self` with elements by cloning `value`. /// /// # Examples diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 8cca714b7393..b6dd130aa35f 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -101,6 +101,7 @@ #![feature(slice_index_methods)] #![feature(slice_internals)] #![feature(slice_partition_dedup)] +#![feature(slice_shift)] #![feature(slice_split_once)] #![feature(sliceindex_wrappers)] #![feature(split_array)] diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs index 6f60f71e8a47..2bb62f36bb0e 100644 --- a/library/coretests/tests/slice.rs +++ b/library/coretests/tests/slice.rs @@ -2507,3 +2507,41 @@ fn test_slice_from_raw_parts_in_const() { assert_eq!(EMPTY_SLICE.as_ptr().addr(), 123456); assert_eq!(EMPTY_SLICE.len(), 0); } + +#[test] +fn test_shift_left() { + #[track_caller] + fn case( + mut a: [i32; M], + i: [i32; N], + j: [i32; N], + b: [i32; M], + ) { + assert_eq!((a.shift_left(i), a), (j, b)); + } + case([], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], []); + case([1], [2, 3, 4, 5], [1, 2, 3, 4], [5]); + case([1, 2], [3, 4, 5], [1, 2, 3], [4, 5]); + case([1, 2, 3], [4, 5], [1, 2], [3, 4, 5]); + case([1, 2, 3, 4], [5], [1], [2, 3, 4, 5]); + case([1, 2, 3, 4, 5], [], [], [1, 2, 3, 4, 5]); +} + +#[test] +fn test_shift_right() { + #[track_caller] + fn case( + i: [i32; N], + mut a: [i32; M], + b: [i32; M], + j: [i32; N], + ) { + assert_eq!((a.shift_right(i), a), (j, b)); + } + case([], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], []); + case([1], [2, 3, 4, 5], [1, 2, 3, 4], [5]); + case([1, 2], [3, 4, 5], [1, 2, 3], [4, 5]); + case([1, 2, 3], [4, 5], [1, 2], [3, 4, 5]); + case([1, 2, 3, 4], [5], [1], [2, 3, 4, 5]); + case([1, 2, 3, 4, 5], [], [], [1, 2, 3, 4, 5]); +} From 83eae6253a198d33b11315f194be4190eded7a68 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 29 Jan 2026 21:15:07 +0200 Subject: [PATCH 243/978] sembr src/tests/compiletest.md --- .../rustc-dev-guide/src/tests/compiletest.md | 327 +++++++++--------- 1 file changed, 158 insertions(+), 169 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 626525fa804d..06a4728c93e1 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -2,8 +2,8 @@ ## Introduction -`compiletest` is the main test harness of the Rust test suite. It allows test -authors to organize large numbers of tests (the Rust compiler has many +`compiletest` is the main test harness of the Rust test suite. +It allows test authors to organize large numbers of tests (the Rust compiler has many thousands), efficient test execution (parallel execution is supported), and allows the test author to configure behavior and expected results of both individual and groups of tests. @@ -22,9 +22,10 @@ individual and groups of tests. `compiletest` may check test code for compile-time or run-time success/failure. Tests are typically organized as a Rust source file with annotations in comments -before and/or within the test code. These comments serve to direct `compiletest` -on if or how to run the test, what behavior to expect, and more. See -[directives](directives.md) and the test suite documentation below for more details +before and/or within the test code. +These comments serve to direct `compiletest` +on if or how to run the test, what behavior to expect, and more. +See [directives](directives.md) and the test suite documentation below for more details on these annotations. See the [Adding new tests](adding.md) and [Best practices](best-practices.md) @@ -40,16 +41,18 @@ Additionally, bootstrap accepts several common arguments directly, e.g. `x test --no-capture --force-rerun --run --pass`. Compiletest itself tries to avoid running tests when the artifacts that are -involved (mainly the compiler) haven't changed. You can use `x test --test-args +involved (mainly the compiler) haven't changed. +You can use `x test --test-args --force-rerun` to rerun a test even when none of the inputs have changed. ## Test suites -All of the tests are in the [`tests`] directory. The tests are organized into -"suites", with each suite in a separate subdirectory. Each test suite behaves a -little differently, with different compiler behavior and different checks for -correctness. For example, the [`tests/incremental`] directory contains tests for -incremental compilation. The various suites are defined in +All of the tests are in the [`tests`] directory. +The tests are organized into "suites", with each suite in a separate subdirectory. +Each test suite behaves a +little differently, with different compiler behavior and different checks for correctness. +For example, the [`tests/incremental`] directory contains tests for incremental compilation. +The various suites are defined in [`src/tools/compiletest/src/common.rs`] in the `pub enum Mode` declaration. The following test suites are available, with links for more information: @@ -105,10 +108,9 @@ Run-make tests pertaining to rustdoc are typically named `run-make/rustdoc-*/`. ### Pretty-printer tests -The tests in [`tests/pretty`] exercise the "pretty-printing" functionality of -`rustc`. The `-Z unpretty` CLI option for `rustc` causes it to translate the -input source into various different formats, such as the Rust source after macro -expansion. +The tests in [`tests/pretty`] exercise the "pretty-printing" functionality of `rustc`. +The `-Z unpretty` CLI option for `rustc` causes it to translate the +input source into various different formats, such as the Rust source after macro expansion. The pretty-printer tests have several [directives](directives.md) described below. These commands can significantly change the behavior of the test, but the @@ -125,17 +127,20 @@ If any of the commands above fail, then the test fails. The directives for pretty-printing tests are: - `pretty-mode` specifies the mode pretty-print tests should run in (that is, - the argument to `-Zunpretty`). The default is `normal` if not specified. + the argument to `-Zunpretty`). + The default is `normal` if not specified. - `pretty-compare-only` causes a pretty test to only compare the pretty-printed - output (stopping after step 3 from above). It will not try to compile the - expanded output to type check it. This is needed for a pretty-mode that does - not expand to valid Rust, or for other situations where the expanded output - cannot be compiled. + output (stopping after step 3 from above). + It will not try to compile the expanded output to type check it. + This is needed for a pretty-mode that does + not expand to valid Rust, or for other situations where the expanded output cannot be compiled. - `pp-exact` is used to ensure a pretty-print test results in specific output. If specified without a value, then it means the pretty-print output should - match the original source. If specified with a value, as in `//@ + match the original source. + If specified with a value, as in `//@ pp-exact:foo.pp`, it will ensure that the pretty-printed output matches the - contents of the given file. Otherwise, if `pp-exact` is not specified, then + contents of the given file. + Otherwise, if `pp-exact` is not specified, then the pretty-printed output will be pretty-printed one more time, and the output of the two pretty-printing rounds will be compared to ensure that the pretty-printed output converges to a steady state. @@ -144,13 +149,12 @@ The directives for pretty-printing tests are: ### Incremental tests -The tests in [`tests/incremental`] exercise incremental compilation. They use -[`revisions` directive](#revisions) to tell compiletest to run the compiler in a +The tests in [`tests/incremental`] exercise incremental compilation. +They use [`revisions` directive](#revisions) to tell compiletest to run the compiler in a series of steps. Compiletest starts with an empty directory with the `-C incremental` flag, and -then runs the compiler for each revision, reusing the incremental results from -previous steps. +then runs the compiler for each revision, reusing the incremental results from previous steps. The revisions should start with: @@ -158,8 +162,7 @@ The revisions should start with: * `rfail` — the test should compile successfully, but the executable should fail to run * `cfail` — the test should fail to compile -To make the revisions unique, you should add a suffix like `rpass1` and -`rpass2`. +To make the revisions unique, you should add a suffix like `rpass1` and `rpass2`. To simulate changing the source, compiletest also passes a `--cfg` flag with the current revision name. @@ -183,20 +186,20 @@ fn main() { foo(); } ``` `cfail` tests support the `forbid-output` directive to specify that a certain -substring must not appear anywhere in the compiler output. This can be useful to -ensure certain errors do not appear, but this can be fragile as error messages -change over time, and a test may no longer be checking the right thing but will -still pass. +substring must not appear anywhere in the compiler output. +This can be useful to ensure certain errors do not appear, but this can be fragile as error messages +change over time, and a test may no longer be checking the right thing but will still pass. `cfail` tests support the `should-ice` directive to specify that a test should -cause an Internal Compiler Error (ICE). This is a highly specialized directive +cause an Internal Compiler Error (ICE). +This is a highly specialized directive to check that the incremental cache continues to work after an ICE. -Incremental tests may use the attribute `#[rustc_clean(...)]` attribute. This attribute compares -the fingerprint from the current compilation session with the previous one. +Incremental tests may use the attribute `#[rustc_clean(...)]` attribute. +This attribute compares the fingerprint from the current compilation session with the previous one. The first revision should never have an active `rustc_clean` attribute, since it will always be dirty. -In the default mode, it asserts that the fingerprints must be the same. +In the default mode, it asserts that the fingerprints must be the same. The attribute takes the following arguments: * `cfg=""` — checks the cfg condition ``, and only runs the check if the config condition evaluates to true. @@ -204,9 +207,10 @@ The attribute takes the following arguments: * `except=",,..."` — asserts that the query results for the listed queries must be different, rather than the same. * `loaded_from_disk=",,..."` — asserts that the query results for the listed queries - were actually loaded from disk (not just marked green). + were actually loaded from disk (not just marked green). This can be useful to ensure that a test is actually exercising the deserialization - logic for a particular query result. This can be combined with `except`. + logic for a particular query result. + This can be combined with `except`. A simple example of a test using `rustc_clean` is the [hello_world test]. @@ -215,9 +219,9 @@ A simple example of a test using `rustc_clean` is the [hello_world test]. ### Debuginfo tests -The tests in [`tests/debuginfo`] test debuginfo generation. They build a -program, launch a debugger, and issue commands to the debugger. A single test -can work with cdb, gdb, and lldb. +The tests in [`tests/debuginfo`] test debuginfo generation. +They build a program, launch a debugger, and issue commands to the debugger. +A single test can work with cdb, gdb, and lldb. Most tests should have the `//@ compile-flags: -g` directive or something similar to generate the appropriate debuginfo. @@ -228,8 +232,7 @@ The debuginfo tests consist of a series of debugger commands along with "check" lines which specify output that is expected from the debugger. The commands are comments of the form `// $DEBUGGER-command:$COMMAND` where -`$DEBUGGER` is the debugger being used and `$COMMAND` is the debugger command -to execute. +`$DEBUGGER` is the debugger being used and `$COMMAND` is the debugger command to execute. The debugger values can be: @@ -245,8 +248,7 @@ The command to check the output are of the form `// $DEBUGGER-check:$OUTPUT` where `$OUTPUT` is the output to expect. For example, the following will build the test, start the debugger, set a -breakpoint, launch the program, inspect a value, and check what the debugger -prints: +breakpoint, launch the program, inspect a value, and check what the debugger prints: ```rust,ignore //@ compile-flags: -g @@ -268,17 +270,16 @@ the debugger currently being used: - `min-cdb-version: 10.0.18317.1001` — ignores the test if the version of cdb is below the given version -- `min-gdb-version: 8.2` — ignores the test if the version of gdb is below the - given version +- `min-gdb-version: 8.2` — ignores the test if the version of gdb is below the given version - `ignore-gdb-version: 9.2` — ignores the test if the version of gdb is equal to the given version - `ignore-gdb-version: 7.11.90 - 8.0.9` — ignores the test if the version of gdb is in a range (inclusive) -- `min-lldb-version: 310` — ignores the test if the version of lldb is below - the given version -- `rust-lldb` — ignores the test if lldb is not contain the Rust plugin. NOTE: - The "Rust" version of LLDB doesn't exist anymore, so this will always be - ignored. This should probably be removed. +- `min-lldb-version: 310` — ignores the test if the version of lldb is below the given version +- `rust-lldb` — ignores the test if lldb is not contain the Rust plugin. + NOTE: The "Rust" version of LLDB doesn't exist anymore, so this will always be + ignored. + This should probably be removed. By passing the `--debugger` option to compiletest, you can specify a single debugger to run tests with. For example, `./x test tests/debuginfo -- --debugger gdb` will only test GDB commands. @@ -311,17 +312,18 @@ For example, `./x test tests/debuginfo -- --debugger gdb` will only test GDB com ### Codegen tests -The tests in [`tests/codegen-llvm`] test LLVM code generation. They compile the -test with the `--emit=llvm-ir` flag to emit LLVM IR. They then run the LLVM -[FileCheck] tool. The test is annotated with various `// CHECK` comments to -check the generated code. See the [FileCheck] documentation for a tutorial and -more information. +The tests in [`tests/codegen-llvm`] test LLVM code generation. +They compile the test with the `--emit=llvm-ir` flag to emit LLVM IR. +They then run the LLVM [FileCheck] tool. +The test is annotated with various `// CHECK` comments to check the generated code. +See the [FileCheck] documentation for a tutorial and more information. See also the [assembly tests](#assembly-tests) for a similar set of tests. By default, codegen tests will have `//@ needs-target-std` *implied* (that the target needs to support std), *unless* the `#![no_std]`/`#![no_core]` attribute -was specified in the test source. You can override this behavior and explicitly +was specified in the test source. +You can override this behavior and explicitly write `//@ needs-target-std` to only run the test when target supports std, even if the test is `#![no_std]`/`#![no_core]`. @@ -334,17 +336,15 @@ If you need to work with `#![no_std]` cross-compiling tests, consult the ### Assembly tests -The tests in [`tests/assembly-llvm`] test LLVM assembly output. They compile the test -with the `--emit=asm` flag to emit a `.s` file with the assembly output. They -then run the LLVM [FileCheck] tool. +The tests in [`tests/assembly-llvm`] test LLVM assembly output. +They compile the test with the `--emit=asm` flag to emit a `.s` file with the assembly output. +They then run the LLVM [FileCheck] tool. Each test should be annotated with the `//@ assembly-output:` directive with a -value of either `emit-asm` or `ptx-linker` to indicate the type of assembly -output. +value of either `emit-asm` or `ptx-linker` to indicate the type of assembly output. -Then, they should be annotated with various `// CHECK` comments to check the -assembly output. See the [FileCheck] documentation for a tutorial and more -information. +Then, they should be annotated with various `// CHECK` comments to check the assembly output. +See the [FileCheck] documentation for a tutorial and more information. See also the [codegen tests](#codegen-tests) for a similar set of tests. @@ -364,13 +364,11 @@ monomorphization collection pass, i.e., `-Zprint-mono-items`, and then special annotations in the file are used to compare against that. Then, the test should be annotated with comments of the form `//~ MONO_ITEM -name` where `name` is the monomorphized string printed by rustc like `fn ::foo`. +name` where `name` is the monomorphized string printed by rustc like `fn ::foo`. To check for CGU partitioning, a comment of the form `//~ MONO_ITEM name @@ cgu` -where `cgu` is a space separated list of the CGU names and the linkage -information in brackets. For example: `//~ MONO_ITEM static function::FOO @@ -statics[Internal]` +where `cgu` is a space separated list of the CGU names and the linkage information in brackets. +For example: `//~ MONO_ITEM static function::FOO @@ statics[Internal]` [`tests/codegen-units`]: https://github.com/rust-lang/rust/tree/HEAD/tests/codegen-units @@ -378,8 +376,8 @@ statics[Internal]` ### Mir-opt tests The tests in [`tests/mir-opt`] check parts of the generated MIR to make sure it -is generated correctly and is doing the expected optimizations. Check out the -[MIR Optimizations](../mir/optimizations.md) chapter for more. +is generated correctly and is doing the expected optimizations. +Check out the [MIR Optimizations](../mir/optimizations.md) chapter for more. Compiletest will build the test with several flags to dump the MIR output and set a baseline for optimizations: @@ -391,23 +389,24 @@ set a baseline for optimizations: * `-Zdump-mir-exclude-pass-number` The test should be annotated with `// EMIT_MIR` comments that specify files that -will contain the expected MIR output. You can use `x test --bless` to create the -initial expected files. +will contain the expected MIR output. +You can use `x test --bless` to create the initial expected files. There are several forms the `EMIT_MIR` comment can take: - `// EMIT_MIR $MIR_PATH.mir` — This will check that the given filename matches - the exact output from the MIR dump. For example, + the exact output from the MIR dump. + For example, `my_test.main.SimplifyCfg-elaborate-drops.after.mir` will load that file from the test directory, and compare it against the dump from rustc. Checking the "after" file (which is after optimization) is useful if you are - interested in the final state after an optimization. Some rare cases may want - to use the "before" file for completeness. + interested in the final state after an optimization. + Some rare cases may want to use the "before" file for completeness. - `// EMIT_MIR $MIR_PATH.diff` — where `$MIR_PATH` is the filename of the MIR - dump, such as `my_test_name.my_function.EarlyOtherwiseBranch`. Compiletest - will diff the `.before.mir` and `.after.mir` files, and compare the diff + dump, such as `my_test_name.my_function.EarlyOtherwiseBranch`. + Compiletest will diff the `.before.mir` and `.after.mir` files, and compare the diff output to the expected `.diff` file from the `EMIT_MIR` comment. This is useful if you want to see how an optimization changes the MIR. @@ -417,8 +416,8 @@ There are several forms the `EMIT_MIR` comment can take: check that the output matches the given file. By default 32 bit and 64 bit targets use the same dump files, which can be -problematic in the presence of pointers in constants or other bit width -dependent things. In that case you can add `// EMIT_MIR_FOR_EACH_BIT_WIDTH` to +problematic in the presence of pointers in constants or other bit width dependent things. +In that case you can add `// EMIT_MIR_FOR_EACH_BIT_WIDTH` to your test, causing separate files to be generated for 32bit and 64bit systems. [`tests/mir-opt`]: https://github.com/rust-lang/rust/tree/HEAD/tests/mir-opt @@ -428,9 +427,8 @@ your test, causing separate files to be generated for 32bit and 64bit systems. The tests in [`tests/run-make`] and [`tests/run-make-cargo`] are general-purpose tests using Rust *recipes*, which are small programs (`rmake.rs`) allowing -arbitrary Rust code such as `rustc` invocations, and is supported by a -[`run_make_support`] library. Using Rust recipes provide the ultimate in -flexibility. +arbitrary Rust code such as `rustc` invocations, and is supported by a [`run_make_support`] library. +Using Rust recipes provide the ultimate in flexibility. `run-make` tests should be used if no other test suites better suit your needs. @@ -441,9 +439,9 @@ faster-to-iterate test suite). ### `build-std` tests -The tests in [`tests/build-std`] check that `-Zbuild-std` works. This is currently -just a run-make test suite with a single recipe. The recipe generates test cases -and runs them in parallel. +The tests in [`tests/build-std`] check that `-Zbuild-std` works. +This is currently just a run-make test suite with a single recipe. +The recipe generates test cases and runs them in parallel. [`tests/build-std`]: https://github.com/rust-lang/rust/tree/HEAD/tests/build-std @@ -457,18 +455,16 @@ If you need new utilities or functionality, consider extending and improving the [`run_make_support`] library. Compiletest directives like `//@ only-` or `//@ ignore-` are -supported in `rmake.rs`, like in UI tests. However, revisions or building -auxiliary via directives are not currently supported. +supported in `rmake.rs`, like in UI tests. +However, revisions or building auxiliary via directives are not currently supported. `rmake.rs` and `run-make-support` may *not* use any nightly/unstable features, -as they must be compilable by a stage 0 rustc that may be a beta or even stable -rustc. +as they must be compilable by a stage 0 rustc that may be a beta or even stable rustc. #### Quickly check if `rmake.rs` tests can be compiled You can quickly check if `rmake.rs` tests can be compiled without having to -build stage1 rustc by forcing `rmake.rs` to be compiled with the stage0 -compiler: +build stage1 rustc by forcing `rmake.rs` to be compiled with the stage0 compiler: ```bash $ COMPILETEST_FORCE_STAGE0=1 x test --stage 0 tests/run-make/ @@ -525,7 +521,8 @@ Then add a corresponding entry to `"rust-analyzer.linkedProjects"` ### Coverage tests The tests in [`tests/coverage`] are shared by multiple test modes that test -coverage instrumentation in different ways. Running the `coverage` test suite +coverage instrumentation in different ways. +Running the `coverage` test suite will automatically run each test in all of the different coverage modes. Each mode also has an alias to run the coverage tests in just that mode: @@ -543,31 +540,28 @@ Each mode also has an alias to run the coverage tests in just that mode: ``` If a particular test should not be run in one of the coverage test modes for -some reason, use the `//@ ignore-coverage-map` or `//@ ignore-coverage-run` -directives. +some reason, use the `//@ ignore-coverage-map` or `//@ ignore-coverage-run` directives. #### `coverage-map` suite In `coverage-map` mode, these tests verify the mappings between source code -regions and coverage counters that are emitted by LLVM. They compile the test -with `--emit=llvm-ir`, then use a custom tool ([`src/tools/coverage-dump`]) to -extract and pretty-print the coverage mappings embedded in the IR. These tests -don't require the profiler runtime, so they run in PR CI jobs and are easy to +regions and coverage counters that are emitted by LLVM. +They compile the test with `--emit=llvm-ir`, then use a custom tool ([`src/tools/coverage-dump`]) to +extract and pretty-print the coverage mappings embedded in the IR. +These tests don't require the profiler runtime, so they run in PR CI jobs and are easy to run/bless locally. These coverage map tests can be sensitive to changes in MIR lowering or MIR -optimizations, producing mappings that are different but produce identical -coverage reports. +optimizations, producing mappings that are different but produce identical coverage reports. As a rule of thumb, any PR that doesn't change coverage-specific code should **feel free to re-bless** the `coverage-map` tests as necessary, without -worrying about the actual changes, as long as the `coverage-run` tests still -pass. +worrying about the actual changes, as long as the `coverage-run` tests still pass. #### `coverage-run` suite -In `coverage-run` mode, these tests perform an end-to-end test of coverage -reporting. They compile a test program with coverage instrumentation, run that +In `coverage-run` mode, these tests perform an end-to-end test of coverage reporting. +They compile a test program with coverage instrumentation, run that program to produce raw coverage data, and then use LLVM tools to process that data into a human-readable code coverage report. @@ -587,8 +581,8 @@ as part of the full set of CI jobs used for merging. #### `coverage-run-rustdoc` suite The tests in [`tests/coverage-run-rustdoc`] also run instrumented doctests and -include them in the coverage report. This avoids having to build rustdoc when -only running the main `coverage` suite. +include them in the coverage report. +This avoids having to build rustdoc when only running the main `coverage` suite. [`tests/coverage`]: https://github.com/rust-lang/rust/tree/HEAD/tests/coverage [`src/tools/coverage-dump`]: https://github.com/rust-lang/rust/tree/HEAD/src/tools/coverage-dump @@ -597,13 +591,12 @@ only running the main `coverage` suite. ### Crash tests [`tests/crashes`] serve as a collection of tests that are expected to cause the -compiler to ICE, panic or crash in some other way, so that accidental fixes are -tracked. Formerly, this was done at but +compiler to ICE, panic or crash in some other way, so that accidental fixes are tracked. +Formerly, this was done at but doing it inside the rust-lang/rust testsuite is more convenient. -It is imperative that a test in the suite causes rustc to ICE, panic, or -crash in some other way. A test will "pass" if rustc exits with an exit status -other than 1 or 0. +It is imperative that a test in the suite causes rustc to ICE, panic, or crash in some other way. +A test will "pass" if rustc exits with an exit status other than 1 or 0. If you want to see verbose stdout/stderr, you need to set `COMPILETEST_VERBOSE_CRASHES=1`, e.g. @@ -612,16 +605,15 @@ If you want to see verbose stdout/stderr, you need to set $ COMPILETEST_VERBOSE_CRASHES=1 ./x test tests/crashes/999999.rs --stage 1 ``` -Anyone can add ["untracked" crashes] from the issue tracker. It's strongly -recommended to include test cases from several issues in a single PR. +Anyone can add ["untracked" crashes] from the issue tracker. +It's strongly recommended to include test cases from several issues in a single PR. When you do so, each issue number should be noted in the file name (`12345.rs` -should suffice) and also inside the file by means of a `//@ known-bug: #12345` -directive. Please [label][labeling] the relevant issues with `S-bug-has-test` -once your PR is merged. +should suffice) and also inside the file by means of a `//@ known-bug: #12345` directive. +Please [label][labeling] the relevant issues with `S-bug-has-test` once your PR is merged. If you happen to fix one of the crashes, please move it to a fitting -subdirectory in `tests/ui` and give it a meaningful name. Please add a doc -comment at the top of the file explaining why this test exists, even better if +subdirectory in `tests/ui` and give it a meaningful name. +Please add a doc comment at the top of the file explaining why this test exists, even better if you can briefly explain how the example causes rustc to crash previously and what was done to prevent rustc to ICE / panic / crash. @@ -635,8 +627,8 @@ Fixes #MMMMM to the description of your pull request will ensure the corresponding tickets be closed automatically upon merge. -Make sure that your fix actually fixes the root cause of the issue and not just -a subset first. The issue numbers can be found in the file name or the `//@ +Make sure that your fix actually fixes the root cause of the issue and not just a subset first. +The issue numbers can be found in the file name or the `//@ known-bug` directive inside the test file. [`tests/crashes`]: https://github.com/rust-lang/rust/tree/HEAD/tests/crashes @@ -654,8 +646,8 @@ There are multiple [directives](directives.md) to assist with that: - `aux-codegen-backend` - `proc-macro` -`aux-build` will build a separate crate from the named source file. The source -file should be in a directory called `auxiliary` beside the test file. +`aux-build` will build a separate crate from the named source file. +The source file should be in a directory called `auxiliary` beside the test file. ```rust,ignore //@ aux-build: my-helper.rs @@ -665,44 +657,48 @@ extern crate my_helper; ``` The aux crate will be built as a dylib if possible (unless on a platform that -does not support them, or the `no-prefer-dynamic` header is specified in the aux -file). The `-L` flag is used to find the extern crates. +does not support them, or the `no-prefer-dynamic` header is specified in the aux file). +The `-L` flag is used to find the extern crates. -`aux-crate` is very similar to `aux-build`. However, it uses the `--extern` flag +`aux-crate` is very similar to `aux-build`. +However, it uses the `--extern` flag to link to the extern crate to make the crate be available as an extern prelude. That allows you to specify the additional syntax of the `--extern` flag, such as -renaming a dependency. For example, `//@ aux-crate:foo=bar.rs` will compile +renaming a dependency. +For example, `//@ aux-crate:foo=bar.rs` will compile `auxiliary/bar.rs` and make it available under then name `foo` within the test. -This is similar to how Cargo does dependency renaming. It is also possible to +This is similar to how Cargo does dependency renaming. +It is also possible to specify [`--extern` modifiers](https://github.com/rust-lang/rust/issues/98405). For example, `//@ aux-crate:noprelude:foo=bar.rs`. -`aux-bin` is similar to `aux-build` but will build a binary instead of a -library. The binary will be available in `auxiliary/bin` relative to the working -directory of the test. +`aux-bin` is similar to `aux-build` but will build a binary instead of a library. +The binary will be available in `auxiliary/bin` relative to the working directory of the test. `aux-codegen-backend` is similar to `aux-build`, but will then pass the compiled -dylib to `-Zcodegen-backend` when building the main file. This will only work -for tests in `tests/ui-fulldeps`, since it requires the use of compiler crates. +dylib to `-Zcodegen-backend` when building the main file. +This will only work for tests in `tests/ui-fulldeps`, since it requires the use of compiler crates. ### Auxiliary proc-macro If you want a proc-macro dependency, then you can use the `proc-macro` directive. This directive behaves just like `aux-build`, i.e. that you should place the proc-macro test auxiliary file under a `auxiliary` folder under the -same parent folder as the main test file. However, it also has four additional +same parent folder as the main test file. +However, it also has four additional preset behavior compared to `aux-build` for the proc-macro test auxiliary: 1. The aux test file is built with `--crate-type=proc-macro`. 2. The aux test file is built without `-C prefer-dynamic`, i.e. it will not try to produce a dylib for the aux crate. 3. The aux crate is made available to the test file via extern prelude with - `--extern `. Note that since UI tests default to edition + `--extern `. + Note that since UI tests default to edition 2015, you still need to specify `extern ` unless the main test file is using an edition that is 2018 or newer if you want to use the aux crate name in a `use` import. -4. The `proc_macro` crate is made available as an extern prelude module. Same - edition 2015 vs newer edition distinction for `extern proc_macro;` applies. +4. The `proc_macro` crate is made available as an extern prelude module. + Same edition 2015 vs newer edition distinction for `extern proc_macro;` applies. For example, you might have a test `tests/ui/cat/meow.rs` and proc-macro auxiliary `tests/ui/cat/auxiliary/whiskers.rs`: @@ -744,19 +740,19 @@ pub fn identity(ts: TokenStream) -> TokenStream { ## Revisions -Revisions allow a single test file to be used for multiple tests. This is done -by adding a special directive at the top of the file: +Revisions allow a single test file to be used for multiple tests. +This is done by adding a special directive at the top of the file: ```rust,ignore //@ revisions: foo bar baz ``` This will result in the test being compiled (and tested) three times, once with -`--cfg foo`, once with `--cfg bar`, and once with `--cfg baz`. You can therefore -use `#[cfg(foo)]` etc within the test to tweak each of these results. +`--cfg foo`, once with `--cfg bar`, and once with `--cfg baz`. +You can therefore use `#[cfg(foo)]` etc within the test to tweak each of these results. -You can also customize directives and expected error messages to a particular -revision. To do this, add `[revision-name]` after the `//@` for directives, and +You can also customize directives and expected error messages to a particular revision. +To do this, add `[revision-name]` after the `//@` for directives, and after `//` for UI error annotations, like so: ```rust,ignore @@ -769,8 +765,7 @@ fn test_foo() { } ``` -Multiple revisions can be specified in a comma-separated list, such as -`//[foo,bar,baz]~^`. +Multiple revisions can be specified in a comma-separated list, such as `//[foo,bar,baz]~^`. In test suites that use the LLVM [FileCheck] tool, the current revision name is also registered as an additional prefix for FileCheck directives: @@ -787,14 +782,13 @@ also registered as an additional prefix for FileCheck directives: fn main() {} ``` -Note that not all directives have meaning when customized to a revision. For -example, the `ignore-test` directives (and all "ignore" directives) currently -only apply to the test as a whole, not to particular revisions. The only -directives that are intended to really work when customized to a revision are +Note that not all directives have meaning when customized to a revision. +For example, the `ignore-test` directives (and all "ignore" directives) currently +only apply to the test as a whole, not to particular revisions. +The only directives that are intended to really work when customized to a revision are error patterns and compiler flags. - -The following test suites support revisions: + The following test suites support revisions: - ui - assembly @@ -802,14 +796,13 @@ The following test suites support revisions: - coverage - debuginfo - rustdoc UI tests -- incremental (these are special in that they inherently cannot be run in - parallel) +- incremental (these are special in that they inherently cannot be run in parallel) ### Ignoring unused revision names Normally, revision names mentioned in other directives and error annotations -must correspond to an actual revision declared in a `revisions` directive. This is -enforced by an `./x test tidy` check. +must correspond to an actual revision declared in a `revisions` directive. +This is enforced by an `./x test tidy` check. If a revision name needs to be temporarily removed from the revision list for some reason, the above check can be suppressed by adding the revision name to an @@ -825,8 +818,7 @@ used to compare the behavior of all tests with different compiler flags enabled. This can help highlight what differences might appear with certain flags, and check for any problems that might arise. -To run the tests in a different mode, you need to pass the `--compare-mode` CLI -flag: +To run the tests in a different mode, you need to pass the `--compare-mode` CLI flag: ```bash ./x test tests/ui --compare-mode=chalk @@ -836,20 +828,17 @@ The possible compare modes are: - `polonius` — Runs with Polonius with `-Zpolonius`. - `chalk` — Runs with Chalk with `-Zchalk`. -- `split-dwarf` — Runs with unpacked split-DWARF with - `-Csplit-debuginfo=unpacked`. -- `split-dwarf-single` — Runs with packed split-DWARF with - `-Csplit-debuginfo=packed`. +- `split-dwarf` — Runs with unpacked split-DWARF with `-Csplit-debuginfo=unpacked`. +- `split-dwarf-single` — Runs with packed split-DWARF with `-Csplit-debuginfo=packed`. See [UI compare modes](ui.md#compare-modes) for more information about how UI tests support different output for different modes. -In CI, compare modes are only used in one Linux builder, and only with the -following settings: +In CI, compare modes are only used in one Linux builder, and only with the following settings: -- `tests/debuginfo`: Uses `split-dwarf` mode. This helps ensure that none of the - debuginfo tests are affected when enabling split-DWARF. +- `tests/debuginfo`: Uses `split-dwarf` mode. + This helps ensure that none of the debuginfo tests are affected when enabling split-DWARF. -Note that compare modes are separate to [revisions](#revisions). All revisions -are tested when running `./x test tests/ui`, however compare-modes must be +Note that compare modes are separate to [revisions](#revisions). +All revisions are tested when running `./x test tests/ui`, however compare-modes must be manually run individually via the `--compare-mode` flag. From b643676267642909e67e5479dc47abc676cccdb7 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 29 Jan 2026 21:57:55 +0200 Subject: [PATCH 244/978] misc improvements --- src/doc/rustc-dev-guide/src/tests/compiletest.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 06a4728c93e1..f0da634129ee 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -204,9 +204,9 @@ The attribute takes the following arguments: * `cfg=""` — checks the cfg condition ``, and only runs the check if the config condition evaluates to true. This can be used to only run the `rustc_clean` attribute in a specific revision. -* `except=",,..."` — asserts that the query results for the listed queries must be different, +* `except=",,..."` — asserts that the query results for the listed queries must be different, rather than the same. -* `loaded_from_disk=",,..."` — asserts that the query results for the listed queries +* `loaded_from_disk=",,..."` — asserts that the query results for the listed queries were actually loaded from disk (not just marked green). This can be useful to ensure that a test is actually exercising the deserialization logic for a particular query result. @@ -288,12 +288,12 @@ For example, `./x test tests/debuginfo -- --debugger gdb` will only test GDB com > > If you want to run lldb debuginfo tests locally, then currently on Windows it > is required that: -> +> > - You have Python 3.10 installed. > - You have `python310.dll` available in your `PATH` env var. This is not > provided by the standard Python installer you obtain from `python.org`; you > need to add this to `PATH` manually. -> +> > Otherwise the lldb debuginfo tests can produce crashes in mysterious ways. [`tests/debuginfo`]: https://github.com/rust-lang/rust/tree/HEAD/tests/debuginfo @@ -613,9 +613,9 @@ Please [label][labeling] the relevant issues with `S-bug-has-test` once your PR If you happen to fix one of the crashes, please move it to a fitting subdirectory in `tests/ui` and give it a meaningful name. -Please add a doc comment at the top of the file explaining why this test exists, even better if -you can briefly explain how the example causes rustc to crash previously and -what was done to prevent rustc to ICE / panic / crash. +Please add a doc comment at the top of the file explaining why this test exists. +Even better will be if you can briefly explain how the example caused rustc to crash previously, +and what was done to fix it. Adding @@ -698,7 +698,7 @@ preset behavior compared to `aux-build` for the proc-macro test auxiliary: test file is using an edition that is 2018 or newer if you want to use the aux crate name in a `use` import. 4. The `proc_macro` crate is made available as an extern prelude module. - Same edition 2015 vs newer edition distinction for `extern proc_macro;` applies. + The same edition 2015 vs newer edition distinction for `extern proc_macro;` applies. For example, you might have a test `tests/ui/cat/meow.rs` and proc-macro auxiliary `tests/ui/cat/auxiliary/whiskers.rs`: From 93049c34888173bec0e849f69df23ff7359a85ae Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 29 Jan 2026 22:06:56 +0200 Subject: [PATCH 245/978] fix sembr tool corner case --- src/doc/rustc-dev-guide/ci/sembr/src/main.rs | 1 + src/doc/rustc-dev-guide/src/tests/compiletest.md | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index 6f4ce4415f04..1de0638deb97 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -83,6 +83,7 @@ fn ignore(line: &str, in_code_block: bool) -> bool { || line.contains(" etc.") || line.contains("i.e.") || line.contains("et. al") + || line.contains(" The following test suites support revisions: + +The following test suites support revisions: - ui - assembly From 03b8ebb91c2331180bce6273026b88f8bb94d215 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 29 Jan 2026 22:09:02 +0200 Subject: [PATCH 246/978] sembr src/tests/ui.md --- src/doc/rustc-dev-guide/src/tests/ui.md | 315 ++++++++++++------------ 1 file changed, 157 insertions(+), 158 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index b7cf446c4a57..bd058fbed02e 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -1,20 +1,18 @@ # UI tests -UI tests are a particular [test suite](compiletest.md#test-suites) of -compiletest. +UI tests are a particular [test suite](compiletest.md#test-suites) of compiletest. ## Introduction The tests in [`tests/ui`] are a collection of general-purpose tests which primarily focus on validating the console output of the compiler, but can be -used for many other purposes. For example, tests can also be configured to [run -the resulting program](#controlling-passfail-expectations) to verify its -behavior. +used for many other purposes. +For example, tests can also be configured to [run +the resulting program](#controlling-passfail-expectations) to verify its behavior. For a survey of each subdirectory's purpose under `tests/ui`, consult the [README.md](https://github.com/rust-lang/rust/tree/HEAD/tests/ui/README.md). -This is useful if you write a new test, and are looking for a category to -place it in. +This is useful if you write a new test, and are looking for a category to place it in. If you need to work with `#![no_std]` cross-compiling tests, consult the [`minicore` test auxiliary](./minicore.md) chapter. @@ -28,61 +26,63 @@ A test consists of a Rust source file located in the `tests/ui` directory. and testing category - placing tests directly in `tests/ui` is not permitted. Compiletest will use `rustc` to compile the test, and compare the output against -the expected output which is stored in a `.stdout` or `.stderr` file located -next to the test. See [Output comparison](#output-comparison) for more. +the expected output which is stored in a `.stdout` or `.stderr` file located next to the test. +See [Output comparison](#output-comparison) for more. -Additionally, errors and warnings should be annotated with comments within the -source file. See [Error annotations](#error-annotations) for more. +Additionally, errors and warnings should be annotated with comments within the source file. +See [Error annotations](#error-annotations) for more. Compiletest [directives](directives.md) in the form of special comments prefixed with `//@` control how the test is compiled and what the expected behavior is. -Tests are expected to fail to compile, since most tests are testing compiler -errors. You can change that behavior with a directive, see [Controlling +Tests are expected to fail to compile, since most tests are testing compiler errors. +You can change that behavior with a directive, see [Controlling pass/fail expectations](#controlling-passfail-expectations). -By default, a test is built as an executable binary. If you need a different -crate type, you can use the `#![crate_type]` attribute to set it as needed. +By default, a test is built as an executable binary. +If you need a different crate type, you can use the `#![crate_type]` attribute to set it as needed. ## Output comparison UI tests store the expected output from the compiler in `.stderr` and `.stdout` -snapshots next to the test. You normally generate these files with the `--bless` -CLI option, and then inspect them manually to verify they contain what you -expect. +snapshots next to the test. +You normally generate these files with the `--bless` +CLI option, and then inspect them manually to verify they contain what you expect. The output is normalized to ignore unwanted differences, see the -[Normalization](#normalization) section. If the file is missing, then -compiletest expects the corresponding output to be empty. +[Normalization](#normalization) section. +If the file is missing, then compiletest expects the corresponding output to be empty. A common reason to use normalization, revisions, and most of the other following tools, -is to account for platform differences. Consider alternatives to these tools, like +is to account for platform differences. +Consider alternatives to these tools, like e.g. using the `extern "rust-invalid"` ABI that is invalid on every platform instead of fixing the test to use cross-compilation and testing every possibly-invalid ABI. -There can be multiple stdout/stderr files. The general form is: +There can be multiple stdout/stderr files. +The general form is: ```text *test-name*`.`*revision*`.`*compare_mode*`.`*extension* ``` -- *test-name* cannot contain dots. This is so that the general form of test +- *test-name* cannot contain dots. + This is so that the general form of test output filenames have a predictable form we can pattern match on in order to track stray test output files. -- *revision* is the [revision](#cfg-revisions) name. This is not included when - not using revisions. -- *compare_mode* is the [compare mode](#compare-modes). This will only be - checked when the given compare mode is active. If the file does not exist, +- *revision* is the [revision](#cfg-revisions) name. + This is not included when not using revisions. +- *compare_mode* is the [compare mode](#compare-modes). + This will only be checked when the given compare mode is active. + If the file does not exist, then compiletest will check for a file without the compare mode. - *extension* is the kind of output being checked: - `stderr` — compiler stderr - `stdout` — compiler stdout - `run.stderr` — stderr when running the test - `run.stdout` — stdout when running the test - - `64bit.stderr` — compiler stderr with `stderr-per-bitwidth` directive on a - 64-bit target - - `32bit.stderr` — compiler stderr with `stderr-per-bitwidth` directive on a - 32-bit target + - `64bit.stderr` — compiler stderr with `stderr-per-bitwidth` directive on a 64-bit target + - `32bit.stderr` — compiler stderr with `stderr-per-bitwidth` directive on a 32-bit target A simple example would be `foo.stderr` next to a `foo.rs` test. A more complex example would be `foo.my-revision.polonius.stderr`. @@ -90,17 +90,16 @@ A more complex example would be `foo.my-revision.polonius.stderr`. There are several [directives](directives.md) which will change how compiletest will check for output files: -- `stderr-per-bitwidth` — checks separate output files based on the target - pointer width. Consider using the `normalize-stderr` directive instead (see - [Normalization](#normalization)). +- `stderr-per-bitwidth` — checks separate output files based on the target pointer width. + Consider using the `normalize-stderr` directive instead (see [Normalization](#normalization)). - `dont-check-compiler-stderr` — Ignores stderr from the compiler. - `dont-check-compiler-stdout` — Ignores stdout from the compiler. - `compare-output-by-lines` — Some tests have non-deterministic orders of output, so we need to compare by lines. UI tests run with `-Zdeduplicate-diagnostics=no` flag which disables rustc's -built-in diagnostic deduplication mechanism. This means you may see some -duplicate messages in the output. This helps illuminate situations where -duplicate diagnostics are being generated. +built-in diagnostic deduplication mechanism. +This means you may see some duplicate messages in the output. +This helps illuminate situations where duplicate diagnostics are being generated. ### Normalization @@ -109,22 +108,22 @@ platforms, mainly about filenames. Compiletest makes the following replacements on the compiler output: -- The directory where the test is defined is replaced with `$DIR`. Example: - `/path/to/rust/tests/ui/error-codes` +- The directory where the test is defined is replaced with `$DIR`. + Example: `/path/to/rust/tests/ui/error-codes` - The directory to the standard library source is replaced with `$SRC_DIR`. Example: `/path/to/rust/library` - Line and column numbers for paths in `$SRC_DIR` are replaced with `LL:COL`. This helps ensure that changes to the layout of the standard library do not - cause widespread changes to the `.stderr` files. Example: - `$SRC_DIR/alloc/src/sync.rs:53:46` -- The base directory where the test's output goes is replaced with - `$TEST_BUILD_DIR`. This only comes up in a few rare circumstances. Example: - `/path/to/rust/build/x86_64-unknown-linux-gnu/test/ui` + cause widespread changes to the `.stderr` files. + Example: `$SRC_DIR/alloc/src/sync.rs:53:46` +- The base directory where the test's output goes is replaced with `$TEST_BUILD_DIR`. + This only comes up in a few rare circumstances. + Example: `/path/to/rust/build/x86_64-unknown-linux-gnu/test/ui` - The real directory to the standard library source is replaced with `$SRC_DIR_REAL`. - The real directory to the compiler source is replaced with `$COMPILER_DIR_REAL`. - Tabs are replaced with `\t`. -- Backslashes (`\`) are converted to forward slashes (`/`) within paths (using a - heuristic). This helps normalize differences with Windows-style paths. +- Backslashes (`\`) are converted to forward slashes (`/`) within paths (using a heuristic). + This helps normalize differences with Windows-style paths. - CRLF newlines are converted to LF. - Error line annotations like `//~ ERROR some message` are removed. - Various v0 and legacy symbol hashes are replaced with placeholders like @@ -135,8 +134,8 @@ the compiler itself to apply some changes to the diagnostic output to make it more suitable for UI testing. For example, it will anonymize line numbers in the output (line numbers -prefixing each source line are replaced with `LL`). In extremely rare -situations, this mode can be disabled with the directive `//@ +prefixing each source line are replaced with `LL`). +In extremely rare situations, this mode can be disabled with the directive `//@ compile-flags: -Z ui-testing=no`. When using `-Z ui-testing=no`, the `--diagnostic-width` argument should also @@ -144,12 +143,14 @@ be set to avoid tests failing or passing depending on the width of the terminal from which the UI test suite is being run. Note: The line and column numbers for `-->` lines pointing to the test are *not* -normalized, and left as-is. This ensures that the compiler continues to point to -the correct location, and keeps the stderr files readable. Ideally all -line/column information would be retained, but small changes to the source +normalized, and left as-is. +This ensures that the compiler continues to point to +the correct location, and keeps the stderr files readable. +Ideally all line/column information would be retained, but small changes to the source causes large diffs, and more frequent merge conflicts and test errors. -Sometimes these built-in normalizations are not enough. In such cases, you may +Sometimes these built-in normalizations are not enough. +In such cases, you may provide custom normalization rules using `normalize-*` directives, e.g. ```rust,ignore @@ -161,8 +162,8 @@ provide custom normalization rules using `normalize-*` directives, e.g. This tells the test, on 32-bit platforms, whenever the compiler writes `fn() (32 bits)` to stderr, it should be normalized to read `fn() ($PTR bits)` instead. -Similar for 64-bit. The replacement is performed by regexes using default regex -flavor provided by `regex` crate. +Similar for 64-bit. +The replacement is performed by regexes using default regex flavor provided by `regex` crate. The corresponding reference file will use the normalized output to test both 32-bit and 64-bit platforms: @@ -175,16 +176,15 @@ The corresponding reference file will use the normalized output to test both ... ``` -Please see [`ui/transmute/main.rs`][mrs] and [`main.stderr`] for a concrete -usage example. +Please see [`ui/transmute/main.rs`][mrs] and [`main.stderr`] for a concrete usage example. [mrs]: https://github.com/rust-lang/rust/blob/HEAD/tests/ui/transmute/main.rs [`main.stderr`]: https://github.com/rust-lang/rust/blob/HEAD/tests/ui/transmute/main.stderr ## Error annotations -Error annotations specify the errors that the compiler is expected to emit. They -are "attached" to the line in source where the error is located. +Error annotations specify the errors that the compiler is expected to emit. +They are "attached" to the line in source where the error is located. ```rust,ignore fn main() { @@ -193,30 +193,30 @@ fn main() { ``` Although UI tests have a `.stderr` file which contains the entire compiler -output, UI tests require that errors are also annotated within the source. This -redundancy helps avoid mistakes since the `.stderr` files are usually -auto-generated. It also helps to directly see where the error spans are expected -to point to by looking at one file instead of having to compare the `.stderr` -file with the source. Finally, they ensure that no additional unexpected errors -are generated. +output, UI tests require that errors are also annotated within the source. +This redundancy helps avoid mistakes since the `.stderr` files are usually +auto-generated. +It also helps to directly see where the error spans are expected +to point to by looking at one file instead of having to compare the `.stderr` file with the source. +Finally, they ensure that no additional unexpected errors are generated. They have several forms, but generally are a comment with the diagnostic level -(such as `ERROR`) and a substring of the expected error output. You don't have -to write out the entire message, just make sure to include the important part of +(such as `ERROR`) and a substring of the expected error output. +You don't have to write out the entire message, just make sure to include the important part of the message to make it self-documenting. -Most error annotations need to match with the line of the diagnostic. There are -several ways to match the message with the line (see the examples below): +Most error annotations need to match with the line of the diagnostic. +There are several ways to match the message with the line (see the examples below): * `~`: Associates the error level and message with the *current* line -* `~^`: Associates the error level and message with the *previous* error - annotation line. Each caret (`^`) that you add adds a line to this, so `~^^^` +* `~^`: Associates the error level and message with the *previous* error annotation line. + Each caret (`^`) that you add adds a line to this, so `~^^^` is three lines above the error annotation line. * `~|`: Associates the error level and message with the *same* line as the *previous comment*. This is more convenient than using multiple carets when there are multiple messages associated with the same line. -* `~v`: Associates the error level and message with the *next* error - annotation line. Each symbol (`v`) that you add adds a line to this, so `~vvv` +* `~v`: Associates the error level and message with the *next* error annotation line. + Each symbol (`v`) that you add adds a line to this, so `~vvv` is three lines below the error annotation line. Example: @@ -232,8 +232,9 @@ The space character between `//~` (or other variants) and the subsequent text is negligible (i.e. there is no semantic difference between `//~ ERROR` and `//~ERROR` although the former is more common in the codebase). -`~? ` (example being `~? ERROR`) -is used to match diagnostics _without_ line info at all, +`~? +` (example being `~? +ERROR`) is used to match diagnostics _without_ line info at all, or where the line info is outside the main test file[^main test file]. These annotations can be placed on any line in the test file. @@ -260,8 +261,8 @@ fn main() { #### Positioned below error line -Use the `//~^` idiom with number of carets in the string to indicate the number -of lines above. In the example below, the error line is four lines above the +Use the `//~^` idiom with number of carets in the string to indicate the number of lines above. +In the example below, the error line is four lines above the error annotation line so four carets are included in the annotation. ```rust,ignore @@ -296,8 +297,8 @@ fn main() { #### Positioned above error line -Use the `//~v` idiom with number of v's in the string to indicate the number -of lines below. This is typically used in lexer or parser tests matching on errors like unclosed +Use the `//~v` idiom with number of v's in the string to indicate the number of lines below. +This is typically used in lexer or parser tests matching on errors like unclosed delimiter or unclosed literal happening at the end of file. ```rust,ignore @@ -337,8 +338,8 @@ fn main() { ``` We want to ensure this shows "index out of bounds", but we cannot use the `ERROR` -annotation since the runtime error doesn't have any span. Then it's time to use the -`error-pattern` directive: +annotation since the runtime error doesn't have any span. +Then it's time to use the `error-pattern` directive: ```rust,ignore //@ error-pattern: index out of bounds @@ -385,7 +386,8 @@ by the compiler instead of or in addition to structured json. `//~` by default. Other kinds only need to be line-annotated if at least one annotation of that kind appears -in the test file. For example, one `//~ NOTE` will also require all other `//~ NOTE`s in the file +in the test file. +For example, one `//~ NOTE` will also require all other `//~ NOTE`s in the file to be written out explicitly. Use directive `//@ dont-require-annotations` to opt out of exhaustive annotations. @@ -398,15 +400,16 @@ for example secondary lines of multiline diagnostics, or ubiquitous diagnostics like `aborting due to N previous errors`. UI tests use the `-A unused` flag by default to ignore all unused warnings, as -unused warnings are usually not the focus of a test. However, simple code -samples often have unused warnings. If the test is specifically testing an +unused warnings are usually not the focus of a test. +However, simple code samples often have unused warnings. +If the test is specifically testing an unused warning, just add the appropriate `#![warn(unused)]` attribute as needed. ### `cfg` revisions When using [revisions](compiletest.md#revisions), different messages can be -conditionally checked based on the current revision. This is done by placing the -revision cfg name in brackets like this: +conditionally checked based on the current revision. +This is done by placing the revision cfg name in brackets like this: ```rust,ignore //@ edition:2018 @@ -428,7 +431,8 @@ In this example, the second error message is only emitted in the `mir` revision. The `thir` revision only emits the first error. If the `cfg` causes the compiler to emit different output, then a test can have -multiple `.stderr` files for the different outputs. In the example above, there +multiple `.stderr` files for the different outputs. +In the example above, there would be a `.mir.stderr` and `.thir.stderr` file with the different outputs of the different revisions. @@ -439,10 +443,10 @@ the different revisions. ## Controlling pass/fail expectations By default, a UI test is expected to **generate a compile error** because most -of the tests are checking for invalid input and error diagnostics. However, you -can also make UI tests where compilation is expected to succeed, and you can -even run the resulting program. Just add one of the following -[directives](directives.md): +of the tests are checking for invalid input and error diagnostics. +However, you can also make UI tests where compilation is expected to succeed, and you can +even run the resulting program. +Just add one of the following [directives](directives.md): - Pass directives: - `//@ check-pass` — compilation should succeed but skip codegen @@ -460,32 +464,33 @@ even run the resulting program. Just add one of the following - Second time is to ensure that the full compile fails - `//@ run-fail` — compilation should succeed, but running the resulting binary should make it exit with a code in the range `1..=127` which - indicates regular failure. On targets without unwind support, crashes - are also accepted. + indicates regular failure. + On targets without unwind support, crashes are also accepted. - `//@ run-crash` — compilation should succeed, but running the resulting - binary should fail with a crash. Crashing is defined as "not exiting with - a code in the range `0..=127`". Example on Linux: Termination by `SIGABRT` - or `SIGSEGV`. Example on Windows: Exiting with the code for - `STATUS_ILLEGAL_INSTRUCTION` (`0xC000001D`). + binary should fail with a crash. + Crashing is defined as "not exiting with a code in the range `0..=127`". + Example on Linux: Termination by `SIGABRT` or `SIGSEGV`. + Example on Windows: Exiting with the code for `STATUS_ILLEGAL_INSTRUCTION` (`0xC000001D`). - `//@ run-fail-or-crash` — compilation should succeed, but running the - resulting binary should either `run-fail` or `run-crash`. Useful if a test - crashes on some targets but just fails on others. + resulting binary should either `run-fail` or `run-crash`. + Useful if a test crashes on some targets but just fails on others. -For `run-pass`. `run-fail`, `run-crash` and `run-fail-or-crash` tests, by +For `run-pass`. +`run-fail`, `run-crash` and `run-fail-or-crash` tests, by default the output of the program itself is not checked. -If you want to check the output of running the program, include the -`check-run-results` directive. This will check for a `.run.stderr` and +If you want to check the output of running the program, include the `check-run-results` directive. +This will check for a `.run.stderr` and `.run.stdout` files to compare against the actual output of the program. -Tests with the `*-pass` directives can be overridden with the `--pass` -command-line option: +Tests with the `*-pass` directives can be overridden with the `--pass` command-line option: ```sh ./x test tests/ui --pass check ``` -The `--pass` option only affects UI tests. Using `--pass check` can run the UI +The `--pass` option only affects UI tests. +Using `--pass check` can run the UI test suite much faster (roughly twice as fast on my system), though obviously not exercising as much. @@ -496,13 +501,12 @@ test won't work properly with that override. ## Known bugs The `known-bug` directive may be used for tests that demonstrate a known bug -that has not yet been fixed. Adding tests for known bugs is helpful for several -reasons, including: +that has not yet been fixed. +Adding tests for known bugs is helpful for several reasons, including: -1. Maintaining a functional test that can be conveniently reused when the bug is - fixed. -2. Providing a sentinel that will fail if the bug is incidentally fixed. This - can alert the developer so they know that the associated issue has been fixed +1. Maintaining a functional test that can be conveniently reused when the bug is fixed. +2. Providing a sentinel that will fail if the bug is incidentally fixed. + This can alert the developer so they know that the associated issue has been fixed and can possibly be closed. This directive takes comma-separated issue numbers as arguments, or `"unknown"`: @@ -513,21 +517,21 @@ This directive takes comma-separated issue numbers as arguments, or `"unknown"`: - `//@ known-bug: unknown` (when there is no known issue yet; preferably open one if it does not already exist) -Do not include [error annotations](#error-annotations) in a test with -`known-bug`. The test should still include other normal directives and -stdout/stderr files. +Do not include [error annotations](#error-annotations) in a test with `known-bug`. +The test should still include other normal directives and stdout/stderr files. ## Test organization When deciding where to place a test file, please try to find a subdirectory that -best matches what you are trying to exercise. Do your best to keep things -organized. Admittedly it can be difficult as some tests can overlap different +best matches what you are trying to exercise. +Do your best to keep things organized. +Admittedly it can be difficult as some tests can overlap different categories, and the existing layout may not fit well. -Name the test by a concise description of what the test is checking. Avoid -including the issue number in the test name. See [best -practices](best-practices.md) for a more in-depth discussion of this. +Name the test by a concise description of what the test is checking. +Avoid including the issue number in the test name. +See [best practices](best-practices.md) for a more in-depth discussion of this. Ideally, the test should be added to a directory that helps identify what piece of code is being tested here (e.g., @@ -535,30 +539,29 @@ of code is being tested here (e.g., When writing a new feature, you may want to **create a subdirectory to store your tests**. For example, if you are implementing RFC 1234 ("Widgets"), then it -might make sense to put the tests in a directory like -`tests/ui/rfc1234-widgets/`. +might make sense to put the tests in a directory like `tests/ui/rfc1234-widgets/`. In other cases, there may already be a suitable directory. -Over time, the [`tests/ui`] directory has grown very fast. There is a check in -[tidy](intro.md#tidy) that will ensure none of the subdirectories has more than -1000 entries. Having too many files causes problems because it isn't editor/IDE -friendly and the GitHub UI won't show more than 1000 entries. However, since -`tests/ui` (UI test root directory) and `tests/ui/issues` directories have more -than 1000 entries, we set a different limit for those directories. So, please -avoid putting a new test there and try to find a more relevant place. +Over time, the [`tests/ui`] directory has grown very fast. +There is a check in [tidy](intro.md#tidy) that will ensure none of the subdirectories has more than +1000 entries. +Having too many files causes problems because it isn't editor/IDE +friendly and the GitHub UI won't show more than 1000 entries. +However, since `tests/ui` (UI test root directory) and `tests/ui/issues` directories have more +than 1000 entries, we set a different limit for those directories. +So, please avoid putting a new test there and try to find a more relevant place. -For example, if your test is related to closures, you should put it in -`tests/ui/closures`. When you reach the limit, you could increase it by tweaking -[here][ui test tidy]. +For example, if your test is related to closures, you should put it in `tests/ui/closures`. +When you reach the limit, you could increase it by tweaking [here][ui test tidy]. [ui test tidy]: https://github.com/rust-lang/rust/blob/HEAD/src/tools/tidy/src/ui_tests.rs ## Rustfix tests UI tests can validate that diagnostic suggestions apply correctly and that the -resulting changes compile correctly. This can be done with the `run-rustfix` -directive: +resulting changes compile correctly. +This can be done with the `run-rustfix` directive: ```rust,ignore //@ run-rustfix @@ -574,37 +577,34 @@ pub struct not_camel_case {} Rustfix tests should have a file with the `.fixed` extension which contains the source file after the suggestion has been applied. -- When the test is run, compiletest first checks that the correct lint/warning - is generated. -- Then, it applies the suggestion and compares against `.fixed` (they must - match). -- Finally, the fixed source is compiled, and this compilation is required to - succeed. +- When the test is run, compiletest first checks that the correct lint/warning is generated. +- Then, it applies the suggestion and compares against `.fixed` (they must match). +- Finally, the fixed source is compiled, and this compilation is required to succeed. Usually when creating a rustfix test you will generate the `.fixed` file automatically with the `x test --bless` option. The `run-rustfix` directive will cause *all* suggestions to be applied, even if -they are not [`MachineApplicable`](../diagnostics.md#suggestions). If this is a -problem, then you can add the `rustfix-only-machine-applicable` directive in -addition to `run-rustfix`. This should be used if there is a mixture of -different suggestion levels, and some of the non-machine-applicable ones do not -apply cleanly. +they are not [`MachineApplicable`](../diagnostics.md#suggestions). +If this is a problem, then you can add the `rustfix-only-machine-applicable` directive in +addition to `run-rustfix`. +This should be used if there is a mixture of +different suggestion levels, and some of the non-machine-applicable ones do not apply cleanly. ## Compare modes [Compare modes](compiletest.md#compare-modes) can be used to run all tests with -different flags from what they are normally compiled with. In some cases, this -might result in different output from the compiler. To support this, different +different flags from what they are normally compiled with. +In some cases, this might result in different output from the compiler. +To support this, different output files can be saved which contain the output based on the compare mode. For example, when using the Polonius mode, a test `foo.rs` will first look for -expected output in `foo.polonius.stderr`, falling back to the usual `foo.stderr` -if not found. This is useful as different modes can sometimes result in -different diagnostics and behavior. This can help track which tests have -differences between the modes, and to visually inspect those diagnostic -differences. +expected output in `foo.polonius.stderr`, falling back to the usual `foo.stderr` if not found. +This is useful as different modes can sometimes result in different diagnostics and behavior. +This can help track which tests have +differences between the modes, and to visually inspect those diagnostic differences. If in the rare case you encounter a test that has different behavior, you can run something like the following to generate the alternate stderr file: @@ -618,15 +618,15 @@ Currently none of the compare modes are checked in CI for UI tests. ## `rustc_*` TEST attributes The compiler defines several perma-unstable `#[rustc_*]` attributes gated behind -the internal feature `rustc_attrs` that dump extra compiler-internal -information. See the corresponding subsection in [compiler debugging] for more -details. +the internal feature `rustc_attrs` that dump extra compiler-internal information. +See the corresponding subsection in [compiler debugging] for more details. They can be used in tests to more precisely, legibly and easily test internal compiler state in cases where it would otherwise be very hard to do the same -with "user-facing" Rust alone. Indeed, one could say that this slightly abuses -the term "UI" (*user* interface) and turns such UI tests from black-box tests -into white-box ones. Use them carefully and sparingly. +with "user-facing" Rust alone. +Indeed, one could say that this slightly abuses +the term "UI" (*user* interface) and turns such UI tests from black-box tests into white-box ones. +Use them carefully and sparingly. [compiler debugging]: ../compiler-debugging.md#rustc_-test-attributes @@ -651,5 +651,4 @@ in-source lint level attributes as required. Note that the `rustfix` version will *not* have `-A unused` passed, meaning that you may have to `#[allow(unused)]` to suppress `unused` -lints on the rustfix'd file (because we might be testing rustfix -on `unused` lints themselves). +lints on the rustfix'd file (because we might be testing rustfix on `unused` lints themselves). From dd8ae230c7988165350502e01e45a999c1d89b0a Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 29 Jan 2026 23:08:29 +0200 Subject: [PATCH 247/978] some improvements --- src/doc/rustc-dev-guide/src/tests/ui.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index bd058fbed02e..0b5a5b3ccbab 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -202,8 +202,8 @@ Finally, they ensure that no additional unexpected errors are generated. They have several forms, but generally are a comment with the diagnostic level (such as `ERROR`) and a substring of the expected error output. -You don't have to write out the entire message, just make sure to include the important part of -the message to make it self-documenting. +You don't have to write out the entire message, +but be sure to include the important part of the message to make it self-documenting. Most error annotations need to match with the line of the diagnostic. There are several ways to match the message with the line (see the examples below): @@ -469,15 +469,14 @@ Just add one of the following [directives](directives.md): - `//@ run-crash` — compilation should succeed, but running the resulting binary should fail with a crash. Crashing is defined as "not exiting with a code in the range `0..=127`". - Example on Linux: Termination by `SIGABRT` or `SIGSEGV`. - Example on Windows: Exiting with the code for `STATUS_ILLEGAL_INSTRUCTION` (`0xC000001D`). + - Example on Linux: Termination by `SIGABRT` or `SIGSEGV`. + - Example on Windows: Exiting with the code for `STATUS_ILLEGAL_INSTRUCTION` (`0xC000001D`). - `//@ run-fail-or-crash` — compilation should succeed, but running the resulting binary should either `run-fail` or `run-crash`. Useful if a test crashes on some targets but just fails on others. -For `run-pass`. -`run-fail`, `run-crash` and `run-fail-or-crash` tests, by -default the output of the program itself is not checked. +For `run-pass`, `run-fail`, `run-crash`, and `run-fail-or-crash` tests, +the output of the program itself is not checked by default. If you want to check the output of running the program, include the `check-run-results` directive. This will check for a `.run.stderr` and @@ -526,7 +525,7 @@ The test should still include other normal directives and stdout/stderr files. When deciding where to place a test file, please try to find a subdirectory that best matches what you are trying to exercise. Do your best to keep things organized. -Admittedly it can be difficult as some tests can overlap different +Admittedly, it can be difficult as some tests can overlap different categories, and the existing layout may not fit well. Name the test by a concise description of what the test is checking. @@ -621,7 +620,7 @@ The compiler defines several perma-unstable `#[rustc_*]` attributes gated behind the internal feature `rustc_attrs` that dump extra compiler-internal information. See the corresponding subsection in [compiler debugging] for more details. -They can be used in tests to more precisely, legibly and easily test internal +They can be used in tests to more precisely, legibly, and easily test internal compiler state in cases where it would otherwise be very hard to do the same with "user-facing" Rust alone. Indeed, one could say that this slightly abuses From dd4870d0cc7b75b644206d00fc229329f5c99dfe Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 29 Jan 2026 23:13:39 +0200 Subject: [PATCH 248/978] fix sembr tool corner case --- src/doc/rustc-dev-guide/ci/sembr/src/main.rs | 4 +++- src/doc/rustc-dev-guide/src/tests/ui.md | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index 1de0638deb97..0ae77af047e6 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -24,7 +24,7 @@ static REGEX_IGNORE_END: LazyLock = static REGEX_IGNORE_LINK_TARGETS: LazyLock = LazyLock::new(|| Regex::new(r"^\[.+\]: ").unwrap()); static REGEX_SPLIT: LazyLock = - LazyLock::new(|| Regex::new(r"([^\.\d\-\*]\.|[^r]\?|!)\s").unwrap()); + LazyLock::new(|| Regex::new(r"([^\.\d\-\*]\.|[^r\~]\?|!)\s").unwrap()); // list elements, numbered (1.) or not (- and *) static REGEX_LIST_ENTRY: LazyLock = LazyLock::new(|| Regex::new(r"^\s*(\d\.|\-|\*|\d\))\s+").unwrap()); @@ -205,6 +205,7 @@ git log main.. compiler o? whatever r? @reviewer r? @reviewer +~? diagnostic "; let expected = " # some. heading @@ -237,6 +238,7 @@ o? whatever r? @reviewer r? @reviewer +~? diagnostic "; assert_eq!(expected, comply(original)); } diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index 0b5a5b3ccbab..7332d1fb3851 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -232,9 +232,8 @@ The space character between `//~` (or other variants) and the subsequent text is negligible (i.e. there is no semantic difference between `//~ ERROR` and `//~ERROR` although the former is more common in the codebase). -`~? -` (example being `~? -ERROR`) is used to match diagnostics _without_ line info at all, +`~? ` (example being `~? ERROR`) +is used to match diagnostics _without_ line info at all, or where the line info is outside the main test file[^main test file]. These annotations can be placed on any line in the test file. From 43fc5a40ee5611cee8a69fc8198c8d2f46358195 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 29 Jan 2026 23:14:55 +0200 Subject: [PATCH 249/978] sembr src/walkthrough.md --- src/doc/rustc-dev-guide/src/walkthrough.md | 40 ++++++++++------------ 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/walkthrough.md b/src/doc/rustc-dev-guide/src/walkthrough.md index 77d0953c4025..212fb298fd0b 100644 --- a/src/doc/rustc-dev-guide/src/walkthrough.md +++ b/src/doc/rustc-dev-guide/src/walkthrough.md @@ -41,18 +41,15 @@ Here is a quick list. We will go through each of these in order below. As I mentioned before, not all of these are needed for every type of contribution. -- **Idea discussion/Pre-RFC** A Pre-RFC is an early draft or design discussion - of a feature. +- **Idea discussion/Pre-RFC** A Pre-RFC is an early draft or design discussion of a feature. This stage is intended to flesh out the design space a bit and get a grasp on the different merits and problems with an idea. - It's a great way to get early feedback on your idea before presenting it to the wider - audience. + It's a great way to get early feedback on your idea before presenting it to the wider audience. You can find the original discussion [here][prerfc]. -- **RFC** This is when you formally present your idea to the community for - consideration. +- **RFC** This is when you formally present your idea to the community for consideration. You can find the RFC [here][rfc]. -- **Implementation** Implement your idea unstably in the compiler. You can - find the original implementation [here][impl1]. +- **Implementation** Implement your idea unstably in the compiler. + You can find the original implementation [here][impl1]. - **Possibly iterate/refine** As the community gets experience with your feature on the nightly compiler and in `std`, there may be additional feedback about design choice that might be adjusted. @@ -114,8 +111,7 @@ In this case, the discussion converged pretty quickly, but for some ideas, a lot more discussion can happen (e.g. see [this RFC][nonascii] which received a whopping 684 comments!). If that happens, don't be discouraged; -it means the community is interested in your idea, but it perhaps needs some -adjustments. +it means the community is interested in your idea, but it perhaps needs some adjustments. [nonascii]: https://github.com/rust-lang/rfcs/pull/2457 @@ -138,10 +134,10 @@ last chance for people to bring up objections. When the FCP is over, the disposition is adopted. Here are the three possible dispositions: -- _Merge_: accept the feature. Here is the proposal to merge for our [`?` macro - feature][rfcmerge]. -- _Close_: this feature in its current form is not a good fit for rust. Don't - be discouraged if this happens to your RFC, and don't take it personally. +- _Merge_: accept the feature. + Here is the proposal to merge for our [`?` macro feature][rfcmerge]. +- _Close_: this feature in its current form is not a good fit for rust. + Don't be discouraged if this happens to your RFC, and don't take it personally. This is not a reflection on you, but rather a community decision that rust will go a different direction. - _Postpone_: there is interest in going this direction but not at the moment. @@ -164,10 +160,12 @@ Here is the tracking issue on for our [`?` macro feature][tracking]. An eRFC is a variant of the RFC process used for complex features where the high-level need is clear, but the design space is too large to settle on a detailed specification upfront. Instead of providing a final design, an eRFC outlines a high-level strategy to authorize -a period of active experimentation. This allows the team to implement the feature behind +a period of active experimentation. +This allows the team to implement the feature behind a feature gate and gather practical data, which then informs a subsequent formal RFC for stabilization. While this process was used for major features like coroutines ([see RFC 2033][rfc2033]), -the explicit "eRFC" label is rarely used today. The project now generally prefers approving a standard +the explicit "eRFC" label is rarely used today. +The project now generally prefers approving a standard RFC for an initial version and iterating on it through the nightly channel before final stabilization. [rfc2033]: https://github.com/rust-lang/rfcs/pull/2033#issuecomment-309057591 @@ -199,8 +197,8 @@ When a new feature is implemented, it goes behind a _feature gate_, which means you have to use `#![feature(my_feature_name)]` to use the feature. The feature gate is removed when the feature is stabilized. -**Most bug fixes and improvements** don't require a feature gate. You can just -make your changes/improvements. +**Most bug fixes and improvements** don't require a feature gate. +You can just make your changes/improvements. When you open a PR on the [rust-lang/rust], a bot will assign your PR to a reviewer. If there is a particular Rust team member you are working with, you can @@ -217,8 +215,7 @@ When you finished iterating on the changes, you can mark the PR as `S-waiting-on-author` label and add the `S-waiting-on-review` label. Feel free to ask questions or discuss things you don't understand or disagree with. -However, recognize that the PR won't be merged unless someone on the Rust team approves -it. +However, recognize that the PR won't be merged unless someone on the Rust team approves it. If a reviewer leave a comment like `r=me after fixing ...`, that means they approve the PR and you can merge it with comment with `@bors r=reviewer-github-id`(e.g. `@bors r=eddyb`) to merge it after fixing trivial issues. @@ -235,8 +232,7 @@ If all tests pass, the PR is merged and becomes part of the next nightly compile There are a couple of things that may happen for some PRs during the review process -- If the change is substantial enough, the reviewer may request an FCP on - the PR. +- If the change is substantial enough, the reviewer may request an FCP on the PR. This gives all members of the appropriate team a chance to review the changes. - If the change may cause breakage, the reviewer may request a [crater] run. This compiles the compiler with your changes and then attempts to compile all From 7d8b5324ebc8eb98b46a0dd749eb3dcb84c18ae9 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 29 Jan 2026 23:27:41 +0200 Subject: [PATCH 250/978] sembr src/debuginfo/lldb-visualizers.md --- .../src/debuginfo/lldb-visualizers.md | 234 +++++++++++------- 1 file changed, 144 insertions(+), 90 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/debuginfo/lldb-visualizers.md b/src/doc/rustc-dev-guide/src/debuginfo/lldb-visualizers.md index 40ab9dce375c..c329e23d6006 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/lldb-visualizers.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/lldb-visualizers.md @@ -28,7 +28,8 @@ LLDB provides 3 mechanisms for customizing output: ## Formats -The official documentation is [here](https://lldb.llvm.org/use/variable.html#type-format). In short, +The official documentation is [here](https://lldb.llvm.org/use/variable.html#type-format). +In short, formats allow one to set the default print format for primitive types (e.g. print `25u8` as decimal `25`, hex `0x19`, or binary `00011001`). @@ -47,13 +48,15 @@ plugins and CLI. [sbvalue]: https://lldb.llvm.org/python_api/lldb.SBValue.html A Synthetic Provider is a Python class, written with a specific interface, that is associated with -one or more Rust types. The Synthetic Provider wraps `SBValue` objects and LLDB will call our +one or more Rust types. +The Synthetic Provider wraps `SBValue` objects and LLDB will call our class's functions when inspecting the variable. The wrapped value is still an `SBValue`, but when calling e.g. `SBValue.GetChildAtIndex`, it will -internally call `SyntheticProvider.get_child_at_index`. You can check if a value has a synthetic -provider via `SBValue.IsSynthetic()`, and which synthetic it is via `SBValue.GetTypeSynthetic()`. If -you want to interact with the underlying non-synthetic value, you can call +internally call `SyntheticProvider.get_child_at_index`. +You can check if a value has a synthetic +provider via `SBValue.IsSynthetic()`, and which synthetic it is via `SBValue.GetTypeSynthetic()`. +If you want to interact with the underlying non-synthetic value, you can call `SBValue.GetNonSyntheticValue()`. @@ -83,18 +86,20 @@ class SyntheticProvider: def get_value(self) -> SBValue: ... ``` -Below are explanations of the methods, their quirks, and how they should generally be used. If a -method overrides an `SBValue` method, that method will be listed. +Below are explanations of the methods, their quirks, and how they should generally be used. +If a method overrides an `SBValue` method, that method will be listed. ### `__init__` This function is called once per object, and must store the `valobj` in the python class so that it -is accessible elsewhere. Very little else should be done here. +is accessible elsewhere. +Very little else should be done here. ### (optional) `update` -This function is called prior to LLDB interacting with a variable, but after `__init__`. LLDB tracks -whether `update` has already been called. If it has been, and if it is not possible for the variable +This function is called prior to LLDB interacting with a variable, but after `__init__`. +LLDB tracks whether `update` has already been called. +If it has been, and if it is not possible for the variable to have changed (e.g. inspecting the same variable a second time without stepping), it will omit the call to `update`. @@ -107,15 +112,18 @@ Typical operations include storing the heap pointer, length, capacity, and eleme determining an enum variable's variant, or checking which slots of a `HashMap` are occupied. The bool returned from this function is somewhat complicated, see: -[`update` caching](#update-caching) below for more info. When in doubt, return `False`/`None`. +[`update` caching](#update-caching) below for more info. +When in doubt, return `False`/`None`. Currently (Nov 2025), none of the visualizers return `True`, but that may change as the debug info test suite is improved. #### `update` caching -LLDB attempts to cache values when possible, including child values. This cache is effectively the +LLDB attempts to cache values when possible, including child values. +This cache is effectively the number of child objects, and the addresses of the underlying debugee memory that the child object -represents. By returning `True`, you indicate to LLDB that the number of children and the addresses +represents. +By returning `True`, you indicate to LLDB that the number of children and the addresses of those children have not changed since the last time `update` was run, meaning it can reuse the cached children. @@ -123,19 +131,23 @@ cached children. information**. Returning `False` indicates that there have been changes, the cache will be flushed, and the -children will be fetched from scratch. It is the safer option if you are unsure. +children will be fetched from scratch. +It is the safer option if you are unsure. -The only relationship that matters is parent-to-child. Grandchildren depend on the `update` function -of their direct parent, not that of the grandparent. +The only relationship that matters is parent-to-child. +Grandchildren depend on the `update` function of their direct parent, not that of the grandparent. -It is important to view the child cache as pointers-to-memory. For example, if a slice's `data_ptr` -value and `length` have not changed, returning `True` is appropriate. Even if the slice is mutable +It is important to view the child cache as pointers-to-memory. +For example, if a slice's `data_ptr` +value and `length` have not changed, returning `True` is appropriate. +Even if the slice is mutable and elements of it are overwritten (e.g. `slice[0] = 15`), because the child cache consists of *pointers*, they will reflect the new data at that memory location. Conversely, if `data_ptr` has changed, that means it is pointing to a new location in memory, the -child pointers are invalid, and the cache must be flushed. If the `length` has changed, we need to -flush the cache to reflect the new number of children. If `length` has changed but `data_ptr` has +child pointers are invalid, and the cache must be flushed. +If the `length` has changed, we need to flush the cache to reflect the new number of children. +If `length` has changed but `data_ptr` has not, it is possible to store the old children in the `SyntheticProvider` itself (e.g. `list[SBValue]`) and dole those out rather than generating them from scratch, only creating new children if they do not already exist in the `SyntheticProvider`'s list. @@ -159,19 +171,21 @@ Often, this will be a one-liner of `return True`/`return False` or > Overrides `SBValue.GetNumChildren` -Returns the total number of children that LLDB should try to access when printing the type. This -number **does not** need to match to total number of synthetic children. +Returns the total number of children that LLDB should try to access when printing the type. +This number **does not** need to match to total number of synthetic children. The `max_children` argument can be returned if calculating the number of children can be expensive (e.g. linked list). If this is not a consideration, `max_children` can be omitted from the function signature. Additionally, fields can be intentionally "hidden" from LLDB while still being accessible to the -user. For example, one might want a `vec![1, 2, 3]` to display only its elements, but still have the -`len` and `capacity` values accessible on request. By returning `3` from `num_children`, one can +user. +For example, one might want a `vec![1, 2, 3]` to display only its elements, but still have the +`len` and `capacity` values accessible on request. +By returning `3` from `num_children`, one can restrict LLDB to only displaying `[1, 2, 3]`, while users can still directly access `v.len` and -`v.capacity`. See: [Example Provider: Vec\](#example-provider-vect) to see an implementation of -this. +`v.capacity`. +See: [Example Provider: Vec\](#example-provider-vect) to see an implementation of this. ### `get_child_index` @@ -179,12 +193,14 @@ this. > > Affects `SBValue.GetChildMemberWithName` -Given a name, returns the index that the child should be accessed at. It is expected that the return -value of this function is passed directly to `get_child_at_index`. As with `num_children`, the +Given a name, returns the index that the child should be accessed at. +It is expected that the return value of this function is passed directly to `get_child_at_index`. +As with `num_children`, the values returned here *can* be arbitrary, so long as they are properly coordinated with `get_child_at_index`. -One special value is `$$dereference$$`. Accounting for this pseudo-field will allow LLDB to use the +One special value is `$$dereference$$`. +Accounting for this pseudo-field will allow LLDB to use the `SBValue` returned from `get_child_at_index` as the result of a dereference via LLDB's expression parser (e.g. `*val` and `val->field`) @@ -192,24 +208,28 @@ parser (e.g. `*val` and `val->field`) > Overrides `SBValue.GetChildAtIndex` -Given an index, returns a child `SBValue`. Often these are generated via +Given an index, returns a child `SBValue`. +Often these are generated via `SBValue.CreateValueFromAddress`, but less commonly `SBValue.CreateChildAtOffset`, -`SBValue.CreateValueFromExpression`, and `SBValue.CreateValueFromData`. These functions can be a +`SBValue.CreateValueFromExpression`, and `SBValue.CreateValueFromData`. +These functions can be a little finicky, so you may need to fiddle with them to get the output you want. -In some cases, `SBValue.Clone` is appropriate. It creates a new child that is an exact copy of an -existing child, but with a new name. This is useful for cases like tuples, which have field names of +In some cases, `SBValue.Clone` is appropriate. +It creates a new child that is an exact copy of an existing child, but with a new name. +This is useful for cases like tuples, which have field names of the style `__0`, `__1`, ... when we would prefer they were named `0`, `1`, ... -Small alterations can be made to the resulting child before it is returned. This is useful for -`&str`/`String`, where we would prefer if the children were displayed as +Small alterations can be made to the resulting child before it is returned. +This is useful for `&str`/`String`, where we would prefer if the children were displayed as `lldb.eFormatBytesWithASCII` rather than just as a decimal value. ### (optional) `get_type_name` > Overrides `SBValue.GetDisplayTypeName` -Overrides the displayed name of a type. For a synthetic `SBValue` whose type name is overridden, the +Overrides the displayed name of a type. +For a synthetic `SBValue` whose type name is overridden, the original type name can still be retrieved via `SBValue.GetTypeName()` and `SBValue.GetType().GetName()` @@ -240,32 +260,39 @@ Summary providers are python functions of the following form: def SummaryProvider(valobj: SBValue, _lldb_internal) -> str: ... ``` -Where the returned string is passed verbatim to the user. If the returned value isn't a string, it +Where the returned string is passed verbatim to the user. +If the returned value isn't a string, it is naively convered to a string (e.g. `return None` prints `"None"`, not an empty string). If the `SBValue` passed in is of a type that has a Synthetic Provider, `valobj.IsSynthetic()` will -return `True`, and the synthetic's corresponding functions will be used. If this is undesirable, the -original value can be retrieved via `valobj.GetNonSyntheticValue()`. This can be helpful in cases +return `True`, and the synthetic's corresponding functions will be used. +If this is undesirable, the original value can be retrieved via `valobj.GetNonSyntheticValue()`. +This can be helpful in cases like `String`, where individually calling `GetChildAtIndex` in a loop is much slower than accessing the heap pointer, reading the whole byte array directly from the debugee's memory, and using Python's `bytes.decode()`. ### Instance Summaries -Regular `SummaryProvider` functions take an opaque `SBValue`. That `SBValue` will reflect the type's +Regular `SummaryProvider` functions take an opaque `SBValue`. +That `SBValue` will reflect the type's `SyntheticProvider` if one exists, but we cannot access the `SyntheticProvider` instance itself, or -any of its internal implementation details. This is deterimental in cases where we need some of -those internal details to help complete the summary. Currently (Nov 2025), in the synthetic we just +any of its internal implementation details. +This is deterimental in cases where we need some of +those internal details to help complete the summary. +Currently (Nov 2025), in the synthetic we just run the non-synthetic value through the synthetic provider (`synth = SyntheticProvider(valobj.GetNonSyntheticValue(), _dict)`), but this is obviously suboptimal and there are plans to use the method outlined below. -Instead, we can leverage the Python module's state to allow for instance summaries. Prior art for +Instead, we can leverage the Python module's state to allow for instance summaries. +Prior art for this technique exists in the [old CodeLLDB Rust visualizer scripts](https://github.com/vadimcn/codelldb/blob/cf9574977b80e29c6de2c44d12f1071a53a54caf/formatters/rust.py#L110). In short: every Synthetic Provider's `__init__` function stores a unique ID and a weak reference to -`self` in a global dictionary. The Synthetic Provider class also implements a `get_summary` -function. The type's `SummaryProvider` is a function that looks up the unique ID in this dictionary, +`self` in a global dictionary. +The Synthetic Provider class also implements a `get_summary` function. +The type's `SummaryProvider` is a function that looks up the unique ID in this dictionary, then calls a `get_summary` on the instance it retrieves. ```python @@ -293,9 +320,11 @@ def InstanceSummaryProvider(valobj: SBValue, _dict) -> str: return SYNTH_BY_ID[valobj.GetNonSyntheticValue().GetID()].get_summary() ``` -For example, one might use this for the Enum synthetic provider. The summary would like to access +For example, one might use this for the Enum synthetic provider. +The summary would like to access the variant name, but there isn't a convenient way to reflect this via the type name or child-values -of the synthetic. By implementing an instance summary, we can retrieve the variant name via +of the synthetic. +By implementing an instance summary, we can retrieve the variant name via `self.variant.GetTypeName()` and some string manipulation. # Writing Visualizer Scripts @@ -304,18 +333,21 @@ of the synthetic. By implementing an instance summary, we can retrieve the varia >Visualizers must be written to account for both formats whenever possible. See: >[rust-codegen](./rust-codegen.md#dwarf-vs-pdb) for an overview of the differences -Scripts are injected into LLDB via the CLI command `command script import .py`. Once +Scripts are injected into LLDB via the CLI command `command script import .py`. +Once injected, classes and functions can be added to the synthetic/summary pool with `type synthetic add` -and `type summary add` respectively. The summaries and synthetics can be associated with a -"category", which is typically named after the language the providers are intended for. The category -we use will be called `Rust`. +and `type summary add` respectively. +The summaries and synthetics can be associated with a +"category", which is typically named after the language the providers are intended for. +The category we use will be called `Rust`. > TIP: all LLDB commands can be prefixed with `help` (e.g. `help type synthetic add`) for a brief description, list of arguments, and examples. Currently (Nov 2025) we use `command source ...`, which executes a series of CLI commands from the file [`lldb_commands`](https://github.com/rust-lang/rust/blob/main/src/etc/lldb_commands) to add -providers. This file is somewhat unwieldy, and will soon be supplanted by the Python API equivalent +providers. +This file is somewhat unwieldy, and will soon be supplanted by the Python API equivalent outlined below. ## `__lldb_init_module` @@ -327,16 +359,20 @@ def __lldb_init_module(debugger: SBDebugger, _lldb_internal) -> None: ... ``` This function is called at the end of `command script import ...`, but before control returns back -to the CLI. It allows the script to initialize its own state. +to the CLI. +It allows the script to initialize its own state. -Crucially, it is passed a reference to the debugger itself. This allows us to create the `Rust` -category and add providers to it. It can also allow us to conditionally change which providers we -use depending on what version of LLDB the script detects. This is vital for backwards compatibility +Crucially, it is passed a reference to the debugger itself. +This allows us to create the `Rust` category and add providers to it. +It can also allow us to conditionally change which providers we +use depending on what version of LLDB the script detects. +This is vital for backwards compatibility once we begin using recognizer functions, as recognizers were added in lldb 19.0. ## Visualizer Resolution -The order that visualizers resolve in is listed [here][formatters_101]. In short: +The order that visualizers resolve in is listed [here][formatters_101]. +In short: [formatters_101]: https://lldb.llvm.org/use/variable.html#finding-formatters-101 @@ -347,14 +383,17 @@ provider), use that * If none of the above work, iterate through the regex type matchers Within each of those steps, **iteration is done backwards** to allow new commands to "override" old -commands. This is important for cases like `Box` vs `Box`, were we want a specialized +commands. +This is important for cases like `Box` vs `Box`, were we want a specialized synthetic for the former, but a more generalized synthetic for the latter. ## Minutiae LLDB's API is very powerful, but there are some "gotchas" and unintuitive behavior, some of which -will be outlined below. The python implementation can be viewed at the path returned by the CLI -command `lldb -P` in `lldb\__init__.py`. In addition to the +will be outlined below. +The python implementation can be viewed at the path returned by the CLI +command `lldb -P` in `lldb\__init__.py`. +In addition to the [examples in the lldb repo][synth_examples], there are also [C++ visualizers][plugin_cpp] that can be used as a reference (e.g. [LibCxxVector, the equivalent to `Vec`][cxx_vector]). While C++'s visualizers are written in C++ and have access to LLDB's internals, the API and general practices @@ -370,19 +409,22 @@ are very similar. children of the pointed-to-object are its own children. * The non-function fields are typically [`property()`][property] fields that point directly to the function anyway (e.g. `SBValue.type = property(GetType, None)`). Accessing through these shorthands -is a bit slower to access than just calling the function directly, so they should be avoided. Some +is a bit slower to access than just calling the function directly, so they should be avoided. +Some of the properties return special objects with special properties (e.g. `SBValue.member` returns an -object that acts like `dict[str, SBValue]` to access children). Internally, many of these special +object that acts like `dict[str, SBValue]` to access children). +Internally, many of these special objects just allocate a new class instance and call the function on the `SBValue` anyway, resulting in additional performance loss (e.g. `SBValue.member` internally just implements `__getitem__` which is the one-liner `return self.valobj.GetChildMemberWithName(name)`) * `SBValue.GetID` returns a unique `int` for each value for the duration of the debug session. -Synthetic `SBValue`'s have a different ID than their underlying `SBValue`. The underlying ID can be -retrieved via `SBValue.GetNonSyntheticValue().GetID()`. +Synthetic `SBValue`'s have a different ID than their underlying `SBValue`. +The underlying ID can be retrieved via `SBValue.GetNonSyntheticValue().GetID()`. * When manually calculating an address, `SBValue.GetValueAsAddress` should be preferred over `SBValue.GetValueAsUnsigned` due to [target-specific behavior][get_address] * Getting a string representation of an `SBValue` can be tricky because `GetSummary` requires a -summary provider and `GetValue` requires the type be representable by a primitive. In almost all +summary provider and `GetValue` requires the type be representable by a primitive. +In almost all cases where neither of those conditions are met, the type is a user defined struct that can be passed through `StructSummaryProvider`. @@ -393,12 +435,14 @@ passed through `StructSummaryProvider`. * "Aggregate type" means a non-primitive struct/class/union * "Template" is equivalent to "Generic" -* Types can be looked up by their name via `SBTarget.FindFirstType(type_name)`. `SBTarget` can be -acquired via `SBValue.GetTarget` +* Types can be looked up by their name via `SBTarget.FindFirstType(type_name)`. + `SBTarget` can be acquired via `SBValue.GetTarget` * `SBType.template_args` returns `None` instead of an empty list if the type has no generics * It is sometimes necessary to transform a type into the type you want via functions like -`SBType.GetArrayType` and `SBType.GetPointerType`. These functions cannot fail. They ask the -underlying LLDB `TypeSystem` plugin for the type, bypassing the debug info completely. Even if the +`SBType.GetArrayType` and `SBType.GetPointerType`. +These functions cannot fail. +They ask the underlying LLDB `TypeSystem` plugin for the type, bypassing the debug info completely. +Even if the type does not exist in the debug info at all, these functions can create the appropriate type. * `SBType.GetCanonicalType` is effectively `SBType.GetTypedefedType` + `SBType.GetUnqualifiedType`. Unlike `SBType.GetTypedefedType`, it will always return a valid `SBType` regardless of whether or @@ -411,11 +455,13 @@ always possible since the static fields are otherwise completely inaccessible. ## SyntheticProvider -We start with the typical prelude, using `__slots__` since we have known fields. In addition to the +We start with the typical prelude, using `__slots__` since we have known fields. +In addition to the object itself, we also need to store the type of the elements because `Vec`'s heap pointer is a -`*mut u8`, not a `*mut T`. Rust is a statically typed language, so the type of `T` will never -change. That means we can store it during initialization. The heap pointer, length, and capacity -*can* change though, and thus are default initialized here. +`*mut u8`, not a `*mut T`. +Rust is a statically typed language, so the type of `T` will never change. +That means we can store it during initialization. +The heap pointer, length, and capacity *can* change though, and thus are default initialized here. ```python import lldb @@ -452,12 +498,15 @@ class VecSyntheticProvider: For the implementation of `get_template_args` and `resolve_msvc_template_arg`, please see: [`lldb_providers.py`](https://github.com/rust-lang/rust/blob/main/src/etc/lldb_providers.py#L136). -Next, the update function. We check if the pointer or length have changed. We can ommit checking the -capacity, as the number of children will remain the same unless `len` changes. If changing the -capacity resulted in a reallocation, `data_ptr`'s address would be different. +Next, the update function. +We check if the pointer or length have changed. +We can ommit checking the +capacity, as the number of children will remain the same unless `len` changes. +If changing the capacity resulted in a reallocation, `data_ptr`'s address would be different. If `data_ptr` and `length` haven't changed, we can take advantage of LLDB's caching and return -early. If they have changed, we store the new values and tell LLDB to flush the cache. +early. +If they have changed, we store the new values and tell LLDB to flush the cache. ```python def update(self): @@ -490,9 +539,10 @@ def num_children(self) -> int: When accessing elements, we expect values of the format `[0]`, `[1]`, etc. to mimic indexing. Additionally, we still want the user to be able to quickly access the length and capacity, as they -can be very useful when debugging. We assign these values `u32::MAX - 1` and `u32::MAX - 2` -respectively, as we can almost surely guarantee that they will not overlap with element values. Note -that we can account for both the full and shorthand `capacity` name. +can be very useful when debugging. +We assign these values `u32::MAX - 1` and `u32::MAX - 2` +respectively, as we can almost surely guarantee that they will not overlap with element values. +Note that we can account for both the full and shorthand `capacity` name. ```python def get_child_index(self, name: str) -> int: @@ -527,17 +577,18 @@ def get_child_at_index(self, index: int) -> SBValue: return self.valobj.CreateValueFromAddress(f"[{index}]", addr, self.element_type) ``` -For the type's display name, we can strip the path qualifier. User defined types named -`Vec` will end up fully qualified, so there shouldn't be any ambiguity. We can also remove the -allocator generic, as it's very very rarely useful. We use `get_template_args` instead of -`self.element_type.GetName()` for 3 reasons: +For the type's display name, we can strip the path qualifier. +User defined types named `Vec` will end up fully qualified, so there shouldn't be any ambiguity. +We can also remove the allocator generic, as it's very very rarely useful. +We use `get_template_args` instead of `self.element_type.GetName()` for 3 reasons: 1. If we fail to resolve the element type for any reason, `self.valobj`'s type name can still let the user know what the real type of the element is 2. Type names are not subject to the limitations of DWARF and PDB nodes, so the template type in the name will reflect things like `*const`/`*mut` and `&`/`&mut`. 3. We do not currently (Nov 2025) normalize MSVC type names, but once we do, we will need to work with the -string-names of types anyway. It's also much easier to cache a string-to-string conversion compared +string-names of types anyway. +It's also much easier to cache a string-to-string conversion compared to an `SBType`-to-string conversion. ```python @@ -550,11 +601,14 @@ the `get_value` function. ## SummaryProvider -The summary provider is very simple thanks to our synthetic provider. The only real hiccup is that -`GetSummary` only returns a value if the object's type has a `SummaryProvider`. If it doesn't, it -will return an empty string which is not ideal. In a full set of visualizer scripts, we can ensure +The summary provider is very simple thanks to our synthetic provider. +The only real hiccup is that +`GetSummary` only returns a value if the object's type has a `SummaryProvider`. +If it doesn't, it will return an empty string which is not ideal. +In a full set of visualizer scripts, we can ensure that every type that doesn't have a `GetSummary()` or a `GetValue()` is a struct, and then delegate -to a generic `StructSummaryProvider`. For this demonstration, I will gloss over that detail. +to a generic `StructSummaryProvider`. +For this demonstration, I will gloss over that detail. ```python def VecSummaryProvider(valobj: SBValue, _lldb_internal) -> str: @@ -659,4 +713,4 @@ We can also confirm that the "hidden" length and capacity are still accessible: (unsigned long long) vec_v.capacity = 5 (lldb) v vec_v.cap (unsigned long long) vec_v.cap = 5 -``` \ No newline at end of file +``` From d4764e3210e6c7a2767b1ac2ec69bc33d3685201 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 29 Jan 2026 23:46:27 +0200 Subject: [PATCH 251/978] some improvements --- .../src/debuginfo/lldb-visualizers.md | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/debuginfo/lldb-visualizers.md b/src/doc/rustc-dev-guide/src/debuginfo/lldb-visualizers.md index c329e23d6006..83e2b0d5794e 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/lldb-visualizers.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/lldb-visualizers.md @@ -1,6 +1,6 @@ # LLDB - Python Providers -> NOTE: LLDB's C++<->Python FFI expects a version of python designated at the time LLDB was +> NOTE: LLDB's C++<->Python FFI expects a version of Python designated at the time LLDB was >compiled. LLDB is careful to correspond this version to the minimum in typical Linux and macOS >distributions, but on Windows there is no easy solution. If you receive an import error regarding >`_lldb` not existing, a mismatched Python version is likely the cause. @@ -11,14 +11,15 @@ [minimal_python_install]: https://discourse.llvm.org/t/a-minimal-python-install-for-lldb/88658 [issue_167001]: https://github.com/llvm/llvm-project/issues/167001 -> NOTE: Currently (Nov 2025), LLDB's minimum supported Python version is 3.8 with plans to update it to ->3.9 or 3.10 depending on several outside factors. Scripts should ideally be written with only the ->features available in the minimum supported Python version. Please see [this discussion][mrpv] for ->more info. +> NOTE: As of Nov 2025, +> LLDB's minimum supported Python version is 3.8, with plans to update it to +> 3.9 or 3.10, depending on several outside factors. Scripts should ideally be written with only the +> features available in the minimum supported Python version. Please see [this discussion][mrpv] for +> more info. [mrpv]: https://discourse.llvm.org/t/rfc-upgrading-llvm-s-minimum-required-python-version/88605/ -> NOTE: The path to LLDB's python package can be located via the CLI command `lldb -P` +> NOTE: The path to LLDB's Python package can be located via the CLI command `lldb -P` LLDB provides 3 mechanisms for customizing output: @@ -91,7 +92,7 @@ If a method overrides an `SBValue` method, that method will be listed. ### `__init__` -This function is called once per object, and must store the `valobj` in the python class so that it +This function is called once per object, and must store the `valobj` in the Python class so that it is accessible elsewhere. Very little else should be done here. @@ -114,7 +115,8 @@ determining an enum variable's variant, or checking which slots of a `HashMap` a The bool returned from this function is somewhat complicated, see: [`update` caching](#update-caching) below for more info. When in doubt, return `False`/`None`. -Currently (Nov 2025), none of the visualizers return `True`, but that may change as the debug info +As of Nov 2025, +none of the visualizers return `True`, but that may change as the debug info test suite is improved. #### `update` caching @@ -155,7 +157,7 @@ children if they do not already exist in the `SyntheticProvider`'s list. For further clarification, see [this discussion](https://discourse.llvm.org/t/when-is-it-safe-to-cache-syntheticprovider-update/88608) > NOTE: when testing the caching behavior, do not rely on LLDB's heuristic to persist variables when -> stepping. Instead, store the variable in a python object (e.g. `v = lldb.frame.var("var_name")`), +> stepping. Instead, store the variable in a Python object (e.g. `v = lldb.frame.var("var_name")`), > step forward, and then inspect the stored variable. ### (optional) `has_children` @@ -248,13 +250,14 @@ access the generic parameters of the type. The `SBValue` returned is expected to be a primitive type or pointer, and is treated as the value of the variable in expressions. -> IMPORTANT: The `SBValue` returned **must be stored in the `SyntheticProvider`**. There is ->currently (Nov 2025) a bug where if the `SBValue` is acquired within `get_value` and not stored ->anywhere, Python will segfault when LLDB attempts to access the value. +> IMPORTANT: The `SBValue` returned **must be stored in the `SyntheticProvider`**. +> As of Nov 2025, +> there is a bug where if the `SBValue` is acquired within `get_value` and not stored +> anywhere, Python will segfault when LLDB attempts to access the value. ## Summary Providers -Summary providers are python functions of the following form: +Summary providers are Python functions of the following form: ```python def SummaryProvider(valobj: SBValue, _lldb_internal) -> str: ... @@ -280,7 +283,7 @@ That `SBValue` will reflect the type's any of its internal implementation details. This is deterimental in cases where we need some of those internal details to help complete the summary. -Currently (Nov 2025), in the synthetic we just +As of Nov 2025, in the synthetic we just run the non-synthetic value through the synthetic provider (`synth = SyntheticProvider(valobj.GetNonSyntheticValue(), _dict)`), but this is obviously suboptimal and there are plans to use the method outlined below. @@ -344,7 +347,8 @@ The category we use will be called `Rust`. > TIP: all LLDB commands can be prefixed with `help` (e.g. `help type synthetic add`) for a brief description, list of arguments, and examples. -Currently (Nov 2025) we use `command source ...`, which executes a series of CLI commands from the +As of Nov 2025, +we use `command source ...`, which executes a series of CLI commands from the file [`lldb_commands`](https://github.com/rust-lang/rust/blob/main/src/etc/lldb_commands) to add providers. This file is somewhat unwieldy, and will soon be supplanted by the Python API equivalent @@ -391,7 +395,7 @@ synthetic for the former, but a more generalized synthetic for the latter. LLDB's API is very powerful, but there are some "gotchas" and unintuitive behavior, some of which will be outlined below. -The python implementation can be viewed at the path returned by the CLI +The Python implementation can be viewed at the path returned by the CLI command `lldb -P` in `lldb\__init__.py`. In addition to the [examples in the lldb repo][synth_examples], there are also [C++ visualizers][plugin_cpp] that can @@ -586,7 +590,8 @@ We use `get_template_args` instead of `self.element_type.GetName()` for 3 reason the user know what the real type of the element is 2. Type names are not subject to the limitations of DWARF and PDB nodes, so the template type in the name will reflect things like `*const`/`*mut` and `&`/`&mut`. -3. We do not currently (Nov 2025) normalize MSVC type names, but once we do, we will need to work with the +3. As of Nov 2025, +we don't normalize MSVC type names, but once we do, we will need to work with the string-names of types anyway. It's also much easier to cache a string-to-string conversion compared to an `SBType`-to-string conversion. From 2aea912db2236e39aba7f3f4dca41f7047dd912d Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 29 Jan 2026 23:51:07 +0200 Subject: [PATCH 252/978] sembr src/building/suggested.md --- .../rustc-dev-guide/src/building/suggested.md | 214 +++++++++--------- 1 file changed, 113 insertions(+), 101 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index c87dc6b28d87..71921532244e 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -1,27 +1,29 @@ # Suggested workflows -The full bootstrapping process takes quite a while. Here are some suggestions to -make your life easier. +The full bootstrapping process takes quite a while. +Here are some suggestions to make your life easier. ## Installing a pre-push hook CI will automatically fail your build if it doesn't pass `tidy`, our internal -tool for ensuring code quality. If you'd like, you can install a [Git +tool for ensuring code quality. +If you'd like, you can install a [Git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) that will -automatically run `./x test tidy` on each push, to ensure your code is up to -par. If the hook fails then run `./x test tidy --bless` and commit the changes. +automatically run `./x test tidy` on each push, to ensure your code is up to par. +If the hook fails then run `./x test tidy --bless` and commit the changes. If you decide later that the pre-push behavior is undesirable, you can delete the `pre-push` file in `.git/hooks`. -A prebuilt git hook lives at [`src/etc/pre-push.sh`]. It can be copied into -your `.git/hooks` folder as `pre-push` (without the `.sh` extension!). +A prebuilt git hook lives at [`src/etc/pre-push.sh`]. + It can be copied into your `.git/hooks` folder as `pre-push` (without the `.sh` extension!). You can also install the hook as a step of running `./x setup`! ## Config extensions When working on different tasks, you might need to switch between different bootstrap configurations. -Sometimes you may want to keep an old configuration for future use. But saving raw config values in +Sometimes you may want to keep an old configuration for future use. +But saving raw config values in random files and manually copying and pasting them can quickly become messy, especially if you have a long history of different configurations. @@ -51,9 +53,10 @@ include = ["cross.toml"] You can also include extensions within extensions recursively. -**Note:** In the `include` field, the overriding logic follows a right-to-left order. For example, -in `include = ["a.toml", "b.toml"]`, extension `b.toml` overrides `a.toml`. Also, parent extensions -always overrides the inner ones. +**Note:** In the `include` field, the overriding logic follows a right-to-left order. +For example, +in `include = ["a.toml", "b.toml"]`, extension `b.toml` overrides `a.toml`. +Also, parent extensions always overrides the inner ones. ## Configuring `rust-analyzer` for `rustc` @@ -61,34 +64,37 @@ always overrides the inner ones. Checking the "library" tree requires a stage1 compiler, which can be a heavy process on some computers. For this reason, bootstrap has a flag called `--skip-std-check-if-no-download-rustc` that skips checking the -"library" tree if `rust.download-rustc` isn't available. If you want to avoid putting a heavy load on your computer +"library" tree if `rust.download-rustc` isn't available. +If you want to avoid putting a heavy load on your computer with `rust-analyzer`, you can add the `--skip-std-check-if-no-download-rustc` flag to your `./x check` command in the `rust-analyzer` configuration. ### Project-local rust-analyzer setup -`rust-analyzer` can help you check and format your code whenever you save a -file. By default, `rust-analyzer` runs the `cargo check` and `rustfmt` commands, +`rust-analyzer` can help you check and format your code whenever you save a file. +By default, `rust-analyzer` runs the `cargo check` and `rustfmt` commands, but you can override these commands to use more adapted versions of these tools -when hacking on `rustc`. With custom setup, `rust-analyzer` can use `./x check` +when hacking on `rustc`. +With custom setup, `rust-analyzer` can use `./x check` to check the sources, and the stage 0 rustfmt to format them. The default `rust-analyzer.check.overrideCommand` command line will check all -the crates and tools in the repository. If you are working on a specific part, -you can override the command to only check the part you are working on to save -checking time. For example, if you are working on the compiler, you can override +the crates and tools in the repository. +If you are working on a specific part, +you can override the command to only check the part you are working on to save checking time. +For example, if you are working on the compiler, you can override the command to `x check compiler --json-output` to only check the compiler part. You can run `x check --help --verbose` to see the available parts. Running `./x setup editor` will prompt you to create a project-local LSP config -file for one of the supported editors. You can also create the config file as a -step of running `./x setup`. +file for one of the supported editors. +You can also create the config file as a step of running `./x setup`. ### Using a separate build directory for rust-analyzer By default, when rust-analyzer runs a check or format command, it will share -the same build directory as manual command-line builds. This can be inconvenient -for two reasons: +the same build directory as manual command-line builds. +This can be inconvenient for two reasons: - Each build will lock the build directory and force the other to wait, so it becomes impossible to run command-line builds while rust-analyzer is running commands in the background. @@ -111,12 +117,11 @@ requires extra disk space. ### Visual Studio Code Selecting `vscode` in `./x setup editor` will prompt you to create a -`.vscode/settings.json` file which will configure Visual Studio code. The -recommended `rust-analyzer` settings live at +`.vscode/settings.json` file which will configure Visual Studio code. +The recommended `rust-analyzer` settings live at [`src/etc/rust_analyzer_settings.json`]. -If running `./x check` on save is inconvenient, in VS Code you can use a [Build -Task] instead: +If running `./x check` on save is inconvenient, in VS Code you can use a [Build Task] instead: ```JSON // .vscode/tasks.json @@ -140,27 +145,26 @@ Task] instead: ### Neovim -For Neovim users, there are a few options. The -easiest way is by using [neoconf.nvim](https://github.com/folke/neoconf.nvim/), -which allows for project-local configuration files with the native LSP. The -steps for how to use it are below. Note that they require rust-analyzer to -already be configured with Neovim. Steps for this can be [found -here](https://rust-analyzer.github.io/manual.html#nvim-lsp). +For Neovim users, there are a few options. +The easiest way is by using [neoconf.nvim](https://github.com/folke/neoconf.nvim/), +which allows for project-local configuration files with the native LSP. +The steps for how to use it are below. +Note that they require rust-analyzer to already be configured with Neovim. +Steps for this can be [found here](https://rust-analyzer.github.io/manual.html#nvim-lsp). -1. First install the plugin. This can be done by following the steps in the - README. -2. Run `./x setup editor`, and select `vscode` to create a - `.vscode/settings.json` file. `neoconf` is able to read and update - rust-analyzer settings automatically when the project is opened when this - file is detected. +1. First install the plugin. + This can be done by following the steps in the README. +2. Run `./x setup editor`, and select `vscode` to create a `.vscode/settings.json` file. + `neoconf` is able to read and update + rust-analyzer settings automatically when the project is opened when this file is detected. If you're using `coc.nvim`, you can run `./x setup editor` and select `vim` to -create a `.vim/coc-settings.json`. The settings can be edited with -`:CocLocalConfig`. The recommended settings live at -[`src/etc/rust_analyzer_settings.json`]. +create a `.vim/coc-settings.json`. +The settings can be edited with `:CocLocalConfig`. +The recommended settings live at [`src/etc/rust_analyzer_settings.json`]. -Another way is without a plugin, and creating your own logic in your -configuration. The following code will work for any checkout of rust-lang/rust (newer than February 2025): +Another way is without a plugin, and creating your own logic in your configuration. +The following code will work for any checkout of rust-lang/rust (newer than February 2025): ```lua local function expand_config_variables(option) @@ -216,8 +220,7 @@ lspconfig.rust_analyzer.setup { If you would like to use the build task that is described above, you may either make your own command in your config, or you can install a plugin such as -[overseer.nvim](https://github.com/stevearc/overseer.nvim) that can [read -VSCode's `task.json` +[overseer.nvim](https://github.com/stevearc/overseer.nvim) that can [read VSCode's `task.json` files](https://github.com/stevearc/overseer.nvim/blob/master/doc/guides.md#vs-code-tasks), and follow the same instructions as above. @@ -240,55 +243,58 @@ Helix comes with built-in LSP and rust-analyzer support. It can be configured through `languages.toml`, as described [here](https://docs.helix-editor.com/languages.html). You can run `./x setup editor` and select `helix`, which will prompt you to -create `languages.toml` with the recommended configuration for Helix. The -recommended settings live at [`src/etc/rust_analyzer_helix.toml`]. +create `languages.toml` with the recommended configuration for Helix. +The recommended settings live at [`src/etc/rust_analyzer_helix.toml`]. ### Zed Zed comes with built-in LSP and rust-analyzer support. It can be configured through `.zed/settings.json`, as described -[here](https://zed.dev/docs/configuring-languages). Selecting `zed` -in `./x setup editor` will prompt you to create a `.zed/settings.json` -file which will configure Zed with the recommended configuration. The -recommended `rust-analyzer` settings live +[here](https://zed.dev/docs/configuring-languages). +Selecting `zed` in `./x setup editor` will prompt you to create a `.zed/settings.json` +file which will configure Zed with the recommended configuration. +The recommended `rust-analyzer` settings live at [`src/etc/rust_analyzer_zed.json`]. ## Check, check, and check again -When doing simple refactoring, it can be useful to run `./x check` -continuously. If you set up `rust-analyzer` as described above, this will be -done for you every time you save a file. Here you are just checking that the +When doing simple refactoring, it can be useful to run `./x check` continuously. +If you set up `rust-analyzer` as described above, this will be +done for you every time you save a file. +Here you are just checking that the compiler can **build**, but often that is all you need (e.g., when renaming a -method). You can then run `./x build` when you actually need to run tests. +method). +You can then run `./x build` when you actually need to run tests. -In fact, it is sometimes useful to put off tests even when you are not 100% sure -the code will work. You can then keep building up refactoring commits and only -run the tests at some later time. You can then use `git bisect` to track down -**precisely** which commit caused the problem. A nice side-effect of this style +In fact, it is sometimes useful to put off tests even when you are not 100% sure the code will work. +You can then keep building up refactoring commits and only run the tests at some later time. +You can then use `git bisect` to track down **precisely** which commit caused the problem. +A nice side-effect of this style is that you are left with a fairly fine-grained set of commits at the end, all -of which build and pass tests. This often helps reviewing. +of which build and pass tests. +This often helps reviewing. ## Configuring `rustup` to use nightly -Some parts of the bootstrap process uses pinned, nightly versions of tools like -rustfmt. To make things like `cargo fmt` work correctly in your repo, run +Some parts of the bootstrap process uses pinned, nightly versions of tools like rustfmt. +To make things like `cargo fmt` work correctly in your repo, run ```console cd rustup override set nightly ``` -after [installing a nightly toolchain] with `rustup`. Don't forget to do this -for all directories you have [setup a worktree for]. You may need to use the -pinned nightly version from `src/stage0`, but often the normal `nightly` channel -will work. +after [installing a nightly toolchain] with `rustup`. +Don't forget to do this for all directories you have [setup a worktree for]. +You may need to use the +pinned nightly version from `src/stage0`, but often the normal `nightly` channel will work. **Note** see [the section on vscode] for how to configure it with this real rustfmt `x` uses, and [the section on rustup] for how to setup `rustup` toolchain for your bootstrapped compiler -**Note** This does _not_ allow you to build `rustc` with cargo directly. You -still have to use `x` to work on the compiler or standard library, this just +**Note** This does _not_ allow you to build `rustc` with cargo directly. +You still have to use `x` to work on the compiler or standard library, this just lets you use `cargo fmt`. [installing a nightly toolchain]: https://rust-lang.github.io/rustup/concepts/channels.html?highlight=nightl#working-with-nightly-rust @@ -300,18 +306,22 @@ lets you use `cargo fmt`. If you are not working on the compiler, you often don't need to build the compiler tree. For example, you can skip building the compiler and only build the `library` tree or the -tools under `src/tools`. To achieve that, you have to enable this by setting the `download-rustc` -option in your configuration. This tells bootstrap to use the latest nightly compiler for `stage > 0` +tools under `src/tools`. +To achieve that, you have to enable this by setting the `download-rustc` +option in your configuration. +This tells bootstrap to use the latest nightly compiler for `stage > 0` steps, meaning it will have two precompiled compilers: stage0 compiler and `download-rustc` compiler -for `stage > 0` steps. This way, it will never need to build the in-tree compiler. As a result, your -build time will be significantly reduced by not building the in-tree compiler. +for `stage > 0` steps. +This way, it will never need to build the in-tree compiler. +As a result, your build time will be significantly reduced by not building the in-tree compiler. ## Faster rebuilds with `--keep-stage-std` -Sometimes just checking whether the compiler builds is not enough. A common -example is that you need to add a `debug!` statement to inspect the value of -some state or better understand the problem. In that case, you don't really need -a full build. By bypassing bootstrap's cache invalidation, you can often get +Sometimes just checking whether the compiler builds is not enough. +A common example is that you need to add a `debug!` statement to inspect the value of +some state or better understand the problem. +In that case, you don't really need a full build. +By bypassing bootstrap's cache invalidation, you can often get these builds to complete very fast (e.g., around 30 seconds). The only catch is this requires a bit of fudging and may produce compilers that don't work (but that is easily detected and fixed). @@ -323,53 +333,54 @@ The sequence of commands you want is as follows: - Note that we added the `--keep-stage-std=1` flag here As mentioned, the effect of `--keep-stage-std=1` is that we just _assume_ that the -old standard library can be re-used. If you are editing the compiler, this is -often true: you haven't changed the standard library, after all. But -sometimes, it's not true: for example, if you are editing the "metadata" part of +old standard library can be re-used. +If you are editing the compiler, this is +often true: you haven't changed the standard library, after all. +But sometimes, it's not true: for example, if you are editing the "metadata" part of the compiler, which controls how the compiler encodes types and other states into the `rlib` files, or if you are editing things that wind up in the metadata (such as the definition of the MIR). **The TL;DR is that you might get weird behavior from a compile when using `--keep-stage-std=1`** -- for example, strange [ICEs](../appendix/glossary.html#ice) -or other panics. In that case, you should simply remove the `--keep-stage-std=1` -from the command and rebuild. That ought to fix the problem. +or other panics. +In that case, you should simply remove the `--keep-stage-std=1` from the command and rebuild. +That ought to fix the problem. -You can also use `--keep-stage-std=1` when running tests. Something like this: +You can also use `--keep-stage-std=1` when running tests. +Something like this: - Initial test run: `./x test tests/ui` - Subsequent test run: `./x test tests/ui --keep-stage-std=1` ## Using incremental compilation -You can further enable the `--incremental` flag to save additional time in -subsequent rebuilds: +You can further enable the `--incremental` flag to save additional time in subsequent rebuilds: ```bash ./x test tests/ui --incremental --test-args issue-1234 ``` -If you don't want to include the flag with every command, you can enable it in -the `bootstrap.toml`: +If you don't want to include the flag with every command, you can enable it in the `bootstrap.toml`: ```toml [rust] incremental = true ``` -Note that incremental compilation will use more disk space than usual. If disk -space is a concern for you, you might want to check the size of the `build` +Note that incremental compilation will use more disk space than usual. +If disk space is a concern for you, you might want to check the size of the `build` directory from time to time. ## Fine-tuning optimizations -Setting `optimize = false` makes the compiler too slow for tests. However, to -improve the test cycle, you can disable optimizations selectively only for the +Setting `optimize = false` makes the compiler too slow for tests. +However, to improve the test cycle, you can disable optimizations selectively only for the crates you'll have to rebuild ([source](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/incremental.20compilation.20question/near/202712165)). For example, when working on `rustc_mir_build`, the `rustc_mir_build` and -`rustc_driver` crates take the most time to incrementally rebuild. You could -therefore set the following in the root `Cargo.toml`: +`rustc_driver` crates take the most time to incrementally rebuild. +You could therefore set the following in the root `Cargo.toml`: ```toml [profile.release.package.rustc_mir_build] @@ -382,22 +393,24 @@ opt-level = 0 Working on multiple branches in parallel can be a little annoying, since building the compiler on one branch will cause the old build and the incremental -compilation cache to be overwritten. One solution would be to have multiple +compilation cache to be overwritten. +One solution would be to have multiple clones of the repository, but that would mean storing the Git metadata multiple times, and having to update each clone individually. -Fortunately, Git has a better solution called [worktrees]. This lets you create -multiple "working trees", which all share the same Git database. Moreover, +Fortunately, Git has a better solution called [worktrees]. +This lets you create multiple "working trees", which all share the same Git database. +Moreover, because all of the worktrees share the same object database, if you update a branch (e.g. `main`) in any of them, you can use the new commits from any of the -worktrees. One caveat, though, is that submodules do not get shared. They will -still be cloned multiple times. +worktrees. +One caveat, though, is that submodules do not get shared. +They will still be cloned multiple times. [worktrees]: https://git-scm.com/docs/git-worktree Given you are inside the root directory for your Rust repository, you can create -a "linked working tree" in a new "rust2" directory by running the following -command: +a "linked working tree" in a new "rust2" directory by running the following command: ```bash git worktree add ../rust2 @@ -409,8 +422,7 @@ Creating a new worktree for a new branch based on `main` looks like: git worktree add -b my-feature ../rust2 main ``` -You can then use that rust2 folder as a separate workspace for modifying and -building `rustc`! +You can then use that rust2 folder as a separate workspace for modifying and building `rustc`! ## Working with nix From ffc3b8a3f163d8978b9f1512113c939e0aeed73e Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 30 Jan 2026 00:03:23 +0200 Subject: [PATCH 253/978] capitalise start of sentence --- src/doc/rustc-dev-guide/src/building/suggested.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index 71921532244e..b5c9b9b4e3d1 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -284,7 +284,7 @@ cd rustup override set nightly ``` -after [installing a nightly toolchain] with `rustup`. +After [installing a nightly toolchain] with `rustup`. Don't forget to do this for all directories you have [setup a worktree for]. You may need to use the pinned nightly version from `src/stage0`, but often the normal `nightly` channel will work. From d7e88cf39b073d4b49d442117511977ec47c8dfd Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 30 Jan 2026 00:08:23 +0200 Subject: [PATCH 254/978] sembr src/git.md --- src/doc/rustc-dev-guide/src/git.md | 255 ++++++++++++++++------------- 1 file changed, 138 insertions(+), 117 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md index abe72b29cb1e..d6665f6e17cc 100644 --- a/src/doc/rustc-dev-guide/src/git.md +++ b/src/doc/rustc-dev-guide/src/git.md @@ -1,20 +1,22 @@ # Using Git -The Rust project uses [Git] to manage its source code. In order to -contribute, you'll need some familiarity with its features so that your changes +The Rust project uses [Git] to manage its source code. +In order to contribute, you'll need some familiarity with its features so that your changes can be incorporated into the compiler. [Git]: https://git-scm.com The goal of this page is to cover some of the more common questions and -problems new contributors face. Although some Git basics will be covered here, +problems new contributors face. +Although some Git basics will be covered here, if you find that this is still a little too fast for you, it might make sense to first read some introductions to Git, such as the Beginner and Getting -started sections of [this tutorial from Atlassian][atlassian-git]. GitHub also -provides [documentation] and [guides] for beginners, or you can consult the +started sections of [this tutorial from Atlassian][atlassian-git]. +GitHub also provides [documentation] and [guides] for beginners, or you can consult the more in depth [book from Git]. -This guide is incomplete. If you run into trouble with git that this page doesn't help with, +This guide is incomplete. +If you run into trouble with git that this page doesn't help with, please [open an issue] so we can document how to fix it. [open an issue]: https://github.com/rust-lang/rustc-dev-guide/issues/new @@ -26,15 +28,15 @@ please [open an issue] so we can document how to fix it. ## Prerequisites We'll assume that you've installed Git, forked [rust-lang/rust], and cloned the -forked repo to your PC. We'll use the command line interface to interact +forked repo to your PC. +We'll use the command line interface to interact with Git; there are also a number of GUIs and IDE integrations that can generally do the same things. [rust-lang/rust]: https://github.com/rust-lang/rust -If you've cloned your fork, then you will be able to reference it with `origin` -in your local repo. It may be helpful to also set up a remote for the official -rust-lang/rust repo via +If you've cloned your fork, then you will be able to reference it with `origin` in your local repo. +It may be helpful to also set up a remote for the official rust-lang/rust repo via ```console git remote add upstream https://github.com/rust-lang/rust.git @@ -54,21 +56,19 @@ useful when contributing to other repositories in the Rust project. ## Standard Process -Below is the normal procedure that you're likely to use for most minor changes -and PRs: +Below is the normal procedure that you're likely to use for most minor changes and PRs: - 1. Ensure that you're making your changes on top of `main`: - `git checkout main`. + 1. Ensure that you're making your changes on top of `main`: `git checkout main`. 2. Get the latest changes from the Rust repo: `git pull upstream main --ff-only`. (see [No-Merge Policy][no-merge-policy] for more info about this). 3. Make a new branch for your change: `git checkout -b issue-12345-fix`. 4. Make some changes to the repo and test them. 5. Stage your changes via `git add src/changed/file.rs src/another/change.rs` - and then commit them with `git commit`. Of course, making intermediate commits - may be a good idea as well. Avoid `git add .`, as it makes it too easy to - unintentionally commit changes that should not be committed, such as submodule - updates. You can use `git status` to check if there are any files you forgot - to stage. + and then commit them with `git commit`. + Of course, making intermediate commits may be a good idea as well. + Avoid `git add .`, as it makes it too easy to + unintentionally commit changes that should not be committed, such as submodule updates. + You can use `git status` to check if there are any files you forgot to stage. 6. Push your changes to your fork: `git push --set-upstream origin issue-12345-fix` (After adding commits, you can use `git push` and after rebasing or pulling-and-rebasing, you can use `git push --force-with-lease`). @@ -100,14 +100,15 @@ Here are some common issues you might run into: ### I made a merge commit by accident. Git has two ways to update your branch with the newest changes: merging and rebasing. -Rust [uses rebasing][no-merge-policy]. If you make a merge commit, it's not too hard to fix: -`git rebase -i upstream/main`. +Rust [uses rebasing][no-merge-policy]. +If you make a merge commit, it's not too hard to fix: `git rebase -i upstream/main`. See [Rebasing](#rebasing) for more about rebasing. ### I deleted my fork on GitHub! -This is not a problem from git's perspective. If you run `git remote -v`, +This is not a problem from git's perspective. +If you run `git remote -v`, it will say something like this: ```console @@ -137,19 +138,21 @@ You might also notice conflicts in the web UI: ![conflict in src/tools/cargo](./img/submodule-conflicts.png) The most common cause is that you rebased after a change and ran `git add .` without first running -`x` to update the submodules. Alternatively, you might have run `cargo fmt` instead of `x fmt` +`x` to update the submodules. + Alternatively, you might have run `cargo fmt` instead of `x fmt` and modified files in a submodule, then committed the changes. To fix it, do the following things (if you changed a submodule other than cargo, replace `src/tools/cargo` with the path to that submodule): 1. See which commit has the accidental changes: `git log --stat -n1 src/tools/cargo` -2. Revert the changes to that commit: `git checkout ~ src/tools/cargo`. Type `~` - literally but replace `` with the output from step 1. +2. Revert the changes to that commit: `git checkout ~ src/tools/cargo`. + Type `~` literally but replace `` with the output from step 1. 3. Tell git to commit the changes: `git commit --fixup ` 4. Repeat steps 1-3 for all the submodules you modified. - If you modified the submodule in several different commits, you will need to repeat steps 1-3 - for each commit you modified. You'll know when to stop when the `git log` command shows a commit + for each commit you modified. + You'll know when to stop when the `git log` command shows a commit that's not authored by you. 5. Squash your changes into the existing commits: `git rebase --autosquash -i upstream/main` 6. [Push your changes](#standard-process). @@ -168,9 +171,11 @@ error: Please commit or stash them. (See for the difference between the two.) -This means you have made changes since the last time you made a commit. To be able to rebase, either +This means you have made changes since the last time you made a commit. +To be able to rebase, either commit your changes, or make a temporary commit called a "stash" to have them still not be committed -when you finish rebasing. You may want to configure git to make this "stash" automatically, which +when you finish rebasing. +You may want to configure git to make this "stash" automatically, which will prevent the "cannot rebase" error in nearly all cases: ```console @@ -191,8 +196,9 @@ rm -r src/stdarch ### I see `<<< HEAD`? -You were probably in the middle of a rebase or merge conflict. See -[Conflicts](#rebasing-and-conflicts) for how to fix the conflict. If you don't care about the changes +You were probably in the middle of a rebase or merge conflict. +See [Conflicts](#rebasing-and-conflicts) for how to fix the conflict. +If you don't care about the changes and just want to get a clean copy of the repository back, you can use `git reset`: ```console @@ -213,17 +219,19 @@ hint: 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details. ``` -The advice this gives is incorrect! Because of Rust's -["no-merge" policy](#no-merge-policy) the merge commit created by `git pull` -will not be allowed in the final PR, in addition to defeating the point of the -rebase! Use `git push --force-with-lease` instead. +The advice this gives is incorrect! +Because of Rust's ["no-merge" policy](#no-merge-policy) the merge commit created by `git pull` +will not be allowed in the final PR, in addition to defeating the point of the rebase! +Use `git push --force-with-lease` instead. ### Git is trying to rebase commits I didn't write? If you see many commits in your rebase list, or merge commits, or commits by other people that you -didn't write, it likely means you're trying to rebase over the wrong branch. For example, you may +didn't write, it likely means you're trying to rebase over the wrong branch. +For example, you may have a `rust-lang/rust` remote `upstream`, but ran `git rebase origin/main` instead of `git rebase -upstream/main`. The fix is to abort the rebase and use the correct branch instead: +upstream/main`. +The fix is to abort the rebase and use the correct branch instead: ```console git rebase --abort @@ -239,7 +247,8 @@ git rebase --interactive upstream/main ### Quick note about submodules When updating your local repository with `git pull`, you may notice that sometimes -Git says you have modified some files that you have never edited. For example, +Git says you have modified some files that you have never edited. +For example, running `git status` gives you something like (note the `new commits` mention): ```console @@ -263,17 +272,18 @@ git submodule update ``` Some submodules are not actually needed; for example, `src/llvm-project` doesn't need to be checked -out if you're using `download-ci-llvm`. To avoid having to keep fetching its history, you can use +out if you're using `download-ci-llvm`. + To avoid having to keep fetching its history, you can use `git submodule deinit -f src/llvm-project`, which will also avoid it showing as modified again. ## Rebasing and Conflicts When you edit your code locally, you are making changes to the version of -rust-lang/rust that existed when you created your feature branch. As such, when -you submit your PR it is possible that some of the changes that have been made +rust-lang/rust that existed when you created your feature branch. +As such, when you submit your PR it is possible that some of the changes that have been made to rust-lang/rust since then are in conflict with the changes you've made. -When this happens, you need to resolve the conflicts before your changes can be -merged. To do that, you need to rebase your work on top of rust-lang/rust. +When this happens, you need to resolve the conflicts before your changes can be merged. +To do that, you need to rebase your work on top of rust-lang/rust. ### Rebasing @@ -294,13 +304,14 @@ git pull --rebase https://github.com/rust-lang/rust.git main > have rebased and fixed all conflicts. When you rebase a branch on main, all the changes on your branch are -reapplied to the most recent version of `main`. In other words, Git tries to +reapplied to the most recent version of `main`. +In other words, Git tries to pretend that the changes you made to the old version of `main` were instead -made to the new version of `main`. During this process, you should expect to +made to the new version of `main`. +During this process, you should expect to encounter at least one "rebase conflict." This happens when Git's attempt to -reapply the changes fails because your changes conflicted with other changes -that have been made. You can tell that this happened because you'll see -lines in the output that look like +reapply the changes fails because your changes conflicted with other changes that have been made. +You can tell that this happened because you'll see lines in the output that look like ```console CONFLICT (content): Merge conflict in file.rs @@ -316,21 +327,23 @@ Your code >>>>>>> 8fbf656... Commit fixes 12345 ``` -This represents the lines in the file that Git could not figure out how to -rebase. The section between `<<<<<<< HEAD` and `=======` has the code from -`main`, while the other side has your version of the code. You'll need to -decide how to deal with the conflict. You may want to keep your changes, +This represents the lines in the file that Git could not figure out how to rebase. +The section between `<<<<<<< HEAD` and `=======` has the code from +`main`, while the other side has your version of the code. +You'll need to decide how to deal with the conflict. +You may want to keep your changes, keep the changes on `main`, or combine the two. -Generally, resolving the conflict consists of two steps: First, fix the -particular conflict. Edit the file to make the changes you want and remove the -`<<<<<<<`, `=======` and `>>>>>>>` lines in the process. Second, check the -surrounding code. If there was a conflict, its likely there are some logical -errors lying around too! It's a good idea to run `x check` here to make sure -there are no glaring errors. +Generally, resolving the conflict consists of two steps: First, fix the particular conflict. +Edit the file to make the changes you want and remove the +`<<<<<<<`, `=======` and `>>>>>>>` lines in the process. +Second, check the surrounding code. +If there was a conflict, its likely there are some logical errors lying around too! +It's a good idea to run `x check` here to make sure there are no glaring errors. Once you're all done fixing the conflicts, you need to stage the files that had -conflicts in them via `git add`. Afterwards, run `git rebase --continue` to let +conflicts in them via `git add`. +Afterwards, run `git rebase --continue` to let Git know that you've resolved the conflicts and it should finish the rebase. Once the rebase has succeeded, you'll want to update the associated branch on @@ -340,13 +353,11 @@ your fork with `git push --force-with-lease`. The [above section](#rebasing) is a specific guide on rebasing work and dealing with merge conflicts. -Here is some general advice about how to keep your local repo -up-to-date with upstream changes: +Here is some general advice about how to keep your local repo up-to-date with upstream changes: -Using `git pull upstream main` while on your local `main` branch regularly -will keep it up-to-date. You will also want to keep your feature branches -up-to-date as well. After pulling, you can checkout the feature branches -and rebase them: +Using `git pull upstream main` while on your local `main` branch regularly will keep it up-to-date. +You will also want to keep your feature branches up-to-date as well. +After pulling, you can checkout the feature branches and rebase them: ```console git checkout main @@ -367,21 +378,21 @@ feature branches are in sync with their state on the Github side. ### Squash your commits -"Squashing" commits into each other causes them to be merged into a single -commit. Both the upside and downside of this is that it simplifies the history. +"Squashing" commits into each other causes them to be merged into a single commit. +Both the upside and downside of this is that it simplifies the history. On the one hand, you lose track of the steps in which changes were made, but the history becomes easier to work with. If there are no conflicts and you are just squashing to clean up the history, -use `git rebase --interactive --keep-base main`. This keeps the fork point -of your PR the same, making it easier to review the diff of what happened +use `git rebase --interactive --keep-base main`. +This keeps the fork point of your PR the same, making it easier to review the diff of what happened across your rebases. Squashing can also be useful as part of conflict resolution. If your branch contains multiple consecutive rewrites of the same code, or if the rebase conflicts are extremely severe, you can use -`git rebase --interactive main` to gain more control over the process. This -allows you to choose to skip commits, edit the commits that you do not skip, +`git rebase --interactive main` to gain more control over the process. +This allows you to choose to skip commits, edit the commits that you do not skip, change the order in which they are applied, or "squash" them into each other. Alternatively, you can sacrifice the commit history like this: @@ -395,34 +406,35 @@ git rebase --continue ``` You also may want to squash just the last few commits together, possibly -because they only represent "fixups" and not real changes. For example, +because they only represent "fixups" and not real changes. +For example, `git rebase --interactive HEAD~2` will allow you to edit the two commits only. ### `git range-diff` After completing a rebase, and before pushing up your changes, you may want to -review the changes between your old branch and your new one. You can do that -with `git range-diff main @{upstream} HEAD`. +review the changes between your old branch and your new one. +You can do that with `git range-diff main @{upstream} HEAD`. The first argument to `range-diff`, `main` in this case, is the base revision -that you're comparing your old and new branch against. The second argument is +that you're comparing your old and new branch against. +The second argument is the old version of your branch; in this case, `@upstream` means the version that -you've pushed to GitHub, which is the same as what people will see in your pull -request. Finally, the third argument to `range-diff` is the *new* version of +you've pushed to GitHub, which is the same as what people will see in your pull request. +Finally, the third argument to `range-diff` is the *new* version of your branch; in this case, it is `HEAD`, which is the commit that is currently checked-out in your local repo. -Note that you can also use the equivalent, abbreviated form `git range-diff -main @{u} HEAD`. +Note that you can also use the equivalent, abbreviated form `git range-diff main @{u} HEAD`. Unlike in regular Git diffs, you'll see a `-` or `+` next to another `-` or `+` -in the range-diff output. The marker on the left indicates a change between the -old branch and the new branch, and the marker on the right indicates a change -you've committed. So, you can think of a range-diff as a "diff of diffs" since +in the range-diff output. +The marker on the left indicates a change between the +old branch and the new branch, and the marker on the right indicates a change you've committed. +So, you can think of a range-diff as a "diff of diffs" since it shows you the differences between your old diff and your new diff. -Here's an example of `git range-diff` output (taken from [Git's -docs][range-diff-example-docs]): +Here's an example of `git range-diff` output (taken from [Git's docs][range-diff-example-docs]): ```console -: ------- > 1: 0ddba11 Prepare for the inevitable! @@ -447,12 +459,13 @@ docs][range-diff-example-docs]): (Note that `git range-diff` output in your terminal will probably be easier to read than in this example because it will have colors.) -Another feature of `git range-diff` is that, unlike `git diff`, it will also -diff commit messages. This feature can be useful when amending several commit +Another feature of `git range-diff` is that, unlike `git diff`, it will also diff commit messages. +This feature can be useful when amending several commit messages so you can make sure you changed the right parts. `git range-diff` is a very useful command, but note that it can take some time -to get used to its output format. You may also find Git's documentation on the +to get used to its output format. +You may also find Git's documentation on the command useful, especially their ["Examples" section][range-diff-example-docs]. [range-diff-example-docs]: https://git-scm.com/docs/git-range-diff#_examples @@ -460,18 +473,19 @@ command useful, especially their ["Examples" section][range-diff-example-docs]. ## No-Merge Policy The rust-lang/rust repo uses what is known as a "rebase workflow." This means -that merge commits in PRs are not accepted. As a result, if you are running -`git merge` locally, chances are good that you should be rebasing instead. Of -course, this is not always true; if your merge will just be a fast-forward, +that merge commits in PRs are not accepted. +As a result, if you are running +`git merge` locally, chances are good that you should be rebasing instead. +Of course, this is not always true; if your merge will just be a fast-forward, like the merges that `git pull` usually performs, then no merge commit is -created and you have nothing to worry about. Running `git config merge.ff only` -(this will apply the config to the local repo) +created and you have nothing to worry about. +Running `git config merge.ff only` (this will apply the config to the local repo) once will ensure that all the merges you perform are of this type, so that you cannot make a mistake. -There are a number of reasons for this decision and like all others, it is a -tradeoff. The main advantage is the generally linear commit history. This -greatly simplifies bisecting and makes the history and commit log much easier +There are a number of reasons for this decision and like all others, it is a tradeoff. +The main advantage is the generally linear commit history. +This greatly simplifies bisecting and makes the history and commit log much easier to follow and understand. ## Tips for reviewing @@ -490,15 +504,17 @@ You can also use `git diff -w origin/main` to view changes locally. To checkout PRs locally, you can use `git fetch upstream pull/NNNNN/head && git checkout FETCH_HEAD`. -You can also use github's cli tool. Github shows a button on PRs where you can copy-paste the -command to check it out locally. See for more info. +You can also use github's cli tool. +Github shows a button on PRs where you can copy-paste the command to check it out locally. +See for more info. ![`gh` suggestion](./img/github-cli.png) ### Using GitHub dev As an alternative to the GitHub web UI, GitHub Dev provides a web-based editor for browsing -repository and PRs. It can be opened by replacing `github.com` with `github.dev` in the URL +repository and PRs. +It can be opened by replacing `github.com` with `github.dev` in the URL or by pressing `.` on a GitHub page. See [the docs for github.dev editor](https://docs.github.com/en/codespaces/the-githubdev-web-based-editor) for more details. @@ -506,8 +522,8 @@ for more details. ### Moving large sections of code Git and Github's default diff view for large moves *within* a file is quite poor; it will show each -line as deleted and each line as added, forcing you to compare each line yourself. Git has an option -to show moved lines in a different color: +line as deleted and each line as added, forcing you to compare each line yourself. +Git has an option to show moved lines in a different color: ```console git log -p --color-moved=dimmed-zebra --color-moved-ws=allow-indentation-change @@ -517,12 +533,14 @@ See [the docs for `--color-moved`](https://git-scm.com/docs/git-diff#Documentati ### range-diff -See [the relevant section for PR authors](#git-range-diff). This can be useful for comparing code +See [the relevant section for PR authors](#git-range-diff). +This can be useful for comparing code that was force-pushed to make sure there are no unexpected changes. ### Ignoring changes to specific files -Many large files in the repo are autogenerated. To view a diff that ignores changes to those files, +Many large files in the repo are autogenerated. +To view a diff that ignores changes to those files, you can use the following syntax (e.g. Cargo.lock): ```console @@ -535,11 +553,13 @@ Arbitrary patterns are supported (e.g. `:!compiler/*`). Patterns use the same sy ## Git submodules **NOTE**: submodules are a nice thing to know about, but it *isn't* an absolute -prerequisite to contribute to `rustc`. If you are using Git for the first time, +prerequisite to contribute to `rustc`. +If you are using Git for the first time, you might want to get used to the main concepts of Git before reading this section. The `rust-lang/rust` repository uses [Git submodules] as a way to use other -Rust projects from within the `rust` repo. Examples include Rust's fork of +Rust projects from within the `rust` repo. +Examples include Rust's fork of `llvm-project`, `cargo` and libraries like `stdarch` and `backtrace`. Those projects are developed and maintained in an separate Git (and GitHub) @@ -547,13 +567,14 @@ repository, and they have their own Git history/commits, issue tracker and PRs. Submodules allow us to create some sort of embedded sub-repository inside the `rust` repository and use them like they were directories in the `rust` repository. -Take `llvm-project` for example. `llvm-project` is maintained in the [`rust-lang/llvm-project`] -repository, but it is used in `rust-lang/rust` by the compiler for code generation and -optimization. We bring it in `rust` as a submodule, in the `src/llvm-project` folder. +Take `llvm-project` for example. +`llvm-project` is maintained in the [`rust-lang/llvm-project`] +repository, but it is used in `rust-lang/rust` by the compiler for code generation and optimization. +We bring it in `rust` as a submodule, in the `src/llvm-project` folder. The contents of submodules are ignored by Git: submodules are in some sense isolated -from the rest of the repository. However, if you try to `cd src/llvm-project` and then -run `git status`: +from the rest of the repository. +However, if you try to `cd src/llvm-project` and then run `git status`: ```console HEAD detached at 9567f08afc943 @@ -566,7 +587,8 @@ particular commit. This is because, like any dependency, we want to be able to control which version to use. Submodules allow us to do just that: every submodule is "pinned" to a certain -commit, which doesn't change unless modified manually. If you use `git checkout ` +commit, which doesn't change unless modified manually. +If you use `git checkout ` in the `llvm-project` directory and go back to the `rust` directory, you can stage this change like any other, e.g. by running `git add src/llvm-project`. (Note that if you *don't* stage the change to commit, then you run the risk that running @@ -576,10 +598,10 @@ it automatically "updates" the submodules.) This version selection is usually done by the maintainers of the project, and looks like [this][llvm-update]. -Git submodules take some time to get used to, so don't worry if it isn't perfectly -clear yet. You will rarely have to use them directly and, again, you don't need -to know everything about submodules to contribute to Rust. Just know that they -exist and that they correspond to some sort of embedded subrepository dependency +Git submodules take some time to get used to, so don't worry if it isn't perfectly clear yet. +You will rarely have to use them directly and, again, you don't need +to know everything about submodules to contribute to Rust. +Just know that they exist and that they correspond to some sort of embedded subrepository dependency that Git can nicely and fairly conveniently handle for us. ### Hard-resetting submodules @@ -639,13 +661,12 @@ src/gcc` in this example, you need to: 2. `rm -rf .git/modules//config` 3. `rm -rf .gitconfig.lock` if somehow the `.gitconfig` lock is orphaned. -Then do something like `./x fmt` to have bootstrap manage the submodule -checkouts for you. +Then do something like `./x fmt` to have bootstrap manage the submodule checkouts for you. ## Ignoring commits during `git blame` -Some commits contain large reformatting changes that don't otherwise change functionality. They can -be instructed to be ignored by `git blame` through +Some commits contain large reformatting changes that don't otherwise change functionality. +They can be instructed to be ignored by `git blame` through [`.git-blame-ignore-revs`](https://github.com/rust-lang/rust/blob/HEAD/.git-blame-ignore-revs): 1. Configure `git blame` to use `.git-blame-ignore-revs` as the list of commits to ignore: `git From d34695f50338f899732994ecc8e11865decc571d Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 30 Jan 2026 00:21:42 +0200 Subject: [PATCH 255/978] some improvements --- src/doc/rustc-dev-guide/src/git.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md index d6665f6e17cc..c0b449e8fb28 100644 --- a/src/doc/rustc-dev-guide/src/git.md +++ b/src/doc/rustc-dev-guide/src/git.md @@ -220,7 +220,7 @@ hint: See the 'Note about fast-forwards' in 'git push --help' for details. ``` The advice this gives is incorrect! -Because of Rust's ["no-merge" policy](#no-merge-policy) the merge commit created by `git pull` +Because of Rust's ["no-merge" policy](#no-merge-policy), the merge commit created by `git pull` will not be allowed in the final PR, in addition to defeating the point of the rebase! Use `git push --force-with-lease` instead. @@ -280,7 +280,7 @@ out if you're using `download-ci-llvm`. When you edit your code locally, you are making changes to the version of rust-lang/rust that existed when you created your feature branch. -As such, when you submit your PR it is possible that some of the changes that have been made +As such, when you submit your PR, it is possible that some of the changes that have been made to rust-lang/rust since then are in conflict with the changes you've made. When this happens, you need to resolve the conflicts before your changes can be merged. To do that, you need to rebase your work on top of rust-lang/rust. @@ -309,7 +309,7 @@ In other words, Git tries to pretend that the changes you made to the old version of `main` were instead made to the new version of `main`. During this process, you should expect to -encounter at least one "rebase conflict." This happens when Git's attempt to +encounter at least one "rebase conflict". This happens when Git's attempt to reapply the changes fails because your changes conflicted with other changes that have been made. You can tell that this happened because you'll see lines in the output that look like @@ -472,7 +472,7 @@ command useful, especially their ["Examples" section][range-diff-example-docs]. ## No-Merge Policy -The rust-lang/rust repo uses what is known as a "rebase workflow." This means +The rust-lang/rust repo uses what is known as a "rebase workflow". This means that merge commits in PRs are not accepted. As a result, if you are running `git merge` locally, chances are good that you should be rebasing instead. @@ -483,7 +483,7 @@ Running `git config merge.ff only` (this will apply the config to the local repo once will ensure that all the merges you perform are of this type, so that you cannot make a mistake. -There are a number of reasons for this decision and like all others, it is a tradeoff. +There are a number of reasons for this decision, and like all others, it is a tradeoff. The main advantage is the generally linear commit history. This greatly simplifies bisecting and makes the history and commit log much easier to follow and understand. @@ -560,7 +560,7 @@ you might want to get used to the main concepts of Git before reading this secti The `rust-lang/rust` repository uses [Git submodules] as a way to use other Rust projects from within the `rust` repo. Examples include Rust's fork of -`llvm-project`, `cargo` and libraries like `stdarch` and `backtrace`. +`llvm-project`, `cargo`, and libraries like `stdarch` and `backtrace`. Those projects are developed and maintained in an separate Git (and GitHub) repository, and they have their own Git history/commits, issue tracker and PRs. From 72338fafb2c607684d9c848ecdb1f0b314cd8588 Mon Sep 17 00:00:00 2001 From: Jamie Hill-Daniel Date: Thu, 29 Jan 2026 15:38:49 +0000 Subject: [PATCH 256/978] Port `rustc_layout` to attribute parser --- .../src/attributes/rustc_internal.rs | 59 +++++++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 3 +- .../rustc_hir/src/attrs/data_structures.rs | 12 ++++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_passes/messages.ftl | 2 - compiler/rustc_passes/src/check_attr.rs | 1 + compiler/rustc_passes/src/errors.rs | 7 --- compiler/rustc_passes/src/layout_test.rs | 49 +++++++-------- tests/ui/layout/debug.rs | 8 +-- tests/ui/layout/debug.stderr | 28 +++++---- 10 files changed, 115 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 365cd55bdc38..6375927b01de 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1,4 +1,5 @@ use rustc_ast::{LitIntType, LitKind, MetaItemLit}; +use rustc_hir::attrs::RustcLayoutType; use rustc_session::errors; use super::prelude::*; @@ -329,3 +330,61 @@ impl NoArgsAttributeParser for RustcOffloadKernelParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOffloadKernel; } + +pub(crate) struct RustcLayoutParser; + +impl CombineAttributeParser for RustcLayoutParser { + const PATH: &[rustc_span::Symbol] = &[sym::rustc_layout]; + + type Item = RustcLayoutType; + + const CONVERT: ConvertFn = |items, _| AttributeKind::RustcLayout(items); + + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Struct), + Allow(Target::Enum), + Allow(Target::Union), + Allow(Target::TyAlias), + ]); + + const TEMPLATE: AttributeTemplate = + template!(List: &["abi", "align", "size", "homogenous_aggregate", "debug"]); + + fn extend( + cx: &mut AcceptContext<'_, '_, S>, + args: &ArgParser, + ) -> impl IntoIterator { + let ArgParser::List(items) = args else { + cx.expected_list(cx.attr_span, args); + return vec![]; + }; + + let mut result = Vec::new(); + for item in items.mixed() { + let Some(arg) = item.meta_item() else { + cx.unexpected_literal(item.span()); + continue; + }; + let Some(ident) = arg.ident() else { + cx.expected_identifier(arg.span()); + return vec![]; + }; + let ty = match ident.name { + sym::abi => RustcLayoutType::Abi, + sym::align => RustcLayoutType::Align, + sym::size => RustcLayoutType::Size, + sym::homogeneous_aggregate => RustcLayoutType::HomogenousAggregate, + sym::debug => RustcLayoutType::Debug, + _ => { + cx.expected_specific_argument( + ident.span, + &[sym::abi, sym::align, sym::size, sym::homogeneous_aggregate, sym::debug], + ); + continue; + } + }; + result.push(ty); + } + result + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 20bdfa45a013..a4d08de515ad 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -75,7 +75,7 @@ use crate::attributes::rustc_dump::{ RustcDumpVtable, }; use crate::attributes::rustc_internal::{ - RustcHasIncoherentInherentImplsParser, RustcLayoutScalarValidRangeEndParser, + RustcHasIncoherentInherentImplsParser, RustcLayoutParser, RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, RustcLegacyConstGenericsParser, RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, RustcLintQueryInstabilityParser, RustcLintUntrackedQueryInformationParser, RustcMainParser, RustcMustImplementOneOfParser, @@ -198,6 +198,7 @@ attribute_parsers!( Combine, Combine, Combine, + Combine, Combine, Combine, // tidy-alphabetical-end diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index ef9ee4b6fb2d..bc58f1d8faa5 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -690,6 +690,15 @@ impl IntoDiagArg for CrateType { } } +#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)] +pub enum RustcLayoutType { + Abi, + Align, + Size, + HomogenousAggregate, + Debug, +} + /// Represents parsed *built-in* inert attributes. /// /// ## Overview @@ -1048,6 +1057,9 @@ pub enum AttributeKind { /// Represents `#[rustc_has_incoherent_inherent_impls]` RustcHasIncoherentInherentImpls, + /// Represents `#[rustc_layout]` + RustcLayout(ThinVec), + /// Represents `#[rustc_layout_scalar_valid_range_end]`. RustcLayoutScalarValidRangeEnd(Box, Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 631b07ff1da2..4fd0f5698a8b 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -111,6 +111,7 @@ impl AttributeKind { RustcDumpVtable(..) => No, RustcDynIncompatibleTrait(..) => No, RustcHasIncoherentInherentImpls => Yes, + RustcLayout(..) => No, RustcLayoutScalarValidRangeEnd(..) => Yes, RustcLayoutScalarValidRangeStart(..) => Yes, RustcLegacyConstGenerics { .. } => Yes, diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 395d940ddae6..f8ff46189c05 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -302,8 +302,6 @@ passes_layout_align = align: {$align} passes_layout_homogeneous_aggregate = homogeneous_aggregate: {$homogeneous_aggregate} -passes_layout_invalid_attribute = - `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases passes_layout_of = layout_of({$normalized_ty}) = {$ty_layout} passes_layout_size = diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 541870607b63..800965f81d3d 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -299,6 +299,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcDumpVtable(..) | AttributeKind::RustcDynIncompatibleTrait(..) | AttributeKind::RustcHasIncoherentInherentImpls + | AttributeKind::RustcLayout(..) | AttributeKind::RustcLayoutScalarValidRangeEnd(..) | AttributeKind::RustcLayoutScalarValidRangeStart(..) | AttributeKind::RustcLintOptDenyFieldAccess { .. } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index bf9b615546d8..29688dd4d537 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -519,13 +519,6 @@ pub(crate) struct LayoutOf<'tcx> { pub ty_layout: String, } -#[derive(Diagnostic)] -#[diag(passes_layout_invalid_attribute)] -pub(crate) struct LayoutInvalidAttribute { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(passes_abi_of)] pub(crate) struct AbiOf { diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index 4054cfa56330..354a98d6d0dc 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -1,20 +1,18 @@ use rustc_abi::{HasDataLayout, TargetDataLayout}; -use rustc_hir::Attribute; +use rustc_hir::attrs::{AttributeKind, RustcLayoutType}; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; +use rustc_hir::find_attr; use rustc_middle::span_bug; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers}; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::Span; use rustc_span::source_map::Spanned; -use rustc_span::{Span, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::TyCtxtInferExt; use rustc_trait_selection::traits; -use crate::errors::{ - LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutInvalidAttribute, LayoutOf, - LayoutSize, UnrecognizedArgument, -}; +use crate::errors::{LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutOf, LayoutSize}; pub fn test_layout(tcx: TyCtxt<'_>) { if !tcx.features().rustc_attrs() { @@ -22,14 +20,14 @@ pub fn test_layout(tcx: TyCtxt<'_>) { return; } for id in tcx.hir_crate_items(()).definitions() { - for attr in tcx.get_attrs(id, sym::rustc_layout) { - match tcx.def_kind(id) { - DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union => { - dump_layout_of(tcx, id, attr); - } - _ => { - tcx.dcx().emit_err(LayoutInvalidAttribute { span: tcx.def_span(id) }); - } + let attrs = tcx.get_all_attrs(id); + if let Some(attrs) = find_attr!(attrs, AttributeKind::RustcLayout(attrs) => attrs) { + // Attribute parsing handles error reporting + if matches!( + tcx.def_kind(id), + DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union + ) { + dump_layout_of(tcx, id, attrs); } } } @@ -66,7 +64,7 @@ pub fn ensure_wf<'tcx>( } } -fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { +fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attrs: &[RustcLayoutType]) { let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id); let ty = tcx.type_of(item_def_id).instantiate_identity(); let span = tcx.def_span(item_def_id.to_def_id()); @@ -75,32 +73,29 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { } match tcx.layout_of(typing_env.as_query_input(ty)) { Ok(ty_layout) => { - // Check out the `#[rustc_layout(..)]` attribute to tell what to dump. - // The `..` are the names of fields to dump. - let meta_items = attr.meta_item_list().unwrap_or_default(); - for meta_item in meta_items { - match meta_item.name() { + for attr in attrs { + match attr { // FIXME: this never was about ABI and now this dump arg is confusing - Some(sym::abi) => { + RustcLayoutType::Abi => { tcx.dcx().emit_err(LayoutAbi { span, abi: format!("{:?}", ty_layout.backend_repr), }); } - Some(sym::align) => { + RustcLayoutType::Align => { tcx.dcx().emit_err(LayoutAlign { span, align: format!("{:?}", ty_layout.align), }); } - Some(sym::size) => { + RustcLayoutType::Size => { tcx.dcx() .emit_err(LayoutSize { span, size: format!("{:?}", ty_layout.size) }); } - Some(sym::homogeneous_aggregate) => { + RustcLayoutType::HomogenousAggregate => { tcx.dcx().emit_err(LayoutHomogeneousAggregate { span, homogeneous_aggregate: format!( @@ -111,16 +106,12 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { }); } - Some(sym::debug) => { + RustcLayoutType::Debug => { let normalized_ty = tcx.normalize_erasing_regions(typing_env, ty); // FIXME: using the `Debug` impl here isn't ideal. let ty_layout = format!("{:#?}", *ty_layout); tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout }); } - - _ => { - tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() }); - } } } } diff --git a/tests/ui/layout/debug.rs b/tests/ui/layout/debug.rs index 90e3c58dad71..60415911d38e 100644 --- a/tests/ui/layout/debug.rs +++ b/tests/ui/layout/debug.rs @@ -68,12 +68,12 @@ union P5 { zst: [u16; 0], byte: u8 } //~ ERROR: layout_of #[rustc_layout(debug)] type X = std::mem::MaybeUninit; //~ ERROR: layout_of -#[rustc_layout(debug)] -const C: () = (); //~ ERROR: can only be applied to +#[rustc_layout(debug)] //~ ERROR: cannot be used on constants +const C: () = (); impl S { - #[rustc_layout(debug)] - const C: () = (); //~ ERROR: can only be applied to + #[rustc_layout(debug)] //~ ERROR: cannot be used on associated consts + const C: () = (); } #[rustc_layout(debug)] diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index 79ce21eb532b..c92f876fa5a1 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -4,6 +4,22 @@ error: unions cannot have zero fields LL | union EmptyUnion {} | ^^^^^^^^^^^^^^^^^^^ +error: `#[rustc_layout]` attribute cannot be used on constants + --> $DIR/debug.rs:71:1 + | +LL | #[rustc_layout(debug)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_layout]` can be applied to data types and type aliases + +error: `#[rustc_layout]` attribute cannot be used on associated consts + --> $DIR/debug.rs:75:5 + | +LL | #[rustc_layout(debug)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_layout]` can be applied to data types and type aliases + error: layout_of(E) = Layout { size: Size(12 bytes), align: AbiAlign { @@ -577,12 +593,6 @@ error: layout_of(MaybeUninit) = Layout { LL | type X = std::mem::MaybeUninit; | ^^^^^^ -error: `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases - --> $DIR/debug.rs:72:1 - | -LL | const C: () = (); - | ^^^^^^^^^^^ - error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/debug.rs:80:19 | @@ -604,12 +614,6 @@ error: the type `T` does not have a fixed layout LL | type TooGeneric = T; | ^^^^^^^^^^^^^^^^^^ -error: `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases - --> $DIR/debug.rs:76:5 - | -LL | const C: () = (); - | ^^^^^^^^^^^ - error: aborting due to 20 previous errors For more information about this error, try `rustc --explain E0277`. From 654a5a3404952815c0aae2f3b2d231623c8f9f8b Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 30 Jan 2026 00:24:39 +0200 Subject: [PATCH 257/978] sembr src/compiler-team.md --- src/doc/rustc-dev-guide/src/compiler-team.md | 64 +++++++++----------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/compiler-team.md b/src/doc/rustc-dev-guide/src/compiler-team.md index 495bd22da4d8..6a02273f24e4 100644 --- a/src/doc/rustc-dev-guide/src/compiler-team.md +++ b/src/doc/rustc-dev-guide/src/compiler-team.md @@ -3,7 +3,8 @@ > NOTE: > There exists much detail about the team [on Forge], making most of the following obsolete. -rustc is maintained by the [Rust compiler team][team]. The people who belong to +rustc is maintained by the [Rust compiler team][team]. +The people who belong to this team collectively work to track regressions and implement new features. Members of the Rust compiler team are people who have made significant contributions to rustc and its design. @@ -34,26 +35,24 @@ who are reviewers of each part. ## Rust compiler meeting The compiler team has a weekly meeting where we do triage and try to -generally stay on top of new bugs, regressions, and discuss important -things in general. -They are held on [Zulip][zulip-meetings]. It works roughly as follows: +generally stay on top of new bugs, regressions, and discuss important things in general. +They are held on [Zulip][zulip-meetings]. +It works roughly as follows: - **Announcements, MCPs/FCPs, and WG-check-ins:** We share some - announcements with the rest of the team about important things we want - everyone to be aware of. We also share the status of MCPs and FCPs and we - use the opportunity to have a couple of WGs giving us an update about - their work. + announcements with the rest of the team about important things we want everyone to be aware of. + We also share the status of MCPs and FCPs and we + use the opportunity to have a couple of WGs giving us an update about their work. - **Check for beta and stable nominations:** These are nominations of things to backport to beta and stable respectively. - We then look for new cases where the compiler broke previously working - code in the wild. Regressions are important issues to fix, so it's + We then look for new cases where the compiler broke previously working code in the wild. + Regressions are important issues to fix, so it's likely that they are tagged as P-critical or P-high; the major exception would be bug fixes (though even there we often [aim to give warnings first][procedure]). - **Review P-critical and P-high bugs:** P-critical and P-high bugs are - those that are sufficiently important for us to actively track - progress. P-critical and P-high bugs should ideally always have an - assignee. + those that are sufficiently important for us to actively track progress. + P-critical and P-high bugs should ideally always have an assignee. - **Check `S-waiting-on-t-compiler` and `I-compiler-nominated` issues:** These are issues where feedback from the team is desired. - **Look over the performance triage report:** We check for PRs that made the @@ -61,8 +60,7 @@ They are held on [Zulip][zulip-meetings]. It works roughly as follows: the regression can be addressed in a future PR. The meeting currently takes place on Thursdays at 10am Boston time -(UTC-4 typically, but daylight savings time sometimes makes things -complicated). +(UTC-4 typically, but daylight savings time sometimes makes things complicated). [procedure]: ./bug-fix-procedure.md [zulip-t-compiler]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler @@ -72,17 +70,16 @@ complicated). ## Team membership Membership in the Rust team is typically offered when someone has been -making significant contributions to the compiler for some -time. Membership is both a recognition but also an obligation: +making significant contributions to the compiler for some time. +Membership is both a recognition but also an obligation: compiler team members are generally expected to help with upkeep as well as doing reviews and other work. If you are interested in becoming a compiler team member, the first -thing to do is to start fixing some bugs, or get involved in a working -group. One good way to find bugs is to look for +thing to do is to start fixing some bugs, or get involved in a working group. +One good way to find bugs is to look for [open issues tagged with E-easy](https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy) -or -[E-mentor](https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AE-mentor). +or [E-mentor](https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AE-mentor). You can also dig through the graveyard of PRs that were [closed due to inactivity](https://github.com/rust-lang/rust/pulls?q=is%3Apr+label%3AS-inactive), @@ -92,18 +89,17 @@ for which the original author didn't have time. ### r+ rights -Once you have made a number of individual PRs to rustc, we will often -offer r+ privileges. This means that you have the right to instruct -"bors" (the robot that manages which PRs get landed into rustc) to -merge a PR +Once you have made a number of individual PRs to rustc, we will often offer r+ privileges. +This means that you have the right to instruct +"bors" (the robot that manages which PRs get landed into rustc) to merge a PR ([here are some instructions for how to talk to bors][bors-guide]). [bors-guide]: https://bors.rust-lang.org/ The guidelines for reviewers are as follows: -- You are always welcome to review any PR, regardless of who it is - assigned to. However, do not r+ PRs unless: +- You are always welcome to review any PR, regardless of who it is assigned to. + However, do not r+ PRs unless: - You are confident in that part of the code. - You are confident that nobody else wants to review it first. - For example, sometimes people will express a desire to review a @@ -119,18 +115,16 @@ The guidelines for reviewers are as follows: Once you have r+ rights, you can also be added to the [reviewer rotation]. [triagebot] is the bot that [automatically assigns] incoming PRs to reviewers. -If you are added, you will be randomly selected to review -PRs. If you find you are assigned a PR that you don't feel comfortable +If you are added, you will be randomly selected to review PRs. +If you find you are assigned a PR that you don't feel comfortable reviewing, you can also leave a comment like `r? @so-and-so` to assign to someone else — if you don't know who to request, just write `r? -@nikomatsakis for reassignment` and @nikomatsakis will pick someone -for you. +@nikomatsakis for reassignment` and @nikomatsakis will pick someone for you. [reviewer rotation]: https://github.com/rust-lang/rust/blob/36285c5de8915ecc00d91ae0baa79a87ed5858d5/triagebot.toml#L528-L577 [triagebot]: https://github.com/rust-lang/triagebot/ [automatically assigns]: https://forge.rust-lang.org/triagebot/pr-assignment.html -Getting on the reviewer rotation is much appreciated as it lowers the -review burden for all of us! However, if you don't have time to give -people timely feedback on their PRs, it may be better that you don't -get on the list. +Getting on the reviewer rotation is much appreciated as it lowers the review burden for all of us! +However, if you don't have time to give +people timely feedback on their PRs, it may be better that you don't get on the list. From b4ded124a73bb4399a8d32747af8904b16f43480 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 30 Jan 2026 00:27:42 +0200 Subject: [PATCH 258/978] extraneous whitespace --- src/doc/rustc-dev-guide/src/compiler-team.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/compiler-team.md b/src/doc/rustc-dev-guide/src/compiler-team.md index 6a02273f24e4..ee058c805f0d 100644 --- a/src/doc/rustc-dev-guide/src/compiler-team.md +++ b/src/doc/rustc-dev-guide/src/compiler-team.md @@ -99,7 +99,7 @@ This means that you have the right to instruct The guidelines for reviewers are as follows: - You are always welcome to review any PR, regardless of who it is assigned to. - However, do not r+ PRs unless: + However, do not r+ PRs unless: - You are confident in that part of the code. - You are confident that nobody else wants to review it first. - For example, sometimes people will express a desire to review a From 84e994ebd45b78a9d4f5c94c1b76f9543912dad5 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 30 Jan 2026 00:28:12 +0200 Subject: [PATCH 259/978] sembr src/tests/ci.md --- src/doc/rustc-dev-guide/src/tests/ci.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md index ce80b07fe08d..723926f2241f 100644 --- a/src/doc/rustc-dev-guide/src/tests/ci.md +++ b/src/doc/rustc-dev-guide/src/tests/ci.md @@ -6,16 +6,15 @@ The primary goal of our CI system is to ensure that the `main` branch of From a high-level point of view, when you open a pull request at `rust-lang/rust`, the following will happen: -- A small [subset](#pull-request-builds) of tests and checks are run after each - push to the PR. +- A small [subset](#pull-request-builds) of tests and checks are run after each push to the PR. This should help catch common errors. - When the PR is approved, the [bors] bot enqueues the PR into a [merge queue]. - Once the PR gets to the front of the queue, bors will create a merge commit and run the [full test suite](#auto-builds) on it. The merge commit either contains only one specific PR or it can be a ["rollup"](#rollups) which combines multiple PRs together, to reduce CI costs and merge delays. -- Once the whole test suite finishes, two things can happen. Either CI fails - with an error that needs to be addressed by the developer, or CI succeeds and +- Once the whole test suite finishes, two things can happen. + Either CI fails with an error that needs to be addressed by the developer, or CI succeeds and the merge commit is then pushed to the `main` branch. If you want to modify what gets executed on CI, see [Modifying CI jobs](#modifying-ci-jobs). @@ -303,8 +302,7 @@ This is worth it because these release artifacts: - Allow perf testing even at a later date. - Allow bisection when bugs are discovered later. -- Ensure release quality since if we're always releasing, we can catch problems - early. +- Ensure release quality since if we're always releasing, we can catch problems early. ### Rollups @@ -449,8 +447,7 @@ If you want to determine which `bootstrap.toml` settings are used in CI for a particular job, it is probably easiest to just look at the build log. To do this: -1. Go to - +1. Go to to find the most recently successful build, and click on it. 2. Choose the job you are interested in on the left-hand side. 3. Click on the gear icon and choose "View raw logs" From c3e9f0007e08508f0e3778d0ffb873563b5a8bf1 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 30 Jan 2026 00:31:17 +0200 Subject: [PATCH 260/978] sembr src/rustdoc-internals/rustdoc-json-test-suite.md --- .../src/rustdoc-internals/rustdoc-json-test-suite.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md index 7a846b711326..3208c84fe554 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md @@ -18,8 +18,7 @@ Each crate's json output is checked by 2 programs: [jsondoclint](#jsondocck) and This makes sure there are no dangling [`Id`]s. +Also, talk about how it works --> ## jsondocck @@ -35,7 +34,7 @@ It uses [JSONPath] as a query language, which takes a path, and returns a *list* - `//@ has `: Check `` exists, and at least 1 of the matches is equal to the given `` - `//@ !has `: Checks `` exists, but none of the matches equal the given ``. - `//@ is `: Check `` matches exactly one value, and it's equal to the given ``. -- `//@ is ...`: Check that `` matches to exactly every given ``. +- `//@ is ...`: Check that `` matches to exactly every given ``. Ordering doesn't matter here. - `//@ !is `: Check `` matches exactly one value, and that value is not equal to the given ``. - `//@ count `: Check that `` matches to `` of values. @@ -48,7 +47,8 @@ These are defined in [`directive.rs`]. Values can be either JSON values, or variables. - JSON values are JSON literals, e.g. `true`, `"string"`, `{"key": "value"}`. - These often need to be quoted using `'`, to be processed as 1 value. See [§Argument splitting](#argument-splitting) + These often need to be quoted using `'`, to be processed as 1 value. + See [§Argument splitting](#argument-splitting) - Variables can be used to store the value in one path, and use it in later queries. They are set with the `//@ set = ` directive, and accessed with `$` From 654945a736b2eba01c62191fffd47d0a124d0018 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 16 Jan 2026 14:48:05 +1100 Subject: [PATCH 261/978] Simplify `QueryStackFrame::new`. Instead of passing a closure that computes a hash and immediately calling it, just compute the hash and pass the value. --- compiler/rustc_query_impl/src/plumbing.rs | 14 ++++++-------- compiler/rustc_query_system/src/query/mod.rs | 4 ++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index c71352c3fd20..d1b1c3356cfd 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -373,14 +373,12 @@ pub(crate) fn create_query_frame< ) -> QueryStackFrame> { let def_id = key.key_as_def_id(); - let hash = || { - tcx.with_stable_hashing_context(|mut hcx| { - let mut hasher = StableHasher::new(); - kind.as_usize().hash_stable(&mut hcx, &mut hasher); - key.hash_stable(&mut hcx, &mut hasher); - hasher.finish::() - }) - }; + let hash = tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + kind.as_usize().hash_stable(&mut hcx, &mut hasher); + key.hash_stable(&mut hcx, &mut hasher); + hasher.finish::() + }); let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle(); let info = diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 701253d50fcc..a689c3ac41b0 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -63,11 +63,11 @@ impl QueryStackFrame { pub fn new( info: I, dep_kind: DepKind, - hash: impl FnOnce() -> Hash64, + hash: Hash64, def_id: Option, def_id_for_ty_in_cycle: Option, ) -> Self { - Self { info, def_id, dep_kind, hash: hash(), def_id_for_ty_in_cycle } + Self { info, def_id, dep_kind, hash, def_id_for_ty_in_cycle } } fn lift>( From 637e2cb5e1d0eb7ecddd61999d54b7abd68ea1e9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 16 Jan 2026 16:31:04 +1100 Subject: [PATCH 262/978] Rename `create_query_frame_extra`. It produces a `QueryStackFrameExtra`, so `stack_` should be in the name. --- compiler/rustc_query_impl/src/plumbing.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index d1b1c3356cfd..b3448a6dc864 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -322,7 +322,7 @@ macro_rules! should_ever_cache_on_disk { }; } -fn create_query_frame_extra<'tcx, K: Key + Copy + 'tcx>( +fn mk_query_stack_frame_extra<'tcx, K: Key + Copy + 'tcx>( (tcx, key, kind, name, do_describe): ( TyCtxt<'tcx>, K, @@ -382,7 +382,7 @@ pub(crate) fn create_query_frame< let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle(); let info = - QueryStackDeferred::new((tcx, key, kind, name, do_describe), create_query_frame_extra); + QueryStackDeferred::new((tcx, key, kind, name, do_describe), mk_query_stack_frame_extra); QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle) } From 31eab45e4a979503a14db53a0a5311dc2cb30e1d Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 30 Jan 2026 00:58:42 +0200 Subject: [PATCH 263/978] fix sembr tool corner case --- src/doc/rustc-dev-guide/ci/sembr/src/main.rs | 13 ++++++++++++- .../rustdoc-internals/rustdoc-json-test-suite.md | 3 ++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index 0ae77af047e6..6720267e14f3 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -83,7 +83,8 @@ fn ignore(line: &str, in_code_block: bool) -> bool { || line.contains(" etc.") || line.contains("i.e.") || line.contains("et. al") - || line.contains("") || line.contains('|') || line.trim_start().starts_with('>') || line.starts_with('#') @@ -266,6 +267,11 @@ leave the text alone ``` + ignore +html comment closing + handle the indented well @@ -292,6 +298,11 @@ leave the text alone ``` + ignore +html comment closing + handle the indented well [a target]: https://example.com diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md index 3208c84fe554..2a4b89250f10 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md @@ -18,7 +18,8 @@ Each crate's json output is checked by 2 programs: [jsondoclint](#jsondocck) and This makes sure there are no dangling [`Id`]s. +Also, talk about how it works + --> ## jsondocck From 62dbe9fbab878473fb9deb765222ecbbe521fb8c Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 30 Jan 2026 00:59:05 +0200 Subject: [PATCH 264/978] whitespace --- .../src/rustdoc-internals/rustdoc-json-test-suite.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md index 2a4b89250f10..f9d9d1b59a91 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals/rustdoc-json-test-suite.md @@ -32,7 +32,7 @@ It uses [JSONPath] as a query language, which takes a path, and returns a *list* - `//@ has `: Checks `` exists, i.e. matches at least 1 value. - `//@ !has `: Checks `` doesn't exist, i.e. matches 0 values. -- `//@ has `: Check `` exists, and at least 1 of the matches is equal to the given `` +- `//@ has `: Check `` exists, and at least 1 of the matches is equal to the given `` - `//@ !has `: Checks `` exists, but none of the matches equal the given ``. - `//@ is `: Check `` matches exactly one value, and it's equal to the given ``. - `//@ is ...`: Check that `` matches to exactly every given ``. @@ -47,7 +47,7 @@ These are defined in [`directive.rs`]. Values can be either JSON values, or variables. -- JSON values are JSON literals, e.g. `true`, `"string"`, `{"key": "value"}`. +- JSON values are JSON literals, e.g. `true`, `"string"`, `{"key": "value"}`. These often need to be quoted using `'`, to be processed as 1 value. See [§Argument splitting](#argument-splitting) - Variables can be used to store the value in one path, and use it in later queries. From 1c3d9abbad36117265b8a4c85b6cff0f78fdeed5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 15 Jan 2026 19:09:07 +1100 Subject: [PATCH 265/978] Reduce generics use in the query system. `QueryStackFrame` is a generic type, and the `I` parameter leaks out to many other related types. However, it only has two instantiations in practice: - `QueryStackFrame` - `QueryStackFrame>` And most of the places that currently use `QueryStackFrame` are actually specific to one of the instantiations. This commit removes the unneeded genericity. The following types are only ever used with `QueryStackDeferred<'tcx>`: - QueryMap - QueryJobInfo - QueryJob - QueryWaiter - QueryLatchInfo - QueryLatch - QueryState - QueryResult and their `` parameter is changed to `<'tcx>`. Also, the `QueryContext::QueryInfo` associated type is removed. `CycleError` and `QueryInfo` are still generic over type, because they are used with both instantiations. This required also adding a `<'tcx>` parameter to the traits `QueryDispatcher` and `QueryContext`, which is annoying but I can't see how to avoid it. --- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/query/plumbing.rs | 2 +- compiler/rustc_query_impl/src/lib.rs | 17 ++-- compiler/rustc_query_impl/src/plumbing.rs | 21 ++--- .../rustc_query_system/src/dep_graph/graph.rs | 20 ++-- .../src/query/dispatcher.rs | 23 ++--- compiler/rustc_query_system/src/query/job.rs | 94 +++++++++---------- compiler/rustc_query_system/src/query/mod.rs | 20 ++-- .../rustc_query_system/src/query/plumbing.rs | 94 +++++++++---------- 9 files changed, 140 insertions(+), 153 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ad63251363e2..cea50f95df4b 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -88,7 +88,7 @@ use rustc_index::IndexVec; use rustc_lint_defs::LintId; use rustc_macros::rustc_queries; use rustc_query_system::ich::StableHashingContext; -use rustc_query_system::query::{QueryMode, QueryStackDeferred, QueryState}; +use rustc_query_system::query::{QueryMode, QueryState}; use rustc_session::Limits; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::cstore::{ diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 7b85dac41aef..2bda014a19fe 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -440,7 +440,7 @@ macro_rules! define_callbacks { #[derive(Default)] pub struct QueryStates<'tcx> { $( - pub $name: QueryState<$($K)*, QueryStackDeferred<'tcx>>, + pub $name: QueryState<'tcx, $($K)*>, )* } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 382b8750a1ce..8fa4fb3090db 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -21,7 +21,7 @@ use rustc_query_system::dep_graph::SerializedDepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ CycleError, CycleErrorHandling, HashResult, QueryCache, QueryDispatcher, QueryMap, QueryMode, - QueryStackDeferred, QueryState, get_query_incr, get_query_non_incr, + QueryState, get_query_incr, get_query_non_incr, }; use rustc_span::{ErrorGuaranteed, Span}; @@ -66,7 +66,7 @@ impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDA // This is `impl QueryDispatcher for SemiDynamicQueryDispatcher`. impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> - QueryDispatcher for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE> + QueryDispatcher<'tcx> for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE> where for<'a> C::Key: HashStable>, { @@ -86,10 +86,7 @@ where } #[inline(always)] - fn query_state<'a>( - self, - qcx: QueryCtxt<'tcx>, - ) -> &'a QueryState> + fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState<'tcx, Self::Key> where QueryCtxt<'tcx>: 'a, { @@ -98,7 +95,7 @@ where unsafe { &*(&qcx.tcx.query_system.states as *const QueryStates<'tcx>) .byte_add(self.vtable.query_state) - .cast::>>() + .cast::>() } } @@ -211,13 +208,15 @@ where /// on the type `rustc_query_impl::query_impl::$name::QueryType`. trait QueryDispatcherUnerased<'tcx> { type UnerasedValue; - type Dispatcher: QueryDispatcher>; + type Dispatcher: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>; const NAME: &'static &'static str; fn query_dispatcher(tcx: TyCtxt<'tcx>) -> Self::Dispatcher; - fn restore_val(value: ::Value) -> Self::UnerasedValue; + fn restore_val( + value: >::Value, + ) -> Self::UnerasedValue; } pub fn query_system<'a>( diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index b3448a6dc864..ef7a62351930 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -60,9 +60,7 @@ impl<'tcx> HasDepContext for QueryCtxt<'tcx> { } } -impl<'tcx> QueryContext for QueryCtxt<'tcx> { - type QueryInfo = QueryStackDeferred<'tcx>; - +impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> { #[inline] fn jobserver_proxy(&self) -> &Proxy { &self.tcx.jobserver_proxy @@ -93,10 +91,7 @@ impl<'tcx> QueryContext for QueryCtxt<'tcx> { /// Prefer passing `false` to `require_complete` to avoid potential deadlocks, /// especially when called from within a deadlock handler, unless a /// complete map is needed and no deadlock is possible at this call site. - fn collect_active_jobs( - self, - require_complete: bool, - ) -> Result>, QueryMap>> { + fn collect_active_jobs(self, require_complete: bool) -> Result, QueryMap<'tcx>> { let mut jobs = QueryMap::default(); let mut complete = true; @@ -415,7 +410,7 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>( } pub(crate) fn query_key_hash_verify<'tcx>( - query: impl QueryDispatcher>, + query: impl QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, qcx: QueryCtxt<'tcx>, ) { let _timer = qcx.tcx.prof.generic_activity_with_arg("query_key_hash_verify_for", query.name()); @@ -443,7 +438,7 @@ pub(crate) fn query_key_hash_verify<'tcx>( fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) where - Q: QueryDispatcher>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { debug_assert!(tcx.dep_graph.is_green(&dep_node)); @@ -489,7 +484,7 @@ where fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool where - Q: QueryDispatcher>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { // We must avoid ever having to call `force_from_dep_node()` for a // `DepNode::codegen_unit`: @@ -732,14 +727,14 @@ macro_rules! define_queries { } #[inline(always)] - fn restore_val(value: ::Value) -> Self::UnerasedValue { + fn restore_val(value: >::Value) -> Self::UnerasedValue { erase::restore_val::>(value) } } pub(crate) fn collect_active_jobs<'tcx>( tcx: TyCtxt<'tcx>, - qmap: &mut QueryMap>, + qmap: &mut QueryMap<'tcx>, require_complete: bool, ) -> Option<()> { let make_query = |tcx, key| { @@ -823,7 +818,7 @@ macro_rules! define_queries { // These arrays are used for iteration and can't be indexed by `DepKind`. const COLLECT_ACTIVE_JOBS: &[ - for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap>, bool) -> Option<()> + for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<'tcx>, bool) -> Option<()> ] = &[$(query_impl::$name::collect_active_jobs),*]; diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index f0cc9636b75c..6d46d144d0f1 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -519,7 +519,11 @@ impl DepGraph { /// This encodes a diagnostic by creating a node with an unique index and associating /// `diagnostic` with it, for use in the next session. #[inline] - pub fn record_diagnostic(&self, qcx: Qcx, diagnostic: &DiagInner) { + pub fn record_diagnostic<'tcx, Qcx: QueryContext<'tcx>>( + &self, + qcx: Qcx, + diagnostic: &DiagInner, + ) { if let Some(ref data) = self.data { D::read_deps(|task_deps| match task_deps { TaskDepsRef::EvalAlways | TaskDepsRef::Ignore => return, @@ -532,7 +536,7 @@ impl DepGraph { /// This forces a diagnostic node green by running its side effect. `prev_index` would /// refer to a node created used `encode_diagnostic` in the previous session. #[inline] - pub fn force_diagnostic_node( + pub fn force_diagnostic_node<'tcx, Qcx: QueryContext<'tcx>>( &self, qcx: Qcx, prev_index: SerializedDepNodeIndex, @@ -669,7 +673,7 @@ impl DepGraphData { /// This encodes a diagnostic by creating a node with an unique index and associating /// `diagnostic` with it, for use in the next session. #[inline] - fn encode_diagnostic( + fn encode_diagnostic<'tcx, Qcx: QueryContext<'tcx>>( &self, qcx: Qcx, diagnostic: &DiagInner, @@ -693,7 +697,7 @@ impl DepGraphData { /// This forces a diagnostic node green by running its side effect. `prev_index` would /// refer to a node created used `encode_diagnostic` in the previous session. #[inline] - fn force_diagnostic_node( + fn force_diagnostic_node<'tcx, Qcx: QueryContext<'tcx>>( &self, qcx: Qcx, prev_index: SerializedDepNodeIndex, @@ -843,7 +847,7 @@ impl DepGraph { DepNodeColor::Unknown } - pub fn try_mark_green>( + pub fn try_mark_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( &self, qcx: Qcx, dep_node: &DepNode, @@ -858,7 +862,7 @@ impl DepGraphData { /// A node will have an index, when it's already been marked green, or when we can mark it /// green. This function will mark the current task as a reader of the specified node, when /// a node index can be found for that node. - pub(crate) fn try_mark_green>( + pub(crate) fn try_mark_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( &self, qcx: Qcx, dep_node: &DepNode, @@ -883,7 +887,7 @@ impl DepGraphData { } #[instrument(skip(self, qcx, parent_dep_node_index, frame), level = "debug")] - fn try_mark_parent_green>( + fn try_mark_parent_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( &self, qcx: Qcx, parent_dep_node_index: SerializedDepNodeIndex, @@ -973,7 +977,7 @@ impl DepGraphData { /// Try to mark a dep-node which existed in the previous compilation session as green. #[instrument(skip(self, qcx, prev_dep_node_index, frame), level = "debug")] - fn try_mark_previous_green>( + fn try_mark_previous_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( &self, qcx: Qcx, prev_dep_node_index: SerializedDepNodeIndex, diff --git a/compiler/rustc_query_system/src/query/dispatcher.rs b/compiler/rustc_query_system/src/query/dispatcher.rs index 1ca76a70364c..d7dd6dd6464a 100644 --- a/compiler/rustc_query_system/src/query/dispatcher.rs +++ b/compiler/rustc_query_system/src/query/dispatcher.rs @@ -14,8 +14,8 @@ pub type HashResult = Option, &V) -> Fingerp /// Unambiguous shorthand for `::DepContext`. #[expect(type_alias_bounds)] -type DepContextOf = - <::Qcx as HasDepContext>::DepContext; +type DepContextOf<'tcx, This: QueryDispatcher<'tcx>> = + <>::Qcx as HasDepContext>::DepContext; /// Trait that can be used as a vtable for a single query, providing operations /// and metadata for that query. @@ -25,15 +25,15 @@ type DepContextOf = /// Those types are not visible from this `rustc_query_system` crate. /// /// "Dispatcher" should be understood as a near-synonym of "vtable". -pub trait QueryDispatcher: Copy { +pub trait QueryDispatcher<'tcx>: Copy { fn name(self) -> &'static str; /// Query context used by this dispatcher, i.e. `rustc_query_impl::QueryCtxt`. - type Qcx: QueryContext; + type Qcx: QueryContext<'tcx>; // `Key` and `Value` are `Copy` instead of `Clone` to ensure copying them stays cheap, // but it isn't necessary. - type Key: DepNodeParams> + Eq + Hash + Copy + Debug; + type Key: DepNodeParams> + Eq + Hash + Copy + Debug; type Value: Copy; type Cache: QueryCache; @@ -41,18 +41,15 @@ pub trait QueryDispatcher: Copy { fn format_value(self) -> fn(&Self::Value) -> String; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_state<'a>( - self, - tcx: Self::Qcx, - ) -> &'a QueryState::QueryInfo>; + fn query_state<'a>(self, tcx: Self::Qcx) -> &'a QueryState<'tcx, Self::Key>; // Don't use this method to access query results, instead use the methods on TyCtxt fn query_cache<'a>(self, tcx: Self::Qcx) -> &'a Self::Cache; - fn cache_on_disk(self, tcx: DepContextOf, key: &Self::Key) -> bool; + fn cache_on_disk(self, tcx: DepContextOf<'tcx, Self>, key: &Self::Key) -> bool; // Don't use this method to compute query results, instead use the methods on TyCtxt - fn execute_query(self, tcx: DepContextOf, k: Self::Key) -> Self::Value; + fn execute_query(self, tcx: DepContextOf<'tcx, Self>, k: Self::Key) -> Self::Value; fn compute(self, tcx: Self::Qcx, key: Self::Key) -> Self::Value; @@ -74,7 +71,7 @@ pub trait QueryDispatcher: Copy { /// Synthesize an error value to let compilation continue after a cycle. fn value_from_cycle_error( self, - tcx: DepContextOf, + tcx: DepContextOf<'tcx, Self>, cycle_error: &CycleError, guar: ErrorGuaranteed, ) -> Self::Value; @@ -89,7 +86,7 @@ pub trait QueryDispatcher: Copy { fn hash_result(self) -> HashResult; // Just here for convenience and checking that the key matches the kind, don't override this. - fn construct_dep_node(self, tcx: DepContextOf, key: &Self::Key) -> DepNode { + fn construct_dep_node(self, tcx: DepContextOf<'tcx, Self>, key: &Self::Key) -> DepNode { DepNode::construct(tcx, self.dep_kind(), key) } } diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 5810ce0cbe66..177bcd63cbc6 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -12,7 +12,7 @@ use rustc_hir::def::DefKind; use rustc_session::Session; use rustc_span::{DUMMY_SP, Span}; -use super::QueryStackFrameExtra; +use super::{QueryStackDeferred, QueryStackFrameExtra}; use crate::dep_graph::DepContext; use crate::error::CycleStack; use crate::query::plumbing::CycleError; @@ -26,8 +26,8 @@ pub struct QueryInfo { pub query: QueryStackFrame, } -impl QueryInfo { - pub(crate) fn lift>( +impl<'tcx> QueryInfo> { + pub(crate) fn lift>( &self, qcx: Qcx, ) -> QueryInfo { @@ -35,39 +35,39 @@ impl QueryInfo { } } -pub type QueryMap = FxHashMap>; +pub type QueryMap<'tcx> = FxHashMap>; /// A value uniquely identifying an active query job. #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct QueryJobId(pub NonZero); impl QueryJobId { - fn query(self, map: &QueryMap) -> QueryStackFrame { + fn query<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> QueryStackFrame> { map.get(&self).unwrap().query.clone() } - fn span(self, map: &QueryMap) -> Span { + fn span<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> Span { map.get(&self).unwrap().job.span } - fn parent(self, map: &QueryMap) -> Option { + fn parent<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> Option { map.get(&self).unwrap().job.parent } - fn latch(self, map: &QueryMap) -> Option<&QueryLatch> { + fn latch<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> Option<&'a QueryLatch<'tcx>> { map.get(&self).unwrap().job.latch.as_ref() } } #[derive(Clone, Debug)] -pub struct QueryJobInfo { - pub query: QueryStackFrame, - pub job: QueryJob, +pub struct QueryJobInfo<'tcx> { + pub query: QueryStackFrame>, + pub job: QueryJob<'tcx>, } /// Represents an active query job. #[derive(Debug)] -pub struct QueryJob { +pub struct QueryJob<'tcx> { pub id: QueryJobId, /// The span corresponding to the reason for which this query was required. @@ -77,23 +77,23 @@ pub struct QueryJob { pub parent: Option, /// The latch that is used to wait on this job. - latch: Option>, + latch: Option>, } -impl Clone for QueryJob { +impl<'tcx> Clone for QueryJob<'tcx> { fn clone(&self) -> Self { Self { id: self.id, span: self.span, parent: self.parent, latch: self.latch.clone() } } } -impl QueryJob { +impl<'tcx> QueryJob<'tcx> { /// Creates a new query job. #[inline] pub fn new(id: QueryJobId, span: Span, parent: Option) -> Self { QueryJob { id, span, parent, latch: None } } - pub(super) fn latch(&mut self) -> QueryLatch { + pub(super) fn latch(&mut self) -> QueryLatch<'tcx> { if self.latch.is_none() { self.latch = Some(QueryLatch::new()); } @@ -113,12 +113,12 @@ impl QueryJob { } impl QueryJobId { - pub(super) fn find_cycle_in_stack( + pub(super) fn find_cycle_in_stack<'tcx>( &self, - query_map: QueryMap, + query_map: QueryMap<'tcx>, current_job: &Option, span: Span, - ) -> CycleError { + ) -> CycleError> { // Find the waitee amongst `current_job` parents let mut cycle = Vec::new(); let mut current_job = Option::clone(current_job); @@ -152,7 +152,10 @@ impl QueryJobId { #[cold] #[inline(never)] - pub fn find_dep_kind_root(&self, query_map: QueryMap) -> (QueryJobInfo, usize) { + pub fn find_dep_kind_root<'tcx>( + &self, + query_map: QueryMap<'tcx>, + ) -> (QueryJobInfo<'tcx>, usize) { let mut depth = 1; let info = query_map.get(&self).unwrap(); let dep_kind = info.query.dep_kind; @@ -172,31 +175,31 @@ impl QueryJobId { } #[derive(Debug)] -struct QueryWaiter { +struct QueryWaiter<'tcx> { query: Option, condvar: Condvar, span: Span, - cycle: Mutex>>, + cycle: Mutex>>>, } #[derive(Debug)] -struct QueryLatchInfo { +struct QueryLatchInfo<'tcx> { complete: bool, - waiters: Vec>>, + waiters: Vec>>, } #[derive(Debug)] -pub(super) struct QueryLatch { - info: Arc>>, +pub(super) struct QueryLatch<'tcx> { + info: Arc>>, } -impl Clone for QueryLatch { +impl<'tcx> Clone for QueryLatch<'tcx> { fn clone(&self) -> Self { Self { info: Arc::clone(&self.info) } } } -impl QueryLatch { +impl<'tcx> QueryLatch<'tcx> { fn new() -> Self { QueryLatch { info: Arc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })), @@ -206,10 +209,10 @@ impl QueryLatch { /// Awaits for the query job to complete. pub(super) fn wait_on( &self, - qcx: impl QueryContext, + qcx: impl QueryContext<'tcx>, query: Option, span: Span, - ) -> Result<(), CycleError> { + ) -> Result<(), CycleError>> { let waiter = Arc::new(QueryWaiter { query, span, cycle: Mutex::new(None), condvar: Condvar::new() }); self.wait_on_inner(qcx, &waiter); @@ -224,7 +227,7 @@ impl QueryLatch { } /// Awaits the caller on this latch by blocking the current thread. - fn wait_on_inner(&self, qcx: impl QueryContext, waiter: &Arc>) { + fn wait_on_inner(&self, qcx: impl QueryContext<'tcx>, waiter: &Arc>) { let mut info = self.info.lock(); if !info.complete { // We push the waiter on to the `waiters` list. It can be accessed inside @@ -260,7 +263,7 @@ impl QueryLatch { /// Removes a single waiter from the list of waiters. /// This is used to break query cycles. - fn extract_waiter(&self, waiter: usize) -> Arc> { + fn extract_waiter(&self, waiter: usize) -> Arc> { let mut info = self.info.lock(); debug_assert!(!info.complete); // Remove the waiter from the list of waiters @@ -280,8 +283,8 @@ type Waiter = (QueryJobId, usize); /// For visits of resumable waiters it returns Some(Some(Waiter)) which has the /// required information to resume the waiter. /// If all `visit` calls returns None, this function also returns None. -fn visit_waiters( - query_map: &QueryMap, +fn visit_waiters<'tcx, F>( + query_map: &QueryMap<'tcx>, query: QueryJobId, mut visit: F, ) -> Option> @@ -314,8 +317,8 @@ where /// `span` is the reason for the `query` to execute. This is initially DUMMY_SP. /// If a cycle is detected, this initial value is replaced with the span causing /// the cycle. -fn cycle_check( - query_map: &QueryMap, +fn cycle_check<'tcx>( + query_map: &QueryMap<'tcx>, query: QueryJobId, span: Span, stack: &mut Vec<(Span, QueryJobId)>, @@ -354,8 +357,8 @@ fn cycle_check( /// Finds out if there's a path to the compiler root (aka. code which isn't in a query) /// from `query` without going through any of the queries in `visited`. /// This is achieved with a depth first search. -fn connected_to_root( - query_map: &QueryMap, +fn connected_to_root<'tcx>( + query_map: &QueryMap<'tcx>, query: QueryJobId, visited: &mut FxHashSet, ) -> bool { @@ -376,7 +379,7 @@ fn connected_to_root( } // Deterministically pick an query from a list -fn pick_query<'a, I: Clone, T, F>(query_map: &QueryMap, queries: &'a [T], f: F) -> &'a T +fn pick_query<'a, 'tcx, T, F>(query_map: &QueryMap<'tcx>, queries: &'a [T], f: F) -> &'a T where F: Fn(&T) -> (Span, QueryJobId), { @@ -401,10 +404,10 @@ where /// the function return true. /// If a cycle was not found, the starting query is removed from `jobs` and /// the function returns false. -fn remove_cycle( - query_map: &QueryMap, +fn remove_cycle<'tcx>( + query_map: &QueryMap<'tcx>, jobs: &mut Vec, - wakelist: &mut Vec>>, + wakelist: &mut Vec>>, ) -> bool { let mut visited = FxHashSet::default(); let mut stack = Vec::new(); @@ -505,10 +508,7 @@ fn remove_cycle( /// uses a query latch and then resuming that waiter. /// There may be multiple cycles involved in a deadlock, so this searches /// all active queries for cycles before finally resuming all the waiters at once. -pub fn break_query_cycles( - query_map: QueryMap, - registry: &rustc_thread_pool::Registry, -) { +pub fn break_query_cycles<'tcx>(query_map: QueryMap<'tcx>, registry: &rustc_thread_pool::Registry) { let mut wakelist = Vec::new(); // It is OK per the comments: // - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798854932 @@ -602,7 +602,7 @@ pub fn report_cycle<'a>( sess.dcx().create_err(cycle_diag) } -pub fn print_query_stack( +pub fn print_query_stack<'tcx, Qcx: QueryContext<'tcx>>( qcx: Qcx, mut current_query: Option, dcx: DiagCtxtHandle<'_>, diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index a689c3ac41b0..63202429679d 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -58,10 +58,10 @@ pub struct QueryStackFrame { pub def_id_for_ty_in_cycle: Option, } -impl QueryStackFrame { +impl<'tcx> QueryStackFrame> { #[inline] pub fn new( - info: I, + info: QueryStackDeferred<'tcx>, dep_kind: DepKind, hash: Hash64, def_id: Option, @@ -70,10 +70,7 @@ impl QueryStackFrame { Self { info, def_id, dep_kind, hash, def_id_for_ty_in_cycle } } - fn lift>( - &self, - qcx: Qcx, - ) -> QueryStackFrame { + fn lift>(&self, qcx: Qcx) -> QueryStackFrame { QueryStackFrame { info: qcx.lift_query_info(&self.info), dep_kind: self.dep_kind, @@ -159,9 +156,7 @@ pub enum QuerySideEffect { Diagnostic(DiagInner), } -pub trait QueryContext: HasDepContext { - type QueryInfo: Clone; - +pub trait QueryContext<'tcx>: HasDepContext { /// Gets a jobserver reference which is used to release then acquire /// a token while waiting on a query. fn jobserver_proxy(&self) -> &Proxy; @@ -171,12 +166,9 @@ pub trait QueryContext: HasDepContext { /// Get the query information from the TLS context. fn current_query_job(self) -> Option; - fn collect_active_jobs( - self, - require_complete: bool, - ) -> Result, QueryMap>; + fn collect_active_jobs(self, require_complete: bool) -> Result, QueryMap<'tcx>>; - fn lift_query_info(self, info: &Self::QueryInfo) -> QueryStackFrameExtra; + fn lift_query_info(self, info: &QueryStackDeferred<'tcx>) -> QueryStackFrameExtra; /// Load a side effect associated to the node in the previous session. fn load_side_effect( diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 7e9f83e8fe82..c4431ff870d0 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -18,7 +18,7 @@ use rustc_errors::{Diag, FatalError, StashKey}; use rustc_span::{DUMMY_SP, Span}; use tracing::instrument; -use super::{QueryDispatcher, QueryStackFrameExtra}; +use super::{QueryDispatcher, QueryStackDeferred, QueryStackFrameExtra}; use crate::dep_graph::{ DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams, HasDepContext, }; @@ -34,23 +34,23 @@ fn equivalent_key(k: &K) -> impl Fn(&(K, V)) -> bool + '_ { move |x| x.0 == *k } -pub struct QueryState { - active: Sharded)>>, +pub struct QueryState<'tcx, K> { + active: Sharded)>>, } /// Indicates the state of a query for a given key in a query map. -enum QueryResult { +enum QueryResult<'tcx> { /// An already executing query. The query job can be used to await for its completion. - Started(QueryJob), + Started(QueryJob<'tcx>), /// The query panicked. Queries trying to wait on this will raise a fatal error which will /// silently panic. Poisoned, } -impl QueryResult { +impl<'tcx> QueryResult<'tcx> { /// Unwraps the query job expecting that it has started. - fn expect_job(self) -> QueryJob { + fn expect_job(self) -> QueryJob<'tcx> { match self { Self::Started(job) => job, Self::Poisoned => { @@ -60,7 +60,7 @@ impl QueryResult { } } -impl QueryState +impl<'tcx, K> QueryState<'tcx, K> where K: Eq + Hash + Copy + Debug, { @@ -71,13 +71,13 @@ where pub fn collect_active_jobs( &self, qcx: Qcx, - make_query: fn(Qcx, K) -> QueryStackFrame, - jobs: &mut QueryMap, + make_query: fn(Qcx, K) -> QueryStackFrame>, + jobs: &mut QueryMap<'tcx>, require_complete: bool, ) -> Option<()> { let mut active = Vec::new(); - let mut collect = |iter: LockGuard<'_, HashTable<(K, QueryResult)>>| { + let mut collect = |iter: LockGuard<'_, HashTable<(K, QueryResult<'tcx>)>>| { for (k, v) in iter.iter() { if let QueryResult::Started(ref job) = *v { active.push((*k, job.clone())); @@ -108,40 +108,40 @@ where } } -impl Default for QueryState { - fn default() -> QueryState { +impl<'tcx, K> Default for QueryState<'tcx, K> { + fn default() -> QueryState<'tcx, K> { QueryState { active: Default::default() } } } /// A type representing the responsibility to execute the job in the `job` field. /// This will poison the relevant query if dropped. -struct JobOwner<'tcx, K, I> +struct JobOwner<'a, 'tcx, K> where K: Eq + Hash + Copy, { - state: &'tcx QueryState, + state: &'a QueryState<'tcx, K>, key: K, } #[cold] #[inline(never)] -fn mk_cycle(query: Q, qcx: Q::Qcx, cycle_error: CycleError) -> Q::Value +fn mk_cycle<'tcx, Q>(query: Q, qcx: Q::Qcx, cycle_error: CycleError) -> Q::Value where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { let error = report_cycle(qcx.dep_context().sess(), &cycle_error); handle_cycle_error(query, qcx, &cycle_error, error) } -fn handle_cycle_error( +fn handle_cycle_error<'tcx, Q>( query: Q, qcx: Q::Qcx, cycle_error: &CycleError, error: Diag<'_>, ) -> Q::Value where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { match query.cycle_error_handling() { CycleErrorHandling::Error => { @@ -170,7 +170,7 @@ where } } -impl<'tcx, K, I> JobOwner<'tcx, K, I> +impl<'a, 'tcx, K> JobOwner<'a, 'tcx, K> where K: Eq + Hash + Copy, { @@ -207,7 +207,7 @@ where } } -impl<'tcx, K, I> Drop for JobOwner<'tcx, K, I> +impl<'a, 'tcx, K> Drop for JobOwner<'a, 'tcx, K> where K: Eq + Hash + Copy, { @@ -241,8 +241,8 @@ pub struct CycleError { pub cycle: Vec>, } -impl CycleError { - fn lift>(&self, qcx: Qcx) -> CycleError { +impl<'tcx> CycleError> { + fn lift>(&self, qcx: Qcx) -> CycleError { CycleError { usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift(qcx))), cycle: self.cycle.iter().map(|info| info.lift(qcx)).collect(), @@ -272,14 +272,14 @@ where #[cold] #[inline(never)] -fn cycle_error( +fn cycle_error<'tcx, Q>( query: Q, qcx: Q::Qcx, try_execute: QueryJobId, span: Span, ) -> (Q::Value, Option) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { // Ensure there was no errors collecting all active jobs. // We need the complete map to ensure we find a cycle to break. @@ -290,16 +290,16 @@ where } #[inline(always)] -fn wait_for_query( +fn wait_for_query<'tcx, Q>( query: Q, qcx: Q::Qcx, span: Span, key: Q::Key, - latch: QueryLatch<::QueryInfo>, + latch: QueryLatch<'tcx>, current: Option, ) -> (Q::Value, Option) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { // For parallel queries, we'll block and wait until the query running // in another thread has completed. Record how long we wait in the @@ -339,7 +339,7 @@ where } #[inline(never)] -fn try_execute_query( +fn try_execute_query<'tcx, Q, const INCR: bool>( query: Q, qcx: Q::Qcx, span: Span, @@ -347,7 +347,7 @@ fn try_execute_query( dep_node: Option, ) -> (Q::Value, Option) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { let state = query.query_state(qcx); let key_hash = sharded::make_hash(&key); @@ -408,17 +408,17 @@ where } #[inline(always)] -fn execute_job( +fn execute_job<'tcx, Q, const INCR: bool>( query: Q, qcx: Q::Qcx, - state: &QueryState::QueryInfo>, + state: &QueryState<'tcx, Q::Key>, key: Q::Key, key_hash: u64, id: QueryJobId, dep_node: Option, ) -> (Q::Value, Option) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { // Use `JobOwner` so the query will be poisoned if executing it panics. let job_owner = JobOwner { state, key }; @@ -480,14 +480,14 @@ where // Fast path for when incr. comp. is off. #[inline(always)] -fn execute_job_non_incr( +fn execute_job_non_incr<'tcx, Q>( query: Q, qcx: Q::Qcx, key: Q::Key, job_id: QueryJobId, ) -> (Q::Value, DepNodeIndex) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled()); @@ -516,7 +516,7 @@ where } #[inline(always)] -fn execute_job_incr( +fn execute_job_incr<'tcx, Q>( query: Q, qcx: Q::Qcx, dep_graph_data: &DepGraphData<::Deps>, @@ -525,7 +525,7 @@ fn execute_job_incr( job_id: QueryJobId, ) -> (Q::Value, DepNodeIndex) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { if !query.anon() && !query.eval_always() { // `to_dep_node` is expensive for some `DepKind`s. @@ -571,7 +571,7 @@ where } #[inline(always)] -fn try_load_from_disk_and_cache_in_memory( +fn try_load_from_disk_and_cache_in_memory<'tcx, Q>( query: Q, dep_graph_data: &DepGraphData<::Deps>, qcx: Q::Qcx, @@ -579,7 +579,7 @@ fn try_load_from_disk_and_cache_in_memory( dep_node: &DepNode, ) -> Option<(Q::Value, DepNodeIndex)> where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { // Note this function can be called concurrently from the same query // We must ensure that this is handled correctly. @@ -757,14 +757,14 @@ fn incremental_verify_ich_failed( /// /// Note: The optimization is only available during incr. comp. #[inline(never)] -fn ensure_must_run( +fn ensure_must_run<'tcx, Q>( query: Q, qcx: Q::Qcx, key: &Q::Key, check_cache: bool, ) -> (bool, Option) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { if query.eval_always() { return (true, None); @@ -809,9 +809,9 @@ pub enum QueryMode { } #[inline(always)] -pub fn get_query_non_incr(query: Q, qcx: Q::Qcx, span: Span, key: Q::Key) -> Q::Value +pub fn get_query_non_incr<'tcx, Q>(query: Q, qcx: Q::Qcx, span: Span, key: Q::Key) -> Q::Value where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled()); @@ -819,7 +819,7 @@ where } #[inline(always)] -pub fn get_query_incr( +pub fn get_query_incr<'tcx, Q>( query: Q, qcx: Q::Qcx, span: Span, @@ -827,7 +827,7 @@ pub fn get_query_incr( mode: QueryMode, ) -> Option where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { debug_assert!(qcx.dep_context().dep_graph().is_fully_enabled()); @@ -849,9 +849,9 @@ where Some(result) } -pub fn force_query(query: Q, qcx: Q::Qcx, key: Q::Key, dep_node: DepNode) +pub fn force_query<'tcx, Q>(query: Q, qcx: Q::Qcx, key: Q::Key, dep_node: DepNode) where - Q: QueryDispatcher, + Q: QueryDispatcher<'tcx>, { // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. From d2aa64fa2d9c23f43253946a17086fd8cfdff539 Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 20 Jan 2026 01:07:54 +0800 Subject: [PATCH 266/978] Fix performance issue in liveness checking --- compiler/rustc_mir_transform/src/liveness.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_mir_transform/src/liveness.rs b/compiler/rustc_mir_transform/src/liveness.rs index a5a2fcd71a9a..f52ddd54e014 100644 --- a/compiler/rustc_mir_transform/src/liveness.rs +++ b/compiler/rustc_mir_transform/src/liveness.rs @@ -1086,11 +1086,6 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> { let Some((name, decl_span)) = self.checked_places.names[index] else { continue }; - // By convention, underscore-prefixed bindings are explicitly allowed to be unused. - if name.as_str().starts_with('_') { - continue; - } - let is_maybe_drop_guard = maybe_drop_guard( tcx, self.typing_env, @@ -1118,6 +1113,11 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> { continue; }; + // By convention, underscore-prefixed bindings are allowed to be unused explicitly + if name.as_str().starts_with('_') { + break; + } + match kind { AccessKind::Assign => { let suggestion = annotate_mut_binding_to_immutable_binding( From cf6796a2b06e5d07250cc7c50b0ecb9d6f008793 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 30 Jan 2026 15:00:20 +1100 Subject: [PATCH 267/978] Remove redundant `IntoQueryParam` calls from query plumbing In each of these contexts, the key must have already been converted by the caller, since otherwise it wouldn't have type `Cache::Key`. --- compiler/rustc_middle/src/query/inner.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/compiler/rustc_middle/src/query/inner.rs b/compiler/rustc_middle/src/query/inner.rs index e41d23f82f12..80e64e6a78ed 100644 --- a/compiler/rustc_middle/src/query/inner.rs +++ b/compiler/rustc_middle/src/query/inner.rs @@ -10,7 +10,6 @@ use rustc_query_system::query::{QueryCache, QueryMode, try_get_cached}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use crate::dep_graph; -use crate::query::IntoQueryParam; use crate::query::erase::{self, Erasable, Erased}; use crate::ty::TyCtxt; @@ -27,7 +26,6 @@ pub(crate) fn query_get_at<'tcx, Cache>( where Cache: QueryCache, { - let key = key.into_query_param(); match try_get_cached(tcx, query_cache, &key) { Some(value) => value, None => execute_query(tcx, span, key, QueryMode::Get).unwrap(), @@ -46,7 +44,6 @@ pub(crate) fn query_ensure<'tcx, Cache>( ) where Cache: QueryCache, { - let key = key.into_query_param(); if try_get_cached(tcx, query_cache, &key).is_none() { execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { check_cache }); } @@ -66,7 +63,6 @@ where Cache: QueryCache>>, Result: Erasable, { - let key = key.into_query_param(); if let Some(res) = try_get_cached(tcx, query_cache, &key) { erase::restore_val(res).map(drop) } else { From 4ae5b43b0f8c7bb4b579ea8e5e34dd928ffe87a2 Mon Sep 17 00:00:00 2001 From: Frank King Date: Fri, 30 Jan 2026 11:04:04 +0800 Subject: [PATCH 268/978] refactor: remove `Ty::pinned_ref` in favor of `Ty::maybe_pinned_ref` Also returns the `Region` of the reference type. --- compiler/rustc_hir_typeck/src/pat.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 22 +++++++------------- compiler/rustc_pattern_analysis/src/rustc.rs | 8 +++---- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index b56ab6dcb4ab..f054145dc7e9 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2841,7 +2841,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // the bad interactions of the given hack detailed in (note_1). debug!("check_pat_ref: expected={:?}", expected); match expected.maybe_pinned_ref() { - Some((r_ty, r_pinned, r_mutbl)) + Some((r_ty, r_pinned, r_mutbl, _)) if ((ref_pat_matches_mut_ref && r_mutbl >= pat_mutbl) || r_mutbl == pat_mutbl) && pat_pinned == r_pinned => diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 4c5bd85e6b72..4be30d8b6c91 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1336,25 +1336,17 @@ impl<'tcx> Ty<'tcx> { } } - pub fn pinned_ref(self) -> Option<(Ty<'tcx>, ty::Mutability)> { - if let Adt(def, args) = self.kind() - && def.is_pin() - && let &ty::Ref(_, ty, mutbl) = args.type_at(0).kind() - { - return Some((ty, mutbl)); - } - None - } - - pub fn maybe_pinned_ref(self) -> Option<(Ty<'tcx>, ty::Pinnedness, ty::Mutability)> { - match *self.kind() { + pub fn maybe_pinned_ref( + self, + ) -> Option<(Ty<'tcx>, ty::Pinnedness, ty::Mutability, Region<'tcx>)> { + match self.kind() { Adt(def, args) if def.is_pin() - && let ty::Ref(_, ty, mutbl) = *args.type_at(0).kind() => + && let &ty::Ref(region, ty, mutbl) = args.type_at(0).kind() => { - Some((ty, ty::Pinnedness::Pinned, mutbl)) + Some((ty, ty::Pinnedness::Pinned, mutbl, region)) } - ty::Ref(_, ty, mutbl) => Some((ty, ty::Pinnedness::Not, mutbl)), + &Ref(region, ty, mutbl) => Some((ty, ty::Pinnedness::Not, mutbl, region)), _ => None, } } diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 3e97842b7f39..dc38f2d8bc70 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -4,8 +4,8 @@ use std::iter::once; use rustc_abi::{FIRST_VARIANT, FieldIdx, Integer, VariantIdx}; use rustc_arena::DroplessArena; +use rustc_hir::HirId; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, HirId}; use rustc_index::{Idx, IndexVec}; use rustc_middle::middle::stability::EvalResult; use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary}; @@ -471,9 +471,9 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { PatKind::Deref { pin, subpattern } => { fields = vec![self.lower_pat(subpattern).at_index(0)]; arity = 1; - ctor = match pin { - hir::Pinnedness::Not if ty.is_ref() => Ref, - hir::Pinnedness::Pinned if let Some((inner_ty, _)) = ty.pinned_ref() => { + ctor = match (pin, ty.maybe_pinned_ref()) { + (ty::Pinnedness::Not, Some((_, ty::Pinnedness::Not, _, _))) => Ref, + (ty::Pinnedness::Pinned, Some((inner_ty, ty::Pinnedness::Pinned, _, _))) => { self.internal_state.has_lowered_deref_pat.set(true); DerefPattern(RevealedTy(inner_ty)) } From 9c135ad1e0ee2f79d16612ec682fa7c764e4a3c6 Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 30 Jan 2026 07:20:28 +0000 Subject: [PATCH 269/978] Show break type expectation cause for let-else --- compiler/rustc_hir_typeck/src/demand.rs | 8 +++++++ .../let-else-break-help-issue-142602.rs | 23 +++++++++++++++++++ .../let-else-break-help-issue-142602.stderr | 21 +++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 tests/ui/let-else/let-else-break-help-issue-142602.rs create mode 100644 tests/ui/let-else/let-else-break-help-issue-142602.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 3f214b4d2fcc..84663ff884b4 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -605,6 +605,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { parent_id = self.tcx.parent_hir_id(*hir_id); parent } + hir::Node::Stmt(hir::Stmt { hir_id, kind: hir::StmtKind::Let(_), .. }) => { + parent_id = self.tcx.parent_hir_id(*hir_id); + parent + } + hir::Node::LetStmt(hir::LetStmt { hir_id, .. }) => { + parent_id = self.tcx.parent_hir_id(*hir_id); + parent + } hir::Node::Block(_) => { parent_id = self.tcx.parent_hir_id(parent_id); parent diff --git a/tests/ui/let-else/let-else-break-help-issue-142602.rs b/tests/ui/let-else/let-else-break-help-issue-142602.rs new file mode 100644 index 000000000000..b57c7f757150 --- /dev/null +++ b/tests/ui/let-else/let-else-break-help-issue-142602.rs @@ -0,0 +1,23 @@ +// testcase from https://github.com/rust-lang/rust/issues/142602 + +pub fn main() { + // Case 1: break before let-else + let _a = loop { + if true { + break; + } + let Some(_) = Some(5) else { + break 3; //~ ERROR mismatched types + }; + }; + + // Case 2: two let-else statements + let _b = loop { + let Some(_) = Some(5) else { + break; + }; + let Some(_) = Some(4) else { + break 3; //~ ERROR mismatched types + }; + }; +} diff --git a/tests/ui/let-else/let-else-break-help-issue-142602.stderr b/tests/ui/let-else/let-else-break-help-issue-142602.stderr new file mode 100644 index 000000000000..aafbaa158ab1 --- /dev/null +++ b/tests/ui/let-else/let-else-break-help-issue-142602.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/let-else-break-help-issue-142602.rs:10:19 + | +LL | break; + | ----- expected because of this `break` +... +LL | break 3; + | ^ expected `()`, found integer + +error[E0308]: mismatched types + --> $DIR/let-else-break-help-issue-142602.rs:20:19 + | +LL | break; + | ----- expected because of this `break` +... +LL | break 3; + | ^ expected `()`, found integer + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From 91feb76d941592145238eda59e73be25fd191af3 Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 30 Jan 2026 08:56:56 +0000 Subject: [PATCH 270/978] Skip unused_allocation lint when method takes &Box --- compiler/rustc_lint/src/unused.rs | 8 ++- .../unused-allocation-box-ref-issue-151846.rs | 54 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lint/unused/unused-allocation-box-ref-issue-151846.rs diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 5516298c5e85..8b630d0d7385 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1782,7 +1782,7 @@ declare_lint! { declare_lint_pass!(UnusedAllocation => [UNUSED_ALLOCATION]); impl<'tcx> LateLintPass<'tcx> for UnusedAllocation { - fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &hir::Expr<'_>) { match e.kind { hir::ExprKind::Call(path_expr, [_]) if let hir::ExprKind::Path(qpath) = &path_expr.kind @@ -1793,6 +1793,12 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation { for adj in cx.typeck_results().expr_adjustments(e) { if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(m)) = adj.kind { + if let ty::Ref(_, inner_ty, _) = adj.target.kind() + && inner_ty.is_box() + { + // If the target type is `&Box` or `&mut Box`, the allocation is necessary + continue; + } match m { adjustment::AutoBorrowMutability::Not => { cx.emit_span_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationDiag); diff --git a/tests/ui/lint/unused/unused-allocation-box-ref-issue-151846.rs b/tests/ui/lint/unused/unused-allocation-box-ref-issue-151846.rs new file mode 100644 index 000000000000..57eefc3891fa --- /dev/null +++ b/tests/ui/lint/unused/unused-allocation-box-ref-issue-151846.rs @@ -0,0 +1,54 @@ +//@ check-pass +// Test for issue #151846: unused_allocation warning should ignore +// allocations to pass Box to things taking self: &Box + +#![deny(unused_allocation)] + +struct MyStruct; + +trait TraitTakesBoxRef { + fn trait_takes_box_ref(&self); +} + +impl TraitTakesBoxRef for Box { + fn trait_takes_box_ref(&self) {} +} + +impl MyStruct { + fn inherent_takes_box_ref(self: &Box) {} +} + +fn takes_box_ref(_: &Box) {} + +trait TraitTakesBoxVal { + fn trait_takes_box_val(self); +} + +impl TraitTakesBoxVal for Box { + fn trait_takes_box_val(self) {} +} + +impl MyStruct { + fn inherent_takes_box_val(self: Box) {} +} + +fn takes_box_val(_: Box) {} + +pub fn foo() { + // These should NOT warn - the allocation is necessary because + // the method takes &Box + Box::new(MyStruct).trait_takes_box_ref(); + Box::new(MyStruct).inherent_takes_box_ref(); + takes_box_ref(&Box::new(MyStruct)); + + // These already don't warn - the allocation is necessary + Box::new(MyStruct).trait_takes_box_val(); + Box::new(MyStruct).inherent_takes_box_val(); + takes_box_val(Box::new(MyStruct)); + + // Fully-qualified syntax also does not warn: + as TraitTakesBoxRef>::trait_takes_box_ref(&Box::new(MyStruct)); + MyStruct::inherent_takes_box_ref(&Box::new(MyStruct)); +} + +fn main() {} From d5e80aa7141283d5a29bf6f2dabf4e9d4a108efa Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 27 Jan 2026 18:13:05 +1100 Subject: [PATCH 271/978] Make `try_load_from_disk_fn` optional in query vtables --- compiler/rustc_middle/src/query/plumbing.rs | 15 ++++++----- compiler/rustc_query_impl/src/lib.rs | 7 ++--- compiler/rustc_query_impl/src/plumbing.rs | 29 +++++++++------------ 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 2bda014a19fe..86eea8f3748e 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -18,6 +18,13 @@ use crate::query::{ }; use crate::ty::TyCtxt; +pub type TryLoadFromDiskFn<'tcx, Key, Value> = fn( + tcx: TyCtxt<'tcx>, + key: &Key, + prev_index: SerializedDepNodeIndex, + index: DepNodeIndex, +) -> Option; + /// Stores function pointers and other metadata for a particular query. /// /// Used indirectly by query plumbing in `rustc_query_system`, via a trait. @@ -34,13 +41,7 @@ pub struct QueryVTable<'tcx, C: QueryCache> { pub cache_on_disk: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool, pub execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value, pub compute: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value, - pub can_load_from_disk: bool, - pub try_load_from_disk: fn( - tcx: TyCtxt<'tcx>, - key: &C::Key, - prev_index: SerializedDepNodeIndex, - index: DepNodeIndex, - ) -> Option, + pub try_load_from_disk_fn: Option>, pub loadable_from_disk: fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool, pub hash_result: HashResult, diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 8fa4fb3090db..21daa020407c 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -128,11 +128,8 @@ where prev_index: SerializedDepNodeIndex, index: DepNodeIndex, ) -> Option { - if self.vtable.can_load_from_disk { - (self.vtable.try_load_from_disk)(qcx.tcx, key, prev_index, index) - } else { - None - } + // `?` will return None immediately for queries that never cache to disk. + self.vtable.try_load_from_disk_fn?(qcx.tcx, key, prev_index, index) } #[inline] diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index ef7a62351930..0b7a2d0aa6a3 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -666,24 +666,21 @@ macro_rules! define_queries { ) ) }, - can_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] true false), - try_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] { - |tcx, key, prev_index, index| { - if ::rustc_middle::query::cached::$name(tcx, key) { - let value = $crate::plumbing::try_load_from_disk::< - queries::$name::ProvidedValue<'tcx> - >( - tcx, - prev_index, - index, - ); - value.map(|value| queries::$name::provided_to_erased(tcx, value)) - } else { - None + try_load_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] { + Some(|tcx, key, prev_index, index| { + // Check the `cache_on_disk_if` condition for this key. + if !::rustc_middle::query::cached::$name(tcx, key) { + return None; } - } + + let value: queries::$name::ProvidedValue<'tcx> = + $crate::plumbing::try_load_from_disk(tcx, prev_index, index)?; + + // Arena-alloc the value if appropriate, and erase it. + Some(queries::$name::provided_to_erased(tcx, value)) + }) } { - |_tcx, _key, _prev_index, _index| None + None }), value_from_cycle_error: |tcx, cycle, guar| { let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle, guar); From d39609b7198328d0f97381883c5b5e1e39e04f42 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 27 Jan 2026 18:19:04 +1100 Subject: [PATCH 272/978] Make `is_loadable_from_disk_fn` optional in query vtables --- compiler/rustc_middle/src/query/plumbing.rs | 6 ++++-- compiler/rustc_query_impl/src/lib.rs | 4 ++-- compiler/rustc_query_impl/src/plumbing.rs | 16 ++++++++-------- .../rustc_query_system/src/query/dispatcher.rs | 2 +- .../rustc_query_system/src/query/plumbing.rs | 4 ++-- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 86eea8f3748e..b280cc821bc2 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -25,6 +25,9 @@ pub type TryLoadFromDiskFn<'tcx, Key, Value> = fn( index: DepNodeIndex, ) -> Option; +pub type IsLoadableFromDiskFn<'tcx, Key> = + fn(tcx: TyCtxt<'tcx>, key: &Key, index: SerializedDepNodeIndex) -> bool; + /// Stores function pointers and other metadata for a particular query. /// /// Used indirectly by query plumbing in `rustc_query_system`, via a trait. @@ -42,8 +45,7 @@ pub struct QueryVTable<'tcx, C: QueryCache> { pub execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value, pub compute: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value, pub try_load_from_disk_fn: Option>, - pub loadable_from_disk: - fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool, + pub is_loadable_from_disk_fn: Option>, pub hash_result: HashResult, pub value_from_cycle_error: fn(tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed) -> C::Value, diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 21daa020407c..912c461f643c 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -133,13 +133,13 @@ where } #[inline] - fn loadable_from_disk( + fn is_loadable_from_disk( self, qcx: QueryCtxt<'tcx>, key: &Self::Key, index: SerializedDepNodeIndex, ) -> bool { - (self.vtable.loadable_from_disk)(qcx.tcx, key, index) + self.vtable.is_loadable_from_disk_fn.map_or(false, |f| f(qcx.tcx, key, index)) } fn value_from_cycle_error( diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 0b7a2d0aa6a3..7fffce051c4d 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -682,18 +682,18 @@ macro_rules! define_queries { } { None }), + is_loadable_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] { + Some(|tcx, key, index| -> bool { + ::rustc_middle::query::cached::$name(tcx, key) && + $crate::plumbing::loadable_from_disk(tcx, index) + }) + } { + None + }), value_from_cycle_error: |tcx, cycle, guar| { let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle, guar); erase::erase_val(result) }, - loadable_from_disk: |_tcx, _key, _index| { - should_ever_cache_on_disk!([$($modifiers)*] { - ::rustc_middle::query::cached::$name(_tcx, _key) && - $crate::plumbing::loadable_from_disk(_tcx, _index) - } { - false - }) - }, hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]), format_value: |value| format!("{:?}", erase::restore_val::>(*value)), } diff --git a/compiler/rustc_query_system/src/query/dispatcher.rs b/compiler/rustc_query_system/src/query/dispatcher.rs index d7dd6dd6464a..dfc06e4c3ef0 100644 --- a/compiler/rustc_query_system/src/query/dispatcher.rs +++ b/compiler/rustc_query_system/src/query/dispatcher.rs @@ -61,7 +61,7 @@ pub trait QueryDispatcher<'tcx>: Copy { index: DepNodeIndex, ) -> Option; - fn loadable_from_disk( + fn is_loadable_from_disk( self, qcx: Self::Qcx, key: &Self::Key, diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index c4431ff870d0..d386f3e70690 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -631,7 +631,7 @@ where // Sanity check for the logic in `ensure`: if the node is green and the result loadable, // we should actually be able to load it. debug_assert!( - !query.loadable_from_disk(qcx, key, prev_dep_node_index), + !query.is_loadable_from_disk(qcx, key, prev_dep_node_index), "missing on-disk cache entry for loadable {dep_node:?}" ); @@ -798,7 +798,7 @@ where return (false, None); } - let loadable = query.loadable_from_disk(qcx, key, serialized_dep_node_index); + let loadable = query.is_loadable_from_disk(qcx, key, serialized_dep_node_index); (!loadable, Some(dep_node)) } From e044220de53b2e9c8a8191ff9da5df4b469eb3ea Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 27 Jan 2026 22:53:22 +1100 Subject: [PATCH 273/978] Make `will_cache_on_disk_for_key_fn` optional in query vtables --- compiler/rustc_macros/src/query.rs | 24 ++++--------------- compiler/rustc_middle/src/query/plumbing.rs | 4 +++- compiler/rustc_query_impl/src/lib.rs | 4 ++-- compiler/rustc_query_impl/src/plumbing.rs | 10 +++++--- .../src/query/dispatcher.rs | 2 +- .../rustc_query_system/src/query/plumbing.rs | 2 +- 6 files changed, 19 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 1ad9bbc3b4b3..0cac699e5b62 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -280,31 +280,21 @@ fn add_query_desc_cached_impl( let crate::query::Providers { #name: _, .. }; }; - // Find out if we should cache the query on disk - let cache = if let Some((args, expr)) = modifiers.cache.as_ref() { + // Generate a function to check whether we should cache the query to disk, for some key. + if let Some((args, expr)) = modifiers.cache.as_ref() { let tcx = args.as_ref().map(|t| quote! { #t }).unwrap_or_else(|| quote! { _ }); // expr is a `Block`, meaning that `{ #expr }` gets expanded // to `{ { stmts... } }`, which triggers the `unused_braces` lint. // we're taking `key` by reference, but some rustc types usually prefer being passed by value - quote! { + cached.extend(quote! { #[allow(unused_variables, unused_braces, rustc::pass_by_value)] #[inline] pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::query::queries::#name::Key<'tcx>) -> bool { #ra_hint #expr } - } - } else { - quote! { - // we're taking `key` by reference, but some rustc types usually prefer being passed by value - #[allow(rustc::pass_by_value)] - #[inline] - pub fn #name<'tcx>(_: TyCtxt<'tcx>, _: &crate::query::queries::#name::Key<'tcx>) -> bool { - #ra_hint - false - } - } - }; + }); + } let (tcx, desc) = &modifiers.desc; let tcx = tcx.as_ref().map_or_else(|| quote! { _ }, |t| quote! { #t }); @@ -322,10 +312,6 @@ fn add_query_desc_cached_impl( descs.extend(quote! { #desc }); - - cached.extend(quote! { - #cache - }); } pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index b280cc821bc2..b21db6eeeea0 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -18,6 +18,8 @@ use crate::query::{ }; use crate::ty::TyCtxt; +pub type WillCacheOnDiskForKeyFn<'tcx, Key> = fn(tcx: TyCtxt<'tcx>, key: &Key) -> bool; + pub type TryLoadFromDiskFn<'tcx, Key, Value> = fn( tcx: TyCtxt<'tcx>, key: &Key, @@ -41,7 +43,7 @@ pub struct QueryVTable<'tcx, C: QueryCache> { pub query_state: usize, // Offset of this query's cache field in the QueryCaches struct pub query_cache: usize, - pub cache_on_disk: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool, + pub will_cache_on_disk_for_key_fn: Option>, pub execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value, pub compute: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value, pub try_load_from_disk_fn: Option>, diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 912c461f643c..4e79d0842da2 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -81,8 +81,8 @@ where } #[inline(always)] - fn cache_on_disk(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool { - (self.vtable.cache_on_disk)(tcx, key) + fn will_cache_on_disk_for_key(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool { + self.vtable.will_cache_on_disk_for_key_fn.map_or(false, |f| f(tcx, key)) } #[inline(always)] diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 7fffce051c4d..2d4e10a0380c 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -396,7 +396,7 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>( assert!(query.query_state(qcx).all_inactive()); let cache = query.query_cache(qcx); cache.iter(&mut |key, value, dep_node| { - if query.cache_on_disk(qcx.tcx, key) { + if query.will_cache_on_disk_for_key(qcx.tcx, key) { let dep_node = SerializedDepNodeIndex::new(dep_node.index()); // Record position of the cache entry. @@ -445,7 +445,7 @@ where let key = Q::Key::recover(tcx, &dep_node).unwrap_or_else(|| { panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash) }); - if query.cache_on_disk(tcx, &key) { + if query.will_cache_on_disk_for_key(tcx, &key) { let _ = query.execute_query(tcx, key); } } @@ -648,7 +648,11 @@ macro_rules! define_queries { cycle_error_handling: cycle_error_handling!([$($modifiers)*]), query_state: std::mem::offset_of!(QueryStates<'tcx>, $name), query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name), - cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key), + will_cache_on_disk_for_key_fn: should_ever_cache_on_disk!([$($modifiers)*] { + Some(::rustc_middle::query::cached::$name) + } { + None + }), execute_query: |tcx, key| erase::erase_val(tcx.$name(key)), compute: |tcx, key| { #[cfg(debug_assertions)] diff --git a/compiler/rustc_query_system/src/query/dispatcher.rs b/compiler/rustc_query_system/src/query/dispatcher.rs index dfc06e4c3ef0..ac6c38dd7db5 100644 --- a/compiler/rustc_query_system/src/query/dispatcher.rs +++ b/compiler/rustc_query_system/src/query/dispatcher.rs @@ -46,7 +46,7 @@ pub trait QueryDispatcher<'tcx>: Copy { // Don't use this method to access query results, instead use the methods on TyCtxt fn query_cache<'a>(self, tcx: Self::Qcx) -> &'a Self::Cache; - fn cache_on_disk(self, tcx: DepContextOf<'tcx, Self>, key: &Self::Key) -> bool; + fn will_cache_on_disk_for_key(self, tcx: DepContextOf<'tcx, Self>, key: &Self::Key) -> bool; // Don't use this method to compute query results, instead use the methods on TyCtxt fn execute_query(self, tcx: DepContextOf<'tcx, Self>, k: Self::Key) -> Self::Value; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index d386f3e70690..04902d0ab10c 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -623,7 +623,7 @@ where // We always expect to find a cached result for things that // can be forced from `DepNode`. debug_assert!( - !query.cache_on_disk(*qcx.dep_context(), key) + !query.will_cache_on_disk_for_key(*qcx.dep_context(), key) || !qcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(), "missing on-disk cache entry for {dep_node:?}" ); From 09117c9b706f5b8a061fe52d5d6029b50de398a1 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 30 Jan 2026 17:17:46 +1100 Subject: [PATCH 274/978] Use the query vtable in `query_feed` plumbing --- compiler/rustc_middle/src/query/inner.rs | 50 +++++++++++-------- compiler/rustc_middle/src/query/mod.rs | 1 - compiler/rustc_middle/src/query/plumbing.rs | 22 ++------ .../rustc_query_system/src/dep_graph/graph.rs | 5 +- 4 files changed, 37 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_middle/src/query/inner.rs b/compiler/rustc_middle/src/query/inner.rs index e41d23f82f12..b25ae06479b9 100644 --- a/compiler/rustc_middle/src/query/inner.rs +++ b/compiler/rustc_middle/src/query/inner.rs @@ -1,17 +1,14 @@ //! Helper functions that serve as the immediate implementation of //! `tcx.$query(..)` and its variations. -use std::fmt::Debug; - -use rustc_data_structures::fingerprint::Fingerprint; use rustc_query_system::dep_graph::{DepKind, DepNodeParams}; -use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{QueryCache, QueryMode, try_get_cached}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use crate::dep_graph; use crate::query::IntoQueryParam; use crate::query::erase::{self, Erasable, Erased}; +use crate::query::plumbing::QueryVTable; use crate::ty::TyCtxt; /// Shared implementation of `tcx.$query(..)` and `tcx.at(span).$query(..)` @@ -84,35 +81,38 @@ where } /// Common implementation of query feeding, used by `define_feedable!`. -pub(crate) fn query_feed<'tcx, Cache, Value>( +pub(crate) fn query_feed<'tcx, Cache>( tcx: TyCtxt<'tcx>, dep_kind: DepKind, - hasher: Option, &Value) -> Fingerprint>, + query_vtable: &QueryVTable<'tcx, Cache>, cache: &Cache, key: Cache::Key, - erased: Erased, + value: Cache::Value, ) where - Cache: QueryCache>, + Cache: QueryCache, Cache::Key: DepNodeParams>, - Value: Erasable + Debug, { - let value = erase::restore_val::(erased); + let format_value = query_vtable.format_value; + // Check whether the in-memory cache already has a value for this key. match try_get_cached(tcx, cache, &key) { Some(old) => { - let old = erase::restore_val::(old); - if let Some(hasher) = hasher { - let (value_hash, old_hash): (Fingerprint, Fingerprint) = tcx - .with_stable_hashing_context(|mut hcx| { - (hasher(&mut hcx, &value), hasher(&mut hcx, &old)) - }); + // The query already has a cached value for this key. + // That's OK if both values are the same, i.e. they have the same hash, + // so now we check their hashes. + if let Some(hasher_fn) = query_vtable.hash_result { + let (old_hash, value_hash) = tcx.with_stable_hashing_context(|ref mut hcx| { + (hasher_fn(hcx, &old), hasher_fn(hcx, &value)) + }); if old_hash != value_hash { // We have an inconsistency. This can happen if one of the two // results is tainted by errors. In this case, delay a bug to // ensure compilation is doomed, and keep the `old` value. tcx.dcx().delayed_bug(format!( "Trying to feed an already recorded value for query {dep_kind:?} key={key:?}:\n\ - old value: {old:?}\nnew value: {value:?}", + old value: {old}\nnew value: {value}", + old = format_value(&old), + value = format_value(&value), )); } } else { @@ -121,14 +121,24 @@ pub(crate) fn query_feed<'tcx, Cache, Value>( // the query should not be marked `no_hash`. bug!( "Trying to feed an already recorded value for query {dep_kind:?} key={key:?}:\n\ - old value: {old:?}\nnew value: {value:?}", + old value: {old}\nnew value: {value}", + old = format_value(&old), + value = format_value(&value), ) } } None => { + // There is no cached value for this key, so feed the query by + // adding the provided value to the cache. let dep_node = dep_graph::DepNode::construct(tcx, dep_kind, &key); - let dep_node_index = tcx.dep_graph.with_feed_task(dep_node, tcx, &value, hasher); - cache.complete(key, erased, dep_node_index); + let dep_node_index = tcx.dep_graph.with_feed_task( + dep_node, + tcx, + &value, + query_vtable.hash_result, + query_vtable.format_value, + ); + cache.complete(key, value, dep_node_index); } } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index cea50f95df4b..c9291d89be8a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -87,7 +87,6 @@ use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, Trait use rustc_index::IndexVec; use rustc_lint_defs::LintId; use rustc_macros::rustc_queries; -use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{QueryMode, QueryState}; use rustc_session::Limits; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 2bda014a19fe..0f08fa77cbc7 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -492,18 +492,6 @@ macro_rules! define_callbacks { }; } -macro_rules! hash_result { - ([]) => {{ - Some(dep_graph::hash_result) - }}; - ([(no_hash) $($rest:tt)*]) => {{ - None - }}; - ([$other:tt $($modifiers:tt)*]) => { - hash_result!([$($modifiers)*]) - }; -} - macro_rules! define_feedable { ($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => { $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> { @@ -513,19 +501,17 @@ macro_rules! define_feedable { let key = self.key().into_query_param(); let tcx = self.tcx; - let erased = queries::$name::provided_to_erased(tcx, value); - let cache = &tcx.query_system.caches.$name; + let erased_value = queries::$name::provided_to_erased(tcx, value); let dep_kind: dep_graph::DepKind = dep_graph::dep_kinds::$name; - let hasher: Option, &_) -> _> = hash_result!([$($modifiers)*]); $crate::query::inner::query_feed( tcx, dep_kind, - hasher, - cache, + &tcx.query_system.query_vtables.$name, + &tcx.query_system.caches.$name, key, - erased, + erased_value, ); } })* diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 6d46d144d0f1..9b9b73d73202 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -561,12 +561,13 @@ impl DepGraph { /// FIXME: If the code is changed enough for this node to be marked before requiring the /// caller's node, we suppose that those changes will be enough to mark this node red and /// force a recomputation using the "normal" way. - pub fn with_feed_task, R: Debug>( + pub fn with_feed_task, R>( &self, node: DepNode, cx: Ctxt, result: &R, hash_result: Option, &R) -> Fingerprint>, + format_value_fn: fn(&R) -> String, ) -> DepNodeIndex { if let Some(data) = self.data.as_ref() { // The caller query has more dependencies than the node we are creating. We may @@ -584,7 +585,7 @@ impl DepGraph { result, prev_index, hash_result, - |value| format!("{value:?}"), + format_value_fn, ); #[cfg(debug_assertions)] From 9e5820379d60942604547640a83480fc57466915 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 29 Jan 2026 17:56:04 +0100 Subject: [PATCH 275/978] Fix flakyness issue with `tests/rustdoc-gui/globals.goml` test --- tests/rustdoc-gui/globals.goml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/rustdoc-gui/globals.goml b/tests/rustdoc-gui/globals.goml index 89f57add8161..4f12175f6ab2 100644 --- a/tests/rustdoc-gui/globals.goml +++ b/tests/rustdoc-gui/globals.goml @@ -4,14 +4,14 @@ include: "utils.goml" // URL query -go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=sa'%3Bda'%3Bds" +go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=sa" wait-for: "#search-tabs" assert-window-property-false: {"searchIndex": null} // Form input go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" call-function: ("perform-search", {"query": "Foo"}) -assert-window-property-false: {"searchIndex": null} +wait-for-window-property-false: {"searchIndex": null} // source sidebar go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html" From acb5ee2f843789c4e8d903a894edcf01dbfd0c23 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 30 Jan 2026 13:01:22 +0100 Subject: [PATCH 276/978] Disable append-elements.rs test with debug assertions The IR is a bit different (in particular wrt naming) if debug-assertions-std is enabled. Peculiarly, the issue goes away if overflow-check-std is also enabled, which is why CI did not catch this. --- tests/codegen-llvm/lib-optimizations/append-elements.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/codegen-llvm/lib-optimizations/append-elements.rs b/tests/codegen-llvm/lib-optimizations/append-elements.rs index b8657104d665..5d7d746dbb6c 100644 --- a/tests/codegen-llvm/lib-optimizations/append-elements.rs +++ b/tests/codegen-llvm/lib-optimizations/append-elements.rs @@ -1,6 +1,7 @@ //@ compile-flags: -O -Zmerge-functions=disabled //@ needs-deterministic-layouts //@ min-llvm-version: 21 +//@ ignore-std-debug-assertions (causes different value naming) #![crate_type = "lib"] //! Check that a temporary intermediate allocations can eliminated and replaced From e12acb9251eb9d5a967aeafbe7ff3b3e97ae401f Mon Sep 17 00:00:00 2001 From: Frank King Date: Mon, 24 Nov 2025 15:18:59 +0800 Subject: [PATCH 277/978] Forbid manual `Unpin` impls for structurally pinned types --- compiler/rustc_hir_analysis/messages.ftl | 4 + .../src/coherence/builtin.rs | 36 +++++++++ compiler/rustc_hir_analysis/src/errors.rs | 11 +++ tests/ui/pin-ergonomics/impl-unpin.adt.stderr | 14 ++++ .../ui/pin-ergonomics/impl-unpin.assoc.stderr | 15 ++++ tests/ui/pin-ergonomics/impl-unpin.rs | 74 +++++++++++++++++++ .../ui/pin-ergonomics/impl-unpin.tait.stderr | 27 +++++++ .../pin-ergonomics/impl-unpin.ty_alias.stderr | 14 ++++ 8 files changed, 195 insertions(+) create mode 100644 tests/ui/pin-ergonomics/impl-unpin.adt.stderr create mode 100644 tests/ui/pin-ergonomics/impl-unpin.assoc.stderr create mode 100644 tests/ui/pin-ergonomics/impl-unpin.rs create mode 100644 tests/ui/pin-ergonomics/impl-unpin.tait.stderr create mode 100644 tests/ui/pin-ergonomics/impl-unpin.ty_alias.stderr diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index d9f8eba65c4a..33b8d3c82965 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -224,6 +224,10 @@ hir_analysis_impl_not_marked_default = `{$ident}` specializes an item from a par hir_analysis_impl_not_marked_default_err = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default` .note = parent implementation is in crate `{$cname}` +hir_analysis_impl_unpin_for_pin_projected_type = explicit impls for the `Unpin` trait are not permitted for structurally pinned types + .label = impl of `Unpin` not allowed + .help = `{$adt_name}` is structurally pinned because it is marked as `#[pin_v2]` + hir_analysis_inherent_dyn = cannot define inherent `impl` for a dyn auto trait .label = impl requires at least one non-auto trait .note = define and implement a new trait or type instead diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 61562cc1e4f3..f81913a9c86f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -38,6 +38,7 @@ pub(super) fn check_trait<'tcx>( checker.check(lang_items.drop_trait(), visit_implementation_of_drop)?; checker.check(lang_items.async_drop_trait(), visit_implementation_of_drop)?; checker.check(lang_items.copy_trait(), visit_implementation_of_copy)?; + checker.check(lang_items.unpin_trait(), visit_implementation_of_unpin)?; checker.check(lang_items.const_param_ty_trait(), |checker| { visit_implementation_of_const_param_ty(checker) })?; @@ -134,6 +135,41 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran } } +fn visit_implementation_of_unpin(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { + let tcx = checker.tcx; + let impl_header = checker.impl_header; + let impl_did = checker.impl_def_id; + debug!("visit_implementation_of_unpin: impl_did={:?}", impl_did); + + let self_type = impl_header.trait_ref.instantiate_identity().self_ty(); + debug!("visit_implementation_of_unpin: self_type={:?}", self_type); + + let span = tcx.def_span(impl_did); + + if tcx.features().pin_ergonomics() { + match self_type.kind() { + // Soundness concerns: a type `T` annotated with `#[pin_v2]` is allowed to project + // `Pin<&mut T>` to its field `Pin<&mut U>` safely (even if `U: !Unpin`). + // If `T` is allowed to impl `Unpin` manually (note that `Unpin` is a safe trait, + // which cannot carry safety properties), then `&mut U` could be obtained from + // `&mut T` that dereferenced by `Pin<&mut T>`, which breaks the safety contract of + // `Pin<&mut U>` for `U: !Unpin`. + ty::Adt(adt, _) if adt.is_pin_project() => { + return Err(tcx.dcx().emit_err(crate::errors::ImplUnpinForPinProjectedType { + span, + adt_span: tcx.def_span(adt.did()), + adt_name: tcx.item_name(adt.did()), + })); + } + ty::Adt(_, _) => {} + _ => { + return Err(tcx.dcx().span_delayed_bug(span, "impl of `Unpin` for a non-adt type")); + } + }; + } + Ok(()) +} + fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { let tcx = checker.tcx; let header = checker.impl_header; diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 2a77d0b997e2..f0c9023c522c 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1690,3 +1690,14 @@ pub(crate) struct EiiWithGenerics { pub eii_name: Symbol, pub impl_name: Symbol, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_impl_unpin_for_pin_projected_type)] +pub(crate) struct ImplUnpinForPinProjectedType { + #[primary_span] + #[label] + pub span: Span, + #[help] + pub adt_span: Span, + pub adt_name: Symbol, +} diff --git a/tests/ui/pin-ergonomics/impl-unpin.adt.stderr b/tests/ui/pin-ergonomics/impl-unpin.adt.stderr new file mode 100644 index 000000000000..56fac42d4e32 --- /dev/null +++ b/tests/ui/pin-ergonomics/impl-unpin.adt.stderr @@ -0,0 +1,14 @@ +error: explicit impls for the `Unpin` trait are not permitted for structurally pinned types + --> $DIR/impl-unpin.rs:14:5 + | +LL | impl Unpin for Foo {} + | ^^^^^^^^^^^^^^^^^^ impl of `Unpin` not allowed + | +help: `Foo` is structurally pinned because it is marked as `#[pin_v2]` + --> $DIR/impl-unpin.rs:7:1 + | +LL | struct Foo; + | ^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/pin-ergonomics/impl-unpin.assoc.stderr b/tests/ui/pin-ergonomics/impl-unpin.assoc.stderr new file mode 100644 index 000000000000..7f0ee1ddd898 --- /dev/null +++ b/tests/ui/pin-ergonomics/impl-unpin.assoc.stderr @@ -0,0 +1,15 @@ +error[E0321]: cross-crate traits with a default impl, like `Unpin`, can only be implemented for a struct/enum type, not `::Assoc` + --> $DIR/impl-unpin.rs:68:5 + | +LL | impl Unpin for ::Assoc {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type + +error[E0321]: cross-crate traits with a default impl, like `Unpin`, can only be implemented for a struct/enum type, not `::Assoc` + --> $DIR/impl-unpin.rs:70:5 + | +LL | impl Unpin for ::Assoc {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0321`. diff --git a/tests/ui/pin-ergonomics/impl-unpin.rs b/tests/ui/pin-ergonomics/impl-unpin.rs new file mode 100644 index 000000000000..ded8b4774dd9 --- /dev/null +++ b/tests/ui/pin-ergonomics/impl-unpin.rs @@ -0,0 +1,74 @@ +//@ revisions: adt tait ty_alias assoc +#![feature(pin_ergonomics)] +#![cfg_attr(tait, feature(type_alias_impl_trait))] +#![allow(incomplete_features)] + +#[pin_v2] +struct Foo; +struct Bar; + +#[cfg(adt)] +mod adt { + use super::*; + + impl Unpin for Foo {} + //[adt]~^ ERROR explicit impls for the `Unpin` trait are not permitted for structurally pinned types + impl Unpin for Bar {} // ok +} + +#[cfg(ty_alias)] +mod ty_alias { + use super::*; + + type Identity = T; + + impl Unpin for Identity {} + //[ty_alias]~^ ERROR explicit impls for the `Unpin` trait are not permitted for structurally pinned types + impl Unpin for Identity {} // ok +} + +#[cfg(tait)] +mod tait { + use super::*; + + trait Identity {} + + impl Identity for T {} + + type FooAlias = impl Identity; + type BarAlias = impl Identity; + + #[define_opaque(FooAlias)] + fn foo_alias() -> FooAlias { + Foo + } + #[define_opaque(BarAlias)] + fn bar_alias() -> BarAlias { + Bar + } + + impl Unpin for FooAlias {} + //[tait]~^ ERROR only traits defined in the current crate can be implemented for arbitrary types + impl Unpin for BarAlias {} + //[tait]~^ ERROR only traits defined in the current crate can be implemented for arbitrary types +} + +#[cfg(assoc)] +mod assoc { + use super::*; + + trait Identity { + type Assoc; + } + + impl Identity for T { + type Assoc = T; + } + + impl Unpin for ::Assoc {} + //[assoc]~^ ERROR cross-crate traits with a default impl, like `Unpin`, can only be implemented for a struct/enum type, not `::Assoc` + impl Unpin for ::Assoc {} + //[assoc]~^ ERROR cross-crate traits with a default impl, like `Unpin`, can only be implemented for a struct/enum type, not `::Assoc` +} + +fn main() {} diff --git a/tests/ui/pin-ergonomics/impl-unpin.tait.stderr b/tests/ui/pin-ergonomics/impl-unpin.tait.stderr new file mode 100644 index 000000000000..5d9392745df3 --- /dev/null +++ b/tests/ui/pin-ergonomics/impl-unpin.tait.stderr @@ -0,0 +1,27 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/impl-unpin.rs:50:5 + | +LL | impl Unpin for FooAlias {} + | ^^^^^^^^^^^^^^^-------- + | | + | type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate + | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/impl-unpin.rs:52:5 + | +LL | impl Unpin for BarAlias {} + | ^^^^^^^^^^^^^^^-------- + | | + | type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate + | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + = note: define and implement a trait or new type instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/pin-ergonomics/impl-unpin.ty_alias.stderr b/tests/ui/pin-ergonomics/impl-unpin.ty_alias.stderr new file mode 100644 index 000000000000..82c1a7d29ddf --- /dev/null +++ b/tests/ui/pin-ergonomics/impl-unpin.ty_alias.stderr @@ -0,0 +1,14 @@ +error: explicit impls for the `Unpin` trait are not permitted for structurally pinned types + --> $DIR/impl-unpin.rs:25:5 + | +LL | impl Unpin for Identity {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Unpin` not allowed + | +help: `Foo` is structurally pinned because it is marked as `#[pin_v2]` + --> $DIR/impl-unpin.rs:7:1 + | +LL | struct Foo; + | ^^^^^^^^^^ + +error: aborting due to 1 previous error + From 2a9de6ba853ff78b9b34b655b87313f0737417c5 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Tue, 27 Jan 2026 21:35:59 +0100 Subject: [PATCH 278/978] CI: rfl: move to temporary commit to pass `-Zunstable-options` for custom target specs This also takes the chance to move forward the job to Linux v6.19-rc7, thus the previous workaround is not needed anymore. Link: https://github.com/rust-lang/rust/pull/151534 Signed-off-by: Miguel Ojeda --- src/ci/docker/scripts/rfl-build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index e7f86e10f55a..535250557740 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -2,8 +2,8 @@ set -euo pipefail -# https://github.com/rust-lang/rust/pull/145974 -LINUX_VERSION=842cfd8e5aff3157cb25481b2900b49c188d628a +# https://github.com/rust-lang/rust/pull/151534 +LINUX_VERSION=eb268c7972f65fa0b11b051c5ef2b92747bb2b62 # Build rustc, rustdoc, cargo, clippy-driver and rustfmt ../x.py build --stage 2 library rustdoc clippy rustfmt From bae7a199f1cd87052396f65b59b51946eae29db1 Mon Sep 17 00:00:00 2001 From: Max Heller Date: Fri, 30 Jan 2026 09:55:34 -0500 Subject: [PATCH 279/978] Address review comments and fix tests --- library/alloc/src/collections/binary_heap/mod.rs | 7 ++++--- library/alloctests/lib.rs | 1 - library/alloctests/tests/collections/binary_heap.rs | 2 +- library/alloctests/tests/lib.rs | 1 + 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 65c8d5213f16..97aafbc7b699 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -656,14 +656,15 @@ impl BinaryHeap { /// # Examples /// /// ``` + /// #![feature(binary_heap_pop_if)] /// use std::collections::BinaryHeap; /// let mut heap = BinaryHeap::from([1, 2]); /// let pred = |x: &i32| *x % 2 == 0; /// /// assert_eq!(heap.pop_if(pred), Some(2)); - /// assert_eq!(heap, BinaryHeap::from([1])); + /// assert_eq!(heap.as_slice(), [1]); /// assert_eq!(heap.pop_if(pred), None); - /// assert_eq!(heap, BinaryHeap::from([1])); + /// assert_eq!(heap.as_slice(), [1]); /// ``` /// /// # Time complexity @@ -671,7 +672,7 @@ impl BinaryHeap { /// The worst case cost of `pop_if` on a heap containing *n* elements is *O*(log(*n*)). #[unstable(feature = "binary_heap_pop_if", issue = "151828")] pub fn pop_if(&mut self, predicate: impl FnOnce(&T) -> bool) -> Option { - let first = self.data.first()?; + let first = self.peek()?; if predicate(first) { self.pop() } else { None } } diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 9806c59ce0e1..fe14480102e3 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -17,7 +17,6 @@ #![feature(allocator_api)] #![feature(array_into_iter_constructors)] #![feature(assert_matches)] -#![feature(binary_heap_pop_if)] #![feature(box_vec_non_null)] #![feature(char_internals)] #![feature(const_alloc_error)] diff --git a/library/alloctests/tests/collections/binary_heap.rs b/library/alloctests/tests/collections/binary_heap.rs index 1b6afec7f355..e1484c32a4f8 100644 --- a/library/alloctests/tests/collections/binary_heap.rs +++ b/library/alloctests/tests/collections/binary_heap.rs @@ -145,7 +145,7 @@ fn test_pop_if() { while let Some(popped) = heap.pop_if(|x| *x > 2) { assert_eq!(popped, sorted.pop().unwrap()); } - assert_eq!(heap.into_sorted_vec(), vec![1, 2]); + assert_eq!(heap.into_sorted_vec(), vec![0, 1, 2]); } #[test] diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index 2926248edbf5..e15c86496cf1 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -1,4 +1,5 @@ #![feature(allocator_api)] +#![feature(binary_heap_pop_if)] #![feature(const_heap)] #![feature(deque_extend_front)] #![feature(iter_array_chunks)] From 38ee80d48efa8c1be83227be36676a9ccfba55ad Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 17 Jan 2026 21:40:27 -0500 Subject: [PATCH 280/978] add `#[rustc_non_const_trait_method]` --- .../src/attributes/rustc_internal.rs | 12 ++++++++++ compiler/rustc_attr_parsing/src/context.rs | 7 +++--- .../src/check_consts/check.rs | 4 ++-- .../src/const_eval/fn_queries.rs | 11 ++++++++-- compiler/rustc_feature/src/builtin_attrs.rs | 6 +++++ .../rustc_hir/src/attrs/data_structures.rs | 3 +++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_middle/src/ty/mod.rs | 9 ++++++-- compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + .../traits/const-traits/partial/attr-gate.rs | 7 ++++++ .../const-traits/partial/attr-gate.stderr | 13 +++++++++++ .../const-traits/partial/no-const-callers.rs | 22 +++++++++++++++++++ .../partial/no-const-callers.stderr | 19 ++++++++++++++++ 14 files changed, 107 insertions(+), 10 deletions(-) create mode 100644 tests/ui/traits/const-traits/partial/attr-gate.rs create mode 100644 tests/ui/traits/const-traits/partial/attr-gate.stderr create mode 100644 tests/ui/traits/const-traits/partial/no-const-callers.rs create mode 100644 tests/ui/traits/const-traits/partial/no-const-callers.stderr diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 6375927b01de..38f728fa9f55 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -388,3 +388,15 @@ impl CombineAttributeParser for RustcLayoutParser { result } } + +pub(crate) struct RustcNonConstTraitMethodParser; + +impl NoArgsAttributeParser for RustcNonConstTraitMethodParser { + const PATH: &'static [Symbol] = &[sym::rustc_non_const_trait_method]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::Trait { body: false })), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonConstTraitMethod; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index a4d08de515ad..0cabc0895053 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -79,9 +79,9 @@ use crate::attributes::rustc_internal::{ RustcLayoutScalarValidRangeStartParser, RustcLegacyConstGenericsParser, RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, RustcLintQueryInstabilityParser, RustcLintUntrackedQueryInformationParser, RustcMainParser, RustcMustImplementOneOfParser, - RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser, RustcNounwindParser, - RustcObjectLifetimeDefaultParser, RustcOffloadKernelParser, RustcScalableVectorParser, - RustcSimdMonomorphizeLaneLimitParser, + RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser, + RustcNonConstTraitMethodParser, RustcNounwindParser, RustcObjectLifetimeDefaultParser, + RustcOffloadKernelParser, RustcScalableVectorParser, RustcSimdMonomorphizeLaneLimitParser, }; use crate::attributes::semantics::MayDangleParser; use crate::attributes::stability::{ @@ -305,6 +305,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 95dbf42d4d44..2abbf75984a4 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -778,12 +778,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // than usual. trace!("attempting to call a trait method"); - let trait_is_const = tcx.is_const_trait(trait_did); + let is_const = tcx.constness(callee) == hir::Constness::Const; // Only consider a trait to be const if the const conditions hold. // Otherwise, it's really misleading to call something "conditionally" // const when it's very obviously not conditionally const. - if trait_is_const && has_const_conditions == Some(ConstConditionsHold::Yes) { + if is_const && has_const_conditions == Some(ConstConditionsHold::Yes) { // Trait calls are always conditionally-const. self.check_op(ops::ConditionallyConstCall { callee, diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index cdf0dcff381f..46cdca53ba8c 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -1,7 +1,8 @@ +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{ Constness, ExprKind, ForeignItemKind, ImplItem, ImplItemImplKind, ImplItemKind, Item, ItemKind, - Node, TraitItem, TraitItemKind, VariantData, + Node, TraitItem, TraitItemKind, VariantData, find_attr, }; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; @@ -36,7 +37,13 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Constness { Constness::NotConst => tcx.constness(tcx.local_parent(def_id)), } } - Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(..), .. }) => tcx.trait_def(tcx.local_parent(def_id)).constness, + Node::TraitItem(ti @ TraitItem { kind: TraitItemKind::Fn(..), .. }) => { + if find_attr!(tcx.hir_attrs(ti.hir_id()), AttributeKind::RustcNonConstTraitMethod) { + Constness::NotConst + } else { + tcx.trait_def(tcx.local_parent(def_id)).constness + } + } _ => { tcx.dcx().span_bug( tcx.def_span(def_id), diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index ded8a5a4ae51..8f447e1477b3 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1329,6 +1329,12 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "`#[rustc_has_incoherent_inherent_impls]` allows the addition of incoherent inherent impls for \ the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`" ), + rustc_attr!( + rustc_non_const_trait_method, AttributeType::Normal, template!(Word), + ErrorFollowing, EncodeCrossCrate::No, + "`#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods \ + as non-const to allow large traits to easier transition to const" + ), BuiltinAttribute { name: sym::rustc_diagnostic_item, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index bc58f1d8faa5..92dda79b0920 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1096,6 +1096,9 @@ pub enum AttributeKind { /// Represents `#[rustc_no_implicit_autorefs]` RustcNoImplicitAutorefs, + /// Represents `#[rustc_non_const_trait_method]`. + RustcNonConstTraitMethod, + /// Represents `#[rustc_nounwind]` RustcNounwind, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 4fd0f5698a8b..816ed07c1dc4 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -124,6 +124,7 @@ impl AttributeKind { RustcMustImplementOneOf { .. } => No, RustcNeverReturnsNullPointer => Yes, RustcNoImplicitAutorefs => Yes, + RustcNonConstTraitMethod => No, // should be reported via other queries like `constness` RustcNounwind => No, RustcObjcClass { .. } => No, RustcObjcSelector { .. } => No, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3e3c9e27186a..044c99ffeb21 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2086,8 +2086,13 @@ impl<'tcx> TyCtxt<'tcx> { DefKind::Impl { of_trait: false } => { self.constness(def_id) == hir::Constness::Const } - DefKind::Impl { of_trait: true } | DefKind::Trait => { - self.is_conditionally_const(parent_def_id) + DefKind::Impl { of_trait: true } => { + self.constness(self.trait_item_of(def_id).unwrap()) == hir::Constness::Const + && self.is_conditionally_const(parent_def_id) + } + DefKind::Trait => { + self.constness(def_id) == hir::Constness::Const + && self.is_conditionally_const(parent_def_id) } _ => bug!("unexpected parent item of associated fn: {parent_def_id:?}"), } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 800965f81d3d..8cf68b280850 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -310,6 +310,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcMain | AttributeKind::RustcNeverReturnsNullPointer | AttributeKind::RustcNoImplicitAutorefs + | AttributeKind::RustcNonConstTraitMethod | AttributeKind::RustcNounwind | AttributeKind::RustcObjcClass { .. } | AttributeKind::RustcObjcSelector { .. } @@ -335,7 +336,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::Used { .. } | AttributeKind::WindowsSubsystem(..) // tidy-alphabetical-end - ) => { /* do nothing */ } Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b80d624bc496..b0ef95d10ffa 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1995,6 +1995,7 @@ symbols! { rustc_no_implicit_autorefs, rustc_no_implicit_bounds, rustc_no_mir_inline, + rustc_non_const_trait_method, rustc_nonnull_optimization_guaranteed, rustc_nounwind, rustc_objc_class, diff --git a/tests/ui/traits/const-traits/partial/attr-gate.rs b/tests/ui/traits/const-traits/partial/attr-gate.rs new file mode 100644 index 000000000000..c59a03de2153 --- /dev/null +++ b/tests/ui/traits/const-traits/partial/attr-gate.rs @@ -0,0 +1,7 @@ +trait A { + #[rustc_non_const_trait_method] + //~^ ERROR: use of an internal attribute + fn a(); +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/partial/attr-gate.stderr b/tests/ui/traits/const-traits/partial/attr-gate.stderr new file mode 100644 index 000000000000..bc86cbe4edf7 --- /dev/null +++ b/tests/ui/traits/const-traits/partial/attr-gate.stderr @@ -0,0 +1,13 @@ +error[E0658]: use of an internal attribute + --> $DIR/attr-gate.rs:2:5 + | +LL | #[rustc_non_const_trait_method] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + = note: the `#[rustc_non_const_trait_method]` attribute is an internal implementation detail that will never be stable + = note: `#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods as non-const to allow large traits to easier transition to const + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/const-traits/partial/no-const-callers.rs b/tests/ui/traits/const-traits/partial/no-const-callers.rs new file mode 100644 index 000000000000..efcdea36f1ca --- /dev/null +++ b/tests/ui/traits/const-traits/partial/no-const-callers.rs @@ -0,0 +1,22 @@ +#![feature(const_trait_impl, rustc_attrs)] + +const trait A { + fn a(); + #[rustc_non_const_trait_method] + fn b() { println!("hi"); } +} + +impl const A for () { + fn a() {} +} + +const fn foo() { + T::a(); + T::b(); + //~^ ERROR: cannot call non-const associated function + <()>::a(); + <()>::b(); + //~^ ERROR: cannot call non-const associated function +} + +fn main() {} diff --git a/tests/ui/traits/const-traits/partial/no-const-callers.stderr b/tests/ui/traits/const-traits/partial/no-const-callers.stderr new file mode 100644 index 000000000000..31179161c5cd --- /dev/null +++ b/tests/ui/traits/const-traits/partial/no-const-callers.stderr @@ -0,0 +1,19 @@ +error[E0015]: cannot call non-const associated function `::b` in constant functions + --> $DIR/no-const-callers.rs:15:5 + | +LL | T::b(); + | ^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const associated function `<() as A>::b` in constant functions + --> $DIR/no-const-callers.rs:18:5 + | +LL | <()>::b(); + | ^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0015`. From 6147a3fc88f9920a2569adf7b6f4e8b63cd887c1 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 17 Jan 2026 23:03:57 -0500 Subject: [PATCH 281/978] constify `Iterator` --- library/core/src/iter/traits/collect.rs | 6 +- library/core/src/iter/traits/iterator.rs | 77 +++++++++++++++++++++++- library/core/src/option.rs | 11 ++-- library/coretests/tests/iter/mod.rs | 15 +++++ library/coretests/tests/lib.rs | 1 + 5 files changed, 103 insertions(+), 7 deletions(-) diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index c3b9a0f0b7a4..9c3edfd4192d 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -279,7 +279,8 @@ pub trait FromIterator: Sized { )] #[rustc_skip_during_method_dispatch(array, boxed_slice)] #[stable(feature = "rust1", since = "1.0.0")] -pub trait IntoIterator { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +pub const trait IntoIterator { /// The type of the elements being iterated over. #[rustc_diagnostic_item = "IntoIteratorItem"] #[stable(feature = "rust1", since = "1.0.0")] @@ -312,7 +313,8 @@ pub trait IntoIterator { } #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for I { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const IntoIterator for I { type Item = I::Item; type IntoIter = I; diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index dc484e2a27f6..d919230d094d 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -37,7 +37,8 @@ fn _assert_is_dyn_compatible(_: &dyn Iterator) {} #[lang = "iterator"] #[rustc_diagnostic_item = "Iterator"] #[must_use = "iterators are lazy and do nothing unless consumed"] -pub trait Iterator { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +pub const trait Iterator { /// The type of the elements being iterated over. #[rustc_diagnostic_item = "IteratorItem"] #[stable(feature = "rust1", since = "1.0.0")] @@ -107,6 +108,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "iter_next_chunk", issue = "98326")] + #[rustc_non_const_trait_method] fn next_chunk( &mut self, ) -> Result<[Self::Item; N], array::IntoIter> @@ -219,6 +221,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn count(self) -> usize where Self: Sized, @@ -251,6 +254,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn last(self) -> Option where Self: Sized, @@ -298,6 +302,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "iter_advance_by", issue = "77404")] + #[rustc_non_const_trait_method] fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { /// Helper trait to specialize `advance_by` via `try_fold` for `Sized` iterators. trait SpecAdvanceBy { @@ -375,6 +380,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn nth(&mut self, n: usize) -> Option { self.advance_by(n).ok()?; self.next() @@ -425,6 +431,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_step_by", since = "1.28.0")] + #[rustc_non_const_trait_method] fn step_by(self, step: usize) -> StepBy where Self: Sized, @@ -496,6 +503,7 @@ pub trait Iterator { /// [`OsStr`]: ../../std/ffi/struct.OsStr.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn chain(self, other: U) -> Chain where Self: Sized, @@ -614,6 +622,7 @@ pub trait Iterator { /// [`zip`]: crate::iter::zip #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn zip(self, other: U) -> Zip where Self: Sized, @@ -657,6 +666,7 @@ pub trait Iterator { /// [`intersperse_with`]: Iterator::intersperse_with #[inline] #[unstable(feature = "iter_intersperse", issue = "79524")] + #[rustc_non_const_trait_method] fn intersperse(self, separator: Self::Item) -> Intersperse where Self: Sized, @@ -715,6 +725,7 @@ pub trait Iterator { /// [`intersperse`]: Iterator::intersperse #[inline] #[unstable(feature = "iter_intersperse", issue = "79524")] + #[rustc_non_const_trait_method] fn intersperse_with(self, separator: G) -> IntersperseWith where Self: Sized, @@ -774,6 +785,7 @@ pub trait Iterator { #[rustc_diagnostic_item = "IteratorMap"] #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn map(self, f: F) -> Map where Self: Sized, @@ -819,6 +831,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_for_each", since = "1.21.0")] + #[rustc_non_const_trait_method] fn for_each(self, f: F) where Self: Sized, @@ -894,6 +907,7 @@ pub trait Iterator { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "iter_filter"] + #[rustc_non_const_trait_method] fn filter

(self, predicate: P) -> Filter where Self: Sized, @@ -939,6 +953,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn filter_map(self, f: F) -> FilterMap where Self: Sized, @@ -986,6 +1001,7 @@ pub trait Iterator { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "enumerate_method"] + #[rustc_non_const_trait_method] fn enumerate(self) -> Enumerate where Self: Sized, @@ -1057,6 +1073,7 @@ pub trait Iterator { /// [`next`]: Iterator::next #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn peekable(self) -> Peekable where Self: Sized, @@ -1122,6 +1139,7 @@ pub trait Iterator { #[inline] #[doc(alias = "drop_while")] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn skip_while

(self, predicate: P) -> SkipWhile where Self: Sized, @@ -1200,6 +1218,7 @@ pub trait Iterator { /// the iteration should stop, but wasn't placed back into the iterator. #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn take_while

(self, predicate: P) -> TakeWhile where Self: Sized, @@ -1288,6 +1307,7 @@ pub trait Iterator { /// [`fuse`]: Iterator::fuse #[inline] #[stable(feature = "iter_map_while", since = "1.57.0")] + #[rustc_non_const_trait_method] fn map_while(self, predicate: P) -> MapWhile where Self: Sized, @@ -1317,6 +1337,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn skip(self, n: usize) -> Skip where Self: Sized, @@ -1389,6 +1410,7 @@ pub trait Iterator { #[doc(alias = "limit")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn take(self, n: usize) -> Take where Self: Sized, @@ -1436,6 +1458,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn scan(self, initial_state: St, f: F) -> Scan where Self: Sized, @@ -1474,6 +1497,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn flat_map(self, f: F) -> FlatMap where Self: Sized, @@ -1558,6 +1582,7 @@ pub trait Iterator { /// [`flat_map()`]: Iterator::flat_map #[inline] #[stable(feature = "iterator_flatten", since = "1.29.0")] + #[rustc_non_const_trait_method] fn flatten(self) -> Flatten where Self: Sized, @@ -1714,6 +1739,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "iter_map_windows", issue = "87155")] + #[rustc_non_const_trait_method] fn map_windows(self, f: F) -> MapWindows where Self: Sized, @@ -1776,6 +1802,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn fuse(self) -> Fuse where Self: Sized, @@ -1860,6 +1887,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn inspect(self, f: F) -> Inspect where Self: Sized, @@ -2019,6 +2047,7 @@ pub trait Iterator { #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] #[rustc_diagnostic_item = "iterator_collect_fn"] + #[rustc_non_const_trait_method] fn collect>(self) -> B where Self: Sized, @@ -2106,6 +2135,7 @@ pub trait Iterator { /// [`collect`]: Iterator::collect #[inline] #[unstable(feature = "iterator_try_collect", issue = "94047")] + #[rustc_non_const_trait_method] fn try_collect(&mut self) -> ChangeOutputType where Self: Sized, @@ -2178,6 +2208,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "iter_collect_into", issue = "94780")] + #[rustc_non_const_trait_method] fn collect_into>(self, collection: &mut E) -> &mut E where Self: Sized, @@ -2210,6 +2241,7 @@ pub trait Iterator { /// assert_eq!(odd, [1, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn partition(self, f: F) -> (B, B) where Self: Sized, @@ -2272,6 +2304,7 @@ pub trait Iterator { /// assert!(a[i..].iter().all(|n| n % 2 == 1)); // odds /// ``` #[unstable(feature = "iter_partition_in_place", issue = "62543")] + #[rustc_non_const_trait_method] fn partition_in_place<'a, T: 'a, P>(mut self, ref mut predicate: P) -> usize where Self: Sized + DoubleEndedIterator, @@ -2329,6 +2362,7 @@ pub trait Iterator { /// assert!(!"IntoIterator".chars().is_partitioned(char::is_uppercase)); /// ``` #[unstable(feature = "iter_is_partitioned", issue = "62544")] + #[rustc_non_const_trait_method] fn is_partitioned

(mut self, mut predicate: P) -> bool where Self: Sized, @@ -2423,6 +2457,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] + #[rustc_non_const_trait_method] fn try_fold(&mut self, init: B, mut f: F) -> R where Self: Sized, @@ -2481,6 +2516,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] + #[rustc_non_const_trait_method] fn try_for_each(&mut self, f: F) -> R where Self: Sized, @@ -2600,6 +2636,7 @@ pub trait Iterator { #[doc(alias = "inject", alias = "foldl")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn fold(mut self, init: B, mut f: F) -> B where Self: Sized, @@ -2637,6 +2674,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_fold_self", since = "1.51.0")] + #[rustc_non_const_trait_method] fn reduce(mut self, f: F) -> Option where Self: Sized, @@ -2708,6 +2746,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "iterator_try_reduce", issue = "87053")] + #[rustc_non_const_trait_method] fn try_reduce( &mut self, f: impl FnMut(Self::Item, Self::Item) -> R, @@ -2766,6 +2805,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn all(&mut self, f: F) -> bool where Self: Sized, @@ -2819,6 +2859,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn any(&mut self, f: F) -> bool where Self: Sized, @@ -2892,6 +2933,7 @@ pub trait Iterator { /// Note that `iter.find(f)` is equivalent to `iter.filter(f).next()`. #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn find

(&mut self, predicate: P) -> Option where Self: Sized, @@ -2923,6 +2965,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_find_map", since = "1.30.0")] + #[rustc_non_const_trait_method] fn find_map(&mut self, f: F) -> Option where Self: Sized, @@ -2981,6 +3024,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "try_find", issue = "63178")] + #[rustc_non_const_trait_method] fn try_find( &mut self, f: impl FnMut(&Self::Item) -> R, @@ -3064,6 +3108,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn position

(&mut self, predicate: P) -> Option where Self: Sized, @@ -3129,6 +3174,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn rposition

(self) -> P where Self: Sized, @@ -3644,6 +3704,7 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().cmp([1].iter()), Ordering::Greater); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn cmp(self, other: I) -> Ordering where I: IntoIterator, @@ -3671,6 +3732,7 @@ pub trait Iterator { /// assert_eq!(xs.into_iter().cmp_by(ys, |x, y| (2 * x).cmp(&y)), Ordering::Greater); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] + #[rustc_non_const_trait_method] fn cmp_by(self, other: I, cmp: F) -> Ordering where Self: Sized, @@ -3727,6 +3789,7 @@ pub trait Iterator { /// ``` /// #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn partial_cmp(self, other: I) -> Option where I: IntoIterator, @@ -3763,6 +3826,7 @@ pub trait Iterator { /// ); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] + #[rustc_non_const_trait_method] fn partial_cmp_by(self, other: I, partial_cmp: F) -> Option where Self: Sized, @@ -3796,6 +3860,7 @@ pub trait Iterator { /// assert_eq!([1].iter().eq([1, 2].iter()), false); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn eq(self, other: I) -> bool where I: IntoIterator, @@ -3819,6 +3884,7 @@ pub trait Iterator { /// assert!(xs.iter().eq_by(ys, |x, y| x * x == y)); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] + #[rustc_non_const_trait_method] fn eq_by(self, other: I, eq: F) -> bool where Self: Sized, @@ -3848,6 +3914,7 @@ pub trait Iterator { /// assert_eq!([1].iter().ne([1, 2].iter()), true); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn ne(self, other: I) -> bool where I: IntoIterator, @@ -3869,6 +3936,7 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().lt([1, 2].iter()), false); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn lt(self, other: I) -> bool where I: IntoIterator, @@ -3890,6 +3958,7 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().le([1, 2].iter()), true); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn le(self, other: I) -> bool where I: IntoIterator, @@ -3911,6 +3980,7 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().gt([1, 2].iter()), false); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn gt(self, other: I) -> bool where I: IntoIterator, @@ -3932,6 +4002,7 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().ge([1, 2].iter()), true); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] + #[rustc_non_const_trait_method] fn ge(self, other: I) -> bool where I: IntoIterator, @@ -3961,6 +4032,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "is_sorted", since = "1.82.0")] + #[rustc_non_const_trait_method] fn is_sorted(self) -> bool where Self: Sized, @@ -3987,6 +4059,7 @@ pub trait Iterator { /// assert!(std::iter::empty::().is_sorted_by(|a, b| true)); /// ``` #[stable(feature = "is_sorted", since = "1.82.0")] + #[rustc_non_const_trait_method] fn is_sorted_by(mut self, compare: F) -> bool where Self: Sized, @@ -4031,6 +4104,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "is_sorted", since = "1.82.0")] + #[rustc_non_const_trait_method] fn is_sorted_by_key(self, f: F) -> bool where Self: Sized, @@ -4046,6 +4120,7 @@ pub trait Iterator { #[inline] #[doc(hidden)] #[unstable(feature = "trusted_random_access", issue = "none")] + #[rustc_non_const_trait_method] unsafe fn __iterator_get_unchecked(&mut self, _idx: usize) -> Self::Item where Self: TrustedRandomAccessNoCoerce, diff --git a/library/core/src/option.rs b/library/core/src/option.rs index eb4f978b7c19..b7c805f5855e 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -2257,7 +2257,8 @@ impl const Default for Option { } #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for Option { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const IntoIterator for Option { type Item = T; type IntoIter = IntoIter; @@ -2429,7 +2430,8 @@ struct Item { opt: Option, } -impl Iterator for Item { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const Iterator for Item { type Item = A; #[inline] @@ -2439,7 +2441,7 @@ impl Iterator for Item { #[inline] fn size_hint(&self) -> (usize, Option) { - let len = self.len(); + let len = self.opt.len(); (len, Some(len)) } } @@ -2563,7 +2565,8 @@ pub struct IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const Iterator for IntoIter { type Item = A; #[inline] diff --git a/library/coretests/tests/iter/mod.rs b/library/coretests/tests/iter/mod.rs index 5b2769d04698..f300f421f7c1 100644 --- a/library/coretests/tests/iter/mod.rs +++ b/library/coretests/tests/iter/mod.rs @@ -99,3 +99,18 @@ pub fn extend_for_unit() { } assert_eq!(x, 5); } + +#[test] +pub fn test_const_iter() { + const X: bool = { + let it = Some(42); + let mut run = false; + #[expect(for_loops_over_fallibles)] + for x in it { + assert!(x == 42); + run = true; + } + run + }; + assert_eq!(true, X); +} diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 8cca714b7393..a24c83834edb 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -27,6 +27,7 @@ #![feature(const_drop_in_place)] #![feature(const_eval_select)] #![feature(const_index)] +#![feature(const_iter)] #![feature(const_ops)] #![feature(const_option_ops)] #![feature(const_ref_cell)] From 02e10b2d90c8d4f0cb3f0f2b4a6a8a3283efa9c3 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 26 Jan 2026 13:00:58 -0500 Subject: [PATCH 282/978] fix issues and ui tests, address reviews --- .../src/check_consts/check.rs | 4 +-- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- .../src/check/compare_impl_item.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 5 ++- src/doc/rustc-dev-guide/src/SUMMARY.md | 2 +- src/doc/rustc-dev-guide/src/effects.md | 17 +++++++++- .../const-traits/partial/attr-gate.stderr | 2 +- .../const-traits/partial/no-const-callers.rs | 17 ++++++++++ .../partial/no-const-callers.stderr | 32 +++++++++++++++++-- .../typeck_type_placeholder_item.stderr | 14 -------- 10 files changed, 72 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 2abbf75984a4..57396b657a3f 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -774,8 +774,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // Attempting to call a trait method? if let Some(trait_did) = tcx.trait_of_assoc(callee) { - // We can't determine the actual callee here, so we have to do different checks - // than usual. + // We can't determine the actual callee (the underlying impl of the trait) here, so we have + // to do different checks than usual. trace!("attempting to call a trait method"); let is_const = tcx.constness(callee) == hir::Constness::Const; diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 8f447e1477b3..182ef6816337 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1333,7 +1333,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_non_const_trait_method, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No, "`#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods \ - as non-const to allow large traits to easier transition to const" + as non-const to allow large traits an easier transition to const" ), BuiltinAttribute { 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 dd7b03c9dac3..9e07d5260d20 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -218,7 +218,7 @@ fn compare_method_predicate_entailment<'tcx>( trait_m_predicates.instantiate_own(tcx, trait_to_impl_args).map(|(predicate, _)| predicate), ); - let is_conditionally_const = tcx.is_conditionally_const(impl_def_id); + let is_conditionally_const = tcx.is_conditionally_const(impl_m.def_id); if is_conditionally_const { // Augment the hybrid param-env with the const conditions // of the impl header and the trait method. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 044c99ffeb21..4e33b8ebb6de 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2087,7 +2087,10 @@ impl<'tcx> TyCtxt<'tcx> { self.constness(def_id) == hir::Constness::Const } DefKind::Impl { of_trait: true } => { - self.constness(self.trait_item_of(def_id).unwrap()) == hir::Constness::Const + let Some(trait_method_did) = self.trait_item_of(def_id) else { + return false; + }; + self.constness(trait_method_did) == hir::Constness::Const && self.is_conditionally_const(parent_def_id) } DefKind::Trait => { diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 1f9e0aac9d0b..5342c54607b7 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -199,7 +199,7 @@ - [Inference details](./opaque-types-impl-trait-inference.md) - [Return Position Impl Trait In Trait](./return-position-impl-trait-in-trait.md) - [Region inference restrictions](./borrow-check/opaque-types-region-inference-restrictions.md) -- [Const condition checking](./effects.md) +- [Const traits and const condition checking](./effects.md) - [Pattern and exhaustiveness checking](./pat-exhaustive-checking.md) - [Unsafety checking](./unsafety-checking.md) - [MIR dataflow](./mir/dataflow.md) diff --git a/src/doc/rustc-dev-guide/src/effects.md b/src/doc/rustc-dev-guide/src/effects.md index 87b0103a7bc4..732ba7153116 100644 --- a/src/doc/rustc-dev-guide/src/effects.md +++ b/src/doc/rustc-dev-guide/src/effects.md @@ -1,4 +1,4 @@ -# Effects and const condition checking +# Effects, const traits, and const condition checking ## The `HostEffect` predicate @@ -154,3 +154,18 @@ be dropped at compile time. [old solver]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_trait_selection/traits/effects.rs.html [new trait solver]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_next_trait_solver/solve/effect_goals.rs.html + +## More on const traits + +To be expanded later. + +### The `#[rustc_non_const_trait_method]` attribute + +This is intended for internal (standard library) usage only. With this attribute +applied to a trait method, the compiler will not check the default body of this +method for ability to run in compile time. Users of the trait will also not be +allowed to use this trait method in const contexts. This attribute is primarily +used for constifying large traits such as `Iterator` without having to make all +its methods `const` at the same time. + +This attribute should not be present while stabilizing the trait as `const`. diff --git a/tests/ui/traits/const-traits/partial/attr-gate.stderr b/tests/ui/traits/const-traits/partial/attr-gate.stderr index bc86cbe4edf7..e46e35d036be 100644 --- a/tests/ui/traits/const-traits/partial/attr-gate.stderr +++ b/tests/ui/traits/const-traits/partial/attr-gate.stderr @@ -6,7 +6,7 @@ LL | #[rustc_non_const_trait_method] | = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable = note: the `#[rustc_non_const_trait_method]` attribute is an internal implementation detail that will never be stable - = note: `#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods as non-const to allow large traits to easier transition to const + = note: `#[rustc_non_const_trait_method]` should only used by the standard library to mark trait methods as non-const to allow large traits an easier transition to const error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/partial/no-const-callers.rs b/tests/ui/traits/const-traits/partial/no-const-callers.rs index efcdea36f1ca..7c198f41ce42 100644 --- a/tests/ui/traits/const-traits/partial/no-const-callers.rs +++ b/tests/ui/traits/const-traits/partial/no-const-callers.rs @@ -10,6 +10,17 @@ impl const A for () { fn a() {} } +impl const A for u8 { + fn a() {} + fn b() { println!("hello"); } + //~^ ERROR: cannot call non-const function +} + +impl const A for i8 { + fn a() {} + fn b() {} +} + const fn foo() { T::a(); T::b(); @@ -17,6 +28,12 @@ const fn foo() { <()>::a(); <()>::b(); //~^ ERROR: cannot call non-const associated function + u8::a(); + u8::b(); + //~^ ERROR: cannot call non-const associated function + i8::a(); + i8::b(); + //~^ ERROR: cannot call non-const associated function } fn main() {} diff --git a/tests/ui/traits/const-traits/partial/no-const-callers.stderr b/tests/ui/traits/const-traits/partial/no-const-callers.stderr index 31179161c5cd..bbb4495943ed 100644 --- a/tests/ui/traits/const-traits/partial/no-const-callers.stderr +++ b/tests/ui/traits/const-traits/partial/no-const-callers.stderr @@ -1,5 +1,15 @@ +error[E0015]: cannot call non-const function `std::io::_print` in constant functions + --> $DIR/no-const-callers.rs:15:14 + | +LL | fn b() { println!("hello"); } + | ^^^^^^^^^^^^^^^^^ + | +note: function `_print` is not const + --> $SRC_DIR/std/src/io/stdio.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + error[E0015]: cannot call non-const associated function `::b` in constant functions - --> $DIR/no-const-callers.rs:15:5 + --> $DIR/no-const-callers.rs:26:5 | LL | T::b(); | ^^^^^^ @@ -7,13 +17,29 @@ LL | T::b(); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants error[E0015]: cannot call non-const associated function `<() as A>::b` in constant functions - --> $DIR/no-const-callers.rs:18:5 + --> $DIR/no-const-callers.rs:29:5 | LL | <()>::b(); | ^^^^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 2 previous errors +error[E0015]: cannot call non-const associated function `::b` in constant functions + --> $DIR/no-const-callers.rs:32:5 + | +LL | u8::b(); + | ^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error[E0015]: cannot call non-const associated function `::b` in constant functions + --> $DIR/no-const-callers.rs:35:5 + | +LL | i8::b(); + | ^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 0b70ac97fd43..2772d55f953a 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -684,13 +684,6 @@ error[E0015]: cannot call non-const method ` as Iterator>:: LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^^^^^^^^^^^^^^^^^^^^^^ | -note: method `filter` is not const because trait `Iterator` is not const - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | - = note: this trait is not const - ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | - = note: this method is not const = note: calls in constants are limited to constant functions, tuple structs and tuple variants error[E0015]: cannot call non-const method `, {closure@$DIR/typeck_type_placeholder_item.rs:240:29: 240:32}> as Iterator>::map::` in constants @@ -699,13 +692,6 @@ error[E0015]: cannot call non-const method `, {closu LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^^^^^^^^^^^^^^ | -note: method `map` is not const because trait `Iterator` is not const - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | - = note: this trait is not const - ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | - = note: this method is not const = note: calls in constants are limited to constant functions, tuple structs and tuple variants error: aborting due to 83 previous errors From ee9967bac019659ce17292fa5162da9b638464ed Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 28 Jan 2026 17:11:05 -0500 Subject: [PATCH 283/978] Fix clippy warning --- build_system/src/test.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index ca2a2a7dc2de..096f8c98376c 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -679,10 +679,10 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { create_dir(projects_path)?; let nb_parts = args.nb_parts.unwrap_or(0); - if nb_parts > 0 { + if let Some(count) = projects.len().checked_div(nb_parts) { // We increment the number of tests by one because if this is an odd number, we would skip // one test. - let count = projects.len() / nb_parts + 1; + let count = count + 1; let current_part = args.current_part.unwrap(); let start = current_part * count; // We remove the projects we don't want to test. From ff4db77564dbf7c94cdda67dba687c244b888d1e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 28 Jan 2026 17:14:27 -0500 Subject: [PATCH 284/978] Fix spelling mistake --- src/intrinsic/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 9a08003a7fb2..7140456c3754 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -618,15 +618,15 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let fn_ptr = func.get_address(None); let fn_ty = fn_ptr.get_type(); - let mut llargs = vec![]; + let mut call_args = vec![]; for arg in args { match arg.val { OperandValue::ZeroSized => {} - OperandValue::Immediate(_) => llargs.push(arg.immediate()), + OperandValue::Immediate(_) => call_args.push(arg.immediate()), OperandValue::Pair(a, b) => { - llargs.push(a); - llargs.push(b); + call_args.push(a); + call_args.push(b); } OperandValue::Ref(op_place_val) => { let mut llval = op_place_val.llval; @@ -643,13 +643,13 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc // We store bools as `i8` so we need to truncate to `i1`. llval = self.to_immediate_scalar(llval, scalar); } - llargs.push(llval); + call_args.push(llval); } } } // FIXME directly use the llvm intrinsic adjustment functions here - let llret = self.call(fn_ty, None, None, fn_ptr, &llargs, None, None); + let llret = self.call(fn_ty, None, None, fn_ptr, &call_args, None, None); if is_cleanup { self.apply_attrs_to_cleanup_callsite(llret); } From d299dce03a37d01b4e25b9033de7ab2e9112a7b4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 28 Jan 2026 17:27:55 -0500 Subject: [PATCH 285/978] Fix the name of failing UI tests --- tests/failing-ui-tests.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 99a80fa7e4f4..73d29426adf8 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -89,11 +89,11 @@ tests/ui/thir-print/offset_of.rs tests/ui/iterators/rangefrom-overflow-debug.rs tests/ui/iterators/rangefrom-overflow-overflow-checks.rs tests/ui/iterators/iter-filter-count-debug-check.rs -tests/ui/eii/codegen_single_crate.rs -tests/ui/eii/codegen_cross_crate.rs +tests/ui/eii/linking/codegen_single_crate.rs +tests/ui/eii/linking/codegen_cross_crate.rs tests/ui/eii/default/local_crate.rs -tests/ui/eii/multiple_impls.rs +tests/ui/eii/duplicate/multiple_impls.rs tests/ui/eii/default/call_default.rs -tests/ui/eii/same-symbol.rs +tests/ui/eii/linking/same-symbol.rs tests/ui/eii/privacy1.rs tests/ui/eii/default/call_impl.rs From dffd4ab825020322303b5e9e287519957b4d2594 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 29 Jan 2026 17:09:53 -0500 Subject: [PATCH 286/978] Ignore failing UI test --- tests/failing-ui-tests.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 73d29426adf8..75ca1845f45e 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -97,3 +97,4 @@ tests/ui/eii/default/call_default.rs tests/ui/eii/linking/same-symbol.rs tests/ui/eii/privacy1.rs tests/ui/eii/default/call_impl.rs +tests/ui/c-variadic/copy.rs From e8282659f9683bb063396a32dbdc489736ee79e4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 30 Jan 2026 08:32:03 -0500 Subject: [PATCH 287/978] Update to nightly-2026-01-30 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 2168c8e72cfb..c2179bc3ff98 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-01-28" +channel = "nightly-2026-01-30" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From fb32a3f52e1a6d54921bcd9d4976bf22421227a4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 30 Jan 2026 08:32:24 -0500 Subject: [PATCH 288/978] Update GCC version --- libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index e49b36557350..25e1105ab07f 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -586d798e864fb33b1b4e842c5493a653841a7c02 +896045775f7c40fafe48c6e398f6c53bf6af889e From a04934421ffa8ac4b6541772b5fef7c2778d3809 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 30 Jan 2026 11:16:26 -0500 Subject: [PATCH 289/978] Switch to new_array_type_u64 --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- src/builder.rs | 2 +- src/common.rs | 6 +++--- src/context.rs | 4 ++-- src/intrinsic/llvm.rs | 12 ++++++------ src/type_.rs | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3b497f83cc0a..a283ea4cb0b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef03c8ae23826a0755b980999a553a262c61f2f585245e647192d95bf09eee79" +checksum = "26b73d18b642ce16378af78f89664841d7eeafa113682ff5d14573424eb0232a" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ff511da413e4a5da6f09607748395ba37525e01ba7d322cbec3efc43095dd60" +checksum = "ee689456c013616942d5aef9a84d613cefcc3b335340d036f3650fc1a7459e15" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 97735e49e84b..29af6a1fc434 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ default = ["master"] [dependencies] object = { version = "0.37.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "3.2.0", features = ["dlopen"] } +gccjit = { version = "3.3.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. diff --git a/src/builder.rs b/src/builder.rs index 3def9a5c015c..ea75b4294e04 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1503,7 +1503,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let element_type = vector_type.get_element_type(); let vec_num_units = vector_type.get_num_units(); let array_type = - self.context.new_array_type(self.location, element_type, vec_num_units as u64); + self.context.new_array_type_u64(self.location, element_type, vec_num_units as u64); let array = self.context.new_bitcast(self.location, vec, array_type).to_rvalue(); self.context.new_array_access(self.location, array, idx).to_rvalue() } diff --git a/src/common.rs b/src/common.rs index 7c2969e58718..e71e1216dbd9 100644 --- a/src/common.rs +++ b/src/common.rs @@ -55,7 +55,7 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> 0 => { let context = &cx.context; let byte_type = context.new_type::(); - let typ = context.new_array_type(None, byte_type, bytes.len() as u64 / 8); + let typ = context.new_array_type_u64(None, byte_type, bytes.len() as u64 / 8); let elements: Vec<_> = bytes .chunks_exact(8) .map(|arr| { @@ -76,7 +76,7 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> 4 => { let context = &cx.context; let byte_type = context.new_type::(); - let typ = context.new_array_type(None, byte_type, bytes.len() as u64 / 4); + let typ = context.new_array_type_u64(None, byte_type, bytes.len() as u64 / 4); let elements: Vec<_> = bytes .chunks_exact(4) .map(|arr| { @@ -95,7 +95,7 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> _ => { let context = cx.context; let byte_type = context.new_type::(); - let typ = context.new_array_type(None, byte_type, bytes.len() as u64); + let typ = context.new_array_type_u64(None, byte_type, bytes.len() as u64); let elements: Vec<_> = bytes .iter() .map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32)) diff --git a/src/context.rs b/src/context.rs index 988743d0aef5..d4d4c490e75e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -201,8 +201,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { // TODO(antoyo): re-enable the alignment when libgccjit fixed the issue in // gcc_jit_context_new_array_constructor (it should not use reinterpret_cast). - let i128_type = context.new_array_type(None, i64_type, 2)/*.get_aligned(i128_align)*/; - let u128_type = context.new_array_type(None, u64_type, 2)/*.get_aligned(u128_align)*/; + let i128_type = context.new_array_type_u64(None, i64_type, 2)/*.get_aligned(i128_align)*/; + let u128_type = context.new_array_type_u64(None, u64_type, 2)/*.get_aligned(u128_align)*/; (i128_type, u128_type) }; diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index fbf3050a8a15..5c8bc5a4791c 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -585,7 +585,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( "__builtin_ia32_encodekey128_u32" => { let mut new_args = args.to_vec(); let m128i = builder.context.new_vector_type(builder.i64_type, 2); - let array_type = builder.context.new_array_type(None, m128i, 6); + let array_type = builder.context.new_array_type_u64(None, m128i, 6); let result = builder.current_func().new_local(None, array_type, "result"); new_args.push(result.get_address(None)); args = new_args.into(); @@ -593,7 +593,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( "__builtin_ia32_encodekey256_u32" => { let mut new_args = args.to_vec(); let m128i = builder.context.new_vector_type(builder.i64_type, 2); - let array_type = builder.context.new_array_type(None, m128i, 7); + let array_type = builder.context.new_array_type_u64(None, m128i, 7); let result = builder.current_func().new_local(None, array_type, "result"); new_args.push(result.get_address(None)); args = new_args.into(); @@ -620,7 +620,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( let first_value = old_args.swap_remove(0); let element_type = first_value.get_type(); - let array_type = builder.context.new_array_type(None, element_type, 8); + let array_type = builder.context.new_array_type_u64(None, element_type, 8); let result = builder.current_func().new_local(None, array_type, "result"); new_args.push(result.get_address(None)); @@ -869,7 +869,7 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( builder.llbb().add_assignment(None, field1, return_value); let field2 = result.access_field(None, field2); let field2_type = field2.to_rvalue().get_type(); - let array_type = builder.context.new_array_type(None, field2_type, 6); + let array_type = builder.context.new_array_type_u64(None, field2_type, 6); let ptr = builder.context.new_cast(None, args[2], array_type.make_pointer()); let field2_ptr = builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer()); @@ -891,7 +891,7 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( builder.llbb().add_assignment(None, field1, return_value); let field2 = result.access_field(None, field2); let field2_type = field2.to_rvalue().get_type(); - let array_type = builder.context.new_array_type(None, field2_type, 7); + let array_type = builder.context.new_array_type_u64(None, field2_type, 7); let ptr = builder.context.new_cast(None, args[3], array_type.make_pointer()); let field2_ptr = builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer()); @@ -937,7 +937,7 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( builder.llbb().add_assignment(None, field1, return_value); let field2 = result.access_field(None, field2); let field2_type = field2.to_rvalue().get_type(); - let array_type = builder.context.new_array_type(None, field2_type, 8); + let array_type = builder.context.new_array_type_u64(None, field2_type, 8); let ptr = builder.context.new_cast(None, args[0], array_type.make_pointer()); let field2_ptr = builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer()); diff --git a/src/type_.rs b/src/type_.rs index d356b6af260a..7a6a5d3a10ea 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -311,7 +311,7 @@ impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { len = 0; } - self.context.new_array_type(None, ty, len) + self.context.new_array_type_u64(None, ty, len) } } From e4b746486c91de2a50eafadb9be71512aa149e73 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 30 Jan 2026 11:32:29 -0500 Subject: [PATCH 290/978] Ignore test when 128-bit integers are disabled --- .github/workflows/ci.yml | 4 ++++ tests/failing-ui-tests-without-128bit-integers.txt | 1 + 2 files changed, 5 insertions(+) create mode 100644 tests/failing-ui-tests-without-128bit-integers.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c8e7d628169..840c09409bba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -113,6 +113,10 @@ jobs: git config --global user.name "User" ./y.sh prepare + - name: Add more failing tests for GCC without 128-bit integers support + if: ${{ matrix.libgccjit_version.gcc == 'gcc-15-without-int128.deb' }} + run: cat tests/failing-ui-tests-without-128bit-integers.txt >> tests/failing-ui-tests.txt + - name: Run tests run: | ./y.sh test --release --clean --build-sysroot ${{ matrix.commands }} diff --git a/tests/failing-ui-tests-without-128bit-integers.txt b/tests/failing-ui-tests-without-128bit-integers.txt new file mode 100644 index 000000000000..1dc3859b335e --- /dev/null +++ b/tests/failing-ui-tests-without-128bit-integers.txt @@ -0,0 +1 @@ +tests/ui/simd/intrinsic/splat.rs From 0271b6b156e602dd8157e3284d37933377c1476c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Fri, 30 Jan 2026 18:25:19 +0100 Subject: [PATCH 291/978] regression test for alias-relate changes in lub --- .../generalize/relate-alias-in-lub.rs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/ui/traits/next-solver/generalize/relate-alias-in-lub.rs diff --git a/tests/ui/traits/next-solver/generalize/relate-alias-in-lub.rs b/tests/ui/traits/next-solver/generalize/relate-alias-in-lub.rs new file mode 100644 index 000000000000..0a948989f981 --- /dev/null +++ b/tests/ui/traits/next-solver/generalize/relate-alias-in-lub.rs @@ -0,0 +1,30 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ check-pass +// Reproduces https://github.com/rust-lang/rust/pull/151746#issuecomment-3822930803. +// +// The change we tried to make there caused relating a type variable with an alias inside lub, +// In 5bd20bbd0ba6c0285664e55a1ffc677d7487c98b, we moved around code +// that adds an alias-relate predicate to be earlier, from one shared codepath into several +// distinct code paths. However, we forgot one codepath, through lub, causing an ICE in serde. +// In the end we dropped said commit, but the reproducer is still a useful as test. + +use std::marker::PhantomData; + +pub trait Trait { + type Error; +} + +pub struct Struct(PhantomData); + +impl Trait for () { + type Error = (); +} + +fn main() { + let _: Struct<<() as Trait>::Error> = match loop {} { + b => loop {}, + a => Struct(PhantomData), + }; +} From ea0ee492bdeb17a8e2df9e84ef14d1e12cb93884 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 30 Jan 2026 19:29:00 +0300 Subject: [PATCH 292/978] resolve: Remove `force` parameter from `resolve_ident_in_scope` --- compiler/rustc_resolve/src/diagnostics.rs | 3 -- compiler/rustc_resolve/src/ident.rs | 34 ++++--------------- compiler/rustc_resolve/src/imports.rs | 1 - compiler/rustc_resolve/src/macros.rs | 7 ++-- ...ro-rules-as-derive-or-attr-issue-132928.rs | 1 - ...ules-as-derive-or-attr-issue-132928.stderr | 13 +------ 6 files changed, 10 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 5c401c3bf828..6f2d3e79d10a 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1709,7 +1709,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ns), parent_scope, None, - false, None, None, ) else { @@ -2546,7 +2545,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ns_to_try), parent_scope, None, - false, ignore_decl, ignore_import, ) @@ -2650,7 +2648,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ValueNS), parent_scope, None, - false, ignore_decl, ignore_import, ) { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 26dca5e6e508..4fbde60d8679 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -350,7 +350,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::Module(ns, module), parent_scope, finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), - finalize.is_some(), ignore_decl, None, ) @@ -368,7 +367,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ns), parent_scope, finalize, - finalize.is_some(), ignore_decl, None, ) @@ -396,12 +394,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { scope_set: ScopeSet<'ra>, parent_scope: &ParentScope<'ra>, finalize: Option, - force: bool, ignore_decl: Option>, ignore_import: Option>, ) -> Result, Determinacy> { - assert!(force || finalize.is_none()); // `finalize` implies `force` - // Make sure `self`, `super` etc produce an error when passed to here. if !matches!(scope_set, ScopeSet::Module(..)) && orig_ident.is_path_segment_keyword() { return Err(Determinacy::Determined); @@ -451,7 +446,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { parent_scope, // Shadowed decls don't need to be marked as used or non-speculatively loaded. if innermost_results.is_empty() { finalize } else { None }, - force, ignore_decl, ignore_import, ) { @@ -509,7 +503,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Scope visiting walked all the scopes and maybe found something in one of them. match innermost_results.first() { Some(&(decl, ..)) => Ok(decl), - None => Err(Determinacy::determined(determinacy == Determinacy::Determined || force)), + None => Err(determinacy), } } @@ -523,7 +517,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { scope_set: ScopeSet<'ra>, parent_scope: &ParentScope<'ra>, finalize: Option, - force: bool, ignore_decl: Option>, ignore_import: Option>, ) -> Result, ControlFlow> { @@ -546,7 +539,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { match self.reborrow().resolve_derive_macro_path( derive, parent_scope, - force, + false, ignore_import, ) { Ok((Some(ext), _)) => { @@ -617,11 +610,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Ok(decl) } Err(ControlFlow::Continue(determinacy)) => Err(determinacy), - Err(ControlFlow::Break(determinacy)) => { - return Err(ControlFlow::Break(Determinacy::determined( - determinacy == Determinacy::Determined || force, - ))); - } + Err(ControlFlow::Break(..)) => return decl, } } Scope::ModuleGlobs(module, derive_fallback_lint_id) => { @@ -668,11 +657,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Ok(binding) } Err(ControlFlow::Continue(determinacy)) => Err(determinacy), - Err(ControlFlow::Break(determinacy)) => { - return Err(ControlFlow::Break(Determinacy::determined( - determinacy == Determinacy::Determined || force, - ))); - } + Err(ControlFlow::Break(..)) => return binding, } } Scope::MacroUsePrelude => match self.macro_use_prelude.get(&ident.name).cloned() { @@ -715,7 +700,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::Module(ns, prelude), parent_scope, None, - false, ignore_decl, ignore_import, ) @@ -951,7 +935,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::Module(ns, module), parent_scope, finalize, - finalize.is_some(), ignore_decl, ignore_import, ), @@ -960,7 +943,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::ModuleAndExternPrelude(ns, module), parent_scope, finalize, - finalize.is_some(), ignore_decl, ignore_import, ), @@ -973,7 +955,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::ExternPrelude, parent_scope, finalize, - finalize.is_some(), ignore_decl, ignore_import, ) @@ -996,7 +977,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ns), parent_scope, finalize, - finalize.is_some(), ignore_decl, ignore_import, ) @@ -1180,7 +1160,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::Module(ns, module), adjusted_parent_scope, None, - false, ignore_decl, ignore_import, ); @@ -1881,7 +1860,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ns), parent_scope, finalize, - finalize.is_some(), ignore_decl, ignore_import, ) @@ -1957,8 +1935,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ); } } - Err(Undetermined) => return PathResult::Indeterminate, - Err(Determined) => { + Err(Undetermined) if finalize.is_none() => return PathResult::Indeterminate, + Err(Determined | Undetermined) => { if let Some(ModuleOrUniformRoot::Module(module)) = module && opt_ns.is_some() && !module.is_normal() diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 7ff24bc612df..057340028085 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1498,7 +1498,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ns), &import.parent_scope, None, - false, decls[ns].get().decl(), None, ) { diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index b7d83d9e130c..b933c2b9d036 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -799,10 +799,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::Macro(kind), parent_scope, None, - force, None, None, ); + let binding = binding.map_err(|determinacy| { + Determinacy::determined(determinacy == Determinacy::Determined || force) + }); if let Err(Determinacy::Undetermined) = binding { return Err(Determinacy::Undetermined); } @@ -958,7 +960,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::Macro(kind), &parent_scope, Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)), - true, None, None, ) { @@ -1013,7 +1014,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::Macro(MacroKind::Attr), &parent_scope, Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)), - true, None, None, ); @@ -1117,7 +1117,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::Macro(MacroKind::Bang), &ParentScope { macro_rules: no_macro_rules, ..*parent_scope }, None, - false, None, None, ); diff --git a/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.rs b/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.rs index a2e1398c61e6..a556983e204d 100644 --- a/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.rs +++ b/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.rs @@ -5,5 +5,4 @@ macro_rules! sample { () => {} } #[sample] //~ ERROR cannot find attribute `sample` in this scope #[derive(sample)] //~ ERROR cannot find derive macro `sample` in this scope //~| ERROR cannot find derive macro `sample` in this scope - //~| ERROR cannot find derive macro `sample` in this scope pub struct S {} diff --git a/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr b/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr index aad4a844ec17..a3c21df43e75 100644 --- a/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr +++ b/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr @@ -1,12 +1,3 @@ -error: cannot find derive macro `sample` in this scope - --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10 - | -LL | macro_rules! sample { () => {} } - | ------ `sample` exists, but has no `derive` rules -... -LL | #[derive(sample)] - | ^^^^^^ - error: cannot find attribute `sample` in this scope --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:5:3 | @@ -24,8 +15,6 @@ LL | macro_rules! sample { () => {} } ... LL | #[derive(sample)] | ^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: cannot find derive macro `sample` in this scope --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10 @@ -38,5 +27,5 @@ LL | #[derive(sample)] | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors From a3f169c75b7625e15e07e4ed7855647871207fd1 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 27 Jan 2026 08:46:08 -0800 Subject: [PATCH 293/978] Use `Bound::copied` instead of `Bound::cloned` --- library/core/src/ops/range.rs | 2 +- library/core/src/slice/index.rs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index a0b74ff383ea..c15c8f20c16b 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -773,7 +773,7 @@ impl Bound<&T> { /// ``` #[unstable(feature = "bound_copied", issue = "145966")] #[must_use] - pub fn copied(self) -> Bound { + pub const fn copied(self) -> Bound { match self { Bound::Unbounded => Bound::Unbounded, Bound::Included(x) => Bound::Included(*x), diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 097310dc8fb0..59802989c18f 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -910,7 +910,7 @@ where R: [const] ops::RangeBounds + [const] Destruct, { let len = bounds.end; - into_slice_range(len, (range.start_bound().cloned(), range.end_bound().cloned())) + into_slice_range(len, (range.start_bound().copied(), range.end_bound().copied())) } /// Performs bounds checking of a range without panicking. @@ -950,7 +950,7 @@ where R: ops::RangeBounds, { let len = bounds.end; - let r = into_range(len, (range.start_bound().cloned(), range.end_bound().cloned()))?; + let r = into_range(len, (range.start_bound().copied(), range.end_bound().copied()))?; if r.start > r.end || r.end > len { None } else { Some(r) } } @@ -977,6 +977,7 @@ pub(crate) const fn into_range_unchecked( /// Converts pair of `ops::Bound`s into `ops::Range`. /// Returns `None` on overflowing indices. #[rustc_const_unstable(feature = "const_range", issue = "none")] +#[inline] pub(crate) const fn into_range( len: usize, (start, end): (ops::Bound, ops::Bound), @@ -1002,6 +1003,7 @@ pub(crate) const fn into_range( /// Converts pair of `ops::Bound`s into `ops::Range`. /// Panics on overflowing indices. +#[inline] pub(crate) const fn into_slice_range( len: usize, (start, end): (ops::Bound, ops::Bound), From 5f76adf7b368b4bec6fb3771fe645ab762ef8236 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Sat, 31 Jan 2026 07:37:52 +0900 Subject: [PATCH 294/978] fix adk installer link --- src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md b/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md index d2680d40853f..2267f9b490f7 100644 --- a/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md @@ -22,8 +22,8 @@ specifically designed to make analyzing rustc easier. You can install WPR and WPA as part of the Windows Performance Toolkit which itself is an option as part of downloading the Windows Assessment and Deployment Kit (ADK). You can download the ADK -installer [here](https://go.microsoft.com/fwlink/?linkid=2086042). Make sure to select the Windows -Performance Toolkit (you don't need to select anything else). +installer [here](https://learn.microsoft.com/en-us/windows-hardware/get-started/adk-install). Make +sure to select the Windows Performance Toolkit (you don't need to select anything else). ## Recording From 8869b7b356d1bf1766427bbcfb075756adebbfaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 31 Jan 2026 00:29:30 +0100 Subject: [PATCH 295/978] Pass `DepNode` by reference more places --- .../rustc_query_system/src/dep_graph/graph.rs | 10 +++++----- .../rustc_query_system/src/dep_graph/mod.rs | 4 ++-- .../src/dep_graph/serialized.rs | 18 +++++++++--------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 6d46d144d0f1..cf3d211d1cc7 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -662,7 +662,7 @@ impl DepGraphData { } #[inline] - pub(crate) fn prev_node_of(&self, prev_index: SerializedDepNodeIndex) -> DepNode { + pub(crate) fn prev_node_of(&self, prev_index: SerializedDepNodeIndex) -> &DepNode { self.previous.index_to_node(prev_index) } @@ -783,7 +783,7 @@ impl DepGraphData { #[cfg(debug_assertions)] self.current.record_edge( dep_node_index, - self.previous.index_to_node(prev_index), + *self.previous.index_to_node(prev_index), self.previous.fingerprint_by_index(prev_index), ); @@ -918,7 +918,7 @@ impl DepGraphData { DepNodeColor::Unknown => {} } - let dep_dep_node = &get_dep_dep_node(); + let dep_dep_node = get_dep_dep_node(); // We don't know the state of this dependency. If it isn't // an eval_always node, let's try to mark it green recursively. @@ -989,7 +989,7 @@ impl DepGraphData { // We never try to mark eval_always nodes as green debug_assert!(!qcx.dep_context().is_eval_always(dep_node.kind)); - debug_assert_eq!(self.previous.index_to_node(prev_dep_node_index), *dep_node); + debug_assert_eq!(self.previous.index_to_node(prev_dep_node_index), dep_node); let prev_deps = self.previous.edge_targets_from(prev_dep_node_index); @@ -1450,7 +1450,7 @@ fn panic_on_forbidden_read(data: &DepGraphData, dep_node_index: DepN // previous session and has been marked green for prev_index in data.colors.values.indices() { if data.colors.current(prev_index) == Some(dep_node_index) { - dep_node = Some(data.previous.index_to_node(prev_index)); + dep_node = Some(*data.previous.index_to_node(prev_index)); break; } } diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 874b41cbf3b1..8f714a2c96d6 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -83,9 +83,9 @@ pub trait DepContext: Copy { } /// Load data from the on-disk cache. - fn try_load_from_on_disk_cache(self, dep_node: DepNode) { + fn try_load_from_on_disk_cache(self, dep_node: &DepNode) { if let Some(try_load_fn) = self.dep_kind_vtable(dep_node.kind).try_load_from_on_disk_cache { - try_load_fn(self, dep_node) + try_load_fn(self, *dep_node) } } diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 403394674a02..aa4c928d3cdc 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -133,8 +133,8 @@ impl SerializedDepGraph { } #[inline] - pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode { - self.nodes[dep_node_index] + pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> &DepNode { + &self.nodes[dep_node_index] } #[inline] @@ -346,7 +346,7 @@ impl SerializedNodeHeader { #[inline] fn new( - node: DepNode, + node: &DepNode, index: DepNodeIndex, fingerprint: Fingerprint, edge_max_index: u32, @@ -379,7 +379,7 @@ impl SerializedNodeHeader { { let res = Self { bytes, _marker: PhantomData }; assert_eq!(fingerprint, res.fingerprint()); - assert_eq!(node, res.node()); + assert_eq!(*node, res.node()); if let Some(len) = res.len() { assert_eq!(edge_count, len as usize); } @@ -452,7 +452,7 @@ struct NodeInfo { impl NodeInfo { fn encode(&self, e: &mut MemEncoder, index: DepNodeIndex) { - let NodeInfo { node, fingerprint, ref edges } = *self; + let NodeInfo { ref node, fingerprint, ref edges } = *self; let header = SerializedNodeHeader::::new( node, index, @@ -482,7 +482,7 @@ impl NodeInfo { #[inline] fn encode_promoted( e: &mut MemEncoder, - node: DepNode, + node: &DepNode, index: DepNodeIndex, fingerprint: Fingerprint, prev_index: SerializedDepNodeIndex, @@ -604,7 +604,7 @@ impl EncoderState { #[inline] fn record( &self, - node: DepNode, + node: &DepNode, index: DepNodeIndex, edge_count: usize, edges: impl FnOnce(&Self) -> Vec, @@ -622,7 +622,7 @@ impl EncoderState { outline(move || { // Do not ICE when a query is called from within `with_query`. if let Some(record_graph) = &mut record_graph.try_lock() { - record_graph.push(index, node, &edges); + record_graph.push(index, *node, &edges); } }); } @@ -661,7 +661,7 @@ impl EncoderState { node.encode::(&mut local.encoder, index); self.flush_mem_encoder(&mut *local); self.record( - node.node, + &node.node, index, node.edges.len(), |_| node.edges[..].to_vec(), From f7ffe3139006ea4d6fdf99c160a8b62b373922e9 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 27 Jan 2026 17:06:12 -0500 Subject: [PATCH 296/978] Update cargo submodule also fixed tests/run-make-cargo/apple-slow-tls/rmake.rs accordingly for the new `-Zjson-target-spec` requirement --- src/tools/cargo | 2 +- tests/run-make-cargo/apple-slow-tls/rmake.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index efcd9f58636c..fe2f314aef06 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit efcd9f58636c1990393d495159045d9c35e43b8f +Subproject commit fe2f314aef06e688a9517da1ac0577bb1854d01f diff --git a/tests/run-make-cargo/apple-slow-tls/rmake.rs b/tests/run-make-cargo/apple-slow-tls/rmake.rs index 231e0b1668e9..476414bcfa1e 100644 --- a/tests/run-make-cargo/apple-slow-tls/rmake.rs +++ b/tests/run-make-cargo/apple-slow-tls/rmake.rs @@ -26,6 +26,7 @@ fn main() { "--target", "t.json", "-Zbuild-std=std,core,panic_abort", + "-Zjson-target-spec", ]) .run(); From 5cb916370bf2b770b15ee9b915fbe8f99b36890e Mon Sep 17 00:00:00 2001 From: "R. Yin" <88910093+thealtofwar@users.noreply.github.com> Date: Fri, 30 Jan 2026 20:02:48 -0600 Subject: [PATCH 297/978] Fix typo in debugging.md --- src/doc/rustc-dev-guide/src/autodiff/debugging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/autodiff/debugging.md b/src/doc/rustc-dev-guide/src/autodiff/debugging.md index 7c7af8589868..3b2278f1a075 100644 --- a/src/doc/rustc-dev-guide/src/autodiff/debugging.md +++ b/src/doc/rustc-dev-guide/src/autodiff/debugging.md @@ -16,7 +16,7 @@ Before generating the llvm-ir, keep in mind two techniques that can help ensure ## 1) Generate an llvm-ir reproducer ```sh -RUSTFLAGS="-Z autodiff=Enable,PrintModbefore" cargo +enzyme build --release &> out.ll +RUSTFLAGS="-Z autodiff=Enable,PrintModBefore" cargo +enzyme build --release &> out.ll ``` This also captures a few warnings and info messages above and below your module. open out.ll and remove every line above `; moduleid = `. Now look at the end of the file and remove everything that's not part of llvm-ir, i.e. remove errors and warnings. The last line of your llvm-ir should now start with `! = `, i.e. `!40831 = !{i32 0, i32 1037508, i32 1037538, i32 1037559}` or `!43760 = !dilocation(line: 297, column: 5, scope: !43746)`. From c8d2f3e6f16ff797d8789fe9818f2c6a144153dc Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Sat, 31 Jan 2026 02:06:09 +0000 Subject: [PATCH 298/978] Prepare for merging from rust-lang/rust This updates the rust-version file to 44e34e1ac6d7e69b40856cf1403d3da145319c30. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 795271ee0ef0..209f4226eae7 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -370143facfb348ad3b29749c0393402d76b280c3 +44e34e1ac6d7e69b40856cf1403d3da145319c30 From f7931c805097f97c9586f0ce49d01ff4adfc972c Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 30 Jan 2026 18:21:19 -0800 Subject: [PATCH 299/978] Remove some unnecessary `try`-related type annotations I left a few, like ```rust let result: Result<_, ModError<'_>> = try { ``` where it felt like seeing it might still be useful for the reader. Feel free to push back on any of these changes if you think seeing the type would be better. --- compiler/rustc_borrowck/src/nll.rs | 4 +-- compiler/rustc_borrowck/src/polonius/dump.rs | 2 +- compiler/rustc_codegen_ssa/src/back/linker.rs | 16 +++++----- compiler/rustc_driver_impl/src/lib.rs | 2 +- .../rustc_expand/src/proc_macro_server.rs | 4 +-- .../src/check/compare_impl_item.rs | 4 +-- compiler/rustc_interface/src/passes.rs | 2 +- compiler/rustc_lint/src/types.rs | 31 +++++++++---------- compiler/rustc_middle/src/mir/pretty.rs | 4 +-- .../rustc_mir_build/src/builder/custom/mod.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 6 ++-- .../error_reporting/infer/need_type_info.rs | 15 +++++---- 12 files changed, 45 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 64e3b59acfff..7cb27638e645 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -230,13 +230,13 @@ pub(super) fn dump_nll_mir<'tcx>( dumper.dump_mir(body); // Also dump the region constraint graph as a graphviz file. - let _: io::Result<()> = try { + let _ = try { let mut file = dumper.create_dump_file("regioncx.all.dot", body)?; regioncx.dump_graphviz_raw_constraints(tcx, &mut file)?; }; // Also dump the region constraint SCC graph as a graphviz file. - let _: io::Result<()> = try { + let _ = try { let mut file = dumper.create_dump_file("regioncx.scc.dot", body)?; regioncx.dump_graphviz_scc_constraints(tcx, &mut file)?; }; diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index 62f9ae173474..a8e7ab234f00 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -58,7 +58,7 @@ pub(crate) fn dump_polonius_mir<'tcx>( let dumper = dumper.set_extra_data(extra_data).set_options(options); - let _: io::Result<()> = try { + let _ = try { let mut file = dumper.create_dump_file("html", body)?; emit_polonius_dump( &dumper, diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index db49f92e39ac..10c4eedb58e8 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -2,7 +2,7 @@ use std::ffi::{OsStr, OsString}; use std::fs::{self, File}; use std::io::prelude::*; use std::path::{Path, PathBuf}; -use std::{env, io, iter, mem, str}; +use std::{env, iter, mem, str}; use find_msvc_tools; use rustc_hir::attrs::WindowsSubsystemKind; @@ -809,7 +809,7 @@ impl<'a> Linker for GccLinker<'a> { if self.sess.target.is_like_darwin { // Write a plain, newline-separated list of symbols - let res: io::Result<()> = try { + let res = try { let mut f = File::create_buffered(&path)?; for (sym, _) in symbols { debug!(" _{sym}"); @@ -821,7 +821,7 @@ impl<'a> Linker for GccLinker<'a> { } self.link_arg("-exported_symbols_list").link_arg(path); } else if self.sess.target.is_like_windows { - let res: io::Result<()> = try { + let res = try { let mut f = File::create_buffered(&path)?; // .def file similar to MSVC one but without LIBRARY section @@ -845,7 +845,7 @@ impl<'a> Linker for GccLinker<'a> { self.link_arg("--export").link_arg(sym); } } else if crate_type == CrateType::Executable && !self.sess.target.is_like_solaris { - let res: io::Result<()> = try { + let res = try { let mut f = File::create_buffered(&path)?; writeln!(f, "{{")?; for (sym, _) in symbols { @@ -860,7 +860,7 @@ impl<'a> Linker for GccLinker<'a> { self.link_arg("--dynamic-list").link_arg(path); } else { // Write an LD version script - let res: io::Result<()> = try { + let res = try { let mut f = File::create_buffered(&path)?; writeln!(f, "{{")?; if !symbols.is_empty() { @@ -1139,7 +1139,7 @@ impl<'a> Linker for MsvcLinker<'a> { } let path = tmpdir.join("lib.def"); - let res: io::Result<()> = try { + let res = try { let mut f = File::create_buffered(&path)?; // Start off with the standard module name header and then go @@ -1735,7 +1735,7 @@ impl<'a> Linker for AixLinker<'a> { symbols: &[(String, SymbolExportKind)], ) { let path = tmpdir.join("list.exp"); - let res: io::Result<()> = try { + let res = try { let mut f = File::create_buffered(&path)?; // FIXME: use llvm-nm to generate export list. for (symbol, _) in symbols { @@ -2135,7 +2135,7 @@ impl<'a> Linker for BpfLinker<'a> { symbols: &[(String, SymbolExportKind)], ) { let path = tmpdir.join("symbols"); - let res: io::Result<()> = try { + let res = try { let mut f = File::create_buffered(&path)?; for (sym, _) in symbols { writeln!(f, "{sym}")?; diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 38ee87601614..5579c25329eb 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -537,7 +537,7 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) { }; // Try to print via the pager, pretty output if possible. - let pager_res: Option<()> = try { + let pager_res = try { let mut pager = cmd.stdin(Stdio::piped()).spawn().ok()?; let pager_stdin = pager.stdin.as_mut()?; diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 12490880ab0e..947b8a6e3e5e 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -7,7 +7,7 @@ use rustc_ast::tokenstream::{self, DelimSpacing, Spacing, TokenStream}; use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult}; +use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan}; use rustc_parse::lexer::{StripTokens, nfc_normalize}; use rustc_parse::parser::Parser; use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal}; @@ -591,7 +591,7 @@ impl server::Server for Rustc<'_, '_> { fn ts_expand_expr(&mut self, stream: &Self::TokenStream) -> Result { // Parse the expression from our tokenstream. - let expr: PResult<'_, _> = try { + let expr = try { let mut p = Parser::new(self.psess(), stream.clone(), Some("proc_macro expand expr")); let expr = p.parse_expr()?; if p.token != token::Eof { 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 dd7b03c9dac3..777929eaadb8 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1845,7 +1845,7 @@ fn compare_synthetic_generics<'tcx>( // The case where the impl method uses `impl Trait` but the trait method uses // explicit generics err.span_label(impl_span, "expected generic parameter, found `impl Trait`"); - let _: Option<_> = try { + try { // try taking the name from the trait impl // FIXME: this is obviously suboptimal since the name can already be used // as another generic argument @@ -1882,7 +1882,7 @@ fn compare_synthetic_generics<'tcx>( // The case where the trait method uses `impl Trait`, but the impl method uses // explicit generics. err.span_label(impl_span, "expected `impl Trait`, found generic parameter"); - let _: Option<_> = try { + try { let impl_m = impl_m.def_id.as_local()?; let impl_m = tcx.hir_expect_impl_item(impl_m); let (sig, _) = impl_m.expect_fn(); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index f5fb8031ab0f..35f8c44b685d 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -582,7 +582,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P let deps_output = outputs.path(OutputType::DepInfo); let deps_filename = deps_output.as_path(); - let result: io::Result<()> = try { + let result = try { // Build a list of files used to compile the output and // write Makefile-compatible dependency rules let mut files: IndexMap)> = sess diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index f3e6db6f2d8e..47e1fef8b82e 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -746,24 +746,23 @@ fn pat_ty_is_known_nonnull<'tcx>( typing_env: ty::TypingEnv<'tcx>, pat: ty::Pattern<'tcx>, ) -> bool { - Option::unwrap_or_default( - try { - match *pat { - ty::PatternKind::Range { start, end } => { - let start = start.try_to_value()?.try_to_bits(tcx, typing_env)?; - let end = end.try_to_value()?.try_to_bits(tcx, typing_env)?; + try { + match *pat { + ty::PatternKind::Range { start, end } => { + let start = start.try_to_value()?.try_to_bits(tcx, typing_env)?; + let end = end.try_to_value()?.try_to_bits(tcx, typing_env)?; - // This also works for negative numbers, as we just need - // to ensure we aren't wrapping over zero. - start > 0 && end >= start - } - ty::PatternKind::NotNull => true, - ty::PatternKind::Or(patterns) => { - patterns.iter().all(|pat| pat_ty_is_known_nonnull(tcx, typing_env, pat)) - } + // This also works for negative numbers, as we just need + // to ensure we aren't wrapping over zero. + start > 0 && end >= start } - }, - ) + ty::PatternKind::NotNull => true, + ty::PatternKind::Or(patterns) => { + patterns.iter().all(|pat| pat_ty_is_known_nonnull(tcx, typing_env, pat)) + } + } + } + .unwrap_or_default() } /// Given a non-null scalar (or transparent) type `ty`, return the nullable version of that type. diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index ded02595563c..2e6e96b4d8a8 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -157,13 +157,13 @@ impl<'dis, 'de, 'tcx> MirDumper<'dis, 'de, 'tcx> { /// - `foo & nll | bar & typeck` == match if `foo` and `nll` both appear in the name /// or `typeck` and `bar` both appear in the name. pub fn dump_mir(&self, body: &Body<'tcx>) { - let _: io::Result<()> = try { + let _ = try { let mut file = self.create_dump_file("mir", body)?; self.dump_mir_to_writer(body, &mut file)?; }; if self.tcx().sess.opts.unstable_opts.dump_mir_graphviz { - let _: io::Result<()> = try { + let _ = try { let mut file = self.create_dump_file("dot", body)?; write_mir_fn_graphviz(self.tcx(), body, false, &mut file)?; }; diff --git a/compiler/rustc_mir_build/src/builder/custom/mod.rs b/compiler/rustc_mir_build/src/builder/custom/mod.rs index 792ad6d782cf..1005dd30d73f 100644 --- a/compiler/rustc_mir_build/src/builder/custom/mod.rs +++ b/compiler/rustc_mir_build/src/builder/custom/mod.rs @@ -85,7 +85,7 @@ pub(super) fn build_custom_mir<'tcx>( block_map: FxHashMap::default(), }; - let res: PResult<_> = try { + let res = try { pctxt.parse_args(params)?; pctxt.parse_body(expr)?; }; diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 333677521023..19c030a94e5c 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1159,14 +1159,14 @@ impl<'tcx> TypePrivacyVisitor<'tcx> { let typeck_results = self .maybe_typeck_results .unwrap_or_else(|| span_bug!(span, "`hir::Expr` or `hir::Pat` outside of a body")); - let result: ControlFlow<()> = try { + try { self.visit(typeck_results.node_type(id))?; self.visit(typeck_results.node_args(id))?; if let Some(adjustments) = typeck_results.adjustments().get(id) { adjustments.iter().try_for_each(|adjustment| self.visit(adjustment.target))?; } - }; - result.is_break() + } + .is_break() } fn check_def_id(&self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index e3c8bfe4a452..b8f11189a11f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -1023,7 +1023,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { hir::ExprKind::MethodCall(segment, ..) => { if let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) { let generics = tcx.generics_of(def_id); - let insertable: Option<_> = try { + let insertable = try { if generics.has_impl_trait() { None? } @@ -1061,7 +1061,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { // // FIXME: We deal with that one separately for now, // would be good to remove this special case. - let last_segment_using_path_data: Option<_> = try { + let last_segment_using_path_data = try { let generics_def_id = tcx.res_generics_def_id(path.res)?; let generics = tcx.generics_of(generics_def_id); if generics.has_impl_trait() { @@ -1117,19 +1117,18 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { }; let generics = tcx.generics_of(def_id); - let segment: Option<_> = try { - if !segment.infer_args || generics.has_impl_trait() { - do yeet (); - } + let segment = if !segment.infer_args || generics.has_impl_trait() { + None + } else { let span = tcx.hir_span(segment.hir_id); let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi()); - InsertableGenericArgs { + Some(InsertableGenericArgs { insert_span, args, generics_def_id: def_id, def_id, have_turbofish: false, - } + }) }; let parent_def_id = generics.parent.unwrap(); From c30563a6bd7a44b867ea077b4ae5ef79d9e65a9a Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 31 Jan 2026 03:12:45 +0000 Subject: [PATCH 300/978] ci: Pin rustc on the native PowerPC job Recent nightlies have a miscompile on PowerPC hosts. Pin to a known working nightly for now. Link: https://github.com/rust-lang/rust/issues/151807 --- library/compiler-builtins/.github/workflows/main.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/compiler-builtins/.github/workflows/main.yaml b/library/compiler-builtins/.github/workflows/main.yaml index 767566dd4147..6a4c72c5bc47 100644 --- a/library/compiler-builtins/.github/workflows/main.yaml +++ b/library/compiler-builtins/.github/workflows/main.yaml @@ -72,6 +72,8 @@ jobs: os: ubuntu-24.04 - target: powerpc64le-unknown-linux-gnu os: ubuntu-24.04-ppc64le + # FIXME(rust#151807): remove once PPC builds work again. + channel: nightly-2026-01-23 - target: riscv64gc-unknown-linux-gnu os: ubuntu-24.04 - target: s390x-unknown-linux-gnu From 04e6afe20a6b5ea3b1a0e17a25df486c43a66df4 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 26 Jan 2026 14:15:15 +1100 Subject: [PATCH 301/978] Re-export `hashbrown::hash_table` from `rustc_data_structures` --- Cargo.lock | 2 -- compiler/rustc_data_structures/src/lib.rs | 4 ++++ compiler/rustc_data_structures/src/sharded.rs | 4 ++-- compiler/rustc_mir_transform/Cargo.toml | 1 - compiler/rustc_mir_transform/src/gvn.rs | 2 +- compiler/rustc_query_system/Cargo.toml | 5 ----- compiler/rustc_query_system/src/query/plumbing.rs | 5 ++--- 7 files changed, 9 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6be4565374af..b63bb619b64e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4354,7 +4354,6 @@ name = "rustc_mir_transform" version = "0.0.0" dependencies = [ "either", - "hashbrown 0.16.1", "itertools", "rustc_abi", "rustc_arena", @@ -4565,7 +4564,6 @@ dependencies = [ name = "rustc_query_system" version = "0.0.0" dependencies = [ - "hashbrown 0.16.1", "parking_lot", "rustc_abi", "rustc_ast", diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 85877d73519a..4467a2811181 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -49,6 +49,10 @@ pub use std::{assert_matches, debug_assert_matches}; pub use atomic_ref::AtomicRef; pub use ena::{snapshot_vec, undo_log, unify}; +// Re-export `hashbrown::hash_table`, because it's part of our API +// (via `ShardedHashMap`), and because it lets other compiler crates use the +// lower-level `HashTable` API without a tricky `hashbrown` dependency. +pub use hashbrown::hash_table; pub use rustc_index::static_assert_size; // Re-export some data-structure crates which are part of our public API. pub use {either, indexmap, smallvec, thin_vec}; diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs index 5de9413cf15d..e10ccccad5bb 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -3,7 +3,7 @@ use std::hash::{Hash, Hasher}; use std::{iter, mem}; use either::Either; -use hashbrown::hash_table::{Entry, HashTable}; +use hashbrown::hash_table::{self, Entry, HashTable}; use crate::fx::FxHasher; use crate::sync::{CacheAligned, Lock, LockGuard, Mode, is_dyn_thread_safe}; @@ -140,7 +140,7 @@ pub fn shards() -> usize { 1 } -pub type ShardedHashMap = Sharded>; +pub type ShardedHashMap = Sharded>; impl ShardedHashMap { pub fn with_capacity(cap: usize) -> Self { diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml index 22de197d374a..404531eb3c91 100644 --- a/compiler/rustc_mir_transform/Cargo.toml +++ b/compiler/rustc_mir_transform/Cargo.toml @@ -6,7 +6,6 @@ edition = "2024" [dependencies] # tidy-alphabetical-start either = "1" -hashbrown = { version = "0.16.1", default-features = false } itertools = "0.12" rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 820998eed100..e06b3625aa7b 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -88,7 +88,6 @@ use std::borrow::Cow; use std::hash::{Hash, Hasher}; use either::Either; -use hashbrown::hash_table::{Entry, HashTable}; use itertools::Itertools as _; use rustc_abi::{self as abi, BackendRepr, FIRST_VARIANT, FieldIdx, Primitive, Size, VariantIdx}; use rustc_arena::DroplessArena; @@ -99,6 +98,7 @@ use rustc_const_eval::interpret::{ }; use rustc_data_structures::fx::FxHasher; use rustc_data_structures::graph::dominators::Dominators; +use rustc_data_structures::hash_table::{Entry, HashTable}; use rustc_hir::def::DefKind; use rustc_index::bit_set::DenseBitSet; use rustc_index::{IndexVec, newtype_index}; diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index 73ab03576dec..0ad8143c5a4f 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -23,8 +23,3 @@ rustc_thread_pool = { path = "../rustc_thread_pool" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end - -[dependencies.hashbrown] -version = "0.16.1" -default-features = false -features = ["nightly"] # for may_dangle diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 04902d0ab10c..7e34957364e4 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -7,9 +7,8 @@ use std::fmt::Debug; use std::hash::Hash; use std::mem; -use hashbrown::HashTable; -use hashbrown::hash_table::Entry; use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::hash_table::{self, Entry, HashTable}; use rustc_data_structures::sharded::{self, Sharded}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::LockGuard; @@ -35,7 +34,7 @@ fn equivalent_key(k: &K) -> impl Fn(&(K, V)) -> bool + '_ { } pub struct QueryState<'tcx, K> { - active: Sharded)>>, + active: Sharded)>>, } /// Indicates the state of a query for a given key in a query map. From c3eb3fd6df785bc5c9db7d5c5c94357189d43663 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 29 Jan 2026 12:18:52 +0000 Subject: [PATCH 302/978] triagebot: Switch to `check-commits = "uncanonicalized"` There is now the option to check for `#xxxx`-style issue numbers that aren't attached to a specific repo. Enable it here. --- library/compiler-builtins/triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/compiler-builtins/triagebot.toml b/library/compiler-builtins/triagebot.toml index b210a5fb5256..d0cdb497edba 100644 --- a/library/compiler-builtins/triagebot.toml +++ b/library/compiler-builtins/triagebot.toml @@ -10,7 +10,7 @@ exclude_titles = ["Rustc pull update"] # when commits are included in subtrees, as well as warning links in commits. # Documentation at: https://forge.rust-lang.org/triagebot/issue-links.html [issue-links] -check-commits = false +check-commits = "uncanonicalized" # Enable issue transfers within the org # Documentation at: https://forge.rust-lang.org/triagebot/transfer.html From 1ba6684e1611d6e2fa6e3258e7d3b6dc300863cb Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Fri, 30 Jan 2026 20:26:52 -0600 Subject: [PATCH 303/978] hexagon: Make `fma` label local to avoid symbol collision The `fma:` label in dffma.s was being exported as a global symbol causing a "symbol 'fma' is already defined" error when linking with libm's `fma` function. Unfortunately rust-lang/compiler-builtins#682 removed `.global fma` but didn't address the implicit global export of the label itself. --- old.txt 2026-01-30 20:31:37.265844316 -0600 +++ new.txt 2026-01-30 20:31:46.531950264 -0600 @@ -1,4 +1,3 @@ -00000000 t fma 00000000 T __hexagon_fmadf4 00000000 T __hexagon_fmadf5 00000000 T __qdsp_fmadf5 --- .../compiler-builtins/src/hexagon/dffma.s | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/library/compiler-builtins/compiler-builtins/src/hexagon/dffma.s b/library/compiler-builtins/compiler-builtins/src/hexagon/dffma.s index 97d05eb1839e..6cd1f1b79f87 100644 --- a/library/compiler-builtins/compiler-builtins/src/hexagon/dffma.s +++ b/library/compiler-builtins/compiler-builtins/src/hexagon/dffma.s @@ -7,7 +7,7 @@ .p2align 5 __hexagon_fmadf4: __hexagon_fmadf5: -fma: +.Lfma: { p0 = dfclass(r1:0,#2) p0 = dfclass(r3:2,#2) @@ -400,7 +400,7 @@ fma: r3:2 = insert(r11:10,#63,#0) r1 -= asl(r28,#20) } - jump fma + jump .Lfma .Lfma_ab_tiny: r9:8 = combine(##0x00100000,#0) @@ -408,7 +408,7 @@ fma: r1:0 = insert(r9:8,#63,#0) r3:2 = insert(r9:8,#63,#0) } - jump fma + jump .Lfma .Lab_inf: { @@ -531,4 +531,3 @@ fma: r5 = insert(r28,#11,#20) jump .Lfma_abnormal_c_restart } -.size fma,.-fma From 56071505525f87c99fab6c271d80dcb786cfdeda Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Sat, 31 Jan 2026 04:31:55 +0000 Subject: [PATCH 304/978] Prepare for merging from rust-lang/rust This updates the rust-version file to 44e34e1ac6d7e69b40856cf1403d3da145319c30. --- library/compiler-builtins/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/compiler-builtins/rust-version b/library/compiler-builtins/rust-version index 6a2835bc2d9e..209f4226eae7 100644 --- a/library/compiler-builtins/rust-version +++ b/library/compiler-builtins/rust-version @@ -1 +1 @@ -23d01cd2412583491621ab1ca4f1b01e37d11e39 +44e34e1ac6d7e69b40856cf1403d3da145319c30 From 9cdcd0c3fa2ec52547d196101d350c5f2e50ead6 Mon Sep 17 00:00:00 2001 From: ritik chahar Date: Sat, 31 Jan 2026 10:15:19 +0530 Subject: [PATCH 305/978] Document enum types used as values for E0423 --- compiler/rustc_error_codes/src/error_codes/E0423.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/compiler/rustc_error_codes/src/error_codes/E0423.md b/compiler/rustc_error_codes/src/error_codes/E0423.md index a98ada17a469..eb5243b59847 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0423.md +++ b/compiler/rustc_error_codes/src/error_codes/E0423.md @@ -44,3 +44,16 @@ fn h1() -> i32 { // did you mean `a::I`? } ``` + + + +### Enum types used as values + +Enums are types and cannot be used directly as values. + +```compile_fail,E0423 +fn main() { + let x = Option::; + //~^ ERROR expected value, found enum `Option` +} +``` \ No newline at end of file From daaff44cbc25c35fbe59878bef315252fbba8a62 Mon Sep 17 00:00:00 2001 From: ritik chahar Date: Sat, 31 Jan 2026 10:46:58 +0530 Subject: [PATCH 306/978] Fix tidy formatting manually for E0423.md --- compiler/rustc_error_codes/src/error_codes/E0423.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0423.md b/compiler/rustc_error_codes/src/error_codes/E0423.md index eb5243b59847..4af17b1221b9 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0423.md +++ b/compiler/rustc_error_codes/src/error_codes/E0423.md @@ -45,15 +45,13 @@ fn h1() -> i32 { } ``` - - ### Enum types used as values Enums are types and cannot be used directly as values. ```compile_fail,E0423 -fn main() { +fn main(){ let x = Option::; - //~^ ERROR expected value, found enum `Option` + //~^ ERROR expected value,found enum `Option` } -``` \ No newline at end of file +``` From 85ae47f83e0750e82e75229ca8adeace7d0e1239 Mon Sep 17 00:00:00 2001 From: delta17920 Date: Sat, 31 Jan 2026 06:44:24 +0000 Subject: [PATCH 307/978] moved 7 tests to organized locations --- .../issue-2074.rs => closures/local-enums-in-closure-2074.rs} | 0 .../struct-function-same-name-2445-b.rs} | 0 .../issue-2445.rs => resolve/struct-function-same-name-2445.rs} | 0 .../struct-function-same-name-2487-a.rs} | 0 .../issue-2502.rs => resolve/struct-function-same-name-2502.rs} | 0 .../issue-2550.rs => resolve/struct-function-same-name-2550.rs} | 0 .../issue-2463.rs => structs/struct-update-syntax-2463.rs} | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{issues/issue-2074.rs => closures/local-enums-in-closure-2074.rs} (100%) rename tests/ui/{issues/issue-2445-b.rs => resolve/struct-function-same-name-2445-b.rs} (100%) rename tests/ui/{issues/issue-2445.rs => resolve/struct-function-same-name-2445.rs} (100%) rename tests/ui/{issues/issue-2487-a.rs => resolve/struct-function-same-name-2487-a.rs} (100%) rename tests/ui/{issues/issue-2502.rs => resolve/struct-function-same-name-2502.rs} (100%) rename tests/ui/{issues/issue-2550.rs => resolve/struct-function-same-name-2550.rs} (100%) rename tests/ui/{issues/issue-2463.rs => structs/struct-update-syntax-2463.rs} (100%) diff --git a/tests/ui/issues/issue-2074.rs b/tests/ui/closures/local-enums-in-closure-2074.rs similarity index 100% rename from tests/ui/issues/issue-2074.rs rename to tests/ui/closures/local-enums-in-closure-2074.rs diff --git a/tests/ui/issues/issue-2445-b.rs b/tests/ui/resolve/struct-function-same-name-2445-b.rs similarity index 100% rename from tests/ui/issues/issue-2445-b.rs rename to tests/ui/resolve/struct-function-same-name-2445-b.rs diff --git a/tests/ui/issues/issue-2445.rs b/tests/ui/resolve/struct-function-same-name-2445.rs similarity index 100% rename from tests/ui/issues/issue-2445.rs rename to tests/ui/resolve/struct-function-same-name-2445.rs diff --git a/tests/ui/issues/issue-2487-a.rs b/tests/ui/resolve/struct-function-same-name-2487-a.rs similarity index 100% rename from tests/ui/issues/issue-2487-a.rs rename to tests/ui/resolve/struct-function-same-name-2487-a.rs diff --git a/tests/ui/issues/issue-2502.rs b/tests/ui/resolve/struct-function-same-name-2502.rs similarity index 100% rename from tests/ui/issues/issue-2502.rs rename to tests/ui/resolve/struct-function-same-name-2502.rs diff --git a/tests/ui/issues/issue-2550.rs b/tests/ui/resolve/struct-function-same-name-2550.rs similarity index 100% rename from tests/ui/issues/issue-2550.rs rename to tests/ui/resolve/struct-function-same-name-2550.rs diff --git a/tests/ui/issues/issue-2463.rs b/tests/ui/structs/struct-update-syntax-2463.rs similarity index 100% rename from tests/ui/issues/issue-2463.rs rename to tests/ui/structs/struct-update-syntax-2463.rs From a77b9e62ccf1f5fd93c6d899a37d074dd84d3eac Mon Sep 17 00:00:00 2001 From: Ada Alakbarova <58857108+ada4a@users.noreply.github.com> Date: Sat, 31 Jan 2026 07:58:24 +0100 Subject: [PATCH 308/978] Fix tense --- src/doc/rustc-dev-guide/src/offload/internals.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/offload/internals.md b/src/doc/rustc-dev-guide/src/offload/internals.md index 77a4cadbcb98..520c48d95896 100644 --- a/src/doc/rustc-dev-guide/src/offload/internals.md +++ b/src/doc/rustc-dev-guide/src/offload/internals.md @@ -13,4 +13,4 @@ We use a single-source, two-pass compilation approach. First we compile all functions that should be offloaded for the device (e.g nvptx64, amdgcn-amd-amdhsa, intel in the future). Currently we require cumbersome `#cfg(target_os="")` annotations, but we intend to recognize those in the future based on our offload intrinsic. -We then compile the code for the host (e.g. x86-64), where most of the offloading logic happens. On the host side, we generate calls to the openmp offload runtime, to inform it about the layout of the types (a simplified version of the autodiff TypeTrees). We also use the type system to figure out whether kernel arguments have to be moved only to the device (e.g. `&[f32;1024]`), from the device, or both (e.g. `&mut [f64]`). We then launched the kernel, after which we inform the runtime to end this environment and move data back (as far as needed). +We then compile the code for the host (e.g. x86-64), where most of the offloading logic happens. On the host side, we generate calls to the openmp offload runtime, to inform it about the layout of the types (a simplified version of the autodiff TypeTrees). We also use the type system to figure out whether kernel arguments have to be moved only to the device (e.g. `&[f32;1024]`), from the device, or both (e.g. `&mut [f64]`). We then launch the kernel, after which we inform the runtime to end this environment and move data back (as far as needed). From 65f075792bc92bc8027806e3152a8fd396954eab Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 25 Jan 2026 23:22:43 +0300 Subject: [PATCH 309/978] resolve: Use `IdentKey` in `resolve_ident_in_scope_set` --- compiler/rustc_resolve/src/diagnostics.rs | 18 +++-- compiler/rustc_resolve/src/ident.rs | 71 +++++++++++++------ .../rustc_resolve/src/late/diagnostics.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 5 +- 4 files changed, 65 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 6f2d3e79d10a..6884ed1891a3 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -32,7 +32,7 @@ use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::{SourceMap, Spanned}; -use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol, SyntaxContext, kw, sym}; +use rustc_span::{BytePos, Ident, Span, Symbol, SyntaxContext, kw, sym}; use thin_vec::{ThinVec, thin_vec}; use tracing::{debug, instrument}; @@ -41,6 +41,7 @@ use crate::errors::{ ExplicitUnsafeTraits, MacroDefinedLater, MacroRulesNot, MacroSuggMovePosition, MaybeMissingMacroRulesName, }; +use crate::hygiene::Macros20NormalizedSyntaxContext; use crate::imports::{Import, ImportKind}; use crate::late::{DiagMetadata, PatternSource, Rib}; use crate::{ @@ -1163,11 +1164,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { suggestions: &mut Vec, scope_set: ScopeSet<'ra>, ps: &ParentScope<'ra>, - ctxt: SyntaxContext, + sp: Span, filter_fn: &impl Fn(Res) -> bool, ) { - let ctxt = DUMMY_SP.with_ctxt(ctxt); - self.cm().visit_scopes(scope_set, ps, ctxt, None, |this, scope, use_prelude, _| { + let ctxt = Macros20NormalizedSyntaxContext::new(sp.ctxt()); + self.cm().visit_scopes(scope_set, ps, ctxt, sp, None, |this, scope, use_prelude, _| { match scope { Scope::DeriveHelpers(expn_id) => { let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); @@ -1269,8 +1270,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { filter_fn: &impl Fn(Res) -> bool, ) -> Option { let mut suggestions = Vec::new(); - let ctxt = ident.span.ctxt(); - self.add_scope_set_candidates(&mut suggestions, scope_set, parent_scope, ctxt, filter_fn); + self.add_scope_set_candidates( + &mut suggestions, + scope_set, + parent_scope, + ident.span, + filter_fn, + ); // Make sure error reporting is deterministic. suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str())); diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 4fbde60d8679..5c85f721c0b8 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -54,9 +54,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { mut self: CmResolver<'r, 'ra, 'tcx>, scope_set: ScopeSet<'ra>, parent_scope: &ParentScope<'ra>, - // Location of the span is not significant, but pass a `Span` instead of `SyntaxContext` - // to avoid extracting and re-packaging the syntax context unnecessarily. - orig_ctxt: Span, + mut ctxt: Macros20NormalizedSyntaxContext, + orig_ident_span: Span, derive_fallback_lint_id: Option, mut visitor: impl FnMut( CmResolver<'_, 'ra, 'tcx>, @@ -128,7 +127,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { TypeNS | ValueNS => Scope::ModuleNonGlobs(module, None), MacroNS => Scope::DeriveHelpers(parent_scope.expansion), }; - let mut ctxt = Macros20NormalizedSyntaxContext::new(orig_ctxt.ctxt()); let mut use_prelude = !module.no_implicit_prelude; loop { @@ -153,7 +151,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { true } Scope::ModuleNonGlobs(..) | Scope::ModuleGlobs(..) => true, - Scope::MacroUsePrelude => use_prelude || orig_ctxt.edition().is_rust_2015(), + Scope::MacroUsePrelude => use_prelude || orig_ident_span.is_rust_2015(), Scope::BuiltinAttrs => true, Scope::ExternPreludeItems | Scope::ExternPreludeFlags => { use_prelude || module_and_extern_prelude || extern_prelude @@ -396,9 +394,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { finalize: Option, ignore_decl: Option>, ignore_import: Option>, + ) -> Result, Determinacy> { + self.resolve_ident_in_scope_set_inner( + IdentKey::new(orig_ident), + orig_ident.span, + scope_set, + parent_scope, + finalize, + ignore_decl, + ignore_import, + ) + } + + fn resolve_ident_in_scope_set_inner<'r>( + self: CmResolver<'r, 'ra, 'tcx>, + ident: IdentKey, + orig_ident_span: Span, + scope_set: ScopeSet<'ra>, + parent_scope: &ParentScope<'ra>, + finalize: Option, + ignore_decl: Option>, + ignore_import: Option>, ) -> Result, Determinacy> { // Make sure `self`, `super` etc produce an error when passed to here. - if !matches!(scope_set, ScopeSet::Module(..)) && orig_ident.is_path_segment_keyword() { + if !matches!(scope_set, ScopeSet::Module(..)) && ident.name.is_path_segment_keyword() { return Err(Determinacy::Determined); } @@ -432,13 +451,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let break_result = self.visit_scopes( scope_set, parent_scope, - orig_ident.span, + ident.ctxt, + orig_ident_span, derive_fallback_lint_id, |mut this, scope, use_prelude, ctxt| { - let ident = IdentKey { name: orig_ident.name, ctxt }; + let ident = IdentKey { name: ident.name, ctxt }; let res = match this.reborrow().resolve_ident_in_scope( ident, - orig_ident.span, + orig_ident_span, ns, scope, use_prelude, @@ -472,7 +492,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if let Some(&(innermost_decl, _)) = innermost_results.first() { // Found another solution, if the first one was "weak", report an error. if this.get_mut().maybe_push_ambiguity( - orig_ident, + ident, + orig_ident_span, ns, scope_set, parent_scope, @@ -695,8 +716,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Scope::StdLibPrelude => { let mut result = Err(Determinacy::Determined); if let Some(prelude) = self.prelude - && let Ok(decl) = self.reborrow().resolve_ident_in_scope_set( - ident.orig(orig_ident_span.with_ctxt(*ident.ctxt)), + && let Ok(decl) = self.reborrow().resolve_ident_in_scope_set_inner( + ident, + orig_ident_span, ScopeSet::Module(ns, prelude), parent_scope, None, @@ -749,7 +771,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn maybe_push_ambiguity( &mut self, - orig_ident: Ident, + ident: IdentKey, + orig_ident_span: Span, ns: Namespace, scope_set: ScopeSet<'ra>, parent_scope: &ParentScope<'ra>, @@ -775,7 +798,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } else if innermost_res == derive_helper_compat { Some(AmbiguityKind::DeriveHelper) } else if res == derive_helper_compat && innermost_res != derive_helper { - span_bug!(orig_ident.span, "impossible inner resolution kind") + span_bug!(orig_ident_span, "impossible inner resolution kind") } else if matches!(innermost_scope, Scope::MacroRules(_)) && matches!(scope, Scope::ModuleNonGlobs(..) | Scope::ModuleGlobs(..)) && !self.disambiguate_macro_rules_vs_modularized(innermost_decl, decl) @@ -790,7 +813,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // we visit all macro_rules scopes (e.g. textual scope macros) // before we visit any modules (e.g. path-based scope macros) span_bug!( - orig_ident.span, + orig_ident_span, "ambiguous scoped macro resolutions with path-based \ scope resolution as first candidate" ) @@ -839,8 +862,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } else { // Turn ambiguity errors for core vs std panic into warnings. // FIXME: Remove with lang team approval. - let is_issue_147319_hack = orig_ident.span.edition() <= Edition::Edition2024 - && matches!(orig_ident.name, sym::panic) + let is_issue_147319_hack = orig_ident_span.edition() <= Edition::Edition2024 + && matches!(ident.name, sym::panic) && matches!(scope, Scope::StdLibPrelude) && matches!(innermost_scope, Scope::ModuleGlobs(_, _)) && ((self.is_specific_builtin_macro(res, sym::std_panic) @@ -852,7 +875,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.ambiguity_errors.push(AmbiguityError { kind, - ident: orig_ident, + ident: ident.orig(orig_ident_span), b1: innermost_decl, b2: decl, scope1: innermost_scope, @@ -1145,8 +1168,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None => return Err(ControlFlow::Continue(Undetermined)), }; let tmp_parent_scope; - let (mut adjusted_parent_scope, mut ctxt) = (parent_scope, *ident.ctxt); - match ctxt.glob_adjust(module.expansion, glob_import.span) { + let (mut adjusted_parent_scope, mut adjusted_ident) = (parent_scope, ident); + match adjusted_ident + .ctxt + .update_unchecked(|ctxt| ctxt.glob_adjust(module.expansion, glob_import.span)) + { Some(Some(def)) => { tmp_parent_scope = ParentScope { module: self.expn_def_scope(def), ..*parent_scope }; @@ -1155,8 +1181,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Some(None) => {} None => continue, }; - let result = self.reborrow().resolve_ident_in_scope_set( - ident.orig(orig_ident_span.with_ctxt(ctxt)), + let result = self.reborrow().resolve_ident_in_scope_set_inner( + adjusted_ident, + orig_ident_span, ScopeSet::Module(ns, module), adjusted_parent_scope, None, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a3ee17ec4a9a..8794c4ff8b02 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2677,7 +2677,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &mut names, ScopeSet::All(ns), parent_scope, - ctxt, + segment.ident.span.with_ctxt(ctxt), filter_fn, ); break; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 5fe1be039a88..dd5ac55d30d8 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1923,7 +1923,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &mut self, current_trait: Option>, parent_scope: &ParentScope<'ra>, - ctxt: Span, + sp: Span, assoc_item: Option<(Symbol, Namespace)>, ) -> Vec { let mut found_traits = Vec::new(); @@ -1940,7 +1940,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } let scope_set = ScopeSet::All(TypeNS); - self.cm().visit_scopes(scope_set, parent_scope, ctxt, None, |mut this, scope, _, _| { + let ctxt = Macros20NormalizedSyntaxContext::new(sp.ctxt()); + self.cm().visit_scopes(scope_set, parent_scope, ctxt, sp, None, |mut this, scope, _, _| { match scope { Scope::ModuleNonGlobs(module, _) => { this.get_mut().traits_in_module(module, assoc_item, &mut found_traits); From 726a0a68b1d9867f1beed0168bd2a9a87aad4e81 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 30 Jan 2026 16:36:42 +0300 Subject: [PATCH 310/978] resolve: Inline `resolve_ident_in_virt_module_unadjusted` into `resolve_ident_in_module` --- compiler/rustc_resolve/src/ident.rs | 56 +++++++---------------------- 1 file changed, 13 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 5c85f721c0b8..5b3fd805ebb8 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -912,55 +912,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ignore_decl: Option>, ignore_import: Option>, ) -> Result, Determinacy> { - let tmp_parent_scope; - let mut adjusted_parent_scope = parent_scope; match module { - ModuleOrUniformRoot::Module(m) => { - if let Some(def) = ident.span.normalize_to_macros_2_0_and_adjust(m.expansion) { + ModuleOrUniformRoot::Module(module) => { + let tmp_parent_scope; + let mut adjusted_parent_scope = parent_scope; + if let Some(def) = ident.span.normalize_to_macros_2_0_and_adjust(module.expansion) { tmp_parent_scope = ParentScope { module: self.expn_def_scope(def), ..*parent_scope }; adjusted_parent_scope = &tmp_parent_scope; } + self.resolve_ident_in_scope_set( + ident, + ScopeSet::Module(ns, module), + &adjusted_parent_scope, + finalize, + ignore_decl, + ignore_import, + ) } - ModuleOrUniformRoot::ExternPrelude => { - ident.span.normalize_to_macros_2_0_and_adjust(ExpnId::root()); - } - ModuleOrUniformRoot::ModuleAndExternPrelude(..) | ModuleOrUniformRoot::CurrentScope => { - // No adjustments - } - } - self.resolve_ident_in_virt_module_unadjusted( - module, - ident, - ns, - adjusted_parent_scope, - finalize, - ignore_decl, - ignore_import, - ) - } - - /// Attempts to resolve `ident` in namespace `ns` of `module`. - #[instrument(level = "debug", skip(self))] - fn resolve_ident_in_virt_module_unadjusted<'r>( - self: CmResolver<'r, 'ra, 'tcx>, - module: ModuleOrUniformRoot<'ra>, - ident: Ident, - ns: Namespace, - parent_scope: &ParentScope<'ra>, - finalize: Option, - ignore_decl: Option>, - ignore_import: Option>, - ) -> Result, Determinacy> { - match module { - ModuleOrUniformRoot::Module(module) => self.resolve_ident_in_scope_set( - ident, - ScopeSet::Module(ns, module), - parent_scope, - finalize, - ignore_decl, - ignore_import, - ), ModuleOrUniformRoot::ModuleAndExternPrelude(module) => self.resolve_ident_in_scope_set( ident, ScopeSet::ModuleAndExternPrelude(ns, module), @@ -973,6 +942,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if ns != TypeNS { Err(Determined) } else { + ident.span.normalize_to_macros_2_0_and_adjust(ExpnId::root()); self.resolve_ident_in_scope_set( ident, ScopeSet::ExternPrelude, From 161fcdeac00c9bc8b284bd62eef207dd5698cc05 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 30 Jan 2026 17:05:57 +0300 Subject: [PATCH 311/978] resolve: Avoid double normalization in `resolve_ident_in_module` --- compiler/rustc_resolve/src/ident.rs | 25 ++++++++++++------------- compiler/rustc_resolve/src/lib.rs | 17 ++++++++++++++++- compiler/rustc_span/src/hygiene.rs | 2 +- 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 5b3fd805ebb8..0e73c349c8cd 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -905,7 +905,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn resolve_ident_in_module<'r>( self: CmResolver<'r, 'ra, 'tcx>, module: ModuleOrUniformRoot<'ra>, - mut ident: Ident, + ident: Ident, ns: Namespace, parent_scope: &ParentScope<'ra>, finalize: Option, @@ -914,15 +914,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) -> Result, Determinacy> { match module { ModuleOrUniformRoot::Module(module) => { - let tmp_parent_scope; - let mut adjusted_parent_scope = parent_scope; - if let Some(def) = ident.span.normalize_to_macros_2_0_and_adjust(module.expansion) { - tmp_parent_scope = - ParentScope { module: self.expn_def_scope(def), ..*parent_scope }; - adjusted_parent_scope = &tmp_parent_scope; - } - self.resolve_ident_in_scope_set( - ident, + let (ident_key, def) = IdentKey::new_adjusted(ident, module.expansion); + let adjusted_parent_scope = match def { + Some(def) => ParentScope { module: self.expn_def_scope(def), ..*parent_scope }, + None => *parent_scope, + }; + self.resolve_ident_in_scope_set_inner( + ident_key, + ident.span, ScopeSet::Module(ns, module), &adjusted_parent_scope, finalize, @@ -942,9 +941,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if ns != TypeNS { Err(Determined) } else { - ident.span.normalize_to_macros_2_0_and_adjust(ExpnId::root()); - self.resolve_ident_in_scope_set( - ident, + self.resolve_ident_in_scope_set_inner( + IdentKey::new_adjusted(ident, ExpnId::root()).0, + ident.span, ScopeSet::ExternPrelude, parent_scope, finalize, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index dd5ac55d30d8..75bd2c62f9b4 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -575,6 +575,12 @@ impl IdentKey { IdentKey { name: ident.name, ctxt: Macros20NormalizedSyntaxContext::new(ident.span.ctxt()) } } + #[inline] + fn new_adjusted(ident: Ident, expn_id: ExpnId) -> (IdentKey, Option) { + let (ctxt, def) = Macros20NormalizedSyntaxContext::new_adjusted(ident.span.ctxt(), expn_id); + (IdentKey { name: ident.name, ctxt }, def) + } + #[inline] fn with_root_ctxt(name: Symbol) -> Self { let ctxt = Macros20NormalizedSyntaxContext::new_unchecked(SyntaxContext::root()); @@ -2724,7 +2730,7 @@ mod ref_mut { } mod hygiene { - use rustc_span::SyntaxContext; + use rustc_span::{ExpnId, SyntaxContext}; /// A newtype around `SyntaxContext` that can only keep contexts produced by /// [SyntaxContext::normalize_to_macros_2_0]. @@ -2737,6 +2743,15 @@ mod hygiene { Macros20NormalizedSyntaxContext(ctxt.normalize_to_macros_2_0()) } + #[inline] + pub(crate) fn new_adjusted( + mut ctxt: SyntaxContext, + expn_id: ExpnId, + ) -> (Macros20NormalizedSyntaxContext, Option) { + let def = ctxt.normalize_to_macros_2_0_and_adjust(expn_id); + (Macros20NormalizedSyntaxContext(ctxt), def) + } + #[inline] pub(crate) fn new_unchecked(ctxt: SyntaxContext) -> Macros20NormalizedSyntaxContext { debug_assert_eq!(ctxt, ctxt.normalize_to_macros_2_0()); diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 2e8037b3f9e4..05f4c8e268a9 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -804,7 +804,7 @@ impl SyntaxContext { /// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0. #[inline] - pub(crate) fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option { + pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option { HygieneData::with(|data| { *self = data.normalize_to_macros_2_0(*self); data.adjust(self, expn_id) From 54f88be3cd4b8e7a3f4cae9ad495d047bfb51d33 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 31 Jan 2026 07:07:53 +0000 Subject: [PATCH 312/978] Revert "Enable `outline-atomics` by default on AArch64 FreeBSD" This reverts commit 383053e01602a1a754a170d7c201cc43fff87739. --- .../rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs index 47775f968400..69a65e6b0f02 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target { data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: Arch::AArch64, options: TargetOptions { - features: "+v8a,+outline-atomics".into(), + features: "+v8a".into(), max_atomic_width: Some(128), stack_probes: StackProbeType::Inline, supported_sanitizers: SanitizerSet::ADDRESS From 63e16520a245d69dae38428aede40303dfc0e410 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 31 Jan 2026 07:07:59 +0000 Subject: [PATCH 313/978] Revert "Enable `outline-atomics` by default on AArch64 OpenBSD" This reverts commit 66c150c1fa29d15e1c5c06dfe708c8443faf42c3. --- .../rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs index 14a2f007f1e8..e5e40cb38b91 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs @@ -13,7 +13,7 @@ pub(crate) fn target() -> Target { data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: Arch::AArch64, options: TargetOptions { - features: "+v8a,+outline-atomics".into(), + features: "+v8a".into(), max_atomic_width: Some(128), stack_probes: StackProbeType::Inline, ..base::openbsd::opts() From a9da102e20153c03e963c3cdf5160cde7c7d81af Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 31 Jan 2026 07:08:05 +0000 Subject: [PATCH 314/978] Revert "Enable `outline-atomics` by default on AArch64 Fuchsia" This reverts commit 21525f862d621bbeb9a131f3631111c402e1a447. --- .../rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs index 8a07f98075a8..6489e2bda809 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs @@ -5,7 +5,7 @@ use crate::spec::{ pub(crate) fn target() -> Target { let mut base = base::fuchsia::opts(); base.cpu = "generic".into(); - base.features = "+v8a,+crc,+aes,+sha2,+neon,+outline-atomics".into(); + base.features = "+v8a,+crc,+aes,+sha2,+neon".into(); base.max_atomic_width = Some(128); base.stack_probes = StackProbeType::Inline; base.supported_sanitizers = SanitizerSet::ADDRESS From 1173034b7bd007d68931cf58cb656deec8af994d Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 31 Jan 2026 07:08:11 +0000 Subject: [PATCH 315/978] Revert "Enable `outline-atomics` by default on AArch64 Android" This reverts commit c45590397843909a1f36d4fd9d89cfc1e7551652. --- compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs index d1810b6fa486..3b158c13521e 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs @@ -21,7 +21,7 @@ pub(crate) fn target() -> Target { max_atomic_width: Some(128), // As documented in https://developer.android.com/ndk/guides/cpu-features.html // the neon (ASIMD) and FP must exist on all android aarch64 targets. - features: "+v8a,+neon,+outline-atomics".into(), + features: "+v8a,+neon".into(), // the AAPCS64 expects use of non-leaf frame pointers per // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not From 9fb68d60efc842614a5ce63eb4d8ecfa6f7deee3 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 31 Jan 2026 07:08:17 +0000 Subject: [PATCH 316/978] Revert "Enable `outline-atomics` by default on AArch64 Windows platforms" This reverts commit 1ed1b6e2674e0884479042ae1b6aac431f1c217c. --- .../rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs | 2 +- .../rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs index db3cf83ddc99..ce17280b153d 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs @@ -3,7 +3,7 @@ use crate::spec::{Arch, Cc, FramePointer, LinkerFlavor, Lld, Target, TargetMetad pub(crate) fn target() -> Target { let mut base = base::windows_gnullvm::opts(); base.max_atomic_width = Some(128); - base.features = "+v8a,+neon,+outline-atomics".into(); + base.features = "+v8a,+neon".into(); base.linker = Some("aarch64-w64-mingw32-clang".into()); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &["-m", "arm64pe"]); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs index e9f7f51a7a35..0d06bec21f4a 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs @@ -3,7 +3,7 @@ use crate::spec::{Arch, FramePointer, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.max_atomic_width = Some(128); - base.features = "+v8a,+neon,+outline-atomics".into(); + base.features = "+v8a,+neon".into(); // Microsoft recommends enabling frame pointers on Arm64 Windows. // From https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#integer-registers From 996425b295bdc783725f42df6ad25311886a1bc8 Mon Sep 17 00:00:00 2001 From: Frank King Date: Fri, 30 Jan 2026 11:06:27 +0800 Subject: [PATCH 317/978] refactor: add an `enum DerefAdjustKind` in favor of `Option` --- compiler/rustc_hir_typeck/src/autoderef.rs | 22 ++++++++++--------- compiler/rustc_hir_typeck/src/coercion.rs | 9 ++++---- .../rustc_hir_typeck/src/expr_use_visitor.rs | 9 ++++---- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 8 ++++--- compiler/rustc_hir_typeck/src/place_op.rs | 7 +++--- compiler/rustc_lint/src/autorefs.rs | 10 ++++++--- compiler/rustc_lint/src/noop_method_call.rs | 7 ++++-- compiler/rustc_middle/src/ty/adjustment.rs | 8 ++++++- compiler/rustc_mir_build/src/thir/cx/expr.rs | 6 ++--- .../error_reporting/infer/need_type_info.rs | 4 ++-- .../clippy/clippy_lints/src/eta_reduction.rs | 4 ++-- .../clippy/clippy_lints/src/format_args.rs | 6 ++--- .../src/loops/while_let_on_iterator.rs | 4 ++-- .../clippy_lints/src/methods/map_clone.rs | 4 ++-- .../src/methods/option_as_ref_deref.rs | 2 +- .../src/methods/swap_with_temporary.rs | 4 ++-- .../src/methods/type_id_on_box.rs | 4 ++-- .../src/methods/unnecessary_to_owned.rs | 10 ++++----- .../clippy_lints/src/methods/useless_asref.rs | 4 ++-- .../clippy/clippy_lints/src/non_copy_const.rs | 4 ++-- .../clippy/clippy_utils/src/eager_or_lazy.rs | 11 +++------- src/tools/clippy/clippy_utils/src/lib.rs | 10 +++++---- src/tools/clippy/clippy_utils/src/ty/mod.rs | 5 +++-- 23 files changed, 90 insertions(+), 72 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index 4fe77278706e..f7700179d2a3 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -6,7 +6,7 @@ use itertools::Itertools; use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind}; use rustc_infer::infer::InferOk; use rustc_infer::traits::PredicateObligations; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind, OverloadedDeref}; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; @@ -45,22 +45,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty())); let steps: Vec<_> = steps .iter() - .map(|&(source, kind)| { - if let AutoderefKind::Overloaded = kind { - self.try_overloaded_deref(autoderef.span(), source).and_then( - |InferOk { value: method, obligations: o }| { + .map(|&(source, kind)| match kind { + AutoderefKind::Overloaded => { + self.try_overloaded_deref(autoderef.span(), source) + .and_then(|InferOk { value: method, obligations: o }| { obligations.extend(o); // FIXME: we should assert the sig is &T here... there's no reason for this to be fallible. if let ty::Ref(_, _, mutbl) = *method.sig.output().kind() { - Some(OverloadedDeref { mutbl, span: autoderef.span() }) + Some(DerefAdjustKind::Overloaded(OverloadedDeref { + mutbl, + span: autoderef.span(), + })) } else { None } - }, - ) - } else { - None + }) + .unwrap_or(DerefAdjustKind::Builtin) } + AutoderefKind::Builtin => DerefAdjustKind::Builtin, }) .zip_eq(targets) .map(|(autoderef, target)| Adjustment { kind: Adjust::Deref(autoderef), target }) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 0e87b90dc6c1..36a07b361d9d 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -50,7 +50,8 @@ use rustc_infer::traits::{ }; use rustc_middle::span_bug; use rustc_middle::ty::adjustment::{ - Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion, + Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, DerefAdjustKind, + PointerCoercion, }; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; @@ -595,7 +596,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let mutbl = AutoBorrowMutability::new(mutbl_b, AllowTwoPhase::No); Some(( - Adjustment { kind: Adjust::Deref(None), target: ty_a }, + Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: ty_a }, Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)), target: Ty::new_ref(self.tcx, r_borrow, ty_a, mutbl_b), @@ -606,7 +607,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { coerce_mutbls(mt_a, mt_b)?; Some(( - Adjustment { kind: Adjust::Deref(None), target: ty_a }, + Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: ty_a }, Adjustment { kind: Adjust::Borrow(AutoBorrow::RawPtr(mt_b)), target: Ty::new_ptr(self.tcx, ty_a, mt_b), @@ -936,7 +937,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.unify_and( a_raw, b, - [Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }], + [Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: mt_a.ty }], Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)), ForceLeakCheck::No, ) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index ad34994526ed..171184d3a562 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -22,6 +22,7 @@ use rustc_middle::hir::place::ProjectionKind; pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection}; use rustc_middle::mir::FakeReadCause; use rustc_middle::thir::DerefPatBorrowMode; +use rustc_middle::ty::adjustment::DerefAdjustKind; use rustc_middle::ty::{ self, BorrowKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment, }; @@ -733,14 +734,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx self.consume_or_copy(&place_with_id, place_with_id.hir_id); } - adjustment::Adjust::Deref(None) => {} + adjustment::Adjust::Deref(DerefAdjustKind::Builtin) => {} // Autoderefs for overloaded Deref calls in fact reference // their receiver. That is, if we have `(*x)` where `x` // is of type `Rc`, then this in fact is equivalent to // `x.deref()`. Since `deref()` is declared with `&self`, // this is an autoref of `x`. - adjustment::Adjust::Deref(Some(ref deref)) => { + adjustment::Adjust::Deref(DerefAdjustKind::Overloaded(deref)) => { let bk = ty::BorrowKind::from_mutbl(deref.mutbl); self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk); } @@ -1272,9 +1273,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx { let target = self.cx.resolve_vars_if_possible(adjustment.target); match adjustment.kind { - adjustment::Adjust::Deref(overloaded) => { + adjustment::Adjust::Deref(deref_kind) => { // Equivalent to *expr or something similar. - let base = if let Some(deref) = overloaded { + let base = if let DerefAdjustKind::Overloaded(deref) = deref_kind { let ref_ty = Ty::new_ref( self.cx.tcx(), self.cx.tcx().lifetimes.re_erased, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 91f91d911444..67007523a067 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -20,7 +20,9 @@ use rustc_hir_analysis::hir_ty_lowering::{ use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::{DefineOpaqueTypes, InferResult}; use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; +use rustc_middle::ty::adjustment::{ + Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, DerefAdjustKind, +}; use rustc_middle::ty::{ self, AdtKind, CanonicalUserType, GenericArgsRef, GenericParamDefKind, IsIdentity, SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs, @@ -266,7 +268,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target); } } - Adjust::Deref(Some(overloaded_deref)) => { + Adjust::Deref(DerefAdjustKind::Overloaded(overloaded_deref)) => { self.enforce_context_effects( None, expr.span, @@ -274,7 +276,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.mk_args(&[expr_ty.into()]), ); } - Adjust::Deref(None) => { + Adjust::Deref(DerefAdjustKind::Builtin) => { // FIXME(const_trait_impl): We *could* enforce `&T: [const] Deref` here. } Adjust::Pointer(_pointer_coercion) => { diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index a48db2cc855c..c33f8bdaffe2 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -4,8 +4,8 @@ use rustc_infer::infer::InferOk; use rustc_infer::traits::{Obligation, ObligationCauseCode}; use rustc_middle::span_bug; use rustc_middle::ty::adjustment::{ - Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, OverloadedDeref, - PointerCoercion, + Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, DerefAdjustKind, + OverloadedDeref, PointerCoercion, }; use rustc_middle::ty::{self, Ty}; use rustc_span::{Span, sym}; @@ -298,7 +298,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow_mut().adjustments_mut().remove(expr.hir_id); if let Some(mut adjustments) = previous_adjustments { for adjustment in &mut adjustments { - if let Adjust::Deref(Some(ref mut deref)) = adjustment.kind + if let Adjust::Deref(DerefAdjustKind::Overloaded(ref mut deref)) = + adjustment.kind && let Some(ok) = self.try_mutable_overloaded_place_op( expr.span, source, diff --git a/compiler/rustc_lint/src/autorefs.rs b/compiler/rustc_lint/src/autorefs.rs index ed7ac0e33244..5bb7df80ffb3 100644 --- a/compiler/rustc_lint/src/autorefs.rs +++ b/compiler/rustc_lint/src/autorefs.rs @@ -1,7 +1,9 @@ use rustc_ast::{BorrowKind, UnOp}; use rustc_hir::attrs::AttributeKind; use rustc_hir::{Expr, ExprKind, Mutability, find_attr}; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, OverloadedDeref}; +use rustc_middle::ty::adjustment::{ + Adjust, Adjustment, AutoBorrow, DerefAdjustKind, OverloadedDeref, +}; use rustc_session::{declare_lint, declare_lint_pass}; use crate::lints::{ @@ -165,12 +167,14 @@ fn peel_derefs_adjustments<'a>(mut adjs: &'a [Adjustment<'a>]) -> &'a [Adjustmen /// an implicit borrow (or has an implicit borrow via an overloaded deref). fn has_implicit_borrow(Adjustment { kind, .. }: &Adjustment<'_>) -> Option<(Mutability, bool)> { match kind { - &Adjust::Deref(Some(OverloadedDeref { mutbl, .. })) => Some((mutbl, true)), + &Adjust::Deref(DerefAdjustKind::Overloaded(OverloadedDeref { mutbl, .. })) => { + Some((mutbl, true)) + } &Adjust::Borrow(AutoBorrow::Ref(mutbl)) => Some((mutbl.into(), false)), Adjust::NeverToAny | Adjust::Pointer(..) | Adjust::ReborrowPin(..) - | Adjust::Deref(None) + | Adjust::Deref(DerefAdjustKind::Builtin) | Adjust::Borrow(AutoBorrow::RawPtr(..)) => None, } } diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 24682c4562a0..66b4e3c16e93 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -1,7 +1,7 @@ use rustc_hir::def::DefKind; use rustc_hir::{Expr, ExprKind}; use rustc_middle::ty; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; @@ -114,7 +114,10 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { // If there is any user defined auto-deref step, then we don't want to warn. // https://github.com/rust-lang/rust-clippy/issues/9272 - if arg_adjustments.iter().any(|adj| matches!(adj.kind, Adjust::Deref(Some(_)))) { + if arg_adjustments + .iter() + .any(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Overloaded(_)))) + { return; } diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index c806366b518a..6d546aede4cf 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -97,7 +97,7 @@ pub enum Adjust { NeverToAny, /// Dereference once, producing a place. - Deref(Option), + Deref(DerefAdjustKind), /// Take the address and produce either a `&` or `*` pointer. Borrow(AutoBorrow), @@ -108,6 +108,12 @@ pub enum Adjust { ReborrowPin(hir::Mutability), } +#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] +pub enum DerefAdjustKind { + Builtin, + Overloaded(OverloadedDeref), +} + /// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)` /// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`. /// The target type is `U` in both cases, with the region and mutability diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 8e02424706ee..0117a10e3a8c 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -14,7 +14,7 @@ use rustc_middle::middle::region; use rustc_middle::mir::{self, AssignOp, BinOp, BorrowKind, UnOp}; use rustc_middle::thir::*; use rustc_middle::ty::adjustment::{ - Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCoercion, + Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, DerefAdjustKind, PointerCoercion, }; use rustc_middle::ty::{ self, AdtKind, GenericArgs, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs, @@ -140,11 +140,11 @@ impl<'tcx> ThirBuildCx<'tcx> { } Adjust::NeverToAny if adjustment.target.is_never() => return expr, Adjust::NeverToAny => ExprKind::NeverToAny { source: self.thir.exprs.push(expr) }, - Adjust::Deref(None) => { + Adjust::Deref(DerefAdjustKind::Builtin) => { adjust_span(&mut expr); ExprKind::Deref { arg: self.thir.exprs.push(expr) } } - Adjust::Deref(Some(deref)) => { + Adjust::Deref(DerefAdjustKind::Overloaded(deref)) => { // We don't need to do call adjust_span here since // deref coercions always start with a built-in deref. let call_def_id = deref.method_call(self.tcx); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index e3c8bfe4a452..ca846bca874e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -12,7 +12,7 @@ use rustc_hir::{ }; use rustc_middle::bug; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, DerefAdjustKind}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer}; use rustc_middle::ty::{ self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Term, TermKind, @@ -615,7 +615,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // first adjustment was not a builtin deref. let adjustment = match typeck_results.expr_adjustments(receiver) { [ - Adjustment { kind: Adjust::Deref(None), target: _ }, + Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: _ }, .., Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), target: _ }, ] => "", diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index 21385ee4fdc7..3e46c370fb70 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -10,7 +10,7 @@ use rustc_hir::attrs::AttributeKind; use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, GenericArgs, Param, PatKind, QPath, Safety, TyKind, find_attr}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_middle::ty::{ self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, Ty, TypeVisitableExt, TypeckResults, }; @@ -236,7 +236,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx .iter() .rev() .fold(0, |acc, adjustment| match adjustment.kind { - Adjust::Deref(Some(_)) => acc + 1, + Adjust::Deref(DerefAdjustKind::Overloaded(_)) => acc + 1, Adjust::Deref(_) if acc > 0 => acc + 1, _ => acc, }) diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs index 011cbf8c5d41..5fb1a0b80f1a 100644 --- a/src/tools/clippy/clippy_lints/src/format_args.rs +++ b/src/tools/clippy/clippy_lints/src/format_args.rs @@ -24,7 +24,7 @@ use rustc_errors::SuggestionStyle::{CompletelyHidden, ShowCode}; use rustc_hir::attrs::AttributeKind; use rustc_hir::{Expr, ExprKind, LangItem, RustcVersion, find_attr}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::{self, GenericArg, List, TraitRef, Ty, TyCtxt, Upcast}; use rustc_session::impl_lint_pass; use rustc_span::edition::Edition::Edition2021; @@ -704,12 +704,12 @@ where let mut n_needed = 0; loop { if let Some(Adjustment { - kind: Adjust::Deref(overloaded_deref), + kind: Adjust::Deref(deref), target, }) = iter.next() { n_total += 1; - if overloaded_deref.is_some() { + if let DerefAdjustKind::Overloaded(..) = deref { n_needed = n_total; } ty = *target; diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs index 6c95c7b54c50..fc0789894cc2 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs @@ -12,7 +12,7 @@ use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{Closure, Expr, ExprKind, HirId, LetStmt, Mutability, UnOp}; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter::OnlyBodies; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_span::Symbol; use rustc_span::symbol::sym; @@ -88,7 +88,7 @@ fn try_parse_iter_expr(cx: &LateContext<'_>, mut e: &Expr<'_>) -> Option, e: &hir::Expr<'_>, recv: &hir::Expr<'_ && cx.tcx.lang_items().clone_trait() == Some(trait_id) // no autoderefs && !cx.typeck_results().expr_adjustments(obj).iter() - .any(|a| matches!(a.kind, Adjust::Deref(Some(..)))) + .any(|a| matches!(a.kind, Adjust::Deref(DerefAdjustKind::Overloaded(..)))) { let obj_ty = cx.typeck_results().expr_ty(obj); if let ty::Ref(_, ty, mutability) = obj_ty.kind() { diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs index 3d489075ce8a..1239d8927acf 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs @@ -58,7 +58,7 @@ pub(super) fn check( .iter() .map(|x| &x.kind) .collect::>() - && let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj + && let [ty::adjustment::Adjust::Deref(ty::adjustment::DerefAdjustKind::Builtin), ty::adjustment::Adjust::Borrow(_)] = *adj && let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap() && let Some(method_name) = cx.tcx.get_diagnostic_name(method_did) { diff --git a/src/tools/clippy/clippy_lints/src/methods/swap_with_temporary.rs b/src/tools/clippy/clippy_lints/src/methods/swap_with_temporary.rs index e378cbd6ae0a..0b8f6ae9f277 100644 --- a/src/tools/clippy/clippy_lints/src/methods/swap_with_temporary.rs +++ b/src/tools/clippy/clippy_lints/src/methods/swap_with_temporary.rs @@ -4,7 +4,7 @@ use rustc_ast::BorrowKind; use rustc_errors::{Applicability, Diag}; use rustc_hir::{Expr, ExprKind, Node, QPath}; use rustc_lint::LateContext; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_span::sym; use super::SWAP_WITH_TEMPORARY; @@ -47,7 +47,7 @@ impl<'tcx> ArgKind<'tcx> { && let adjustments = cx.typeck_results().expr_adjustments(arg) && adjustments .first() - .is_some_and(|adj| matches!(adj.kind, Adjust::Deref(None))) + .is_some_and(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Builtin))) && adjustments .last() .is_some_and(|adj| matches!(adj.kind, Adjust::Borrow(_))) diff --git a/src/tools/clippy/clippy_lints/src/methods/type_id_on_box.rs b/src/tools/clippy/clippy_lints/src/methods/type_id_on_box.rs index e67ba5c4d314..98f319be7a45 100644 --- a/src/tools/clippy/clippy_lints/src/methods/type_id_on_box.rs +++ b/src/tools/clippy/clippy_lints/src/methods/type_id_on_box.rs @@ -4,7 +4,7 @@ use clippy_utils::source::snippet; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::{self, ExistentialPredicate, Ty}; use rustc_span::{Span, sym}; @@ -58,7 +58,7 @@ pub(super) fn check(cx: &LateContext<'_>, receiver: &Expr<'_>, call_span: Span) |diag| { let derefs = recv_adjusts .iter() - .filter(|adj| matches!(adj.kind, Adjust::Deref(None))) + .filter(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Builtin))) .count(); diag.note( diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 74e8dbc15a6c..607aaef9627b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -14,7 +14,7 @@ use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::mir::Mutability; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind, OverloadedDeref}; use rustc_middle::ty::{ self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate, TraitPredicate, Ty, }; @@ -78,7 +78,7 @@ fn check_addr_of_expr( // For matching uses of `Cow::from` [ Adjustment { - kind: Adjust::Deref(None), + kind: Adjust::Deref(DerefAdjustKind::Builtin), target: referent_ty, }, Adjustment { @@ -89,7 +89,7 @@ fn check_addr_of_expr( // For matching uses of arrays | [ Adjustment { - kind: Adjust::Deref(None), + kind: Adjust::Deref(DerefAdjustKind::Builtin), target: referent_ty, }, Adjustment { @@ -104,11 +104,11 @@ fn check_addr_of_expr( // For matching everything else | [ Adjustment { - kind: Adjust::Deref(None), + kind: Adjust::Deref(DerefAdjustKind::Builtin), target: referent_ty, }, Adjustment { - kind: Adjust::Deref(Some(OverloadedDeref { .. })), + kind: Adjust::Deref(DerefAdjustKind::Overloaded(OverloadedDeref { .. })), .. }, Adjustment { diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs index f852080d0f2a..3737249a40cb 100644 --- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs @@ -7,7 +7,7 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{self as hir, LangItem, Node}; use rustc_lint::LateContext; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_middle::ty::{Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_span::{Span, Symbol, sym}; @@ -161,7 +161,7 @@ fn is_calling_clone(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool { && cx.tcx.lang_items().clone_trait().is_some_and(|id| id == trait_id) // no autoderefs && !cx.typeck_results().expr_adjustments(obj).iter() - .any(|a| matches!(a.kind, Adjust::Deref(Some(..)))) + .any(|a| matches!(a.kind, Adjust::Deref(DerefAdjustKind::Overloaded(..)))) && obj.res_local_id() == Some(local_id) { true diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 9b0008a29c6b..f99748127a8f 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -33,7 +33,7 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::mir::{ConstValue, UnevaluatedConst}; -use rustc_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::{ self, AliasTyKind, EarlyBinder, GenericArgs, GenericArgsRef, Instance, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeckResults, TypingEnv, @@ -907,7 +907,7 @@ fn does_adjust_borrow(adjust: &Adjustment<'_>) -> Option { match adjust.kind { Adjust::Borrow(_) => Some(BorrowCause::AutoBorrow), // Custom deref calls `::deref(&x)` resulting in a borrow. - Adjust::Deref(Some(_)) => Some(BorrowCause::AutoDeref), + Adjust::Deref(DerefAdjustKind::Overloaded(_)) => Some(BorrowCause::AutoDeref), // All other adjustments read the value. _ => None, } diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs index 2bdd5739a557..d184744162e4 100644 --- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs +++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs @@ -19,7 +19,7 @@ use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, QPath, UnOp}; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_span::Symbol; use std::{cmp, ops}; @@ -132,7 +132,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS .typeck_results() .expr_adjustments(e) .iter() - .any(|adj| matches!(adj.kind, Adjust::Deref(Some(_)))) + .any(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Overloaded(_)))) { self.eagerness |= NoChange; return; @@ -211,12 +211,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS // Custom `Deref` impl might have side effects ExprKind::Unary(UnOp::Deref, e) - if self - .cx - .typeck_results() - .expr_ty(e) - .builtin_deref(true) - .is_none() => + if self.cx.typeck_results().expr_ty(e).builtin_deref(true).is_none() => { self.eagerness |= NoChange; }, diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 6b10f4b51442..16bedf199e20 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -108,7 +108,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::hir::place::PlaceBase; use rustc_middle::lint::LevelAndSource; use rustc_middle::mir::{AggregateKind, Operand, RETURN_PLACE, Rvalue, StatementKind, TerminatorKind}; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, PointerCoercion}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, DerefAdjustKind, PointerCoercion}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, GenericArgKind, GenericArgsRef, IntTy, Ty, TyCtxt, @@ -477,8 +477,8 @@ pub fn expr_custom_deref_adjustment(cx: &LateContext<'_>, e: &Expr<'_>) -> Optio .expr_adjustments(e) .iter() .find_map(|a| match a.kind { - Adjust::Deref(Some(d)) => Some(Some(d.mutbl)), - Adjust::Deref(None) => None, + Adjust::Deref(DerefAdjustKind::Overloaded(d)) => Some(Some(d.mutbl)), + Adjust::Deref(DerefAdjustKind::Builtin) => None, _ => Some(None), }) .and_then(|x| x) @@ -3537,7 +3537,9 @@ pub fn expr_adjustment_requires_coercion(cx: &LateContext<'_>, expr: &Expr<'_>) cx.typeck_results().expr_adjustments(expr).iter().any(|adj| { matches!( adj.kind, - Adjust::Deref(Some(_)) | Adjust::Pointer(PointerCoercion::Unsize) | Adjust::NeverToAny + Adjust::Deref(DerefAdjustKind::Overloaded(_)) + | Adjust::Pointer(PointerCoercion::Unsize) + | Adjust::NeverToAny ) }) } diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 0f11df98fc17..46456528fdf8 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -17,7 +17,7 @@ use rustc_lint::LateContext; use rustc_middle::mir::ConstValue; use rustc_middle::mir::interpret::Scalar; use rustc_middle::traits::EvaluationResult; -use rustc_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ self, AdtDef, AliasTy, AssocItem, AssocTag, Binder, BoundRegion, BoundVarIndexKind, FnSig, GenericArg, @@ -1345,6 +1345,7 @@ pub fn get_field_idx_by_name(ty: Ty<'_>, name: Symbol) -> Option { pub fn adjust_derefs_manually_drop<'tcx>(adjustments: &'tcx [Adjustment<'tcx>], mut ty: Ty<'tcx>) -> bool { adjustments.iter().any(|a| { let ty = mem::replace(&mut ty, a.target); - matches!(a.kind, Adjust::Deref(Some(op)) if op.mutbl == Mutability::Mut) && is_manually_drop(ty) + matches!(a.kind, Adjust::Deref(DerefAdjustKind::Overloaded(op)) if op.mutbl == Mutability::Mut) + && is_manually_drop(ty) }) } From cdee2fbff588eed1d399897263e8dcafd51f86df Mon Sep 17 00:00:00 2001 From: Frank King Date: Fri, 30 Jan 2026 11:06:27 +0800 Subject: [PATCH 318/978] refactor: add an `enum DerefAdjustKind` in favor of `Option` --- clippy_lints/src/eta_reduction.rs | 4 ++-- clippy_lints/src/format_args.rs | 6 +++--- clippy_lints/src/loops/while_let_on_iterator.rs | 4 ++-- clippy_lints/src/methods/map_clone.rs | 4 ++-- clippy_lints/src/methods/option_as_ref_deref.rs | 2 +- clippy_lints/src/methods/swap_with_temporary.rs | 4 ++-- clippy_lints/src/methods/type_id_on_box.rs | 4 ++-- clippy_lints/src/methods/unnecessary_to_owned.rs | 10 +++++----- clippy_lints/src/methods/useless_asref.rs | 4 ++-- clippy_lints/src/non_copy_const.rs | 4 ++-- clippy_utils/src/eager_or_lazy.rs | 11 +++-------- clippy_utils/src/lib.rs | 10 ++++++---- clippy_utils/src/ty/mod.rs | 5 +++-- 13 files changed, 35 insertions(+), 37 deletions(-) diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 21385ee4fdc7..3e46c370fb70 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -10,7 +10,7 @@ use rustc_hir::attrs::AttributeKind; use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, GenericArgs, Param, PatKind, QPath, Safety, TyKind, find_attr}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_middle::ty::{ self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, Ty, TypeVisitableExt, TypeckResults, }; @@ -236,7 +236,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx .iter() .rev() .fold(0, |acc, adjustment| match adjustment.kind { - Adjust::Deref(Some(_)) => acc + 1, + Adjust::Deref(DerefAdjustKind::Overloaded(_)) => acc + 1, Adjust::Deref(_) if acc > 0 => acc + 1, _ => acc, }) diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index 011cbf8c5d41..5fb1a0b80f1a 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -24,7 +24,7 @@ use rustc_errors::SuggestionStyle::{CompletelyHidden, ShowCode}; use rustc_hir::attrs::AttributeKind; use rustc_hir::{Expr, ExprKind, LangItem, RustcVersion, find_attr}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::{self, GenericArg, List, TraitRef, Ty, TyCtxt, Upcast}; use rustc_session::impl_lint_pass; use rustc_span::edition::Edition::Edition2021; @@ -704,12 +704,12 @@ where let mut n_needed = 0; loop { if let Some(Adjustment { - kind: Adjust::Deref(overloaded_deref), + kind: Adjust::Deref(deref), target, }) = iter.next() { n_total += 1; - if overloaded_deref.is_some() { + if let DerefAdjustKind::Overloaded(..) = deref { n_needed = n_total; } ty = *target; diff --git a/clippy_lints/src/loops/while_let_on_iterator.rs b/clippy_lints/src/loops/while_let_on_iterator.rs index 6c95c7b54c50..fc0789894cc2 100644 --- a/clippy_lints/src/loops/while_let_on_iterator.rs +++ b/clippy_lints/src/loops/while_let_on_iterator.rs @@ -12,7 +12,7 @@ use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{Closure, Expr, ExprKind, HirId, LetStmt, Mutability, UnOp}; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter::OnlyBodies; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_span::Symbol; use rustc_span::symbol::sym; @@ -88,7 +88,7 @@ fn try_parse_iter_expr(cx: &LateContext<'_>, mut e: &Expr<'_>) -> Option, e: &hir::Expr<'_>, recv: &hir::Expr<'_ && cx.tcx.lang_items().clone_trait() == Some(trait_id) // no autoderefs && !cx.typeck_results().expr_adjustments(obj).iter() - .any(|a| matches!(a.kind, Adjust::Deref(Some(..)))) + .any(|a| matches!(a.kind, Adjust::Deref(DerefAdjustKind::Overloaded(..)))) { let obj_ty = cx.typeck_results().expr_ty(obj); if let ty::Ref(_, ty, mutability) = obj_ty.kind() { diff --git a/clippy_lints/src/methods/option_as_ref_deref.rs b/clippy_lints/src/methods/option_as_ref_deref.rs index 3d489075ce8a..1239d8927acf 100644 --- a/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/clippy_lints/src/methods/option_as_ref_deref.rs @@ -58,7 +58,7 @@ pub(super) fn check( .iter() .map(|x| &x.kind) .collect::>() - && let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj + && let [ty::adjustment::Adjust::Deref(ty::adjustment::DerefAdjustKind::Builtin), ty::adjustment::Adjust::Borrow(_)] = *adj && let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap() && let Some(method_name) = cx.tcx.get_diagnostic_name(method_did) { diff --git a/clippy_lints/src/methods/swap_with_temporary.rs b/clippy_lints/src/methods/swap_with_temporary.rs index e378cbd6ae0a..0b8f6ae9f277 100644 --- a/clippy_lints/src/methods/swap_with_temporary.rs +++ b/clippy_lints/src/methods/swap_with_temporary.rs @@ -4,7 +4,7 @@ use rustc_ast::BorrowKind; use rustc_errors::{Applicability, Diag}; use rustc_hir::{Expr, ExprKind, Node, QPath}; use rustc_lint::LateContext; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_span::sym; use super::SWAP_WITH_TEMPORARY; @@ -47,7 +47,7 @@ impl<'tcx> ArgKind<'tcx> { && let adjustments = cx.typeck_results().expr_adjustments(arg) && adjustments .first() - .is_some_and(|adj| matches!(adj.kind, Adjust::Deref(None))) + .is_some_and(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Builtin))) && adjustments .last() .is_some_and(|adj| matches!(adj.kind, Adjust::Borrow(_))) diff --git a/clippy_lints/src/methods/type_id_on_box.rs b/clippy_lints/src/methods/type_id_on_box.rs index e67ba5c4d314..98f319be7a45 100644 --- a/clippy_lints/src/methods/type_id_on_box.rs +++ b/clippy_lints/src/methods/type_id_on_box.rs @@ -4,7 +4,7 @@ use clippy_utils::source::snippet; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::{self, ExistentialPredicate, Ty}; use rustc_span::{Span, sym}; @@ -58,7 +58,7 @@ pub(super) fn check(cx: &LateContext<'_>, receiver: &Expr<'_>, call_span: Span) |diag| { let derefs = recv_adjusts .iter() - .filter(|adj| matches!(adj.kind, Adjust::Deref(None))) + .filter(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Builtin))) .count(); diag.note( diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 74e8dbc15a6c..607aaef9627b 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -14,7 +14,7 @@ use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::mir::Mutability; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind, OverloadedDeref}; use rustc_middle::ty::{ self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate, TraitPredicate, Ty, }; @@ -78,7 +78,7 @@ fn check_addr_of_expr( // For matching uses of `Cow::from` [ Adjustment { - kind: Adjust::Deref(None), + kind: Adjust::Deref(DerefAdjustKind::Builtin), target: referent_ty, }, Adjustment { @@ -89,7 +89,7 @@ fn check_addr_of_expr( // For matching uses of arrays | [ Adjustment { - kind: Adjust::Deref(None), + kind: Adjust::Deref(DerefAdjustKind::Builtin), target: referent_ty, }, Adjustment { @@ -104,11 +104,11 @@ fn check_addr_of_expr( // For matching everything else | [ Adjustment { - kind: Adjust::Deref(None), + kind: Adjust::Deref(DerefAdjustKind::Builtin), target: referent_ty, }, Adjustment { - kind: Adjust::Deref(Some(OverloadedDeref { .. })), + kind: Adjust::Deref(DerefAdjustKind::Overloaded(OverloadedDeref { .. })), .. }, Adjustment { diff --git a/clippy_lints/src/methods/useless_asref.rs b/clippy_lints/src/methods/useless_asref.rs index f852080d0f2a..3737249a40cb 100644 --- a/clippy_lints/src/methods/useless_asref.rs +++ b/clippy_lints/src/methods/useless_asref.rs @@ -7,7 +7,7 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{self as hir, LangItem, Node}; use rustc_lint::LateContext; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_middle::ty::{Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_span::{Span, Symbol, sym}; @@ -161,7 +161,7 @@ fn is_calling_clone(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool { && cx.tcx.lang_items().clone_trait().is_some_and(|id| id == trait_id) // no autoderefs && !cx.typeck_results().expr_adjustments(obj).iter() - .any(|a| matches!(a.kind, Adjust::Deref(Some(..)))) + .any(|a| matches!(a.kind, Adjust::Deref(DerefAdjustKind::Overloaded(..)))) && obj.res_local_id() == Some(local_id) { true diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 9b0008a29c6b..f99748127a8f 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -33,7 +33,7 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::mir::{ConstValue, UnevaluatedConst}; -use rustc_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::{ self, AliasTyKind, EarlyBinder, GenericArgs, GenericArgsRef, Instance, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeckResults, TypingEnv, @@ -907,7 +907,7 @@ fn does_adjust_borrow(adjust: &Adjustment<'_>) -> Option { match adjust.kind { Adjust::Borrow(_) => Some(BorrowCause::AutoBorrow), // Custom deref calls `::deref(&x)` resulting in a borrow. - Adjust::Deref(Some(_)) => Some(BorrowCause::AutoDeref), + Adjust::Deref(DerefAdjustKind::Overloaded(_)) => Some(BorrowCause::AutoDeref), // All other adjustments read the value. _ => None, } diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index 2bdd5739a557..d184744162e4 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -19,7 +19,7 @@ use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, QPath, UnOp}; use rustc_lint::LateContext; use rustc_middle::ty; -use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; use rustc_span::Symbol; use std::{cmp, ops}; @@ -132,7 +132,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS .typeck_results() .expr_adjustments(e) .iter() - .any(|adj| matches!(adj.kind, Adjust::Deref(Some(_)))) + .any(|adj| matches!(adj.kind, Adjust::Deref(DerefAdjustKind::Overloaded(_)))) { self.eagerness |= NoChange; return; @@ -211,12 +211,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS // Custom `Deref` impl might have side effects ExprKind::Unary(UnOp::Deref, e) - if self - .cx - .typeck_results() - .expr_ty(e) - .builtin_deref(true) - .is_none() => + if self.cx.typeck_results().expr_ty(e).builtin_deref(true).is_none() => { self.eagerness |= NoChange; }, diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 6b10f4b51442..16bedf199e20 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -108,7 +108,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::hir::place::PlaceBase; use rustc_middle::lint::LevelAndSource; use rustc_middle::mir::{AggregateKind, Operand, RETURN_PLACE, Rvalue, StatementKind, TerminatorKind}; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, PointerCoercion}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, DerefAdjustKind, PointerCoercion}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, GenericArgKind, GenericArgsRef, IntTy, Ty, TyCtxt, @@ -477,8 +477,8 @@ pub fn expr_custom_deref_adjustment(cx: &LateContext<'_>, e: &Expr<'_>) -> Optio .expr_adjustments(e) .iter() .find_map(|a| match a.kind { - Adjust::Deref(Some(d)) => Some(Some(d.mutbl)), - Adjust::Deref(None) => None, + Adjust::Deref(DerefAdjustKind::Overloaded(d)) => Some(Some(d.mutbl)), + Adjust::Deref(DerefAdjustKind::Builtin) => None, _ => Some(None), }) .and_then(|x| x) @@ -3537,7 +3537,9 @@ pub fn expr_adjustment_requires_coercion(cx: &LateContext<'_>, expr: &Expr<'_>) cx.typeck_results().expr_adjustments(expr).iter().any(|adj| { matches!( adj.kind, - Adjust::Deref(Some(_)) | Adjust::Pointer(PointerCoercion::Unsize) | Adjust::NeverToAny + Adjust::Deref(DerefAdjustKind::Overloaded(_)) + | Adjust::Pointer(PointerCoercion::Unsize) + | Adjust::NeverToAny ) }) } diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index 0f11df98fc17..46456528fdf8 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -17,7 +17,7 @@ use rustc_lint::LateContext; use rustc_middle::mir::ConstValue; use rustc_middle::mir::interpret::Scalar; use rustc_middle::traits::EvaluationResult; -use rustc_middle::ty::adjustment::{Adjust, Adjustment}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ self, AdtDef, AliasTy, AssocItem, AssocTag, Binder, BoundRegion, BoundVarIndexKind, FnSig, GenericArg, @@ -1345,6 +1345,7 @@ pub fn get_field_idx_by_name(ty: Ty<'_>, name: Symbol) -> Option { pub fn adjust_derefs_manually_drop<'tcx>(adjustments: &'tcx [Adjustment<'tcx>], mut ty: Ty<'tcx>) -> bool { adjustments.iter().any(|a| { let ty = mem::replace(&mut ty, a.target); - matches!(a.kind, Adjust::Deref(Some(op)) if op.mutbl == Mutability::Mut) && is_manually_drop(ty) + matches!(a.kind, Adjust::Deref(DerefAdjustKind::Overloaded(op)) if op.mutbl == Mutability::Mut) + && is_manually_drop(ty) }) } From 565b772fa5ed898981f7db684c2756338e8daa77 Mon Sep 17 00:00:00 2001 From: ThanhNguyxn Date: Thu, 22 Jan 2026 18:28:54 +0700 Subject: [PATCH 319/978] Add regression test for ICE with undefined type in async fn --- tests/ui/mir/gvn-opt-138225.rs | 16 ++++++++++++++++ tests/ui/mir/gvn-opt-138225.stderr | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 tests/ui/mir/gvn-opt-138225.rs create mode 100644 tests/ui/mir/gvn-opt-138225.stderr diff --git a/tests/ui/mir/gvn-opt-138225.rs b/tests/ui/mir/gvn-opt-138225.rs new file mode 100644 index 000000000000..46359e044e2e --- /dev/null +++ b/tests/ui/mir/gvn-opt-138225.rs @@ -0,0 +1,16 @@ +//! Regression test for + +pub struct A { + name: NestedOption>, + //~^ ERROR cannot find type `NestedOption` in this scope +} + +impl A { + pub async fn func1() -> &'static A { + //~^ ERROR `async fn` is not permitted in Rust 2015 + static RES: A = A { name: None }; + &RES + } +} + +fn main() {} diff --git a/tests/ui/mir/gvn-opt-138225.stderr b/tests/ui/mir/gvn-opt-138225.stderr new file mode 100644 index 000000000000..b2e3d4476bf8 --- /dev/null +++ b/tests/ui/mir/gvn-opt-138225.stderr @@ -0,0 +1,19 @@ +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/gvn-opt-138225.rs:9:9 + | +LL | pub async fn func1() -> &'static A { + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2024` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0425]: cannot find type `NestedOption` in this scope + --> $DIR/gvn-opt-138225.rs:4:11 + | +LL | name: NestedOption>, + | ^^^^^^^^^^^^ not found in this scope + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0425, E0670. +For more information about an error, try `rustc --explain E0425`. From dc48704f98f77822e8f6aea7fdac255c5aea101f Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 31 Jan 2026 02:05:07 +0000 Subject: [PATCH 320/978] Fix ICE when parsing frontmatter without newline --- compiler/rustc_parse/src/lexer/mod.rs | 2 +- .../frontmatter-no-trailing-newline/rmake.rs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tests/run-make/frontmatter-no-trailing-newline/rmake.rs diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index f9bf50de091a..76f610df1eb0 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -623,7 +623,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { self.dcx().emit_err(errors::FrontmatterInvalidInfostring { span }); } - let last_line_start = real_s.rfind('\n').map_or(0, |i| i + 1); + let last_line_start = real_s.rfind('\n').map_or(line_end, |i| i + 1); let content = &real_s[line_end..last_line_start]; if let Some(cr_offset) = content.find('\r') { diff --git a/tests/run-make/frontmatter-no-trailing-newline/rmake.rs b/tests/run-make/frontmatter-no-trailing-newline/rmake.rs new file mode 100644 index 000000000000..204062201ad3 --- /dev/null +++ b/tests/run-make/frontmatter-no-trailing-newline/rmake.rs @@ -0,0 +1,19 @@ +// Regression test for issue #151882 +// See https://github.com/rust-lang/rust/issues/151882 + +//@ only-nightly +//@ needs-target-std + +use run_make_support::{rfs, rustc}; + +fn main() { + rfs::write("test.rs", b"----"); + + // Ensure rustc does not ICE when parsing a file with frontmatter syntax + // that has no trailing newline + rustc() + .input("test.rs") + .run_fail() + .assert_stderr_contains("invalid infostring for frontmatter") + .assert_stderr_not_contains("unexpectedly panicked"); +} From 1689fcd1cc8a7288b0d3ae88211549ad8de9df7d Mon Sep 17 00:00:00 2001 From: kouhe3 <25522053+kouhe3@users.noreply.github.com> Date: Thu, 29 Jan 2026 17:23:06 +0800 Subject: [PATCH 321/978] feat(windows): add Unix domain socket support This commit introduces initial, unstable support for Unix domain sockets (UDS) on Windows, behind the `windows_unix_domain_sockets` feature gate Added types: - `std::os::windows::net::SocketAddr`: represents a UDS address with support for pathname addresses (abstract and unnamed are parsed but not yet fully supported). - `std::os::windows::net::UnixListener`: server-side UDS listener. - `std::os::windows::net::UnixStream`: client/server stream for UDS. Key features: - Binding and connecting using filesystem paths. - Basic I/O via `Read`/`Write`. - Address querying (`local_addr`, `peer_addr`). - Non-blocking mode, timeouts, and socket duplication. - Includes basic test coverage for smoke, echo, path length, and bind reuse. --- library/std/src/os/windows/mod.rs | 2 + library/std/src/os/windows/net/addr.rs | 173 +++++++++ library/std/src/os/windows/net/listener.rs | 342 +++++++++++++++++ library/std/src/os/windows/net/mod.rs | 6 + library/std/src/os/windows/net/stream.rs | 421 +++++++++++++++++++++ library/std/src/sys/pal/windows/mod.rs | 5 + library/std/tests/windows_unix_socket.rs | 86 +++++ 7 files changed, 1035 insertions(+) create mode 100644 library/std/src/os/windows/net/addr.rs create mode 100644 library/std/src/os/windows/net/listener.rs create mode 100644 library/std/src/os/windows/net/mod.rs create mode 100644 library/std/src/os/windows/net/stream.rs create mode 100644 library/std/tests/windows_unix_socket.rs diff --git a/library/std/src/os/windows/mod.rs b/library/std/src/os/windows/mod.rs index f452403ee842..53c33d17a9f6 100644 --- a/library/std/src/os/windows/mod.rs +++ b/library/std/src/os/windows/mod.rs @@ -29,6 +29,8 @@ pub mod ffi; pub mod fs; pub mod io; +#[unstable(feature = "windows_unix_domain_sockets", issue = "150487")] +pub mod net; pub mod process; pub mod raw; pub mod thread; diff --git a/library/std/src/os/windows/net/addr.rs b/library/std/src/os/windows/net/addr.rs new file mode 100644 index 000000000000..ef2263edcf61 --- /dev/null +++ b/library/std/src/os/windows/net/addr.rs @@ -0,0 +1,173 @@ +#![unstable(feature = "windows_unix_domain_sockets", issue = "150487")] +use crate::bstr::ByteStr; +use crate::ffi::OsStr; +use crate::path::Path; +#[cfg(not(doc))] +use crate::sys::c::{AF_UNIX, SOCKADDR, SOCKADDR_UN}; +use crate::sys::cvt_nz; +use crate::{fmt, io, mem, ptr}; + +#[cfg(not(doc))] +pub fn sockaddr_un(path: &Path) -> io::Result<(SOCKADDR_UN, usize)> { + // SAFETY: All zeros is a valid representation for `sockaddr_un`. + let mut addr: SOCKADDR_UN = unsafe { mem::zeroed() }; + addr.sun_family = AF_UNIX; + + // path to UTF-8 bytes + let bytes = path + .to_str() + .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "path must be valid UTF-8"))? + .as_bytes(); + if bytes.len() >= addr.sun_path.len() { + return Err(io::const_error!(io::ErrorKind::InvalidInput, "path too long")); + } + // SAFETY: `bytes` and `addr.sun_path` are not overlapping and + // both point to valid memory. + // NOTE: We zeroed the memory above, so the path is already null + // terminated. + unsafe { + ptr::copy_nonoverlapping(bytes.as_ptr(), addr.sun_path.as_mut_ptr().cast(), bytes.len()) + }; + + let len = SUN_PATH_OFFSET + bytes.len() + 1; + Ok((addr, len)) +} +#[cfg(not(doc))] +const SUN_PATH_OFFSET: usize = mem::offset_of!(SOCKADDR_UN, sun_path); +pub struct SocketAddr { + #[cfg(not(doc))] + pub(super) addr: SOCKADDR_UN, + pub(super) len: u32, // Use u32 here as same as libc::socklen_t +} +impl fmt::Debug for SocketAddr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.address() { + AddressKind::Unnamed => write!(fmt, "(unnamed)"), + AddressKind::Abstract(name) => write!(fmt, "{name:?} (abstract)"), + AddressKind::Pathname(path) => write!(fmt, "{path:?} (pathname)"), + } + } +} + +impl SocketAddr { + #[cfg(not(doc))] + pub(super) fn new(f: F) -> io::Result + where + F: FnOnce(*mut SOCKADDR, *mut i32) -> i32, + { + unsafe { + let mut addr: SOCKADDR_UN = mem::zeroed(); + let mut len = mem::size_of::() as i32; + cvt_nz(f(&raw mut addr as *mut _, &mut len))?; + SocketAddr::from_parts(addr, len) + } + } + #[cfg(not(doc))] + pub(super) fn from_parts(addr: SOCKADDR_UN, len: i32) -> io::Result { + if addr.sun_family != AF_UNIX { + Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid address family")) + } else if len < SUN_PATH_OFFSET as _ || len > mem::size_of::() as _ { + Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid address length")) + } else { + Ok(SocketAddr { addr, len: len as _ }) + } + } + + /// Returns the contents of this address if it is a `pathname` address. + /// + /// # Examples + /// + /// With a pathname: + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// use std::path::Path; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixListener::bind("/tmp/sock")?; + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); + /// Ok(()) + /// } + /// ``` + pub fn as_pathname(&self) -> Option<&Path> { + if let AddressKind::Pathname(path) = self.address() { Some(path) } else { None } + } + + /// Constructs a `SockAddr` with the family `AF_UNIX` and the provided path. + /// + /// # Errors + /// + /// Returns an error if the path is longer than `SUN_LEN` or if it contains + /// NULL bytes. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::SocketAddr; + /// use std::path::Path; + /// + /// # fn main() -> std::io::Result<()> { + /// let address = SocketAddr::from_pathname("/path/to/socket")?; + /// assert_eq!(address.as_pathname(), Some(Path::new("/path/to/socket"))); + /// # Ok(()) + /// # } + /// ``` + /// + /// Creating a `SocketAddr` with a NULL byte results in an error. + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::SocketAddr; + /// + /// assert!(SocketAddr::from_pathname("/path/with/\0/bytes").is_err()); + /// ``` + pub fn from_pathname

(path: P) -> io::Result + where + P: AsRef, + { + sockaddr_un(path.as_ref()).map(|(addr, len)| SocketAddr { addr, len: len as _ }) + } + fn address(&self) -> AddressKind<'_> { + let len = self.len as usize - SUN_PATH_OFFSET; + let path = unsafe { mem::transmute::<&[i8], &[u8]>(&self.addr.sun_path) }; + + if len == 0 { + AddressKind::Unnamed + } else if self.addr.sun_path[0] == 0 { + AddressKind::Abstract(ByteStr::from_bytes(&path[1..len])) + } else { + AddressKind::Pathname(unsafe { + OsStr::from_encoded_bytes_unchecked(&path[..len - 1]).as_ref() + }) + } + } + + /// Returns `true` if the address is unnamed. + /// + /// # Examples + /// + /// A named address: + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixListener::bind("/tmp/sock")?; + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// assert_eq!(addr.is_unnamed(), false); + /// Ok(()) + /// } + /// ``` + pub fn is_unnamed(&self) -> bool { + matches!(self.address(), AddressKind::Unnamed) + } +} +enum AddressKind<'a> { + Unnamed, + Pathname(&'a Path), + Abstract(&'a ByteStr), +} diff --git a/library/std/src/os/windows/net/listener.rs b/library/std/src/os/windows/net/listener.rs new file mode 100644 index 000000000000..332b116ee1a3 --- /dev/null +++ b/library/std/src/os/windows/net/listener.rs @@ -0,0 +1,342 @@ +#![unstable(feature = "windows_unix_domain_sockets", issue = "150487")] +use crate::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}; +use crate::os::windows::net::{SocketAddr, UnixStream}; +use crate::path::Path; +#[cfg(not(doc))] +use crate::sys::c::{AF_UNIX, SOCK_STREAM, SOCKADDR_UN, bind, getsockname, listen}; +use crate::sys::net::Socket; +#[cfg(not(doc))] +use crate::sys::winsock::startup; +use crate::sys::{AsInner, cvt_nz}; +use crate::{fmt, io}; + +/// A structure representing a Unix domain socket server. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(windows_unix_domain_sockets)] +/// use std::thread; +/// use std::os::windows::net::{UnixStream, UnixListener}; +/// +/// fn handle_client(stream: UnixStream) { +/// // ... +/// } +/// +/// fn main() -> std::io::Result<()> { +/// let listener = UnixListener::bind("/path/to/the/socket")?; +/// +/// // accept connections and process them, spawning a new thread for each one +/// for stream in listener.incoming() { +/// match stream { +/// Ok(stream) => { +/// /* connection succeeded */ +/// thread::spawn(|| handle_client(stream)); +/// } +/// Err(err) => { +/// /* connection failed */ +/// break; +/// } +/// } +/// } +/// Ok(()) +/// } +/// ``` +pub struct UnixListener(Socket); + +impl fmt::Debug for UnixListener { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut builder = fmt.debug_struct("UnixListener"); + builder.field("sock", self.0.as_inner()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } + builder.finish() + } +} +impl UnixListener { + /// Creates a new `UnixListener` bound to the specified socket. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// + /// let listener = match UnixListener::bind("/path/to/the/socket") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {e:?}"); + /// return + /// } + /// }; + /// ``` + pub fn bind>(path: P) -> io::Result { + let socket_addr = SocketAddr::from_pathname(path)?; + Self::bind_addr(&socket_addr) + } + + /// Creates a new `UnixListener` bound to the specified [`socket address`]. + /// + /// [`socket address`]: crate::os::windows::net::SocketAddr + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::{UnixListener}; + /// + /// fn main() -> std::io::Result<()> { + /// let listener1 = UnixListener::bind("path/to/socket")?; + /// let addr = listener1.local_addr()?; + /// + /// let listener2 = match UnixListener::bind_addr(&addr) { + /// Ok(sock) => sock, + /// Err(err) => { + /// println!("Couldn't bind: {err:?}"); + /// return Err(err); + /// } + /// }; + /// Ok(()) + /// } + /// ``` + pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result { + startup(); + let inner = Socket::new(AF_UNIX as _, SOCK_STREAM)?; + unsafe { + cvt_nz(bind(inner.as_raw(), &raw const socket_addr.addr as _, socket_addr.len as _))?; + cvt_nz(listen(inner.as_raw(), 128))?; + } + Ok(UnixListener(inner)) + } + + /// Accepts a new incoming connection to this listener. + /// + /// This function will block the calling thread until a new Unix connection + /// is established. When established, the corresponding [`UnixStream`] and + /// the remote peer's address will be returned. + /// + /// [`UnixStream`]: crate::os::windows::net::UnixStream + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// + /// fn main() -> std::io::Result<()> { + /// let listener = UnixListener::bind("/path/to/the/socket")?; + /// + /// match listener.accept() { + /// Ok((socket, addr)) => println!("Got a client: {addr:?}"), + /// Err(e) => println!("accept function failed: {e:?}"), + /// } + /// Ok(()) + /// } + /// ``` + pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { + let mut storage = SOCKADDR_UN::default(); + let mut len = size_of::() as _; + let inner = self.0.accept(&raw mut storage as *mut _, &raw mut len)?; + let addr = SocketAddr::from_parts(storage, len)?; + Ok((UnixStream(inner), addr)) + } + + /// Returns the local socket address of this listener. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// + /// fn main() -> std::io::Result<()> { + /// let listener = UnixListener::bind("/path/to/the/socket")?; + /// let addr = listener.local_addr().expect("Couldn't get local address"); + /// Ok(()) + /// } + /// ``` + pub fn local_addr(&self) -> io::Result { + SocketAddr::new(|addr, len| unsafe { getsockname(self.0.as_raw(), addr, len) }) + } + + /// Creates a new independently owned handle to the underlying socket. + /// + /// The returned `UnixListener` is a reference to the same socket that this + /// object references. Both handles can be used to accept incoming + /// connections and options set on one listener will affect the other. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// + /// fn main() -> std::io::Result<()> { + /// let listener = UnixListener::bind("/path/to/the/socket")?; + /// let listener_copy = listener.try_clone().expect("try_clone failed"); + /// Ok(()) + /// } + /// ``` + pub fn try_clone(&self) -> io::Result { + self.0.duplicate().map(UnixListener) + } + + /// Moves the socket into or out of nonblocking mode. + /// + /// This will result in the `accept` operation becoming nonblocking, + /// i.e., immediately returning from their calls. If the IO operation is + /// successful, `Ok` is returned and no further action is required. If the + /// IO operation could not be completed and needs to be retried, an error + /// with kind [`io::ErrorKind::WouldBlock`] is returned. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// + /// fn main() -> std::io::Result<()> { + /// let listener = UnixListener::bind("/path/to/the/socket")?; + /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); + /// Ok(()) + /// } + /// ``` + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixListener; + /// + /// fn main() -> std::io::Result<()> { + /// let listener = UnixListener::bind("/tmp/sock")?; + /// + /// if let Ok(Some(err)) = listener.take_error() { + /// println!("Got error: {err:?}"); + /// } + /// Ok(()) + /// } + /// ``` + pub fn take_error(&self) -> io::Result> { + self.0.take_error() + } + + /// Returns an iterator over incoming connections. + /// + /// The iterator will never return [`None`] and will also not yield the + /// peer's [`SocketAddr`] structure. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::thread; + /// use std::os::windows::net::{UnixStream, UnixListener}; + /// + /// fn handle_client(stream: UnixStream) { + /// // ... + /// } + /// + /// fn main() -> std::io::Result<()> { + /// let listener = UnixListener::bind("/path/to/the/socket")?; + /// + /// for stream in listener.incoming() { + /// match stream { + /// Ok(stream) => { + /// thread::spawn(|| handle_client(stream)); + /// } + /// Err(err) => { + /// break; + /// } + /// } + /// } + /// Ok(()) + /// } + /// ``` + pub fn incoming(&self) -> Incoming<'_> { + Incoming { listener: self } + } +} + +/// An iterator over incoming connections to a [`UnixListener`]. +/// +/// It will never return [`None`]. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(windows_unix_domain_sockets)] +/// use std::thread; +/// use std::os::windows::net::{UnixStream, UnixListener}; +/// +/// fn handle_client(stream: UnixStream) { +/// // ... +/// } +/// +/// fn main() -> std::io::Result<()> { +/// let listener = UnixListener::bind("/path/to/the/socket")?; +/// +/// for stream in listener.incoming() { +/// match stream { +/// Ok(stream) => { +/// thread::spawn(|| handle_client(stream)); +/// } +/// Err(err) => { +/// break; +/// } +/// } +/// } +/// Ok(()) +/// } +/// ``` +pub struct Incoming<'a> { + listener: &'a UnixListener, +} + +impl<'a> Iterator for Incoming<'a> { + type Item = io::Result; + + fn next(&mut self) -> Option> { + Some(self.listener.accept().map(|s| s.0)) + } + + fn size_hint(&self) -> (usize, Option) { + (usize::MAX, None) + } +} + +impl AsRawSocket for UnixListener { + #[inline] + fn as_raw_socket(&self) -> RawSocket { + self.0.as_raw_socket() + } +} + +impl FromRawSocket for UnixListener { + #[inline] + unsafe fn from_raw_socket(sock: RawSocket) -> Self { + UnixListener(unsafe { Socket::from_raw_socket(sock) }) + } +} + +impl IntoRawSocket for UnixListener { + #[inline] + fn into_raw_socket(self) -> RawSocket { + self.0.into_raw_socket() + } +} + +impl<'a> IntoIterator for &'a UnixListener { + type Item = io::Result; + type IntoIter = Incoming<'a>; + + fn into_iter(self) -> Incoming<'a> { + self.incoming() + } +} diff --git a/library/std/src/os/windows/net/mod.rs b/library/std/src/os/windows/net/mod.rs new file mode 100644 index 000000000000..6b3f062b8ab4 --- /dev/null +++ b/library/std/src/os/windows/net/mod.rs @@ -0,0 +1,6 @@ +mod addr; +mod listener; +mod stream; +pub use addr::*; +pub use listener::*; +pub use stream::*; diff --git a/library/std/src/os/windows/net/stream.rs b/library/std/src/os/windows/net/stream.rs new file mode 100644 index 000000000000..c31f03fdf53f --- /dev/null +++ b/library/std/src/os/windows/net/stream.rs @@ -0,0 +1,421 @@ +#![unstable(feature = "windows_unix_domain_sockets", issue = "150487")] +use crate::net::Shutdown; +use crate::os::windows::io::{ + AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, RawSocket, +}; +use crate::os::windows::net::SocketAddr; +use crate::path::Path; +#[cfg(not(doc))] +use crate::sys::c::{ + AF_UNIX, SO_RCVTIMEO, SO_SNDTIMEO, SOCK_STREAM, connect, getpeername, getsockname, +}; +use crate::sys::net::Socket; +#[cfg(not(doc))] +use crate::sys::winsock::startup; +use crate::sys::{AsInner, cvt_nz}; +use crate::time::Duration; +use crate::{fmt, io}; +/// A Unix stream socket. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(windows_unix_domain_sockets)] +/// use std::os::windows::net::UnixStream; +/// use std::io::prelude::*; +/// +/// fn main() -> std::io::Result<()> { +/// let mut stream = UnixStream::connect("/path/to/my/socket")?; +/// stream.write_all(b"hello world")?; +/// let mut response = String::new(); +/// stream.read_to_string(&mut response)?; +/// println!("{response}"); +/// Ok(()) +/// } +/// ``` +pub struct UnixStream(pub(super) Socket); +impl fmt::Debug for UnixStream { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut builder = fmt.debug_struct("UnixStream"); + builder.field("sock", self.0.as_inner()); + if let Ok(addr) = self.local_addr() { + builder.field("local", &addr); + } + if let Ok(addr) = self.peer_addr() { + builder.field("peer", &addr); + } + builder.finish() + } +} +impl UnixStream { + /// Connects to the socket named by `path`. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// + /// let socket = match UnixStream::connect("/tmp/sock") { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {e:?}"); + /// return + /// } + /// }; + /// ``` + pub fn connect>(path: P) -> io::Result { + let socket_addr = SocketAddr::from_pathname(path)?; + Self::connect_addr(&socket_addr) + } + + /// Connects to the socket specified by [`address`]. + /// + /// [`address`]: crate::os::windows::net::SocketAddr + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::{UnixListener, UnixStream}; + /// + /// fn main() -> std::io::Result<()> { + /// let listener = UnixListener::bind("/path/to/the/socket")?; + /// let addr = listener.local_addr()?; + /// + /// let sock = match UnixStream::connect_addr(&addr) { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {e:?}"); + /// return Err(e) + /// } + /// }; + /// Ok(()) + /// } + /// ```` + pub fn connect_addr(socket_addr: &SocketAddr) -> io::Result { + startup(); + let inner = Socket::new(AF_UNIX as _, SOCK_STREAM)?; + unsafe { + cvt_nz(connect( + inner.as_raw(), + &raw const socket_addr.addr as *const _, + socket_addr.len as _, + ))?; + } + Ok(UnixStream(inner)) + } + + /// Returns the socket address of the local half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// Ok(()) + /// } + /// ``` + pub fn local_addr(&self) -> io::Result { + SocketAddr::new(|addr, len| unsafe { getsockname(self.0.as_raw(), addr, len) }) + } + + /// Returns the socket address of the remote half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// let addr = socket.peer_addr().expect("Couldn't get peer address"); + /// Ok(()) + /// } + /// ``` + pub fn peer_addr(&self) -> io::Result { + SocketAddr::new(|addr, len| unsafe { getpeername(self.0.as_raw(), addr, len) }) + } + + /// Returns the read timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// use std::time::Duration; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// assert_eq!(socket.read_timeout()?, Some(Duration::new(1, 0))); + /// Ok(()) + /// } + /// ``` + pub fn read_timeout(&self) -> io::Result> { + self.0.timeout(SO_RCVTIMEO) + } + + /// Moves the socket into or out of nonblocking mode. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); + /// Ok(()) + /// } + /// ``` + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.0.set_nonblocking(nonblocking) + } + + /// Sets the read timeout for the socket. + /// + /// If the provided value is [`None`], then [`read`] calls will block + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method. + /// + /// [`read`]: io::Read::read + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// use std::time::Duration; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// Ok(()) + /// } + /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::io; + /// use std::os::windows::net::UnixStream; + /// use std::time::Duration; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); + /// Ok(()) + /// } + /// ``` + pub fn set_read_timeout(&self, dur: Option) -> io::Result<()> { + self.0.set_timeout(dur, SO_RCVTIMEO) + } + + /// Sets the write timeout for the socket. + /// + /// If the provided value is [`None`], then [`write`] calls will block + /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is + /// passed to this method. + /// + /// [`read`]: io::Read::read + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// use std::time::Duration; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// socket.set_write_timeout(Some(Duration::new(1, 0))) + /// .expect("Couldn't set write timeout"); + /// Ok(()) + /// } + /// ``` + /// + /// An [`Err`] is returned if the zero [`Duration`] is passed to this + /// method: + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::io; + /// use std::os::windows::net::UnixStream; + /// use std::time::Duration; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); + /// let err = result.unwrap_err(); + /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); + /// Ok(()) + /// } + /// ``` + pub fn set_write_timeout(&self, dur: Option) -> io::Result<()> { + self.0.set_timeout(dur, SO_SNDTIMEO) + } + + /// Shuts down the read, write, or both halves of this connection. + /// + /// This function will cause all pending and future I/O calls on the + /// specified portions to immediately return with an appropriate value + /// (see the documentation of [`Shutdown`]). + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// use std::net::Shutdown; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); + /// Ok(()) + /// } + /// ``` + pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { + self.0.shutdown(how) + } + + /// Returns the value of the `SO_ERROR` option. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// if let Ok(Some(err)) = socket.take_error() { + /// println!("Got error: {err:?}"); + /// } + /// Ok(()) + /// } + /// ``` + pub fn take_error(&self) -> io::Result> { + self.0.take_error() + } + + /// Creates a new independently owned handle to the underlying socket. + /// + /// The returned `UnixStream` is a reference to the same stream that this + /// object references. Both handles will read and write the same stream of + /// data, and options set on one stream will be propagated to the other + /// stream. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); + /// Ok(()) + /// } + /// ``` + pub fn try_clone(&self) -> io::Result { + self.0.duplicate().map(UnixStream) + } + + /// Returns the write timeout of this socket. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(windows_unix_domain_sockets)] + /// use std::os::windows::net::UnixStream; + /// use std::time::Duration; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// socket.set_write_timeout(Some(Duration::new(1, 0))) + /// .expect("Couldn't set write timeout"); + /// assert_eq!(socket.write_timeout()?, Some(Duration::new(1, 0))); + /// Ok(()) + /// } + /// ``` + pub fn write_timeout(&self) -> io::Result> { + self.0.timeout(SO_SNDTIMEO) + } +} + +impl io::Read for UnixStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + io::Read::read(&mut &*self, buf) + } +} + +impl<'a> io::Read for &'a UnixStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } +} + +impl io::Write for UnixStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + io::Write::write(&mut &*self, buf) + } + + fn flush(&mut self) -> io::Result<()> { + io::Write::flush(&mut &*self) + } +} +impl<'a> io::Write for &'a UnixStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.write_vectored(&[io::IoSlice::new(buf)]) + } + #[inline] + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result { + self.0.write_vectored(bufs) + } + #[inline] + fn is_write_vectored(&self) -> bool { + self.0.is_write_vectored() + } +} + +impl AsSocket for UnixStream { + #[inline] + fn as_socket(&self) -> BorrowedSocket<'_> { + self.0.as_socket() + } +} + +impl AsRawSocket for UnixStream { + #[inline] + fn as_raw_socket(&self) -> RawSocket { + self.0.as_raw_socket() + } +} + +impl FromRawSocket for UnixStream { + #[inline] + unsafe fn from_raw_socket(sock: RawSocket) -> Self { + unsafe { UnixStream(Socket::from_raw_socket(sock)) } + } +} + +impl IntoRawSocket for UnixStream { + fn into_raw_socket(self) -> RawSocket { + self.0.into_raw_socket() + } +} diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 17e3cdbecd5c..0cd915261471 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -233,6 +233,11 @@ pub fn cvt(i: I) -> io::Result { if i.is_zero() { Err(io::Error::last_os_error()) } else { Ok(i) } } +#[allow(dead_code)] +pub fn cvt_nz(i: I) -> crate::io::Result<()> { + if i.is_zero() { Ok(()) } else { Err(crate::io::Error::last_os_error()) } +} + pub fn dur2timeout(dur: Duration) -> u32 { // Note that a duration is a (u64, u32) (seconds, nanoseconds) pair, and the // timeouts in windows APIs are typically u32 milliseconds. To translate, we diff --git a/library/std/tests/windows_unix_socket.rs b/library/std/tests/windows_unix_socket.rs new file mode 100644 index 000000000000..18f4c52e72c2 --- /dev/null +++ b/library/std/tests/windows_unix_socket.rs @@ -0,0 +1,86 @@ +#![cfg(windows)] +#![feature(windows_unix_domain_sockets)] +// Now only test windows_unix_domain_sockets feature +// in the future, will test both unix and windows uds +use std::io::{Read, Write}; +use std::os::windows::net::{UnixListener, UnixStream}; +use std::thread; + +#[test] +fn win_uds_smoke_bind_connect() { + let tmp = std::env::temp_dir(); + let sock_path = tmp.join("rust-test-uds-smoke.sock"); + let _ = std::fs::remove_file(&sock_path); + let listener = UnixListener::bind(&sock_path).expect("bind failed"); + let sock_path_clone = sock_path.clone(); + let tx = thread::spawn(move || { + let mut stream = UnixStream::connect(&sock_path_clone).expect("connect failed"); + stream.write_all(b"hello").expect("write failed"); + }); + + let (mut stream, _) = listener.accept().expect("accept failed"); + let mut buf = [0; 5]; + stream.read_exact(&mut buf).expect("read failed"); + assert_eq!(&buf, b"hello"); + + tx.join().unwrap(); + + drop(listener); + let _ = std::fs::remove_file(&sock_path); +} + +#[test] +fn win_uds_echo() { + let tmp = std::env::temp_dir(); + let sock_path = tmp.join("rust-test-uds-echo.sock"); + let _ = std::fs::remove_file(&sock_path); + + let listener = UnixListener::bind(&sock_path).expect("bind failed"); + let srv = thread::spawn(move || { + let (mut stream, _) = listener.accept().expect("accept failed"); + let mut buf = [0u8; 128]; + loop { + let n = match stream.read(&mut buf) { + Ok(0) => break, + Ok(n) => n, + Err(e) => panic!("read error: {}", e), + }; + stream.write_all(&buf[..n]).expect("write_all failed"); + } + }); + + let sock_path_clone = sock_path.clone(); + let cli = thread::spawn(move || { + let mut stream = UnixStream::connect(&sock_path_clone).expect("connect failed"); + let req = b"hello windows uds"; + stream.write_all(req).expect("write failed"); + let mut resp = vec![0u8; req.len()]; + stream.read_exact(&mut resp).expect("read failed"); + assert_eq!(resp, req); + }); + + cli.join().unwrap(); + srv.join().unwrap(); + + let _ = std::fs::remove_file(&sock_path); +} + +#[test] +fn win_uds_path_too_long() { + let tmp = std::env::temp_dir(); + let long_path = tmp.join("a".repeat(200)); + let result = UnixListener::bind(&long_path); + assert!(result.is_err()); + let _ = std::fs::remove_file(&long_path); +} +#[test] +fn win_uds_existing_bind() { + let tmp = std::env::temp_dir(); + let sock_path = tmp.join("rust-test-uds-existing.sock"); + let _ = std::fs::remove_file(&sock_path); + let listener = UnixListener::bind(&sock_path).expect("bind failed"); + let result = UnixListener::bind(&sock_path); + assert!(result.is_err()); + drop(listener); + let _ = std::fs::remove_file(&sock_path); +} From 8c0d93bc54f857bf04c294a25bdbfbe1e29b0900 Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 31 Jan 2026 11:01:45 +0000 Subject: [PATCH 322/978] Skip overlapping spans in argument error suggestions --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 10 ++- .../disjoint-spans-issue-151607.rs | 16 ++++ .../disjoint-spans-issue-151607.stderr | 85 +++++++++++++++++++ 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 tests/ui/argument-suggestions/disjoint-spans-issue-151607.rs create mode 100644 tests/ui/argument-suggestions/disjoint-spans-issue-151607.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index c07cbfae256d..2e85410c8960 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2647,7 +2647,15 @@ impl<'a, 'b, 'tcx> FnCallDiagCtxt<'a, 'b, 'tcx> { // To suggest a multipart suggestion when encountering `foo(1, "")` where the def // was `fn foo(())`. let (_, expected_ty) = self.formal_and_expected_inputs[expected_idx]; - suggestions.push((*arg_span, self.ty_to_snippet(expected_ty, expected_idx))); + // Check if the new suggestion would overlap with any existing suggestion. + // This can happen when we have both removal suggestions (which may include + // adjacent commas) and type replacement suggestions for the same span. + let dominated = suggestions + .iter() + .any(|(span, _)| span.contains(*arg_span) || arg_span.overlaps(*span)); + if !dominated { + suggestions.push((*arg_span, self.ty_to_snippet(expected_ty, expected_idx))); + } } } } diff --git a/tests/ui/argument-suggestions/disjoint-spans-issue-151607.rs b/tests/ui/argument-suggestions/disjoint-spans-issue-151607.rs new file mode 100644 index 000000000000..31390faa488b --- /dev/null +++ b/tests/ui/argument-suggestions/disjoint-spans-issue-151607.rs @@ -0,0 +1,16 @@ +// Regression test for #151607 +// The ICE was "all spans must be disjoint" when emitting diagnostics +// with overlapping suggestion spans. + +struct B; +struct D; +struct F; +fn foo(g: F, y: F, e: &E) { + //~^ ERROR cannot find type `E` in this scope + foo(B, g, D, E, F, G) + //~^ ERROR this function takes 3 arguments but 6 arguments were supplied + //~| ERROR cannot find value `E` in this scope + //~| ERROR cannot find value `G` in this scope +} + +fn main() {} diff --git a/tests/ui/argument-suggestions/disjoint-spans-issue-151607.stderr b/tests/ui/argument-suggestions/disjoint-spans-issue-151607.stderr new file mode 100644 index 000000000000..f1bda1203347 --- /dev/null +++ b/tests/ui/argument-suggestions/disjoint-spans-issue-151607.stderr @@ -0,0 +1,85 @@ +error[E0425]: cannot find type `E` in this scope + --> $DIR/disjoint-spans-issue-151607.rs:8:24 + | +LL | struct B; + | --------- similarly named struct `B` defined here +... +LL | fn foo(g: F, y: F, e: &E) { + | ^ + | +help: a struct with a similar name exists + | +LL - fn foo(g: F, y: F, e: &E) { +LL + fn foo(g: F, y: F, e: &B) { + | +help: you might be missing a type parameter + | +LL | fn foo(g: F, y: F, e: &E) { + | +++ + +error[E0425]: cannot find value `E` in this scope + --> $DIR/disjoint-spans-issue-151607.rs:10:18 + | +LL | foo(B, g, D, E, F, G) + | ^ + | +help: a local variable with a similar name exists + | +LL - foo(B, g, D, E, F, G) +LL + foo(B, g, D, e, F, G) + | +help: consider importing one of these constants + | +LL + use std::f128::consts::E; + | +LL + use std::f16::consts::E; + | +LL + use std::f32::consts::E; + | +LL + use std::f64::consts::E; + | + +error[E0425]: cannot find value `G` in this scope + --> $DIR/disjoint-spans-issue-151607.rs:10:24 + | +LL | foo(B, g, D, E, F, G) + | ^ + | +help: a local variable with a similar name exists + | +LL - foo(B, g, D, E, F, G) +LL + foo(B, g, D, E, F, g) + | +help: you might be missing a const parameter + | +LL | fn foo(g: F, y: F, e: &E) { + | +++++++++++++++++++++ + +error[E0061]: this function takes 3 arguments but 6 arguments were supplied + --> $DIR/disjoint-spans-issue-151607.rs:10:5 + | +LL | foo(B, g, D, E, F, G) + | ^^^ - - - unexpected argument #4 + | | | + | | unexpected argument #3 of type `D` + | unexpected argument #1 of type `B` + | +note: function defined here + --> $DIR/disjoint-spans-issue-151607.rs:8:4 + | +LL | fn foo(g: F, y: F, e: &E) { + | ^^^ ----- +help: consider borrowing here + | +LL | foo(B, g, D, E, F, &G) + | + +help: remove the extra arguments + | +LL - foo(B, g, D, E, F, G) +LL + foo(, g, F, G) + | + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0061, E0425. +For more information about an error, try `rustc --explain E0061`. From 9c1ca3a2456c9ed021312f030af27ffec7bb7e7d Mon Sep 17 00:00:00 2001 From: AudaciousAxiom <179637270+AudaciousAxiom@users.noreply.github.com> Date: Sat, 31 Jan 2026 11:37:39 +0100 Subject: [PATCH 323/978] doc_paragraphs_missing_punctuation: allow some non-punctuated paragraphs --- .../doc/doc_paragraphs_missing_punctuation.rs | 22 ++++++++----- .../doc_paragraphs_missing_punctuation.fixed | 25 +++++++++++---- .../doc/doc_paragraphs_missing_punctuation.rs | 25 +++++++++++---- .../doc_paragraphs_missing_punctuation.stderr | 32 ++++++++----------- 4 files changed, 63 insertions(+), 41 deletions(-) diff --git a/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs b/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs index a8f734637672..605d35f48baf 100644 --- a/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs +++ b/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs @@ -53,21 +53,26 @@ fn is_missing_punctuation(doc_string: &str) -> Vec { let mut no_report_depth = 0; let mut missing_punctuation = Vec::new(); let mut current_paragraph = None; + let mut current_event_is_missing_punctuation = false; for (event, offset) in Parser::new_ext(doc_string, main_body_opts() - Options::ENABLE_SMART_PUNCTUATION).into_offset_iter() { + let last_event_was_missing_punctuation = current_event_is_missing_punctuation; + current_event_is_missing_punctuation = false; + match event { - Event::Start( - Tag::CodeBlock(..) - | Tag::FootnoteDefinition(_) - | Tag::Heading { .. } - | Tag::HtmlBlock - | Tag::List(..) - | Tag::Table(_), - ) => { + Event::Start(Tag::FootnoteDefinition(_) | Tag::Heading { .. } | Tag::HtmlBlock | Tag::Table(_)) => { no_report_depth += 1; }, + Event::Start(Tag::CodeBlock(..) | Tag::List(..)) => { + no_report_depth += 1; + if last_event_was_missing_punctuation { + // Remove the error from the previous paragraph as it is followed by a code + // block or a list. + missing_punctuation.pop(); + } + }, Event::End(TagEnd::FootnoteDefinition) => { no_report_depth -= 1; }, @@ -83,6 +88,7 @@ fn is_missing_punctuation(doc_string: &str) -> Vec { Event::End(TagEnd::Paragraph) => { if let Some(mp) = current_paragraph { missing_punctuation.push(mp); + current_event_is_missing_punctuation = true; } }, Event::Code(..) | Event::Start(Tag::Link { .. }) | Event::End(TagEnd::Link) diff --git a/tests/ui/doc/doc_paragraphs_missing_punctuation.fixed b/tests/ui/doc/doc_paragraphs_missing_punctuation.fixed index 95d65039440b..faabbb381318 100644 --- a/tests/ui/doc/doc_paragraphs_missing_punctuation.fixed +++ b/tests/ui/doc/doc_paragraphs_missing_punctuation.fixed @@ -46,13 +46,6 @@ enum Exceptions { /// | -------------- | ----- | /// | Markdown table | A-ok | MarkdownTable, - /// Here is a snippet. - //~^ doc_paragraphs_missing_punctuation - /// - /// ``` - /// // Code blocks are no issues. - /// ``` - CodeBlock, } // Check the lint can be expected on a whole enum at once. @@ -130,6 +123,24 @@ enum OrderedLists { Paren, } +/// Some elements do not have to be introduced by an independent clause. +enum NotIndependentClause { + /// Lists are allowed to be introduced by a clause that is not independent: this usually + /// requires that + /// + /// - items end with a comma or a semicolon, which is not enforced; + /// - the last item end with a period, which is also not enforced. + List, + /// For instance, the function + /// + /// ``` + /// fn answer() {} + /// ``` + /// + /// returns the Answer to the Ultimate Question of Life, the Universe, and Everything. + CodeBlock, +} + /// Doc comments with trailing blank lines are supported. //~^ doc_paragraphs_missing_punctuation /// diff --git a/tests/ui/doc/doc_paragraphs_missing_punctuation.rs b/tests/ui/doc/doc_paragraphs_missing_punctuation.rs index 35b74d7d13b9..9821115601a6 100644 --- a/tests/ui/doc/doc_paragraphs_missing_punctuation.rs +++ b/tests/ui/doc/doc_paragraphs_missing_punctuation.rs @@ -46,13 +46,6 @@ enum Exceptions { /// | -------------- | ----- | /// | Markdown table | A-ok | MarkdownTable, - /// Here is a snippet - //~^ doc_paragraphs_missing_punctuation - /// - /// ``` - /// // Code blocks are no issues. - /// ``` - CodeBlock, } // Check the lint can be expected on a whole enum at once. @@ -130,6 +123,24 @@ enum OrderedLists { Paren, } +/// Some elements do not have to be introduced by an independent clause. +enum NotIndependentClause { + /// Lists are allowed to be introduced by a clause that is not independent: this usually + /// requires that + /// + /// - items end with a comma or a semicolon, which is not enforced; + /// - the last item end with a period, which is also not enforced. + List, + /// For instance, the function + /// + /// ``` + /// fn answer() {} + /// ``` + /// + /// returns the Answer to the Ultimate Question of Life, the Universe, and Everything. + CodeBlock, +} + /// Doc comments with trailing blank lines are supported //~^ doc_paragraphs_missing_punctuation /// diff --git a/tests/ui/doc/doc_paragraphs_missing_punctuation.stderr b/tests/ui/doc/doc_paragraphs_missing_punctuation.stderr index 49aa4e8aeb88..6645e771c6d3 100644 --- a/tests/ui/doc/doc_paragraphs_missing_punctuation.stderr +++ b/tests/ui/doc/doc_paragraphs_missing_punctuation.stderr @@ -32,82 +32,76 @@ LL | /// | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:49:26 - | -LL | /// Here is a snippet - | ^ help: end the paragraph with some punctuation: `.` - -error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:72:15 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:65:15 | LL | /// U+0001 | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:79:29 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:72:29 | LL | //! inner attributes too | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:90:47 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:83:47 | LL | /// **But sometimes it is missing a period** | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:95:46 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:88:46 | LL | /// _But sometimes it is missing a period_ | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:104:56 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:97:56 | LL | /// Doc comments can end with an [inline link](#anchor) | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:108:65 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:101:65 | LL | /// Some doc comments contain [link reference definitions][spec] | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:133:57 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:144:57 | LL | /// Doc comments with trailing blank lines are supported | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:139:48 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:150:48 | LL | /// This first paragraph is missing punctuation | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:143:34 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:154:34 | LL | /// And it has multiple sentences | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:146:37 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:157:37 | LL | /// Same for this third and last one | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:153:33 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:164:33 | LL | /// This ends with a code `span` | ^ help: end the paragraph with some punctuation: `.` error: doc paragraphs should end with a terminal punctuation mark - --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:162:27 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:173:27 | LL | * Block doc comments work | ^ help: end the paragraph with some punctuation: `.` -error: aborting due to 18 previous errors +error: aborting due to 17 previous errors From e60c475471ab934c6047465e00d5d2849c3711e3 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 31 Jan 2026 22:56:49 +1100 Subject: [PATCH 324/978] Remove unused method `DroplessArena::contains_slice` --- compiler/rustc_arena/src/lib.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 524baf5b07fe..6217bf46a942 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -510,19 +510,6 @@ impl DroplessArena { } } - /// Used by `Lift` to check whether this slice is allocated - /// in this arena. - #[inline] - pub fn contains_slice(&self, slice: &[T]) -> bool { - for chunk in self.chunks.borrow_mut().iter_mut() { - let ptr = slice.as_ptr().cast::().cast_mut(); - if chunk.start() <= ptr && chunk.end() >= ptr { - return true; - } - } - false - } - /// Allocates a string slice that is copied into the `DroplessArena`, returning a /// reference to it. Will panic if passed an empty string. /// From 4df307acc1ff152518eab3cc142fbd0a394143e4 Mon Sep 17 00:00:00 2001 From: zedddie Date: Fri, 30 Jan 2026 16:27:13 +0100 Subject: [PATCH 325/978] move some tests --- .../associated-const-access.rs} | 0 .../issue-49824.rs => closures/nested-closure-escape-borrow.rs} | 0 .../nested-closure-escape-borrow.stderr} | 0 .../ui/{issues/issue-17651.rs => closures/unsized_value_move.rs} | 0 .../issue-17651.stderr => closures/unsized_value_move.stderr} | 0 tests/ui/{issues/issue-18767.rs => deref/deref-in-for-loop.rs} | 0 .../ui/{issues/issue-34569.rs => match/closure-in-match-guard.rs} | 0 tests/ui/{issues/issue-29740.rs => match/large-match-mir-gen.rs} | 0 .../issue-32004.rs => pattern/constructor-type-mismatch.rs} | 0 .../constructor-type-mismatch.stderr} | 0 .../{issues/issue-3038.rs => pattern/multiple-bindings-on-var.rs} | 0 .../issue-3038.stderr => pattern/multiple-bindings-on-var.stderr} | 0 .../issue-2849.rs => pattern/or-pattern-binding-mismatch.rs} | 0 .../or-pattern-binding-mismatch.stderr} | 0 .../or-pattern-mismatched-variable-and-variant.rs} | 0 .../or-pattern-mismatched-variable-and-variant.stderr} | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{issues/issue-31267.rs => associated-consts/associated-const-access.rs} (100%) rename tests/ui/{issues/issue-49824.rs => closures/nested-closure-escape-borrow.rs} (100%) rename tests/ui/{issues/issue-49824.stderr => closures/nested-closure-escape-borrow.stderr} (100%) rename tests/ui/{issues/issue-17651.rs => closures/unsized_value_move.rs} (100%) rename tests/ui/{issues/issue-17651.stderr => closures/unsized_value_move.stderr} (100%) rename tests/ui/{issues/issue-18767.rs => deref/deref-in-for-loop.rs} (100%) rename tests/ui/{issues/issue-34569.rs => match/closure-in-match-guard.rs} (100%) rename tests/ui/{issues/issue-29740.rs => match/large-match-mir-gen.rs} (100%) rename tests/ui/{issues/issue-32004.rs => pattern/constructor-type-mismatch.rs} (100%) rename tests/ui/{issues/issue-32004.stderr => pattern/constructor-type-mismatch.stderr} (100%) rename tests/ui/{issues/issue-3038.rs => pattern/multiple-bindings-on-var.rs} (100%) rename tests/ui/{issues/issue-3038.stderr => pattern/multiple-bindings-on-var.stderr} (100%) rename tests/ui/{issues/issue-2849.rs => pattern/or-pattern-binding-mismatch.rs} (100%) rename tests/ui/{issues/issue-2849.stderr => pattern/or-pattern-binding-mismatch.stderr} (100%) rename tests/ui/{issues/issue-2848.rs => pattern/or-pattern-mismatched-variable-and-variant.rs} (100%) rename tests/ui/{issues/issue-2848.stderr => pattern/or-pattern-mismatched-variable-and-variant.stderr} (100%) diff --git a/tests/ui/issues/issue-31267.rs b/tests/ui/associated-consts/associated-const-access.rs similarity index 100% rename from tests/ui/issues/issue-31267.rs rename to tests/ui/associated-consts/associated-const-access.rs diff --git a/tests/ui/issues/issue-49824.rs b/tests/ui/closures/nested-closure-escape-borrow.rs similarity index 100% rename from tests/ui/issues/issue-49824.rs rename to tests/ui/closures/nested-closure-escape-borrow.rs diff --git a/tests/ui/issues/issue-49824.stderr b/tests/ui/closures/nested-closure-escape-borrow.stderr similarity index 100% rename from tests/ui/issues/issue-49824.stderr rename to tests/ui/closures/nested-closure-escape-borrow.stderr diff --git a/tests/ui/issues/issue-17651.rs b/tests/ui/closures/unsized_value_move.rs similarity index 100% rename from tests/ui/issues/issue-17651.rs rename to tests/ui/closures/unsized_value_move.rs diff --git a/tests/ui/issues/issue-17651.stderr b/tests/ui/closures/unsized_value_move.stderr similarity index 100% rename from tests/ui/issues/issue-17651.stderr rename to tests/ui/closures/unsized_value_move.stderr diff --git a/tests/ui/issues/issue-18767.rs b/tests/ui/deref/deref-in-for-loop.rs similarity index 100% rename from tests/ui/issues/issue-18767.rs rename to tests/ui/deref/deref-in-for-loop.rs diff --git a/tests/ui/issues/issue-34569.rs b/tests/ui/match/closure-in-match-guard.rs similarity index 100% rename from tests/ui/issues/issue-34569.rs rename to tests/ui/match/closure-in-match-guard.rs diff --git a/tests/ui/issues/issue-29740.rs b/tests/ui/match/large-match-mir-gen.rs similarity index 100% rename from tests/ui/issues/issue-29740.rs rename to tests/ui/match/large-match-mir-gen.rs diff --git a/tests/ui/issues/issue-32004.rs b/tests/ui/pattern/constructor-type-mismatch.rs similarity index 100% rename from tests/ui/issues/issue-32004.rs rename to tests/ui/pattern/constructor-type-mismatch.rs diff --git a/tests/ui/issues/issue-32004.stderr b/tests/ui/pattern/constructor-type-mismatch.stderr similarity index 100% rename from tests/ui/issues/issue-32004.stderr rename to tests/ui/pattern/constructor-type-mismatch.stderr diff --git a/tests/ui/issues/issue-3038.rs b/tests/ui/pattern/multiple-bindings-on-var.rs similarity index 100% rename from tests/ui/issues/issue-3038.rs rename to tests/ui/pattern/multiple-bindings-on-var.rs diff --git a/tests/ui/issues/issue-3038.stderr b/tests/ui/pattern/multiple-bindings-on-var.stderr similarity index 100% rename from tests/ui/issues/issue-3038.stderr rename to tests/ui/pattern/multiple-bindings-on-var.stderr diff --git a/tests/ui/issues/issue-2849.rs b/tests/ui/pattern/or-pattern-binding-mismatch.rs similarity index 100% rename from tests/ui/issues/issue-2849.rs rename to tests/ui/pattern/or-pattern-binding-mismatch.rs diff --git a/tests/ui/issues/issue-2849.stderr b/tests/ui/pattern/or-pattern-binding-mismatch.stderr similarity index 100% rename from tests/ui/issues/issue-2849.stderr rename to tests/ui/pattern/or-pattern-binding-mismatch.stderr diff --git a/tests/ui/issues/issue-2848.rs b/tests/ui/pattern/or-pattern-mismatched-variable-and-variant.rs similarity index 100% rename from tests/ui/issues/issue-2848.rs rename to tests/ui/pattern/or-pattern-mismatched-variable-and-variant.rs diff --git a/tests/ui/issues/issue-2848.stderr b/tests/ui/pattern/or-pattern-mismatched-variable-and-variant.stderr similarity index 100% rename from tests/ui/issues/issue-2848.stderr rename to tests/ui/pattern/or-pattern-mismatched-variable-and-variant.stderr From 086dc0258bd5d12570a79f23b73ea030c0acbd00 Mon Sep 17 00:00:00 2001 From: zedddie Date: Fri, 30 Jan 2026 16:27:49 +0100 Subject: [PATCH 326/978] clean up some tests --- tests/ui/associated-consts/associated-const-access.rs | 2 +- tests/ui/closures/nested-closure-escape-borrow.rs | 1 + tests/ui/closures/nested-closure-escape-borrow.stderr | 2 +- tests/ui/closures/unsized_value_move.rs | 1 + tests/ui/closures/unsized_value_move.stderr | 2 +- tests/ui/deref/deref-in-for-loop.rs | 1 + tests/ui/match/closure-in-match-guard.rs | 1 + tests/ui/match/large-match-mir-gen.rs | 5 +++-- tests/ui/pattern/constructor-type-mismatch.rs | 1 + tests/ui/pattern/constructor-type-mismatch.stderr | 4 ++-- tests/ui/pattern/multiple-bindings-on-var.rs | 1 + tests/ui/pattern/multiple-bindings-on-var.stderr | 6 +++--- tests/ui/pattern/or-pattern-binding-mismatch.rs | 1 + tests/ui/pattern/or-pattern-binding-mismatch.stderr | 2 +- .../pattern/or-pattern-mismatched-variable-and-variant.rs | 1 + .../or-pattern-mismatched-variable-and-variant.stderr | 4 ++-- 16 files changed, 22 insertions(+), 13 deletions(-) diff --git a/tests/ui/associated-consts/associated-const-access.rs b/tests/ui/associated-consts/associated-const-access.rs index d6081bb87439..d6508d4922ae 100644 --- a/tests/ui/associated-consts/associated-const-access.rs +++ b/tests/ui/associated-consts/associated-const-access.rs @@ -1,5 +1,5 @@ +//! regression test for //@ run-pass -// Regression test for issue #31267 struct Foo; diff --git a/tests/ui/closures/nested-closure-escape-borrow.rs b/tests/ui/closures/nested-closure-escape-borrow.rs index bc1cd6856bc9..afd440ba4250 100644 --- a/tests/ui/closures/nested-closure-escape-borrow.rs +++ b/tests/ui/closures/nested-closure-escape-borrow.rs @@ -1,3 +1,4 @@ +//! regression test for fn main() { let mut x = 0; || { diff --git a/tests/ui/closures/nested-closure-escape-borrow.stderr b/tests/ui/closures/nested-closure-escape-borrow.stderr index 1c77090de27b..5a77652fa376 100644 --- a/tests/ui/closures/nested-closure-escape-borrow.stderr +++ b/tests/ui/closures/nested-closure-escape-borrow.stderr @@ -1,5 +1,5 @@ error: captured variable cannot escape `FnMut` closure body - --> $DIR/issue-49824.rs:4:9 + --> $DIR/nested-closure-escape-borrow.rs:5:9 | LL | let mut x = 0; | ----- variable defined here diff --git a/tests/ui/closures/unsized_value_move.rs b/tests/ui/closures/unsized_value_move.rs index 7629a5a3be1e..da39cc0f35f4 100644 --- a/tests/ui/closures/unsized_value_move.rs +++ b/tests/ui/closures/unsized_value_move.rs @@ -1,3 +1,4 @@ +//! regression test for // Test that moves of unsized values within closures are caught // and rejected. diff --git a/tests/ui/closures/unsized_value_move.stderr b/tests/ui/closures/unsized_value_move.stderr index 9519507320d8..a9a26a42d167 100644 --- a/tests/ui/closures/unsized_value_move.stderr +++ b/tests/ui/closures/unsized_value_move.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time - --> $DIR/issue-17651.rs:5:18 + --> $DIR/unsized_value_move.rs:6:18 | LL | (|| Box::new(*(&[0][..])))(); | -------- ^^^^^^^^^^^ doesn't have a size known at compile-time diff --git a/tests/ui/deref/deref-in-for-loop.rs b/tests/ui/deref/deref-in-for-loop.rs index 87762406da60..26921c3f1dda 100644 --- a/tests/ui/deref/deref-in-for-loop.rs +++ b/tests/ui/deref/deref-in-for-loop.rs @@ -1,3 +1,4 @@ +//! regression test for //@ run-pass // Test that regionck uses the right memcat for patterns in for loops // and doesn't ICE. diff --git a/tests/ui/match/closure-in-match-guard.rs b/tests/ui/match/closure-in-match-guard.rs index 25b2e7fbe160..c3f16dad4bfb 100644 --- a/tests/ui/match/closure-in-match-guard.rs +++ b/tests/ui/match/closure-in-match-guard.rs @@ -1,3 +1,4 @@ +//! regression test for //@ run-pass //@ compile-flags:-g diff --git a/tests/ui/match/large-match-mir-gen.rs b/tests/ui/match/large-match-mir-gen.rs index e26e2c882dc3..bb084a9ef0d0 100644 --- a/tests/ui/match/large-match-mir-gen.rs +++ b/tests/ui/match/large-match-mir-gen.rs @@ -1,7 +1,8 @@ +//! regression test for //@ check-pass #![allow(dead_code)] -// Regression test for #29740. Inefficient MIR matching algorithms -// generated way too much code for this sort of case, leading to OOM. +// Inefficient MIR matching algorithms generated way +// too much code for this sort of case, leading to OOM. #![allow(non_snake_case)] pub mod KeyboardEventConstants { diff --git a/tests/ui/pattern/constructor-type-mismatch.rs b/tests/ui/pattern/constructor-type-mismatch.rs index b3493508c5a9..77b8e5312dca 100644 --- a/tests/ui/pattern/constructor-type-mismatch.rs +++ b/tests/ui/pattern/constructor-type-mismatch.rs @@ -1,3 +1,4 @@ +//! regression test for enum Foo { Bar(i32), Baz diff --git a/tests/ui/pattern/constructor-type-mismatch.stderr b/tests/ui/pattern/constructor-type-mismatch.stderr index fcbec97661b4..6610e12cdc75 100644 --- a/tests/ui/pattern/constructor-type-mismatch.stderr +++ b/tests/ui/pattern/constructor-type-mismatch.stderr @@ -1,5 +1,5 @@ error[E0532]: expected unit struct, unit variant or constant, found tuple variant `Foo::Bar` - --> $DIR/issue-32004.rs:10:9 + --> $DIR/constructor-type-mismatch.rs:11:9 | LL | Bar(i32), | -------- `Foo::Bar` defined here @@ -20,7 +20,7 @@ LL + Foo::Baz => {} | error[E0532]: expected tuple struct or tuple variant, found unit struct `S` - --> $DIR/issue-32004.rs:16:9 + --> $DIR/constructor-type-mismatch.rs:17:9 | LL | struct S; | --------- `S` defined here diff --git a/tests/ui/pattern/multiple-bindings-on-var.rs b/tests/ui/pattern/multiple-bindings-on-var.rs index cf3ba009f00c..f84276257b67 100644 --- a/tests/ui/pattern/multiple-bindings-on-var.rs +++ b/tests/ui/pattern/multiple-bindings-on-var.rs @@ -1,3 +1,4 @@ +//! regression test for enum F { G(isize, isize) } enum H { I(J, K) } diff --git a/tests/ui/pattern/multiple-bindings-on-var.stderr b/tests/ui/pattern/multiple-bindings-on-var.stderr index 210da2ceff9b..c2ec11c43465 100644 --- a/tests/ui/pattern/multiple-bindings-on-var.stderr +++ b/tests/ui/pattern/multiple-bindings-on-var.stderr @@ -1,17 +1,17 @@ error[E0416]: identifier `x` is bound more than once in the same pattern - --> $DIR/issue-3038.rs:12:15 + --> $DIR/multiple-bindings-on-var.rs:13:15 | LL | F::G(x, x) => { println!("{}", x + x); } | ^ used in a pattern more than once error[E0416]: identifier `x` is bound more than once in the same pattern - --> $DIR/issue-3038.rs:17:32 + --> $DIR/multiple-bindings-on-var.rs:18:32 | LL | H::I(J::L(x, _), K::M(_, x)) | ^ used in a pattern more than once error[E0416]: identifier `x` is bound more than once in the same pattern - --> $DIR/issue-3038.rs:23:13 + --> $DIR/multiple-bindings-on-var.rs:24:13 | LL | (x, x) => { x } | ^ used in a pattern more than once diff --git a/tests/ui/pattern/or-pattern-binding-mismatch.rs b/tests/ui/pattern/or-pattern-binding-mismatch.rs index 787ab0e28960..a207c3f81899 100644 --- a/tests/ui/pattern/or-pattern-binding-mismatch.rs +++ b/tests/ui/pattern/or-pattern-binding-mismatch.rs @@ -1,3 +1,4 @@ +//! regression test for enum Foo { Alpha, Beta(isize) } fn main() { diff --git a/tests/ui/pattern/or-pattern-binding-mismatch.stderr b/tests/ui/pattern/or-pattern-binding-mismatch.stderr index ef5cdb42e610..46984fac03ce 100644 --- a/tests/ui/pattern/or-pattern-binding-mismatch.stderr +++ b/tests/ui/pattern/or-pattern-binding-mismatch.stderr @@ -1,5 +1,5 @@ error[E0408]: variable `i` is not bound in all patterns - --> $DIR/issue-2849.rs:5:7 + --> $DIR/or-pattern-binding-mismatch.rs:6:7 | LL | Foo::Alpha | Foo::Beta(i) => {} | ^^^^^^^^^^ - variable not in all patterns diff --git a/tests/ui/pattern/or-pattern-mismatched-variable-and-variant.rs b/tests/ui/pattern/or-pattern-mismatched-variable-and-variant.rs index 8499459cec26..0447fd2ad589 100644 --- a/tests/ui/pattern/or-pattern-mismatched-variable-and-variant.rs +++ b/tests/ui/pattern/or-pattern-mismatched-variable-and-variant.rs @@ -1,3 +1,4 @@ +//! regression test for #[allow(non_camel_case_types)] mod bar { diff --git a/tests/ui/pattern/or-pattern-mismatched-variable-and-variant.stderr b/tests/ui/pattern/or-pattern-mismatched-variable-and-variant.stderr index 1cef27c34635..66c7d7d348c9 100644 --- a/tests/ui/pattern/or-pattern-mismatched-variable-and-variant.stderr +++ b/tests/ui/pattern/or-pattern-mismatched-variable-and-variant.stderr @@ -1,5 +1,5 @@ error[E0408]: variable `beta` is not bound in all patterns - --> $DIR/issue-2848.rs:14:7 + --> $DIR/or-pattern-mismatched-variable-and-variant.rs:15:7 | LL | alpha | beta => {} | ^^^^^ ---- variable not in all patterns @@ -7,7 +7,7 @@ LL | alpha | beta => {} | pattern doesn't bind `beta` error[E0170]: pattern binding `beta` is named the same as one of the variants of the type `bar::foo` - --> $DIR/issue-2848.rs:14:15 + --> $DIR/or-pattern-mismatched-variable-and-variant.rs:15:15 | LL | alpha | beta => {} | ^^^^ help: to match on the variant, qualify the path: `bar::foo::beta` From 9ea3034b584962c763d970d49b897e69dadf1061 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 31 Jan 2026 17:15:16 +0100 Subject: [PATCH 327/978] powerpc: implement `vnmsubfp` using `intrinsics::simd` --- .../stdarch/crates/core_arch/src/powerpc/altivec.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs index fb1a9d8ed9e2..9d54abc5833b 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/altivec.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/altivec.rs @@ -129,8 +129,6 @@ unsafe extern "C" { b: vector_signed_short, c: vector_signed_int, ) -> vector_signed_int; - #[link_name = "llvm.ppc.altivec.vnmsubfp"] - fn vnmsubfp(a: vector_float, b: vector_float, c: vector_float) -> vector_float; #[link_name = "llvm.ppc.altivec.vsum2sws"] fn vsum2sws(a: vector_signed_int, b: vector_signed_int) -> vector_signed_int; #[link_name = "llvm.ppc.altivec.vsum4ubs"] @@ -1881,9 +1879,9 @@ mod sealed { #[inline] #[target_feature(enable = "altivec")] - #[cfg_attr(test, assert_instr(vnmsubfp))] - unsafe fn vec_vnmsubfp(a: vector_float, b: vector_float, c: vector_float) -> vector_float { - vnmsubfp(a, b, c) + #[cfg_attr(test, assert_instr(xvnmsubasp))] + pub unsafe fn vec_vnmsubfp(a: vector_float, b: vector_float, c: vector_float) -> vector_float { + simd_neg(simd_fma(a, b, simd_neg(c))) } #[inline] @@ -4281,7 +4279,7 @@ pub unsafe fn vec_madd(a: vector_float, b: vector_float, c: vector_float) -> vec #[target_feature(enable = "altivec")] #[unstable(feature = "stdarch_powerpc", issue = "111145")] pub unsafe fn vec_nmsub(a: vector_float, b: vector_float, c: vector_float) -> vector_float { - vnmsubfp(a, b, c) + sealed::vec_vnmsubfp(a, b, c) } /// Vector Select From ebc618aab5f6476b215f2b908cbf919765534f6d Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 31 Jan 2026 18:47:56 +0100 Subject: [PATCH 328/978] wasm: use `intrinsics::simd` for the narrow functions --- .../crates/core_arch/src/wasm32/simd128.rs | 72 +++++++++++++++---- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/wasm32/simd128.rs b/library/stdarch/crates/core_arch/src/wasm32/simd128.rs index c864d6a516e0..e1a375496590 100644 --- a/library/stdarch/crates/core_arch/src/wasm32/simd128.rs +++ b/library/stdarch/crates/core_arch/src/wasm32/simd128.rs @@ -86,10 +86,6 @@ unsafe extern "unadjusted" { fn llvm_i8x16_all_true(x: simd::i8x16) -> i32; #[link_name = "llvm.wasm.bitmask.v16i8"] fn llvm_bitmask_i8x16(a: simd::i8x16) -> i32; - #[link_name = "llvm.wasm.narrow.signed.v16i8.v8i16"] - fn llvm_narrow_i8x16_s(a: simd::i16x8, b: simd::i16x8) -> simd::i8x16; - #[link_name = "llvm.wasm.narrow.unsigned.v16i8.v8i16"] - fn llvm_narrow_i8x16_u(a: simd::i16x8, b: simd::i16x8) -> simd::i8x16; #[link_name = "llvm.wasm.avgr.unsigned.v16i8"] fn llvm_avgr_u_i8x16(a: simd::i8x16, b: simd::i8x16) -> simd::i8x16; @@ -103,10 +99,6 @@ unsafe extern "unadjusted" { fn llvm_i16x8_all_true(x: simd::i16x8) -> i32; #[link_name = "llvm.wasm.bitmask.v8i16"] fn llvm_bitmask_i16x8(a: simd::i16x8) -> i32; - #[link_name = "llvm.wasm.narrow.signed.v8i16.v4i32"] - fn llvm_narrow_i16x8_s(a: simd::i32x4, b: simd::i32x4) -> simd::i16x8; - #[link_name = "llvm.wasm.narrow.unsigned.v8i16.v4i32"] - fn llvm_narrow_i16x8_u(a: simd::i32x4, b: simd::i32x4) -> simd::i16x8; #[link_name = "llvm.wasm.avgr.unsigned.v8i16"] fn llvm_avgr_u_i16x8(a: simd::i16x8, b: simd::i16x8) -> simd::i16x8; @@ -2281,7 +2273,23 @@ pub use i8x16_bitmask as u8x16_bitmask; #[doc(alias("i8x16.narrow_i16x8_s"))] #[stable(feature = "wasm_simd", since = "1.54.0")] pub fn i8x16_narrow_i16x8(a: v128, b: v128) -> v128 { - unsafe { llvm_narrow_i8x16_s(a.as_i16x8(), b.as_i16x8()).v128() } + unsafe { + let v: simd::i16x16 = simd_shuffle!( + a.as_i16x8(), + b.as_i16x8(), + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + ); + + let max = simd_splat(i16::from(i8::MAX)); + let min = simd_splat(i16::from(i8::MIN)); + + let v = simd_select(simd_gt::<_, simd::i16x16>(v, max), max, v); + let v = simd_select(simd_lt::<_, simd::i16x16>(v, min), min, v); + + let v: simd::i8x16 = simd_cast(v); + + v.v128() + } } /// Converts two input vectors into a smaller lane vector by narrowing each @@ -2295,7 +2303,23 @@ pub fn i8x16_narrow_i16x8(a: v128, b: v128) -> v128 { #[doc(alias("i8x16.narrow_i16x8_u"))] #[stable(feature = "wasm_simd", since = "1.54.0")] pub fn u8x16_narrow_i16x8(a: v128, b: v128) -> v128 { - unsafe { llvm_narrow_i8x16_u(a.as_i16x8(), b.as_i16x8()).v128() } + unsafe { + let v: simd::i16x16 = simd_shuffle!( + a.as_i16x8(), + b.as_i16x8(), + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + ); + + let max = simd_splat(i16::from(u8::MAX)); + let min = simd_splat(i16::from(u8::MIN)); + + let v = simd_select(simd_gt::<_, simd::i16x16>(v, max), max, v); + let v = simd_select(simd_lt::<_, simd::i16x16>(v, min), min, v); + + let v: simd::u8x16 = simd_cast(v); + + v.v128() + } } /// Shifts each lane to the left by the specified number of bits. @@ -2593,7 +2617,19 @@ pub use i16x8_bitmask as u16x8_bitmask; #[doc(alias("i16x8.narrow_i32x4_s"))] #[stable(feature = "wasm_simd", since = "1.54.0")] pub fn i16x8_narrow_i32x4(a: v128, b: v128) -> v128 { - unsafe { llvm_narrow_i16x8_s(a.as_i32x4(), b.as_i32x4()).v128() } + unsafe { + let v: simd::i32x8 = simd_shuffle!(a, b, [0, 1, 2, 3, 4, 5, 6, 7]); + + let max = simd_splat(i32::from(i16::MAX)); + let min = simd_splat(i32::from(i16::MIN)); + + let v = simd_select(simd_gt::<_, simd::i32x8>(v, max), max, v); + let v = simd_select(simd_lt::<_, simd::i32x8>(v, min), min, v); + + let v: simd::i16x8 = simd_cast(v); + + v.v128() + } } /// Converts two input vectors into a smaller lane vector by narrowing each @@ -2607,7 +2643,19 @@ pub fn i16x8_narrow_i32x4(a: v128, b: v128) -> v128 { #[doc(alias("i16x8.narrow_i32x4_u"))] #[stable(feature = "wasm_simd", since = "1.54.0")] pub fn u16x8_narrow_i32x4(a: v128, b: v128) -> v128 { - unsafe { llvm_narrow_i16x8_u(a.as_i32x4(), b.as_i32x4()).v128() } + unsafe { + let v: simd::i32x8 = simd_shuffle!(a, b, [0, 1, 2, 3, 4, 5, 6, 7]); + + let max = simd_splat(i32::from(u16::MAX)); + let min = simd_splat(i32::from(u16::MIN)); + + let v = simd_select(simd_gt::<_, simd::i32x8>(v, max), max, v); + let v = simd_select(simd_lt::<_, simd::i32x8>(v, min), min, v); + + let v: simd::u16x8 = simd_cast(v); + + v.v128() + } } /// Converts low half of the smaller lane vector to a larger lane From 631120b803ddf096922832d41ea88afd212e5ed0 Mon Sep 17 00:00:00 2001 From: linshuy2 Date: Sat, 31 Jan 2026 17:48:26 +0000 Subject: [PATCH 329/978] fix: `unwrap_used` and `expect_used` FN when using fully qualified syntax --- clippy_lints/src/methods/mod.rs | 10 +++ .../src/methods/unwrap_expect_used.rs | 68 +++++++++++++++++++ tests/ui/unwrap_expect_used.rs | 12 ++++ tests/ui/unwrap_expect_used.stderr | 50 +++++++++++++- 4 files changed, 139 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 3ca7f6bc29c5..355b34d195da 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -4965,6 +4965,16 @@ impl<'tcx> LateLintPass<'tcx> for Methods { io_other_error::check(cx, expr, func, args, self.msrv); swap_with_temporary::check(cx, expr, func, args); ip_constant::check(cx, expr, func, args); + unwrap_expect_used::check_call( + cx, + expr, + func, + args, + self.allow_unwrap_in_tests, + self.allow_expect_in_tests, + self.allow_unwrap_in_consts, + self.allow_expect_in_consts, + ); }, ExprKind::MethodCall(..) => { self.check_methods(cx, expr); diff --git a/clippy_lints/src/methods/unwrap_expect_used.rs b/clippy_lints/src/methods/unwrap_expect_used.rs index 30db2a75df57..4effab3a5e63 100644 --- a/clippy_lints/src/methods/unwrap_expect_used.rs +++ b/clippy_lints/src/methods/unwrap_expect_used.rs @@ -3,6 +3,7 @@ use clippy_utils::res::MaybeDef; use clippy_utils::ty::is_never_like; use clippy_utils::{is_in_test, is_inside_always_const_context, is_lint_allowed}; use rustc_hir::Expr; +use rustc_hir::def::DefKind; use rustc_lint::{LateContext, Lint}; use rustc_middle::ty; use rustc_span::sym; @@ -87,3 +88,70 @@ pub(super) fn check( }, ); } + +#[expect(clippy::too_many_arguments, clippy::fn_params_excessive_bools)] +pub(super) fn check_call( + cx: &LateContext<'_>, + expr: &Expr<'_>, + func: &Expr<'_>, + args: &[Expr<'_>], + allow_unwrap_in_consts: bool, + allow_unwrap_in_tests: bool, + allow_expect_in_consts: bool, + allow_expect_in_tests: bool, +) { + let Some(recv) = args.first() else { + return; + }; + let Some((DefKind::AssocFn, def_id)) = cx.typeck_results().type_dependent_def(func.hir_id) else { + return; + }; + + match cx.tcx.item_name(def_id) { + sym::unwrap => { + check( + cx, + expr, + recv, + false, + allow_unwrap_in_consts, + allow_unwrap_in_tests, + Variant::Unwrap, + ); + }, + sym::expect => { + check( + cx, + expr, + recv, + false, + allow_expect_in_consts, + allow_expect_in_tests, + Variant::Expect, + ); + }, + clippy_utils::sym::unwrap_err => { + check( + cx, + expr, + recv, + true, + allow_unwrap_in_consts, + allow_unwrap_in_tests, + Variant::Unwrap, + ); + }, + clippy_utils::sym::expect_err => { + check( + cx, + expr, + recv, + true, + allow_expect_in_consts, + allow_expect_in_tests, + Variant::Expect, + ); + }, + _ => (), + } +} diff --git a/tests/ui/unwrap_expect_used.rs b/tests/ui/unwrap_expect_used.rs index b429f3a8a0bb..207d4dd815be 100644 --- a/tests/ui/unwrap_expect_used.rs +++ b/tests/ui/unwrap_expect_used.rs @@ -83,3 +83,15 @@ mod with_expansion { let _ = open!(file).expect_err("can open"); //~ expect_used } } + +fn issue16484() { + let opt = Some(()); + Option::unwrap(opt); //~ unwrap_used + Option::expect(opt, "error message"); //~ expect_used + + let res: Result<(), i32> = Ok(()); + Result::unwrap(res); //~ unwrap_used + Result::expect(res, "error message"); //~ expect_used + Result::unwrap_err(res); //~ unwrap_used + Result::expect_err(res, "error message"); //~ expect_used +} diff --git a/tests/ui/unwrap_expect_used.stderr b/tests/ui/unwrap_expect_used.stderr index 6fd1b84d8123..b9a2844b284c 100644 --- a/tests/ui/unwrap_expect_used.stderr +++ b/tests/ui/unwrap_expect_used.stderr @@ -82,5 +82,53 @@ LL | let _ = open!(file).expect_err("can open"); | = note: if this value is an `Ok`, it will panic -error: aborting due to 10 previous errors +error: used `unwrap()` on an `Option` value + --> tests/ui/unwrap_expect_used.rs:89:5 + | +LL | Option::unwrap(opt); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is `None`, it will panic + +error: used `expect()` on an `Option` value + --> tests/ui/unwrap_expect_used.rs:90:5 + | +LL | Option::expect(opt, "error message"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is `None`, it will panic + +error: used `unwrap()` on a `Result` value + --> tests/ui/unwrap_expect_used.rs:93:5 + | +LL | Result::unwrap(res); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is an `Err`, it will panic + +error: used `expect()` on a `Result` value + --> tests/ui/unwrap_expect_used.rs:94:5 + | +LL | Result::expect(res, "error message"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is an `Err`, it will panic + +error: used `unwrap_err()` on a `Result` value + --> tests/ui/unwrap_expect_used.rs:95:5 + | +LL | Result::unwrap_err(res); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is an `Ok`, it will panic + +error: used `expect_err()` on a `Result` value + --> tests/ui/unwrap_expect_used.rs:96:5 + | +LL | Result::expect_err(res, "error message"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is an `Ok`, it will panic + +error: aborting due to 16 previous errors From 7bb156395edb2bdc591b4774bc2cea9dd28d94da Mon Sep 17 00:00:00 2001 From: JayanAXHF Date: Sat, 31 Jan 2026 23:37:56 +0530 Subject: [PATCH 330/978] fix: fix `handle_explain` to always respect `--color always` --- compiler/rustc_driver_impl/src/lib.rs | 37 ++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 38ee87601614..2b837cc8442b 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -491,10 +491,18 @@ fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, col } text.push('\n'); } + + // If output is a terminal, use a pager to display the content. if io::stdout().is_terminal() { show_md_content_with_pager(&text, color); } else { - safe_print!("{text}"); + // Otherwise, if the user has requested colored output + // print the content in color, else print the md content. + if color == ColorConfig::Always { + show_colored_md_content(&text); + } else { + safe_print!("{text}"); + } } } else { early_dcx.early_fatal(format!("{code} is not a valid error code")); @@ -564,6 +572,33 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) { safe_print!("{content}"); } +/// Prints the markdown content with colored output. +/// +/// This function is used when the output is not a terminal, +/// but the user has requested colored output with `--color=always`. +fn show_colored_md_content(content: &str) { + // Try to prettify the raw markdown text. + let mut pretty_data = { + let mdstream = markdown::MdStream::parse_str(content); + let bufwtr = markdown::create_stdout_bufwtr(); + let mut mdbuf = Vec::new(); + if mdstream.write_anstream_buf(&mut mdbuf, Some(&highlighter::highlight)).is_ok() { + Some((bufwtr, mdbuf)) + } else { + None + } + }; + + if let Some((bufwtr, mdbuf)) = &mut pretty_data + && bufwtr.write_all(&mdbuf).is_ok() + { + return; + } + + // Everything failed. Print the raw markdown text. + safe_print!("{content}"); +} + fn process_rlink(sess: &Session, compiler: &interface::Compiler) { assert!(sess.opts.unstable_opts.link_only); let dcx = sess.dcx(); From a3e94c843398b096b79c05506ee248638afd1e6c Mon Sep 17 00:00:00 2001 From: JayanAXHF Date: Sun, 1 Feb 2026 00:23:04 +0530 Subject: [PATCH 331/978] test: add tests to ensure that `--color always` is always respected --- tests/ui/explain/ensure-color-always-works.rs | 2 + .../explain/ensure-color-always-works.stdout | 50 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 tests/ui/explain/ensure-color-always-works.rs create mode 100644 tests/ui/explain/ensure-color-always-works.stdout diff --git a/tests/ui/explain/ensure-color-always-works.rs b/tests/ui/explain/ensure-color-always-works.rs new file mode 100644 index 000000000000..81ee716e78b4 --- /dev/null +++ b/tests/ui/explain/ensure-color-always-works.rs @@ -0,0 +1,2 @@ +//@ compile-flags: --explain E0591 --color always --error-format=human +//@ check-pass diff --git a/tests/ui/explain/ensure-color-always-works.stdout b/tests/ui/explain/ensure-color-always-works.stdout new file mode 100644 index 000000000000..7e5358bcfb7e --- /dev/null +++ b/tests/ui/explain/ensure-color-always-works.stdout @@ -0,0 +1,50 @@ +Per ]8;;https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md\RFC 401]8;;\, if you have a function declaration foo: + +struct S; + +// For the purposes of this explanation, all of these +// different kinds of `fn` declarations are equivalent: + +fn foo(x: S) { /* ... */ } +extern "C" { + fn foo(x: S); +} +impl S { + fn foo(self) { /* ... */ } +} + +the type of foo is not fn(S), as one might expect. Rather, it is a unique, zero-sized marker type written here as typeof(foo). However, typeof(foo) + can be coerced to a function pointer fn(S), so you rarely notice this: + +let x: fn(S) = foo; // OK, coerces + +The reason that this matter is that the type fn(S) is not specific to any particular function: it's a function pointer. So calling x() +results in a virtual call, whereas foo() is statically dispatched, because the type of foo tells us precisely what function is being called. + +As noted above, coercions mean that most code doesn't have to be concerned with this distinction. However, you can tell the difference when +using transmute to convert a fn item into a fn pointer. + +This is sometimes done as part of an FFI: + +extern "C" fn foo(userdata: Box<i32>) { + /* ... */ +} + +unsafe { + let f: extern "C" fn(*mut i32) = transmute(foo); + callback(f); +} + +Here, transmute is being used to convert the types of the fn arguments. This pattern is incorrect because the type of foo is a function item +(typeof(foo)), which is zero-sized, and the target type (fn()) is a function pointer, which is not zero-sized. This pattern should be +rewritten. There are a few possible ways to do this: + +* change the original fn declaration to match the expected signature, and do the cast in the fn body (the preferred option) +* cast the fn item of a fn pointer before calling transmute, as shown here: + +let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); +let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too + +The same applies to transmutes to *mut fn(), which were observed in practice. Note though that use of this type is generally incorrect. The +intention is typically to describe a function pointer, but just fn() alone suffices for that. *mut fn() is a pointer to a fn pointer. (Since these +values are typically just passed to C code, however, this rarely makes a difference in practice.) From 49f9fe75ee257070af2d689265ccd16f1c9ddf76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 31 Jan 2026 00:15:00 +0100 Subject: [PATCH 332/978] Remove the `dep_node` argument from `try_mark_previous_green` --- .../rustc_query_system/src/dep_graph/graph.rs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index cf3d211d1cc7..36f5ccfc68f4 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -872,6 +872,8 @@ impl DepGraphData { // Return None if the dep node didn't exist in the previous session let prev_index = self.previous.node_to_index_opt(dep_node)?; + debug_assert_eq!(self.previous.index_to_node(prev_index), dep_node); + match self.colors.get(prev_index) { DepNodeColor::Green(dep_node_index) => Some((prev_index, dep_node_index)), DepNodeColor::Red => None, @@ -880,7 +882,7 @@ impl DepGraphData { // in the previous compilation session too, so we can try to // mark it as green by recursively marking all of its // dependencies green. - self.try_mark_previous_green(qcx, prev_index, dep_node, None) + self.try_mark_previous_green(qcx, prev_index, None) .map(|dep_node_index| (prev_index, dep_node_index)) } } @@ -928,8 +930,7 @@ impl DepGraphData { dep_dep_node, dep_dep_node.hash, ); - let node_index = - self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node, Some(frame)); + let node_index = self.try_mark_previous_green(qcx, parent_dep_node_index, Some(frame)); if node_index.is_some() { debug!("managed to MARK dependency {dep_dep_node:?} as green"); @@ -981,15 +982,15 @@ impl DepGraphData { &self, qcx: Qcx, prev_dep_node_index: SerializedDepNodeIndex, - dep_node: &DepNode, frame: Option<&MarkFrame<'_>>, ) -> Option { let frame = MarkFrame { index: prev_dep_node_index, parent: frame }; // We never try to mark eval_always nodes as green - debug_assert!(!qcx.dep_context().is_eval_always(dep_node.kind)); - - debug_assert_eq!(self.previous.index_to_node(prev_dep_node_index), dep_node); + debug_assert!( + !qcx.dep_context() + .is_eval_always(self.previous.index_to_node(prev_dep_node_index).kind) + ); let prev_deps = self.previous.edge_targets_from(prev_dep_node_index); @@ -1010,7 +1011,10 @@ impl DepGraphData { // ... and finally storing a "Green" entry in the color map. // Multiple threads can all write the same color here - debug!("successfully marked {dep_node:?} as green"); + debug!( + "successfully marked {:?} as green", + self.previous.index_to_node(prev_dep_node_index) + ); Some(dep_node_index) } } From 4cf181bfa40957696c46b7637e6d2250fa18617b Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 31 Jan 2026 21:55:02 +0200 Subject: [PATCH 333/978] suggested.md: improve a bit It is awkward to continue a sentence after a code block --- src/doc/rustc-dev-guide/src/building/suggested.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index b5c9b9b4e3d1..5eb214fac904 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -277,14 +277,14 @@ This often helps reviewing. ## Configuring `rustup` to use nightly Some parts of the bootstrap process uses pinned, nightly versions of tools like rustfmt. -To make things like `cargo fmt` work correctly in your repo, run +To make things like `cargo fmt` work correctly in your repo, +[install a nightly toolchain] with rustup, then run this command: ```console cd rustup override set nightly ``` -After [installing a nightly toolchain] with `rustup`. Don't forget to do this for all directories you have [setup a worktree for]. You may need to use the pinned nightly version from `src/stage0`, but often the normal `nightly` channel will work. @@ -297,7 +297,7 @@ toolchain for your bootstrapped compiler You still have to use `x` to work on the compiler or standard library, this just lets you use `cargo fmt`. -[installing a nightly toolchain]: https://rust-lang.github.io/rustup/concepts/channels.html?highlight=nightl#working-with-nightly-rust +[install a nightly toolchain]: https://rust-lang.github.io/rustup/concepts/channels.html?highlight=nightl#working-with-nightly-rust [setup a worktree for]: ./suggested.md#working-on-multiple-branches-at-the-same-time [the section on vscode]: suggested.md#configuring-rust-analyzer-for-rustc [the section on rustup]: how-to-build-and-run.md?highlight=rustup#creating-a-rustup-toolchain From c8ce14018f082a747307a5bbc5b46ec24c2642dd Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sun, 1 Feb 2026 05:27:13 +0900 Subject: [PATCH 334/978] check if ProjectionTy or ProjectionConst fmt --- .../src/error_reporting/traits/fulfillment_errors.rs | 2 ++ .../opaque-alias-relate-issue-151331.rs | 10 ++++++++++ .../opaque-alias-relate-issue-151331.stderr | 9 +++++++++ 3 files changed, 21 insertions(+) create mode 100644 tests/ui/type-alias-impl-trait/opaque-alias-relate-issue-151331.rs create mode 100644 tests/ui/type-alias-impl-trait/opaque-alias-relate-issue-151331.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 6872d038fb7f..45e4f5fe23a6 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1607,6 +1607,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; if let Some(lhs) = lhs.to_alias_term() + && let ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst = lhs.kind(self.tcx) && let Some((better_type_err, expected_term)) = derive_better_type_error(lhs, rhs) { @@ -1615,6 +1616,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { better_type_err, ) } else if let Some(rhs) = rhs.to_alias_term() + && let ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst = rhs.kind(self.tcx) && let Some((better_type_err, expected_term)) = derive_better_type_error(rhs, lhs) { diff --git a/tests/ui/type-alias-impl-trait/opaque-alias-relate-issue-151331.rs b/tests/ui/type-alias-impl-trait/opaque-alias-relate-issue-151331.rs new file mode 100644 index 000000000000..684f2498d584 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/opaque-alias-relate-issue-151331.rs @@ -0,0 +1,10 @@ +//@ compile-flags: -Znext-solver=globally +#![feature(type_alias_impl_trait)] + +type Foo = Vec; + +#[define_opaque(Foo)] +fn make_foo() -> Foo {} +//~^ ERROR type mismatch resolving + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/opaque-alias-relate-issue-151331.stderr b/tests/ui/type-alias-impl-trait/opaque-alias-relate-issue-151331.stderr new file mode 100644 index 000000000000..dd73ed1a247c --- /dev/null +++ b/tests/ui/type-alias-impl-trait/opaque-alias-relate-issue-151331.stderr @@ -0,0 +1,9 @@ +error[E0271]: type mismatch resolving `Foo == ()` + --> $DIR/opaque-alias-relate-issue-151331.rs:7:18 + | +LL | fn make_foo() -> Foo {} + | ^^^ types differ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. From e40ae4fe2c8f0b08265d0a40a59a55f46c65e865 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 31 Jan 2026 22:11:50 +0100 Subject: [PATCH 335/978] x86: use `intrinsics::simd` for `hadds`/`hsubs` --- .../stdarch/crates/core_arch/src/x86/avx2.rs | 36 +++++++++++++++---- .../stdarch/crates/core_arch/src/x86/ssse3.rs | 22 +++++++----- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index 6a39a0aaf8fe..83aef753c9d9 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -991,7 +991,21 @@ pub const fn _mm256_hadd_epi32(a: __m256i, b: __m256i) -> __m256i { #[cfg_attr(test, assert_instr(vphaddsw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm256_hadds_epi16(a: __m256i, b: __m256i) -> __m256i { - unsafe { transmute(phaddsw(a.as_i16x16(), b.as_i16x16())) } + let a = a.as_i16x16(); + let b = b.as_i16x16(); + unsafe { + let even: i16x16 = simd_shuffle!( + a, + b, + [0, 2, 4, 6, 16, 18, 20, 22, 8, 10, 12, 14, 24, 26, 28, 30] + ); + let odd: i16x16 = simd_shuffle!( + a, + b, + [1, 3, 5, 7, 17, 19, 21, 23, 9, 11, 13, 15, 25, 27, 29, 31] + ); + simd_saturating_add(even, odd).as_m256i() + } } /// Horizontally subtract adjacent pairs of 16-bit integers in `a` and `b`. @@ -1047,7 +1061,21 @@ pub const fn _mm256_hsub_epi32(a: __m256i, b: __m256i) -> __m256i { #[cfg_attr(test, assert_instr(vphsubsw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm256_hsubs_epi16(a: __m256i, b: __m256i) -> __m256i { - unsafe { transmute(phsubsw(a.as_i16x16(), b.as_i16x16())) } + let a = a.as_i16x16(); + let b = b.as_i16x16(); + unsafe { + let even: i16x16 = simd_shuffle!( + a, + b, + [0, 2, 4, 6, 16, 18, 20, 22, 8, 10, 12, 14, 24, 26, 28, 30] + ); + let odd: i16x16 = simd_shuffle!( + a, + b, + [1, 3, 5, 7, 17, 19, 21, 23, 9, 11, 13, 15, 25, 27, 29, 31] + ); + simd_saturating_sub(even, odd).as_m256i() + } } /// Returns values from `slice` at offsets determined by `offsets * scale`, @@ -3791,10 +3819,6 @@ pub const fn _mm256_extract_epi16(a: __m256i) -> i32 { #[allow(improper_ctypes)] unsafe extern "C" { - #[link_name = "llvm.x86.avx2.phadd.sw"] - fn phaddsw(a: i16x16, b: i16x16) -> i16x16; - #[link_name = "llvm.x86.avx2.phsub.sw"] - fn phsubsw(a: i16x16, b: i16x16) -> i16x16; #[link_name = "llvm.x86.avx2.pmadd.wd"] fn pmaddwd(a: i16x16, b: i16x16) -> i32x8; #[link_name = "llvm.x86.avx2.pmadd.ub.sw"] diff --git a/library/stdarch/crates/core_arch/src/x86/ssse3.rs b/library/stdarch/crates/core_arch/src/x86/ssse3.rs index 4426a3274c38..1d7a97944a37 100644 --- a/library/stdarch/crates/core_arch/src/x86/ssse3.rs +++ b/library/stdarch/crates/core_arch/src/x86/ssse3.rs @@ -188,7 +188,13 @@ pub const fn _mm_hadd_epi16(a: __m128i, b: __m128i) -> __m128i { #[cfg_attr(test, assert_instr(phaddsw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm_hadds_epi16(a: __m128i, b: __m128i) -> __m128i { - unsafe { transmute(phaddsw128(a.as_i16x8(), b.as_i16x8())) } + let a = a.as_i16x8(); + let b = b.as_i16x8(); + unsafe { + let even: i16x8 = simd_shuffle!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); + let odd: i16x8 = simd_shuffle!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); + simd_saturating_add(even, odd).as_m128i() + } } /// Horizontally adds the adjacent pairs of values contained in 2 packed @@ -240,7 +246,13 @@ pub const fn _mm_hsub_epi16(a: __m128i, b: __m128i) -> __m128i { #[cfg_attr(test, assert_instr(phsubsw))] #[stable(feature = "simd_x86", since = "1.27.0")] pub fn _mm_hsubs_epi16(a: __m128i, b: __m128i) -> __m128i { - unsafe { transmute(phsubsw128(a.as_i16x8(), b.as_i16x8())) } + let a = a.as_i16x8(); + let b = b.as_i16x8(); + unsafe { + let even: i16x8 = simd_shuffle!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); + let odd: i16x8 = simd_shuffle!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); + simd_saturating_sub(even, odd).as_m128i() + } } /// Horizontally subtract the adjacent pairs of values contained in 2 @@ -337,12 +349,6 @@ unsafe extern "C" { #[link_name = "llvm.x86.ssse3.pshuf.b.128"] fn pshufb128(a: u8x16, b: u8x16) -> u8x16; - #[link_name = "llvm.x86.ssse3.phadd.sw.128"] - fn phaddsw128(a: i16x8, b: i16x8) -> i16x8; - - #[link_name = "llvm.x86.ssse3.phsub.sw.128"] - fn phsubsw128(a: i16x8, b: i16x8) -> i16x8; - #[link_name = "llvm.x86.ssse3.pmadd.ub.sw.128"] fn pmaddubsw128(a: u8x16, b: i8x16) -> i16x8; From 4e02b6db0aac951f02d13fa316ea7d7e3acc0e98 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 1 Feb 2026 00:00:26 +0200 Subject: [PATCH 336/978] typeck_root_def_id: improve doc comment This was initially written to be exhaustive, but one more type that can only be type-checked with its containing item has since been added, and was not mentioned. So, make it future-proof by mentioning just the one example. Also, a previous refactor left this less readable. --- compiler/rustc_middle/src/ty/util.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index c4212eee8e40..d6e6ffae7300 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -642,12 +642,8 @@ impl<'tcx> TyCtxt<'tcx> { /// has its own type-checking context or "inference environment". /// /// For example, a closure has its own `DefId`, but it is type-checked - /// with the containing item. Similarly, an inline const block has its - /// own `DefId` but it is type-checked together with the containing item. - /// - /// Therefore, when we fetch the - /// `typeck` the closure, for example, we really wind up - /// fetching the `typeck` the enclosing fn item. + /// with the containing item. Therefore, when we fetch the `typeck` of the closure, + /// for example, we really wind up fetching the `typeck` of the enclosing fn item. pub fn typeck_root_def_id(self, def_id: DefId) -> DefId { let mut def_id = def_id; while self.is_typeck_child(def_id) { From 16844173269ade1ea68f302c24ac1ebc8efedbb4 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 1 Feb 2026 00:31:55 +0200 Subject: [PATCH 337/978] ty::context: clean some code a little The explicit `return` was not needed --- compiler/rustc_middle/src/ty/context.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a6960523f6cf..41e1388e3146 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3470,10 +3470,9 @@ impl<'tcx> TyCtxt<'tcx> { pub fn intrinsic(self, def_id: impl IntoQueryParam + Copy) -> Option { match self.def_kind(def_id) { - DefKind::Fn | DefKind::AssocFn => {} - _ => return None, + DefKind::Fn | DefKind::AssocFn => self.intrinsic_raw(def_id), + _ => None, } - self.intrinsic_raw(def_id) } pub fn next_trait_solver_globally(self) -> bool { From f0b76d5a1591fc39d8a6f9c35772695a3fad0036 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Sat, 31 Jan 2026 18:57:32 -0600 Subject: [PATCH 338/978] Use with_capacity in query_key_hash_verify --- .../rustc_data_structures/src/vec_cache.rs | 4 ++++ compiler/rustc_query_impl/src/plumbing.rs | 3 +-- .../rustc_query_system/src/query/caches.rs | 18 ++++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_data_structures/src/vec_cache.rs b/compiler/rustc_data_structures/src/vec_cache.rs index 599970663db8..c3baae204f66 100644 --- a/compiler/rustc_data_structures/src/vec_cache.rs +++ b/compiler/rustc_data_structures/src/vec_cache.rs @@ -331,6 +331,10 @@ where } } } + + pub fn len(&self) -> usize { + self.len.load(Ordering::Acquire) + } } #[cfg(test)] diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 2d4e10a0380c..55c5ff911c31 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -415,9 +415,8 @@ pub(crate) fn query_key_hash_verify<'tcx>( ) { let _timer = qcx.tcx.prof.generic_activity_with_arg("query_key_hash_verify_for", query.name()); - let mut map = UnordMap::default(); - let cache = query.query_cache(qcx); + let mut map = UnordMap::with_capacity(cache.len()); cache.iter(&mut |key, _, _| { let node = DepNode::construct(qcx.tcx, query.dep_kind(), key); if let Some(other_key) = map.insert(node, *key) { diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs index 30b5d7e59549..67ad767d4d31 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_query_system/src/query/caches.rs @@ -30,6 +30,8 @@ pub trait QueryCache: Sized { fn complete(&self, key: Self::Key, value: Self::Value, index: DepNodeIndex); fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)); + + fn len(&self) -> usize; } /// In-memory cache for queries whose keys aren't suitable for any of the @@ -71,6 +73,10 @@ where } } } + + fn len(&self) -> usize { + self.cache.len() + } } /// In-memory cache for queries whose key type only has one value (e.g. `()`). @@ -107,6 +113,10 @@ where f(&(), &value.0, value.1) } } + + fn len(&self) -> usize { + self.cache.get().is_some().into() + } } /// In-memory cache for queries whose key is a [`DefId`]. @@ -157,6 +167,10 @@ where }); self.foreign.iter(f); } + + fn len(&self) -> usize { + self.local.len() + self.foreign.len() + } } impl QueryCache for VecCache @@ -180,4 +194,8 @@ where fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) { self.iter(f) } + + fn len(&self) -> usize { + self.len() + } } From a7f8b2ff97767029ba122b317f7e9431ac39c0e9 Mon Sep 17 00:00:00 2001 From: jyn Date: Sat, 31 Jan 2026 16:00:57 -0500 Subject: [PATCH 339/978] remove unnecessary uses of paths() --- src/bootstrap/src/core/build_steps/test.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 61015a141e46..7130517a91de 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -3816,7 +3816,7 @@ impl Step for CodegenCranelift { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.paths(&["compiler/rustc_codegen_cranelift"]) + run.path("compiler/rustc_codegen_cranelift") } fn is_default_step(_builder: &Builder<'_>) -> bool { @@ -3937,7 +3937,7 @@ impl Step for CodegenGCC { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.paths(&["compiler/rustc_codegen_gcc"]) + run.path("compiler/rustc_codegen_gcc") } fn is_default_step(_builder: &Builder<'_>) -> bool { From e251fba475714560d60555a26b9c1a4264776bc8 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sun, 1 Feb 2026 10:42:57 +0900 Subject: [PATCH 340/978] Replace plain text link with md link to cargo-pgo repo --- src/doc/rustc/src/profile-guided-optimization.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc/src/profile-guided-optimization.md b/src/doc/rustc/src/profile-guided-optimization.md index 4050494793a3..fa6e0912f7f0 100644 --- a/src/doc/rustc/src/profile-guided-optimization.md +++ b/src/doc/rustc/src/profile-guided-optimization.md @@ -151,7 +151,9 @@ to use PGO with Rust. As an alternative to directly using the compiler for Profile-Guided Optimization, you may choose to go with `cargo-pgo`, which has an intuitive command-line API and saves you the trouble of doing all the manual work. You can read more about -it in their repository accessible from this link: https://github.com/Kobzol/cargo-pgo +it in [their repository][cargo-pgo]. + +[cargo-pgo]: https://github.com/Kobzol/cargo-pgo For the sake of completeness, here are the corresponding steps using `cargo-pgo`: From 9b04184cbc7f1387f38a35e2e219cd88f7089cf6 Mon Sep 17 00:00:00 2001 From: Sergei Izmailov Date: Sun, 1 Feb 2026 10:46:02 +0900 Subject: [PATCH 341/978] reword --- src/doc/rustc/src/profile-guided-optimization.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/profile-guided-optimization.md b/src/doc/rustc/src/profile-guided-optimization.md index fa6e0912f7f0..eeeeffe65a02 100644 --- a/src/doc/rustc/src/profile-guided-optimization.md +++ b/src/doc/rustc/src/profile-guided-optimization.md @@ -151,7 +151,7 @@ to use PGO with Rust. As an alternative to directly using the compiler for Profile-Guided Optimization, you may choose to go with `cargo-pgo`, which has an intuitive command-line API and saves you the trouble of doing all the manual work. You can read more about -it in [their repository][cargo-pgo]. +it in [cargo-pgo repository][cargo-pgo]. [cargo-pgo]: https://github.com/Kobzol/cargo-pgo From 60f567916cc39add8a9b6571c1865577204ca729 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Sat, 31 Jan 2026 19:11:06 -0600 Subject: [PATCH 342/978] Add capacity to PlaceholderExpander --- compiler/rustc_expand/src/expand.rs | 4 +++- compiler/rustc_expand/src/placeholders.rs | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index cfa7725c7400..dc2f28992105 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -508,6 +508,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // Unresolved macros produce dummy outputs as a recovery measure. invocations.reverse(); let mut expanded_fragments = Vec::new(); + let mut expanded_fragments_len = 0; let mut undetermined_invocations = Vec::new(); let (mut progress, mut force) = (false, !self.monotonic); loop { @@ -602,6 +603,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { expanded_fragments.push(Vec::new()); } expanded_fragments[depth - 1].push((expn_id, expanded_fragment)); + expanded_fragments_len += 1; invocations.extend(derive_invocations.into_iter().rev()); } ExpandResult::Retry(invoc) => { @@ -622,7 +624,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.force_mode = orig_force_mode; // Finally incorporate all the expanded macros into the input AST fragment. - let mut placeholder_expander = PlaceholderExpander::default(); + let mut placeholder_expander = PlaceholderExpander::with_capacity(expanded_fragments_len); while let Some(expanded_fragments) = expanded_fragments.pop() { for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() { placeholder_expander diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 05f9a5aa43f7..2db18429a521 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -218,12 +218,17 @@ pub(crate) fn placeholder( } } -#[derive(Default)] pub(crate) struct PlaceholderExpander { expanded_fragments: FxHashMap, } impl PlaceholderExpander { + pub(crate) fn with_capacity(capacity: usize) -> Self { + PlaceholderExpander { + expanded_fragments: FxHashMap::with_capacity_and_hasher(capacity, Default::default()), + } + } + pub(crate) fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) { fragment.mut_visit_with(self); self.expanded_fragments.insert(id, fragment); From bf2536ae6498d04029ee9afac1cc28f7895bf725 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 31 Jan 2026 22:17:10 +1100 Subject: [PATCH 343/978] Rename `QueryResult` to `ActiveKeyStatus` --- .../rustc_query_system/src/query/plumbing.rs | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 7e34957364e4..98bbd3ebc4a0 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -33,13 +33,24 @@ fn equivalent_key(k: &K) -> impl Fn(&(K, V)) -> bool + '_ { move |x| x.0 == *k } +/// For a particular query, keeps track of "active" keys, i.e. keys whose +/// evaluation has started but has not yet finished successfully. +/// +/// (Successful query evaluation for a key is represented by an entry in the +/// query's in-memory cache.) pub struct QueryState<'tcx, K> { - active: Sharded)>>, + active: Sharded)>>, } -/// Indicates the state of a query for a given key in a query map. -enum QueryResult<'tcx> { - /// An already executing query. The query job can be used to await for its completion. +/// For a particular query and key, tracks the status of a query evaluation +/// that has started, but has not yet finished successfully. +/// +/// (Successful query evaluation for a key is represented by an entry in the +/// query's in-memory cache.) +enum ActiveKeyStatus<'tcx> { + /// Some thread is already evaluating the query for this key. + /// + /// The enclosed [`QueryJob`] can be used to wait for it to finish. Started(QueryJob<'tcx>), /// The query panicked. Queries trying to wait on this will raise a fatal error which will @@ -47,8 +58,9 @@ enum QueryResult<'tcx> { Poisoned, } -impl<'tcx> QueryResult<'tcx> { - /// Unwraps the query job expecting that it has started. +impl<'tcx> ActiveKeyStatus<'tcx> { + /// Obtains the enclosed [`QueryJob`], or panics if this query evaluation + /// was poisoned by a panic. fn expect_job(self) -> QueryJob<'tcx> { match self { Self::Started(job) => job, @@ -76,9 +88,9 @@ where ) -> Option<()> { let mut active = Vec::new(); - let mut collect = |iter: LockGuard<'_, HashTable<(K, QueryResult<'tcx>)>>| { + let mut collect = |iter: LockGuard<'_, HashTable<(K, ActiveKeyStatus<'tcx>)>>| { for (k, v) in iter.iter() { - if let QueryResult::Started(ref job) = *v { + if let ActiveKeyStatus::Started(ref job) = *v { active.push((*k, job.clone())); } } @@ -222,7 +234,7 @@ where Err(_) => panic!(), Ok(occupied) => { let ((key, value), vacant) = occupied.remove(); - vacant.insert((key, QueryResult::Poisoned)); + vacant.insert((key, ActiveKeyStatus::Poisoned)); value.expect_job() } } @@ -319,7 +331,7 @@ where let shard = query.query_state(qcx).active.lock_shard_by_hash(key_hash); match shard.find(key_hash, equivalent_key(&key)) { // The query we waited on panicked. Continue unwinding here. - Some((_, QueryResult::Poisoned)) => FatalError.raise(), + Some((_, ActiveKeyStatus::Poisoned)) => FatalError.raise(), _ => panic!( "query '{}' result must be in the cache or the query must be poisoned after a wait", query.name() @@ -373,7 +385,7 @@ where // state map. let id = qcx.next_job_id(); let job = QueryJob::new(id, span, current_job_id); - entry.insert((key, QueryResult::Started(job))); + entry.insert((key, ActiveKeyStatus::Started(job))); // Drop the lock before we start executing the query drop(state_lock); @@ -382,7 +394,7 @@ where } Entry::Occupied(mut entry) => { match &mut entry.get_mut().1 { - QueryResult::Started(job) => { + ActiveKeyStatus::Started(job) => { if sync::is_dyn_thread_safe() { // Get the latch out let latch = job.latch(); @@ -400,7 +412,7 @@ where // so we just return the error. cycle_error(query, qcx, id, span) } - QueryResult::Poisoned => FatalError.raise(), + ActiveKeyStatus::Poisoned => FatalError.raise(), } } } From b4bf57b7aa46ae7dfd31c9a7468102342f91c713 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 25 Jan 2026 14:25:18 +1100 Subject: [PATCH 344/978] Move the `fingerprint_style` special case into `DepKindVTable` creation --- compiler/rustc_query_impl/src/plumbing.rs | 8 ++++++-- compiler/rustc_query_system/src/dep_graph/dep_node.rs | 5 +++-- compiler/rustc_query_system/src/dep_graph/mod.rs | 11 +++++------ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 2d4e10a0380c..cfcfffa0fdfb 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -24,7 +24,7 @@ use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::print::with_reduced_queries; use rustc_middle::ty::tls::{self, ImplicitCtxt}; use rustc_middle::ty::{self, TyCtxt}; -use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext}; +use rustc_query_system::dep_graph::{DepNodeParams, FingerprintStyle, HasDepContext}; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ QueryCache, QueryContext, QueryDispatcher, QueryJobId, QueryMap, QuerySideEffect, @@ -519,7 +519,11 @@ pub(crate) fn make_dep_kind_vtable_for_query<'tcx, Q>( where Q: QueryDispatcherUnerased<'tcx>, { - let fingerprint_style = ::Key::fingerprint_style(); + let fingerprint_style = if is_anon { + FingerprintStyle::Opaque + } else { + ::Key::fingerprint_style() + }; if is_anon || !fingerprint_style.reconstructible() { return DepKindVTable { diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 72bdcd2d534d..b9d35bc5a937 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -237,8 +237,9 @@ pub struct DepKindVTable { /// cached within one compiler invocation. pub is_eval_always: bool, - /// Whether the query key can be recovered from the hashed fingerprint. - /// See [DepNodeParams] trait for the behaviour of each key type. + /// Indicates whether and how the query key can be recovered from its hashed fingerprint. + /// + /// The [`DepNodeParams`] trait determines the fingerprint style for each key type. pub fingerprint_style: FingerprintStyle, /// The red/green evaluation system will try to mark a specific DepNode in the diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 8f714a2c96d6..c3ac1c7bc2d5 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -39,11 +39,7 @@ pub trait DepContext: Copy { #[inline(always)] fn fingerprint_style(self, kind: DepKind) -> FingerprintStyle { - let vtable = self.dep_kind_vtable(kind); - if vtable.is_anon { - return FingerprintStyle::Opaque; - } - vtable.fingerprint_style + self.dep_kind_vtable(kind).fingerprint_style } #[inline(always)] @@ -148,6 +144,9 @@ impl HasDepContext for (T, Q) { } /// Describes the contents of the fingerprint generated by a given query. +/// +/// This is mainly for determining whether and how we can reconstruct a key +/// from the fingerprint. #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum FingerprintStyle { /// The fingerprint is actually a DefPathHash. @@ -156,7 +155,7 @@ pub enum FingerprintStyle { HirId, /// Query key was `()` or equivalent, so fingerprint is just zero. Unit, - /// Some opaque hash. + /// The fingerprint is an opaque hash, and a key cannot be reconstructed from it. Opaque, } From a7dea5504bd3e706bf37bb158b25af8d5fe37c3c Mon Sep 17 00:00:00 2001 From: delta17920 Date: Sat, 31 Jan 2026 06:52:17 +0000 Subject: [PATCH 345/978] rename various regression tests --- .../closures/local-enums-in-closure-2074.rs | 13 ++++++-- .../struct-function-same-name-2445-b.rs | 30 ------------------- .../resolve/struct-function-same-name-2445.rs | 8 ++--- ...a.rs => struct-function-same-name-2487.rs} | 17 ++++++----- .../resolve/struct-function-same-name-2502.rs | 14 ++++----- .../resolve/struct-function-same-name-2550.rs | 10 +++---- tests/ui/structs/struct-update-syntax-2463.rs | 25 ++++++---------- 7 files changed, 41 insertions(+), 76 deletions(-) delete mode 100644 tests/ui/resolve/struct-function-same-name-2445-b.rs rename tests/ui/resolve/{struct-function-same-name-2487-a.rs => struct-function-same-name-2487.rs} (64%) diff --git a/tests/ui/closures/local-enums-in-closure-2074.rs b/tests/ui/closures/local-enums-in-closure-2074.rs index b6e3fb1fa23a..29cd6f13e3bb 100644 --- a/tests/ui/closures/local-enums-in-closure-2074.rs +++ b/tests/ui/closures/local-enums-in-closure-2074.rs @@ -1,15 +1,22 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/2074 + //@ run-pass #![allow(non_camel_case_types)] pub fn main() { let one = || { - enum r { a } + enum r { + a, + } r::a as usize }; let two = || { - enum r { a } + enum r { + a, + } r::a as usize }; - one(); two(); + one(); + two(); } diff --git a/tests/ui/resolve/struct-function-same-name-2445-b.rs b/tests/ui/resolve/struct-function-same-name-2445-b.rs deleted file mode 100644 index 3a54c62a771b..000000000000 --- a/tests/ui/resolve/struct-function-same-name-2445-b.rs +++ /dev/null @@ -1,30 +0,0 @@ -//@ run-pass -#![allow(dead_code)] -#![allow(non_camel_case_types)] - - -struct c1 { - x: T, -} - -impl c1 { - pub fn f1(&self, _x: isize) { - } -} - -fn c1(x: T) -> c1 { - c1 { - x: x - } -} - -impl c1 { - pub fn f2(&self, _x: isize) { - } -} - - -pub fn main() { - c1::(3).f1(4); - c1::(3).f2(4); -} diff --git a/tests/ui/resolve/struct-function-same-name-2445.rs b/tests/ui/resolve/struct-function-same-name-2445.rs index e6c33a8fd016..8a0490efa3aa 100644 --- a/tests/ui/resolve/struct-function-same-name-2445.rs +++ b/tests/ui/resolve/struct-function-same-name-2445.rs @@ -1,8 +1,9 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/2445 + //@ run-pass #![allow(dead_code)] #![allow(non_camel_case_types)] - struct c1 { x: T, } @@ -12,16 +13,13 @@ impl c1 { } fn c1(x: T) -> c1 { - c1 { - x: x - } + c1 { x } } impl c1 { pub fn f2(&self, _x: T) {} } - pub fn main() { c1::(3).f1(4); c1::(3).f2(4); diff --git a/tests/ui/resolve/struct-function-same-name-2487-a.rs b/tests/ui/resolve/struct-function-same-name-2487.rs similarity index 64% rename from tests/ui/resolve/struct-function-same-name-2487-a.rs rename to tests/ui/resolve/struct-function-same-name-2487.rs index d38616929fae..5f9a61c3260b 100644 --- a/tests/ui/resolve/struct-function-same-name-2487-a.rs +++ b/tests/ui/resolve/struct-function-same-name-2487.rs @@ -2,10 +2,8 @@ #![allow(dead_code)] #![allow(non_camel_case_types)] - struct socket { sock: isize, - } impl Drop for socket { @@ -13,19 +11,22 @@ impl Drop for socket { } impl socket { - pub fn set_identity(&self) { + pub fn set_identity(&self) { closure(|| setsockopt_bytes(self.sock.clone())) } } fn socket() -> socket { - socket { - sock: 1 - } + socket { sock: 1 } } -fn closure(f: F) where F: FnOnce() { f() } +fn closure(f: F) +where + F: FnOnce(), +{ + f() +} -fn setsockopt_bytes(_sock: isize) { } +fn setsockopt_bytes(_sock: isize) {} pub fn main() {} diff --git a/tests/ui/resolve/struct-function-same-name-2502.rs b/tests/ui/resolve/struct-function-same-name-2502.rs index 98a52a3b5a7d..5305c7d0a96f 100644 --- a/tests/ui/resolve/struct-function-same-name-2502.rs +++ b/tests/ui/resolve/struct-function-same-name-2502.rs @@ -1,11 +1,11 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/2502 + //@ check-pass #![allow(dead_code)] #![allow(non_camel_case_types)] - - struct font<'a> { - fontbuf: &'a Vec , + fontbuf: &'a Vec, } impl<'a> font<'a> { @@ -14,10 +14,8 @@ impl<'a> font<'a> { } } -fn font(fontbuf: &Vec ) -> font<'_> { - font { - fontbuf: fontbuf - } +fn font(fontbuf: &Vec) -> font<'_> { + font { fontbuf } } -pub fn main() { } +pub fn main() {} diff --git a/tests/ui/resolve/struct-function-same-name-2550.rs b/tests/ui/resolve/struct-function-same-name-2550.rs index 450db9be627e..c96f58374c6d 100644 --- a/tests/ui/resolve/struct-function-same-name-2550.rs +++ b/tests/ui/resolve/struct-function-same-name-2550.rs @@ -1,20 +1,18 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/2550 + //@ run-pass #![allow(dead_code)] #![allow(non_snake_case)] - struct C { x: usize, } fn C(x: usize) -> C { - C { - x: x - } + C { x } } -fn f(_x: T) { -} +fn f(_x: T) {} pub fn main() { f(C(1)); diff --git a/tests/ui/structs/struct-update-syntax-2463.rs b/tests/ui/structs/struct-update-syntax-2463.rs index 8fff9763bd9e..5b2a90a5adf9 100644 --- a/tests/ui/structs/struct-update-syntax-2463.rs +++ b/tests/ui/structs/struct-update-syntax-2463.rs @@ -1,24 +1,17 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/2463 + //@ run-pass #![allow(dead_code)] -struct Pair { f: isize, g: isize } +struct Pair { + f: isize, + g: isize, +} pub fn main() { + let x = Pair { f: 0, g: 0 }; - let x = Pair { - f: 0, - g: 0, - }; - - let _y = Pair { - f: 1, - g: 1, - .. x - }; - - let _z = Pair { - f: 1, - .. x - }; + let _y = Pair { f: 1, g: 1, ..x }; + let _z = Pair { f: 1, ..x }; } From 8927aa57385144c22a2cf9060a2f7a74071d2e0e Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 30 Jan 2026 17:46:36 +0100 Subject: [PATCH 346/978] Add `inline` syntax for diagnostic messages --- compiler/rustc_error_messages/src/lib.rs | 11 ++- compiler/rustc_errors/src/translation.rs | 26 ++++++- .../src/diagnostics/diagnostic.rs | 15 ++-- .../src/diagnostics/diagnostic_builder.rs | 76 ++++++++++++------- .../rustc_macros/src/diagnostics/message.rs | 28 +++++++ compiler/rustc_macros/src/diagnostics/mod.rs | 1 + .../src/diagnostics/subdiagnostic.rs | 10 ++- .../rustc_macros/src/diagnostics/utils.rs | 26 ++++++- 8 files changed, 151 insertions(+), 42 deletions(-) create mode 100644 compiler/rustc_macros/src/diagnostics/message.rs diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index c0737edd7d65..c9e887061305 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -247,6 +247,9 @@ pub enum SubdiagMessage { /// Identifier of a Fluent message. Instances of this variant are generated by the /// `Subdiagnostic` derive. FluentIdentifier(FluentId), + /// An inline Fluent message. Instances of this variant are generated by the + /// `Subdiagnostic` derive. + Inline(Cow<'static, str>), /// Attribute of a Fluent message. Needs to be combined with a Fluent identifier to produce an /// actual translated message. Instances of this variant are generated by the `fluent_messages` /// macro. @@ -291,6 +294,8 @@ pub enum DiagMessage { /// /// FluentIdentifier(FluentId, Option), + /// An inline Fluent message, containing the to be translated diagnostic message. + Inline(Cow<'static, str>), } impl DiagMessage { @@ -305,21 +310,22 @@ impl DiagMessage { SubdiagMessage::FluentIdentifier(id) => { return DiagMessage::FluentIdentifier(id, None); } + SubdiagMessage::Inline(s) => return DiagMessage::Inline(s), SubdiagMessage::FluentAttr(attr) => attr, }; match self { - DiagMessage::Str(s) => DiagMessage::Str(s.clone()), DiagMessage::FluentIdentifier(id, _) => { DiagMessage::FluentIdentifier(id.clone(), Some(attr)) } + _ => panic!("Tried to add a subdiagnostic to a message without a fluent identifier"), } } pub fn as_str(&self) -> Option<&str> { match self { DiagMessage::Str(s) => Some(s), - DiagMessage::FluentIdentifier(_, _) => None, + DiagMessage::FluentIdentifier(_, _) | DiagMessage::Inline(_) => None, } } } @@ -353,6 +359,7 @@ impl From for SubdiagMessage { // There isn't really a sensible behaviour for this because it loses information but // this is the most sensible of the behaviours. DiagMessage::FluentIdentifier(_, Some(attr)) => SubdiagMessage::FluentAttr(attr), + DiagMessage::Inline(s) => SubdiagMessage::Inline(s), } } } diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index 43d5fca301ec..0ee2b7b06090 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -3,11 +3,13 @@ use std::env; use std::error::Report; use std::sync::Arc; +use rustc_error_messages::langid; pub use rustc_error_messages::{FluentArgs, LazyFallbackBundle}; use tracing::{debug, trace}; use crate::error::{TranslateError, TranslateErrorKind}; -use crate::{DiagArg, DiagMessage, FluentBundle, Style}; +use crate::fluent_bundle::FluentResource; +use crate::{DiagArg, DiagMessage, FluentBundle, Style, fluent_bundle}; /// Convert diagnostic arguments (a rustc internal type that exists to implement /// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation. @@ -79,6 +81,28 @@ impl Translator { return Ok(Cow::Borrowed(msg)); } DiagMessage::FluentIdentifier(identifier, attr) => (identifier, attr), + // This translates an inline fluent diagnostic message + // It does this by creating a new `FluentBundle` with only one message, + // and then translating using this bundle. + DiagMessage::Inline(msg) => { + const GENERATED_MSG_ID: &str = "generated_msg"; + let resource = + FluentResource::try_new(format!("{GENERATED_MSG_ID} = {msg}\n")).unwrap(); + let mut bundle = fluent_bundle::FluentBundle::new(vec![langid!("en-US")]); + bundle.set_use_isolating(false); + bundle.add_resource(resource).unwrap(); + let message = bundle.get_message(GENERATED_MSG_ID).unwrap(); + let value = message.value().unwrap(); + + let mut errs = vec![]; + let translated = bundle.format_pattern(value, Some(args), &mut errs).to_string(); + debug!(?translated, ?errs); + return if errs.is_empty() { + Ok(Cow::Owned(translated)) + } else { + Err(TranslateError::fluent(&Cow::Borrowed(GENERATED_MSG_ID), args, errs)) + }; + } }; let translate_with_bundle = |bundle: &'a FluentBundle| -> Result, TranslateError<'_>> { diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 7e784e3464e9..1ae6393b2860 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -27,15 +27,17 @@ impl<'a> DiagnosticDerive<'a> { let preamble = builder.preamble(variant); let body = builder.body(variant); - let Some(slug) = builder.primary_message() else { + let Some(message) = builder.primary_message() else { return DiagnosticDeriveError::ErrorHandled.to_compile_error(); }; - slugs.borrow_mut().push(slug.clone()); + slugs.borrow_mut().extend(message.slug().cloned()); + let message = message.diag_message(); + let init = quote! { let mut diag = rustc_errors::Diag::new( dcx, level, - crate::fluent_generated::#slug + #message ); }; @@ -91,12 +93,13 @@ impl<'a> LintDiagnosticDerive<'a> { let preamble = builder.preamble(variant); let body = builder.body(variant); - let Some(slug) = builder.primary_message() else { + let Some(message) = builder.primary_message() else { return DiagnosticDeriveError::ErrorHandled.to_compile_error(); }; - slugs.borrow_mut().push(slug.clone()); + slugs.borrow_mut().extend(message.slug().cloned()); + let message = message.diag_message(); let primary_message = quote! { - diag.primary_message(crate::fluent_generated::#slug); + diag.primary_message(#message); }; let formatting_init = &builder.formatting_init; diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 25110fd4f908..14eda017970f 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -4,13 +4,14 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote, quote_spanned}; use syn::parse::ParseStream; use syn::spanned::Spanned; -use syn::{Attribute, Meta, Path, Token, Type, parse_quote}; +use syn::{Attribute, LitStr, Meta, Path, Token, Type, parse_quote}; use synstructure::{BindingInfo, Structure, VariantInfo}; use super::utils::SubdiagnosticVariant; use crate::diagnostics::error::{ DiagnosticDeriveError, span_err, throw_invalid_attr, throw_span_err, }; +use crate::diagnostics::message::Message; use crate::diagnostics::utils::{ FieldInfo, FieldInnerTy, FieldMap, SetOnce, SpannedOption, SubdiagnosticKind, build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error, @@ -41,9 +42,9 @@ pub(crate) struct DiagnosticDeriveVariantBuilder { /// derive builder. pub field_map: FieldMap, - /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that + /// Message is a mandatory part of the struct attribute as corresponds to the Fluent message that /// has the actual diagnostic message. - pub slug: Option, + pub message: Option, /// Error codes are a optional part of the struct attribute - this is only set to detect /// multiple specifications. @@ -90,7 +91,7 @@ impl DiagnosticDeriveKind { span, field_map: build_field_mapping(variant), formatting_init: TokenStream::new(), - slug: None, + message: None, code: None, }; f(builder, variant) @@ -105,8 +106,8 @@ impl DiagnosticDeriveKind { } impl DiagnosticDeriveVariantBuilder { - pub(crate) fn primary_message(&self) -> Option<&Path> { - match self.slug.as_ref() { + pub(crate) fn primary_message(&self) -> Option<&Message> { + match self.message.as_ref() { None => { span_err(self.span, "diagnostic slug not specified") .help( @@ -116,7 +117,7 @@ impl DiagnosticDeriveVariantBuilder { .emit(); None } - Some(slug) + Some(Message::Slug(slug)) if let Some(Mismatch { slug_name, crate_name, slug_prefix }) = Mismatch::check(slug) => { @@ -126,7 +127,7 @@ impl DiagnosticDeriveVariantBuilder { .emit(); None } - Some(slug) => Some(slug), + Some(msg) => Some(msg), } } @@ -163,7 +164,7 @@ impl DiagnosticDeriveVariantBuilder { fn parse_subdiag_attribute( &self, attr: &Attribute, - ) -> Result, DiagnosticDeriveError> { + ) -> Result, DiagnosticDeriveError> { let Some(subdiag) = SubdiagnosticVariant::from_attr(attr, &self.field_map)? else { // Some attributes aren't errors - like documentation comments - but also aren't // subdiagnostics. @@ -175,15 +176,18 @@ impl DiagnosticDeriveVariantBuilder { .help("consider creating a `Subdiagnostic` instead")); } - let slug = subdiag.slug.unwrap_or_else(|| match subdiag.kind { - SubdiagnosticKind::Label => parse_quote! { _subdiag::label }, - SubdiagnosticKind::Note => parse_quote! { _subdiag::note }, - SubdiagnosticKind::NoteOnce => parse_quote! { _subdiag::note_once }, - SubdiagnosticKind::Help => parse_quote! { _subdiag::help }, - SubdiagnosticKind::HelpOnce => parse_quote! { _subdiag::help_once }, - SubdiagnosticKind::Warn => parse_quote! { _subdiag::warn }, - SubdiagnosticKind::Suggestion { .. } => parse_quote! { _subdiag::suggestion }, - SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(), + // For subdiagnostics without a message specified, insert a placeholder slug + let slug = subdiag.slug.unwrap_or_else(|| { + Message::Slug(match subdiag.kind { + SubdiagnosticKind::Label => parse_quote! { _subdiag::label }, + SubdiagnosticKind::Note => parse_quote! { _subdiag::note }, + SubdiagnosticKind::NoteOnce => parse_quote! { _subdiag::note_once }, + SubdiagnosticKind::Help => parse_quote! { _subdiag::help }, + SubdiagnosticKind::HelpOnce => parse_quote! { _subdiag::help_once }, + SubdiagnosticKind::Warn => parse_quote! { _subdiag::warn }, + SubdiagnosticKind::Suggestion { .. } => parse_quote! { _subdiag::suggestion }, + SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(), + }) }); Ok(Some((subdiag.kind, slug, false))) @@ -210,13 +214,28 @@ impl DiagnosticDeriveVariantBuilder { let mut input = &*input; let slug_recovery_point = input.fork(); - let slug = input.parse::()?; - if input.is_empty() || input.peek(Token![,]) { - self.slug = Some(slug); + if input.peek(LitStr) { + // Parse an inline message + let message = input.parse::()?; + if !message.suffix().is_empty() { + span_err( + message.span().unwrap(), + "Inline message is not allowed to have a suffix", + ) + .emit(); + } + self.message = Some(Message::Inline(message.value())); } else { - input = &slug_recovery_point; + // Parse a slug + let slug = input.parse::()?; + if input.is_empty() || input.peek(Token![,]) { + self.message = Some(Message::Slug(slug)); + } else { + input = &slug_recovery_point; + } } + // Parse arguments while !input.is_empty() { input.parse::()?; // Allow trailing comma @@ -429,6 +448,7 @@ impl DiagnosticDeriveVariantBuilder { applicability.set_once(quote! { #static_applicability }, span); } + let message = slug.diag_message(); let applicability = applicability .value() .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified }); @@ -438,7 +458,7 @@ impl DiagnosticDeriveVariantBuilder { Ok(quote! { diag.span_suggestions_with_style( #span_field, - crate::fluent_generated::#slug, + #message, #code_field, #applicability, #style @@ -455,22 +475,24 @@ impl DiagnosticDeriveVariantBuilder { &self, field_binding: TokenStream, kind: &Ident, - fluent_attr_identifier: Path, + message: Message, ) -> TokenStream { let fn_name = format_ident!("span_{}", kind); + let message = message.diag_message(); quote! { diag.#fn_name( #field_binding, - crate::fluent_generated::#fluent_attr_identifier + #message ); } } /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug /// and `fluent_attr_identifier`. - fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream { + fn add_subdiagnostic(&self, kind: &Ident, message: Message) -> TokenStream { + let message = message.diag_message(); quote! { - diag.#kind(crate::fluent_generated::#fluent_attr_identifier); + diag.#kind(#message); } } diff --git a/compiler/rustc_macros/src/diagnostics/message.rs b/compiler/rustc_macros/src/diagnostics/message.rs new file mode 100644 index 000000000000..cfce252fbdd8 --- /dev/null +++ b/compiler/rustc_macros/src/diagnostics/message.rs @@ -0,0 +1,28 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::Path; + +pub(crate) enum Message { + Slug(Path), + Inline(String), +} + +impl Message { + pub(crate) fn slug(&self) -> Option<&Path> { + match self { + Message::Slug(slug) => Some(slug), + Message::Inline(_) => None, + } + } + + pub(crate) fn diag_message(&self) -> TokenStream { + match self { + Message::Slug(slug) => { + quote! { crate::fluent_generated::#slug } + } + Message::Inline(message) => { + quote! { rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed(#message)) } + } + } + } +} diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index 55228248188e..09f05ce972f1 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -1,6 +1,7 @@ mod diagnostic; mod diagnostic_builder; mod error; +mod message; mod subdiagnostic; mod utils; diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index db2a19ab85ba..61a234f96d12 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -11,6 +11,7 @@ use super::utils::SubdiagnosticVariant; use crate::diagnostics::error::{ DiagnosticDeriveError, invalid_attr, span_err, throw_invalid_attr, throw_span_err, }; +use crate::diagnostics::message::Message; use crate::diagnostics::utils::{ AllowMultipleAlternatives, FieldInfo, FieldInnerTy, FieldMap, SetOnce, SpannedOption, SubdiagnosticKind, build_field_mapping, build_suggestion_code, is_doc_comment, new_code_ident, @@ -182,7 +183,9 @@ impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics { } impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { - fn identify_kind(&mut self) -> Result, DiagnosticDeriveError> { + fn identify_kind( + &mut self, + ) -> Result, DiagnosticDeriveError> { let mut kind_slugs = vec![]; for attr in self.variant.ast().attrs { @@ -532,9 +535,8 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let mut calls = TokenStream::new(); for (kind, slug) in kind_slugs { let message = format_ident!("__message"); - calls.extend( - quote! { let #message = #diag.eagerly_translate(crate::fluent_generated::#slug); }, - ); + let message_stream = slug.diag_message(); + calls.extend(quote! { let #message = #diag.eagerly_translate(#message_stream); }); let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); let call = match kind { diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index f084ba60ae3f..0718448a0513 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -16,6 +16,7 @@ use super::error::invalid_attr; use crate::diagnostics::error::{ DiagnosticDeriveError, span_err, throw_invalid_attr, throw_span_err, }; +use crate::diagnostics::message::Message; thread_local! { pub(crate) static CODE_IDENT_COUNT: RefCell = RefCell::new(0); @@ -587,7 +588,7 @@ pub(super) enum SubdiagnosticKind { pub(super) struct SubdiagnosticVariant { pub(super) kind: SubdiagnosticKind, - pub(super) slug: Option, + pub(super) slug: Option, } impl SubdiagnosticVariant { @@ -696,11 +697,31 @@ impl SubdiagnosticVariant { list.parse_args_with(|input: ParseStream<'_>| { let mut is_first = true; while !input.is_empty() { + // Try to parse an inline diagnostic message + if input.peek(LitStr) { + let message = input.parse::()?; + if !message.suffix().is_empty() { + span_err( + message.span().unwrap(), + "Inline message is not allowed to have a suffix", + ).emit(); + } + if !input.is_empty() { input.parse::()?; } + if is_first { + slug = Some(Message::Inline(message.value())); + is_first = false; + } else { + span_err(message.span().unwrap(), "a diagnostic message must be the first argument to the attribute").emit(); + } + continue + } + + // Try to parse a slug instead let arg_name: Path = input.parse::()?; let arg_name_span = arg_name.span().unwrap(); if input.is_empty() || input.parse::().is_ok() { if is_first { - slug = Some(arg_name); + slug = Some(Message::Slug(arg_name)); is_first = false; } else { span_err(arg_name_span, "a diagnostic slug must be the first argument to the attribute").emit(); @@ -709,6 +730,7 @@ impl SubdiagnosticVariant { } is_first = false; + // Try to parse an argument match (arg_name.require_ident()?.to_string().as_str(), &mut kind) { ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => { let code_init = build_suggestion_code( From 378c6fc6fe1ac3315364b0864068c7957b432b1a Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 30 Jan 2026 19:26:33 +0100 Subject: [PATCH 347/978] Uitests for `#[diagnostic]` --- .../diagnostic-derive-inline.rs | 764 ++++++++++++++++++ .../diagnostic-derive-inline.stderr | 627 ++++++++++++++ 2 files changed, 1391 insertions(+) create mode 100644 tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs create mode 100644 tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs new file mode 100644 index 000000000000..7d9af0522f63 --- /dev/null +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs @@ -0,0 +1,764 @@ +//@ check-fail +// Tests error conditions for specifying diagnostics using #[derive(Diagnostic)] +// This test specifically tests diagnostic derives involving the inline fluent syntax. + +//@ normalize-stderr: "the following other types implement trait `IntoDiagArg`:(?:.*\n){0,9}\s+and \d+ others" -> "normalized in stderr" +//@ normalize-stderr: "(COMPILER_DIR/.*\.rs):[0-9]+:[0-9]+" -> "$1:LL:CC" + +// The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly, +// changing the output of this test. Since Diagnostic is strictly internal to the compiler +// the test is just ignored on stable and beta: +//@ ignore-stage1 +//@ ignore-beta +//@ ignore-stable + +#![feature(rustc_private)] +#![crate_type = "lib"] + +extern crate rustc_span; +use rustc_span::symbol::Ident; +use rustc_span::Span; + +extern crate rustc_fluent_macro; +extern crate rustc_macros; +use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; + +extern crate rustc_middle; +use rustc_middle::ty::Ty; + +extern crate rustc_errors; +use rustc_errors::{Applicability, DiagMessage, ErrCode, MultiSpan, SubdiagMessage}; + +extern crate rustc_session; + +extern crate core; + +// E0123 and E0456 are no longer used, so we define our own constants here just for this test. +const E0123: ErrCode = ErrCode::from_u32(0123); +const E0456: ErrCode = ErrCode::from_u32(0456); + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct Hello {} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +//~^ ERROR unsupported type attribute for diagnostic derive enum +enum DiagnosticOnEnum { + Foo, + //~^ ERROR diagnostic slug not specified + Bar, + //~^ ERROR diagnostic slug not specified +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +#[diag = "E0123"] +//~^ ERROR expected parentheses: #[diag(...)] +struct WrongStructAttrStyle {} + +#[derive(Diagnostic)] +#[nonsense("this is an example message", code = E0123)] +//~^ ERROR `#[nonsense(...)]` is not a valid attribute +//~^^ ERROR diagnostic slug not specified +//~^^^ ERROR cannot find attribute `nonsense` in this scope +struct InvalidStructAttr {} + +#[derive(Diagnostic)] +#[diag(code = E0123)] +//~^ ERROR diagnostic slug not specified +struct InvalidLitNestedAttr {} + +#[derive(Diagnostic)] +#[diag(nonsense("foo"), code = E0123, slug = "foo")] +//~^ ERROR derive(Diagnostic): diagnostic slug not specified +struct InvalidNestedStructAttr1 {} + +#[derive(Diagnostic)] +#[diag(nonsense = "...", code = E0123, slug = "foo")] +//~^ ERROR diagnostic slug not specified +struct InvalidNestedStructAttr2 {} + +#[derive(Diagnostic)] +#[diag(nonsense = 4, code = E0123, slug = "foo")] +//~^ ERROR diagnostic slug not specified +struct InvalidNestedStructAttr3 {} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123, slug = "foo")] +//~^ ERROR unknown argument +struct InvalidNestedStructAttr4 {} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct WrongPlaceField { + #[suggestion = "bar"] + //~^ ERROR `#[suggestion = ...]` is not a valid attribute + sp: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +#[diag("this is an example message", code = E0456)] +//~^ ERROR specified multiple times +struct DiagSpecifiedTwice {} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123, code = E0456)] +//~^ ERROR specified multiple times +struct CodeSpecifiedTwice {} + +#[derive(Diagnostic)] +#[diag("this is an example message", no_crate::example, code = E0123)] +//~^ ERROR diagnostic slug must be the first argument +struct SlugSpecifiedTwice {} + +#[derive(Diagnostic)] +struct KindNotProvided {} //~ ERROR diagnostic slug not specified + +#[derive(Diagnostic)] +#[diag(code = E0123)] +//~^ ERROR diagnostic slug not specified +struct SlugNotProvided {} + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct CodeNotProvided {} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct MessageWrongType { + #[primary_span] + //~^ ERROR `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` + foo: String, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct InvalidPathFieldAttr { + #[nonsense] + //~^ ERROR `#[nonsense]` is not a valid attribute + //~^^ ERROR cannot find attribute `nonsense` in this scope + foo: String, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct ErrorWithField { + name: String, + #[label("with a label")] + span: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct ErrorWithMessageAppliedToField { + #[label("with a label")] + //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` + name: String, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct ErrorWithNonexistentField { + #[suggestion("with a suggestion", code = "{name}")] + //~^ ERROR `name` doesn't refer to a field on this type + suggestion: (Span, Applicability), +} + +#[derive(Diagnostic)] +//~^ ERROR invalid format string: expected `}` +#[diag("this is an example message", code = E0123)] +struct ErrorMissingClosingBrace { + #[suggestion("with a suggestion", code = "{name")] + suggestion: (Span, Applicability), + name: String, + val: usize, +} + +#[derive(Diagnostic)] +//~^ ERROR invalid format string: unmatched `}` +#[diag("this is an example message", code = E0123)] +struct ErrorMissingOpeningBrace { + #[suggestion("with a suggestion", code = "name}")] + suggestion: (Span, Applicability), + name: String, + val: usize, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct LabelOnSpan { + #[label("with a label")] + sp: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct LabelOnNonSpan { + #[label("with a label")] + //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` + id: u32, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct Suggest { + #[suggestion("with a suggestion", code = "This is the suggested code")] + #[suggestion("with a suggestion", code = "This is the suggested code", style = "normal")] + #[suggestion("with a suggestion", code = "This is the suggested code", style = "short")] + #[suggestion("with a suggestion", code = "This is the suggested code", style = "hidden")] + #[suggestion("with a suggestion", code = "This is the suggested code", style = "verbose")] + suggestion: (Span, Applicability), +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct SuggestWithoutCode { + #[suggestion("with a suggestion")] + //~^ ERROR suggestion without `code = "..."` + suggestion: (Span, Applicability), +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct SuggestWithBadKey { + #[suggestion("with a suggestion", nonsense = "bar")] + //~^ ERROR invalid nested attribute + //~| ERROR suggestion without `code = "..."` + suggestion: (Span, Applicability), +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct SuggestWithShorthandMsg { + #[suggestion("with a suggestion", msg = "bar")] + //~^ ERROR invalid nested attribute + //~| ERROR suggestion without `code = "..."` + suggestion: (Span, Applicability), +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct SuggestWithoutMsg { + #[suggestion("with a suggestion", code = "bar")] + suggestion: (Span, Applicability), +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct SuggestWithTypesSwapped { + #[suggestion("with a suggestion", code = "This is suggested code")] + suggestion: (Applicability, Span), +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct SuggestWithWrongTypeApplicabilityOnly { + #[suggestion("with a suggestion", code = "This is suggested code")] + //~^ ERROR wrong field type for suggestion + suggestion: Applicability, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct SuggestWithSpanOnly { + #[suggestion("with a suggestion", code = "This is suggested code")] + suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct SuggestWithDuplicateSpanAndApplicability { + #[suggestion("with a suggestion", code = "This is suggested code")] + suggestion: (Span, Span, Applicability), + //~^ ERROR specified multiple times +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct SuggestWithDuplicateApplicabilityAndSpan { + #[suggestion("with a suggestion", code = "This is suggested code")] + suggestion: (Applicability, Applicability, Span), + //~^ ERROR specified multiple times +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct WrongKindOfAnnotation { + #[label = "bar"] + //~^ ERROR `#[label = ...]` is not a valid attribute + z: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct OptionsInErrors { + #[label("with a label")] + label: Option, + #[suggestion("with a suggestion", code = "...")] + opt_sugg: Option<(Span, Applicability)>, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct MoveOutOfBorrowError<'tcx> { + name: Ident, + ty: Ty<'tcx>, + #[primary_span] + #[label("with a label")] + span: Span, + #[label("with a label")] + other_span: Span, + #[suggestion("with a suggestion", code = "{name}.clone()")] + opt_sugg: Option<(Span, Applicability)>, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct ErrorWithLifetime<'a> { + #[label("with a label")] + span: Span, + name: &'a str, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct ArgFieldWithoutSkip { + #[primary_span] + span: Span, + other: Hello, + //~^ ERROR the trait bound `Hello: IntoDiagArg` is not satisfied +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct ArgFieldWithSkip { + #[primary_span] + span: Span, + // `Hello` does not implement `IntoDiagArg` so this would result in an error if + // not for `#[skip_arg]`. + #[skip_arg] + other: Hello, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct ErrorWithSpannedNote { + #[note("with a note")] + span: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +#[note("with a note")] +struct ErrorWithNote { + val: String, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct ErrorWithSpannedHelpCustom { + #[help("with a help")] + span: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +#[help("with a help")] +struct ErrorWithHelp { + val: String, +} + +#[derive(Diagnostic)] +#[help("with a help")] +#[diag("this is an example message", code = E0123)] +struct ErrorWithHelpWrongOrder { + val: String, +} + +#[derive(Diagnostic)] +#[note("with a note")] +#[diag("this is an example message", code = E0123)] +struct ErrorWithNoteWrongOrder { + val: String, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct ApplicabilityInBoth { + #[suggestion("with a suggestion", code = "...", applicability = "maybe-incorrect")] + //~^ ERROR specified multiple times + suggestion: (Span, Applicability), +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct InvalidApplicability { + #[suggestion("with a suggestion", code = "...", applicability = "batman")] + //~^ ERROR invalid applicability + suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct ValidApplicability { + #[suggestion("with a suggestion", code = "...", applicability = "maybe-incorrect")] + suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct NoApplicability { + #[suggestion("with a suggestion", code = "...")] + suggestion: Span, +} + +#[derive(Subdiagnostic)] +#[note("this is an example message")] +struct Note; + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct Subdiagnostic { + #[subdiagnostic] + note: Note, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct VecField { + #[primary_span] + #[label("with a label")] + spans: Vec, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct UnitField { + #[primary_span] + spans: Span, + #[help("with a help")] + bar: (), +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct OptUnitField { + #[primary_span] + spans: Span, + #[help("with a help")] + foo: Option<()>, +} + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct BoolField { + #[primary_span] + spans: Span, + #[help("with a help")] + foo: bool, + #[help("with a help")] + //~^ ERROR the `#[help(...)]` attribute can only be applied to fields of type + // only allow plain 'bool' fields + bar: Option, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct LabelWithTrailingPath { + #[label("with a label", foo)] + //~^ ERROR a diagnostic slug must be the first argument to the attribute + span: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct LabelWithTrailingNameValue { + #[label("with a label", foo = "...")] + //~^ ERROR no nested attribute expected here + span: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct LabelWithTrailingList { + #[label("with a label", foo("..."))] + //~^ ERROR no nested attribute expected here + span: Span, +} + +#[derive(LintDiagnostic)] +#[diag("this is an example message")] +struct LintsGood {} + +#[derive(LintDiagnostic)] +#[diag("this is an example message")] +struct PrimarySpanOnLint { + #[primary_span] + //~^ ERROR `#[primary_span]` is not a valid attribute + span: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct ErrorWithMultiSpan { + #[primary_span] + span: MultiSpan, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +#[warning("with a warning")] +struct ErrorWithWarn { + val: String, +} + +#[derive(Diagnostic)] +#[error("this is an example message", code = E0123)] +//~^ ERROR `#[error(...)]` is not a valid attribute +//~| ERROR diagnostic slug not specified +//~| ERROR cannot find attribute `error` in this scope +struct ErrorAttribute {} + +#[derive(Diagnostic)] +#[warn_("this is an example message", code = E0123)] +//~^ ERROR `#[warn_(...)]` is not a valid attribute +//~| ERROR diagnostic slug not specified +//~| ERROR cannot find attribute `warn_` in this scope +struct WarnAttribute {} + +#[derive(Diagnostic)] +#[lint("this is an example message", code = E0123)] +//~^ ERROR `#[lint(...)]` is not a valid attribute +//~| ERROR diagnostic slug not specified +//~| ERROR cannot find attribute `lint` in this scope +struct LintAttributeOnSessionDiag {} + +#[derive(LintDiagnostic)] +#[lint("this is an example message", code = E0123)] +//~^ ERROR `#[lint(...)]` is not a valid attribute +//~| ERROR diagnostic slug not specified +//~| ERROR cannot find attribute `lint` in this scope +struct LintAttributeOnLintDiag {} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct DuplicatedSuggestionCode { + #[suggestion("with a suggestion", code = "...", code = ",,,")] + //~^ ERROR specified multiple times + suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct InvalidTypeInSuggestionTuple { + #[suggestion("with a suggestion", code = "...")] + suggestion: (Span, usize), + //~^ ERROR wrong types for suggestion +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct MissingApplicabilityInSuggestionTuple { + #[suggestion("with a suggestion", code = "...")] + suggestion: (Span,), + //~^ ERROR wrong types for suggestion +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct MissingCodeInSuggestion { + #[suggestion("with a suggestion")] + //~^ ERROR suggestion without `code = "..."` + suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +#[multipart_suggestion("with a suggestion")] +//~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute +//~| ERROR cannot find attribute `multipart_suggestion` in this scope +#[multipart_suggestion()] +//~^ ERROR cannot find attribute `multipart_suggestion` in this scope +//~| ERROR `#[multipart_suggestion(...)]` is not a valid attribute +struct MultipartSuggestion { + #[multipart_suggestion("with a suggestion")] + //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute + //~| ERROR cannot find attribute `multipart_suggestion` in this scope + suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +#[suggestion("with a suggestion", code = "...")] +//~^ ERROR `#[suggestion(...)]` is not a valid attribute +struct SuggestionOnStruct { + #[primary_span] + suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +#[label] +//~^ ERROR `#[label]` is not a valid attribute +struct LabelOnStruct { + #[primary_span] + suggestion: Span, +} + +#[derive(Diagnostic)] +enum ExampleEnum { + #[diag("this is an example message")] + Foo { + #[primary_span] + sp: Span, + #[note("with a note")] + note_sp: Span, + }, + #[diag("this is an example message")] + Bar { + #[primary_span] + sp: Span, + }, + #[diag("this is an example message")] + Baz, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct RawIdentDiagnosticArg { + pub r#type: String, +} + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct SubdiagnosticBad { + #[subdiagnostic(bad)] + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute + note: Note, +} + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct SubdiagnosticBadStr { + #[subdiagnostic = "bad"] + //~^ ERROR `#[subdiagnostic = ...]` is not a valid attribute + note: Note, +} + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct SubdiagnosticBadTwice { + #[subdiagnostic(bad, bad)] + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute + note: Note, +} + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct SubdiagnosticBadLitStr { + #[subdiagnostic("bad")] + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute + note: Note, +} + +#[derive(LintDiagnostic)] +#[diag("this is an example message")] +struct SubdiagnosticEagerLint { + #[subdiagnostic(eager)] + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute + note: Note, +} + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct SubdiagnosticEagerFormerlyCorrect { + #[subdiagnostic(eager)] + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute + note: Note, +} + +// Check that formatting of `correct` in suggestion doesn't move the binding for that field, making +// the `arg` call a compile error; and that isn't worked around by moving the `arg` call +// after the `span_suggestion` call - which breaks eager translation. + +#[derive(Subdiagnostic)] +#[suggestion("example message", applicability = "machine-applicable", code = "{correct}")] +pub(crate) struct SubdiagnosticWithSuggestion { + #[primary_span] + span: Span, + invalid: String, + correct: String, +} + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct SubdiagnosticEagerSuggestion { + #[subdiagnostic(eager)] + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute + sub: SubdiagnosticWithSuggestion, +} + +/// with a doc comment on the type.. +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct WithDocComment { + /// ..and the field + #[primary_span] + span: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct SuggestionsGood { + #[suggestion("with a suggestion", code("foo", "bar"))] + sub: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct SuggestionsSingleItem { + #[suggestion("with a suggestion", code("foo"))] + sub: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct SuggestionsNoItem { + #[suggestion("with a suggestion", code())] + //~^ ERROR expected at least one string literal for `code(...)` + sub: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct SuggestionsInvalidItem { + #[suggestion("with a suggestion", code(foo))] + //~^ ERROR `code(...)` must contain only string literals + //~| ERROR unexpected token, expected `)` + sub: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct SuggestionsInvalidLiteral { + #[suggestion("with a suggestion", code = 3)] + //~^ ERROR expected string literal + sub: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct SuggestionStyleGood { + #[suggestion("with a suggestion", code = "", style = "hidden")] + sub: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message")] +struct SuggestionOnVec { + #[suggestion("with a suggestion", code = "")] + //~^ ERROR `#[suggestion(...)]` is not a valid attribute + sub: Vec, +} diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr new file mode 100644 index 000000000000..bec07a425762 --- /dev/null +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr @@ -0,0 +1,627 @@ +error: derive(Diagnostic): unsupported type attribute for diagnostic derive enum + --> $DIR/diagnostic-derive-inline.rs:45:1 + | +LL | #[diag("this is an example message", code = E0123)] + | ^ + +error: derive(Diagnostic): diagnostic slug not specified + --> $DIR/diagnostic-derive-inline.rs:48:5 + | +LL | Foo, + | ^^^ + | + = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + +error: derive(Diagnostic): diagnostic slug not specified + --> $DIR/diagnostic-derive-inline.rs:50:5 + | +LL | Bar, + | ^^^ + | + = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + +error: expected parentheses: #[diag(...)] + --> $DIR/diagnostic-derive-inline.rs:56:8 + | +LL | #[diag = "E0123"] + | ^ + +error: derive(Diagnostic): `#[nonsense(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:61:1 + | +LL | #[nonsense("this is an example message", code = E0123)] + | ^ + +error: derive(Diagnostic): diagnostic slug not specified + --> $DIR/diagnostic-derive-inline.rs:61:1 + | +LL | #[nonsense("this is an example message", code = E0123)] + | ^ + | + = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + +error: derive(Diagnostic): diagnostic slug not specified + --> $DIR/diagnostic-derive-inline.rs:68:1 + | +LL | #[diag(code = E0123)] + | ^ + | + = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + +error: derive(Diagnostic): diagnostic slug not specified + --> $DIR/diagnostic-derive-inline.rs:73:1 + | +LL | #[diag(nonsense("foo"), code = E0123, slug = "foo")] + | ^ + | + = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + +error: derive(Diagnostic): diagnostic slug not specified + --> $DIR/diagnostic-derive-inline.rs:78:1 + | +LL | #[diag(nonsense = "...", code = E0123, slug = "foo")] + | ^ + | + = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + +error: derive(Diagnostic): diagnostic slug not specified + --> $DIR/diagnostic-derive-inline.rs:83:1 + | +LL | #[diag(nonsense = 4, code = E0123, slug = "foo")] + | ^ + | + = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + +error: derive(Diagnostic): unknown argument + --> $DIR/diagnostic-derive-inline.rs:88:52 + | +LL | #[diag("this is an example message", code = E0123, slug = "foo")] + | ^^^^ + | + = note: only the `code` parameter is valid after the slug + +error: derive(Diagnostic): `#[suggestion = ...]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:95:5 + | +LL | #[suggestion = "bar"] + | ^ + +error: derive(Diagnostic): attribute specified multiple times + --> $DIR/diagnostic-derive-inline.rs:102:38 + | +LL | #[diag("this is an example message", code = E0456)] + | ^^^^ + | +note: previously specified here + --> $DIR/diagnostic-derive-inline.rs:101:38 + | +LL | #[diag("this is an example message", code = E0123)] + | ^^^^ + +error: derive(Diagnostic): attribute specified multiple times + --> $DIR/diagnostic-derive-inline.rs:107:52 + | +LL | #[diag("this is an example message", code = E0123, code = E0456)] + | ^^^^ + | +note: previously specified here + --> $DIR/diagnostic-derive-inline.rs:107:38 + | +LL | #[diag("this is an example message", code = E0123, code = E0456)] + | ^^^^ + +error: derive(Diagnostic): diagnostic slug must be the first argument + --> $DIR/diagnostic-derive-inline.rs:112:38 + | +LL | #[diag("this is an example message", no_crate::example, code = E0123)] + | ^^^^^^^^ + +error: derive(Diagnostic): diagnostic slug not specified + --> $DIR/diagnostic-derive-inline.rs:117:1 + | +LL | struct KindNotProvided {} + | ^^^^^^ + | + = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + +error: derive(Diagnostic): diagnostic slug not specified + --> $DIR/diagnostic-derive-inline.rs:120:1 + | +LL | #[diag(code = E0123)] + | ^ + | + = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + +error: derive(Diagnostic): the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` + --> $DIR/diagnostic-derive-inline.rs:131:5 + | +LL | #[primary_span] + | ^ + +error: derive(Diagnostic): `#[nonsense]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:139:5 + | +LL | #[nonsense] + | ^ + +error: derive(Diagnostic): the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` + --> $DIR/diagnostic-derive-inline.rs:156:5 + | +LL | #[label("with a label")] + | ^ + +error: derive(Diagnostic): `name` doesn't refer to a field on this type + --> $DIR/diagnostic-derive-inline.rs:164:46 + | +LL | #[suggestion("with a suggestion", code = "{name}")] + | ^^^^^^^^ + +error: invalid format string: expected `}` but string was terminated + --> $DIR/diagnostic-derive-inline.rs:169:10 + | +LL | #[derive(Diagnostic)] + | ^^^^^^^^^^ expected `}` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: invalid format string: unmatched `}` found + --> $DIR/diagnostic-derive-inline.rs:179:10 + | +LL | #[derive(Diagnostic)] + | ^^^^^^^^^^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: derive(Diagnostic): the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` + --> $DIR/diagnostic-derive-inline.rs:199:5 + | +LL | #[label("with a label")] + | ^ + +error: derive(Diagnostic): suggestion without `code = "..."` + --> $DIR/diagnostic-derive-inline.rs:218:5 + | +LL | #[suggestion("with a suggestion")] + | ^ + +error: derive(Diagnostic): invalid nested attribute + --> $DIR/diagnostic-derive-inline.rs:226:39 + | +LL | #[suggestion("with a suggestion", nonsense = "bar")] + | ^^^^^^^^ + | + = help: only `style`, `code` and `applicability` are valid nested attributes + +error: derive(Diagnostic): suggestion without `code = "..."` + --> $DIR/diagnostic-derive-inline.rs:226:5 + | +LL | #[suggestion("with a suggestion", nonsense = "bar")] + | ^ + +error: derive(Diagnostic): invalid nested attribute + --> $DIR/diagnostic-derive-inline.rs:235:39 + | +LL | #[suggestion("with a suggestion", msg = "bar")] + | ^^^ + | + = help: only `style`, `code` and `applicability` are valid nested attributes + +error: derive(Diagnostic): suggestion without `code = "..."` + --> $DIR/diagnostic-derive-inline.rs:235:5 + | +LL | #[suggestion("with a suggestion", msg = "bar")] + | ^ + +error: derive(Diagnostic): wrong field type for suggestion + --> $DIR/diagnostic-derive-inline.rs:258:5 + | +LL | #[suggestion("with a suggestion", code = "This is suggested code")] + | ^ + | + = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` + +error: derive(Diagnostic): attribute specified multiple times + --> $DIR/diagnostic-derive-inline.rs:274:24 + | +LL | suggestion: (Span, Span, Applicability), + | ^^^^ + | +note: previously specified here + --> $DIR/diagnostic-derive-inline.rs:274:18 + | +LL | suggestion: (Span, Span, Applicability), + | ^^^^ + +error: derive(Diagnostic): attribute specified multiple times + --> $DIR/diagnostic-derive-inline.rs:282:33 + | +LL | suggestion: (Applicability, Applicability, Span), + | ^^^^^^^^^^^^^ + | +note: previously specified here + --> $DIR/diagnostic-derive-inline.rs:282:18 + | +LL | suggestion: (Applicability, Applicability, Span), + | ^^^^^^^^^^^^^ + +error: derive(Diagnostic): `#[label = ...]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:289:5 + | +LL | #[label = "bar"] + | ^ + +error: derive(Diagnostic): attribute specified multiple times + --> $DIR/diagnostic-derive-inline.rs:390:5 + | +LL | #[suggestion("with a suggestion", code = "...", applicability = "maybe-incorrect")] + | ^ + | +note: previously specified here + --> $DIR/diagnostic-derive-inline.rs:392:24 + | +LL | suggestion: (Span, Applicability), + | ^^^^^^^^^^^^^ + +error: derive(Diagnostic): invalid applicability + --> $DIR/diagnostic-derive-inline.rs:398:69 + | +LL | #[suggestion("with a suggestion", code = "...", applicability = "batman")] + | ^^^^^^^^ + +error: derive(Diagnostic): the `#[help(...)]` attribute can only be applied to fields of type `Span`, `MultiSpan`, `bool` or `()` + --> $DIR/diagnostic-derive-inline.rs:461:5 + | +LL | #[help("with a help")] + | ^ + +error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute + --> $DIR/diagnostic-derive-inline.rs:470:29 + | +LL | #[label("with a label", foo)] + | ^^^ + +error: derive(Diagnostic): no nested attribute expected here + --> $DIR/diagnostic-derive-inline.rs:478:29 + | +LL | #[label("with a label", foo = "...")] + | ^^^ + +error: derive(Diagnostic): no nested attribute expected here + --> $DIR/diagnostic-derive-inline.rs:486:29 + | +LL | #[label("with a label", foo("..."))] + | ^^^ + +error: derive(Diagnostic): `#[primary_span]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:498:5 + | +LL | #[primary_span] + | ^ + | + = help: the `primary_span` field attribute is not valid for lint diagnostics + +error: derive(Diagnostic): `#[error(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:518:1 + | +LL | #[error("this is an example message", code = E0123)] + | ^ + +error: derive(Diagnostic): diagnostic slug not specified + --> $DIR/diagnostic-derive-inline.rs:518:1 + | +LL | #[error("this is an example message", code = E0123)] + | ^ + | + = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + +error: derive(Diagnostic): `#[warn_(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:525:1 + | +LL | #[warn_("this is an example message", code = E0123)] + | ^ + +error: derive(Diagnostic): diagnostic slug not specified + --> $DIR/diagnostic-derive-inline.rs:525:1 + | +LL | #[warn_("this is an example message", code = E0123)] + | ^ + | + = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + +error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:532:1 + | +LL | #[lint("this is an example message", code = E0123)] + | ^ + +error: derive(Diagnostic): diagnostic slug not specified + --> $DIR/diagnostic-derive-inline.rs:532:1 + | +LL | #[lint("this is an example message", code = E0123)] + | ^ + | + = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + +error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:539:1 + | +LL | #[lint("this is an example message", code = E0123)] + | ^ + +error: derive(Diagnostic): diagnostic slug not specified + --> $DIR/diagnostic-derive-inline.rs:539:1 + | +LL | #[lint("this is an example message", code = E0123)] + | ^ + | + = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + +error: derive(Diagnostic): attribute specified multiple times + --> $DIR/diagnostic-derive-inline.rs:548:53 + | +LL | #[suggestion("with a suggestion", code = "...", code = ",,,")] + | ^^^^ + | +note: previously specified here + --> $DIR/diagnostic-derive-inline.rs:548:39 + | +LL | #[suggestion("with a suggestion", code = "...", code = ",,,")] + | ^^^^ + +error: derive(Diagnostic): wrong types for suggestion + --> $DIR/diagnostic-derive-inline.rs:557:24 + | +LL | suggestion: (Span, usize), + | ^^^^^ + | + = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` + +error: derive(Diagnostic): wrong types for suggestion + --> $DIR/diagnostic-derive-inline.rs:565:17 + | +LL | suggestion: (Span,), + | ^^^^^^^ + | + = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` + +error: derive(Diagnostic): suggestion without `code = "..."` + --> $DIR/diagnostic-derive-inline.rs:572:5 + | +LL | #[suggestion("with a suggestion")] + | ^ + +error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:579:1 + | +LL | #[multipart_suggestion("with a suggestion")] + | ^ + | + = help: consider creating a `Subdiagnostic` instead + +error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:582:1 + | +LL | #[multipart_suggestion()] + | ^ + | + = help: consider creating a `Subdiagnostic` instead + +error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:586:5 + | +LL | #[multipart_suggestion("with a suggestion")] + | ^ + | + = help: consider creating a `Subdiagnostic` instead + +error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:594:1 + | +LL | #[suggestion("with a suggestion", code = "...")] + | ^ + | + = help: `#[label]` and `#[suggestion]` can only be applied to fields + +error: derive(Diagnostic): `#[label]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:603:1 + | +LL | #[label] + | ^ + | + = help: `#[label]` and `#[suggestion]` can only be applied to fields + +error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:637:5 + | +LL | #[subdiagnostic(bad)] + | ^ + +error: derive(Diagnostic): `#[subdiagnostic = ...]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:645:5 + | +LL | #[subdiagnostic = "bad"] + | ^ + +error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:653:5 + | +LL | #[subdiagnostic(bad, bad)] + | ^ + +error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:661:5 + | +LL | #[subdiagnostic("bad")] + | ^ + +error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:669:5 + | +LL | #[subdiagnostic(eager)] + | ^ + +error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:677:5 + | +LL | #[subdiagnostic(eager)] + | ^ + +error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:698:5 + | +LL | #[subdiagnostic(eager)] + | ^ + +error: derive(Diagnostic): expected at least one string literal for `code(...)` + --> $DIR/diagnostic-derive-inline.rs:729:44 + | +LL | #[suggestion("with a suggestion", code())] + | ^ + +error: derive(Diagnostic): `code(...)` must contain only string literals + --> $DIR/diagnostic-derive-inline.rs:737:44 + | +LL | #[suggestion("with a suggestion", code(foo))] + | ^^^ + +error: unexpected token, expected `)` + --> $DIR/diagnostic-derive-inline.rs:737:44 + | +LL | #[suggestion("with a suggestion", code(foo))] + | ^^^ + +error: expected string literal + --> $DIR/diagnostic-derive-inline.rs:746:46 + | +LL | #[suggestion("with a suggestion", code = 3)] + | ^ + +error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:761:5 + | +LL | #[suggestion("with a suggestion", code = "")] + | ^ + | + = note: `#[suggestion(...)]` applied to `Vec` field is ambiguous + = help: to show a suggestion consisting of multiple parts, use a `Subdiagnostic` annotated with `#[multipart_suggestion(...)]` + = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]` + +error: cannot find attribute `nonsense` in this scope + --> $DIR/diagnostic-derive-inline.rs:61:3 + | +LL | #[nonsense("this is an example message", code = E0123)] + | ^^^^^^^^ + +error: cannot find attribute `nonsense` in this scope + --> $DIR/diagnostic-derive-inline.rs:139:7 + | +LL | #[nonsense] + | ^^^^^^^^ + +error: cannot find attribute `error` in this scope + --> $DIR/diagnostic-derive-inline.rs:518:3 + | +LL | #[error("this is an example message", code = E0123)] + | ^^^^^ + | +help: `error` is an attribute that can be used by the derive macro `Error`, you might be missing a `derive` attribute + | +LL + #[derive(Error)] +LL | struct ErrorAttribute {} + | + +error: cannot find attribute `warn_` in this scope + --> $DIR/diagnostic-derive-inline.rs:525:3 + | +LL | #[warn_("this is an example message", code = E0123)] + | ^^^^^ + | +help: a built-in attribute with a similar name exists + | +LL - #[warn_("this is an example message", code = E0123)] +LL + #[warn("this is an example message", code = E0123)] + | + +error: cannot find attribute `lint` in this scope + --> $DIR/diagnostic-derive-inline.rs:532:3 + | +LL | #[lint("this is an example message", code = E0123)] + | ^^^^ + | +help: a built-in attribute with a similar name exists + | +LL - #[lint("this is an example message", code = E0123)] +LL + #[link("this is an example message", code = E0123)] + | + +error: cannot find attribute `lint` in this scope + --> $DIR/diagnostic-derive-inline.rs:539:3 + | +LL | #[lint("this is an example message", code = E0123)] + | ^^^^ + | +help: a built-in attribute with a similar name exists + | +LL - #[lint("this is an example message", code = E0123)] +LL + #[link("this is an example message", code = E0123)] + | + +error: cannot find attribute `multipart_suggestion` in this scope + --> $DIR/diagnostic-derive-inline.rs:579:3 + | +LL | #[multipart_suggestion("with a suggestion")] + | ^^^^^^^^^^^^^^^^^^^^ + | +help: `multipart_suggestion` is an attribute that can be used by the derive macro `Subdiagnostic`, you might be missing a `derive` attribute + | +LL + #[derive(Subdiagnostic)] +LL | struct MultipartSuggestion { + | + +error: cannot find attribute `multipart_suggestion` in this scope + --> $DIR/diagnostic-derive-inline.rs:582:3 + | +LL | #[multipart_suggestion()] + | ^^^^^^^^^^^^^^^^^^^^ + | +help: `multipart_suggestion` is an attribute that can be used by the derive macro `Subdiagnostic`, you might be missing a `derive` attribute + | +LL + #[derive(Subdiagnostic)] +LL | struct MultipartSuggestion { + | + +error: cannot find attribute `multipart_suggestion` in this scope + --> $DIR/diagnostic-derive-inline.rs:586:7 + | +LL | #[multipart_suggestion("with a suggestion")] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `multipart_suggestion` is an attribute that can be used by the derive macro `Subdiagnostic`, you might be missing a `derive` attribute + +error[E0277]: the trait bound `Hello: IntoDiagArg` is not satisfied + --> $DIR/diagnostic-derive-inline.rs:330:12 + | +LL | #[derive(Diagnostic)] + | ---------- required by a bound introduced by this call +... +LL | other: Hello, + | ^^^^^ unsatisfied trait bound + | +help: the nightly-only, unstable trait `IntoDiagArg` is not implemented for `Hello` + --> $DIR/diagnostic-derive-inline.rs:42:1 + | +LL | struct Hello {} + | ^^^^^^^^^^^^ + = help: normalized in stderr +note: required by a bound in `Diag::<'a, G>::arg` + --> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC + ::: $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC + | + = note: in this macro invocation + = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 79 previous errors + +For more information about this error, try `rustc --explain E0277`. From 523d9d920028753e4c170d34366871e14f13a9fc Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 30 Jan 2026 19:26:57 +0100 Subject: [PATCH 348/978] Uitests for subdiagnostics --- .../subdiagnostic-derive-inline.rs | 807 ++++++++++++++++++ .../subdiagnostic-derive-inline.stderr | 549 ++++++++++++ .../subdiagnostic-derive.rs | 9 - .../subdiagnostic-derive.stderr | 168 ++-- 4 files changed, 1437 insertions(+), 96 deletions(-) create mode 100644 tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs create mode 100644 tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs new file mode 100644 index 000000000000..eaa681d40be5 --- /dev/null +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs @@ -0,0 +1,807 @@ +//@ check-fail +// Tests error conditions for specifying inline subdiagnostics using #[derive(Subdiagnostic)] + +// The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly, +// changing the output of this test. Since Subdiagnostic is strictly internal to the compiler +// the test is just ignored on stable and beta: +//@ ignore-stage1 +//@ ignore-beta +//@ ignore-stable + +#![feature(rustc_private)] +#![crate_type = "lib"] + +extern crate rustc_errors; +extern crate rustc_fluent_macro; +extern crate rustc_macros; +extern crate rustc_session; +extern crate rustc_span; +extern crate core; + +use rustc_errors::{Applicability, DiagMessage, SubdiagMessage}; +use rustc_macros::Subdiagnostic; +use rustc_span::Span; + +#[derive(Subdiagnostic)] +#[label("example message")] +struct A { + #[primary_span] + span: Span, + var: String, +} + +#[derive(Subdiagnostic)] +enum B { + #[label("example message")] + A { + #[primary_span] + span: Span, + var: String, + }, + #[label("example message")] + B { + #[primary_span] + span: Span, + var: String, + }, +} + +#[derive(Subdiagnostic)] +#[label("example message")] +//~^ ERROR label without `#[primary_span]` field +struct C { + var: String, +} + +#[derive(Subdiagnostic)] +#[label] +//~^ ERROR diagnostic slug must be first argument +struct D { + #[primary_span] + span: Span, + var: String, +} + +#[derive(Subdiagnostic)] +#[foo] +//~^ ERROR `#[foo]` is not a valid attribute +//~^^ ERROR cannot find attribute `foo` in this scope +struct E { + #[primary_span] + span: Span, + var: String, +} + +#[derive(Subdiagnostic)] +#[label = "..."] +//~^ ERROR `#[label = ...]` is not a valid attribute +struct F { + #[primary_span] + span: Span, + var: String, +} + +#[derive(Subdiagnostic)] +#[label(bug = "...")] +//~^ ERROR no nested attribute expected here +//~| ERROR diagnostic slug must be first argument +struct G { + #[primary_span] + span: Span, + var: String, +} + +#[derive(Subdiagnostic)] +#[label(slug = 4)] +//~^ ERROR no nested attribute expected here +//~| ERROR diagnostic slug must be first argument +struct J { + #[primary_span] + span: Span, + var: String, +} + +#[derive(Subdiagnostic)] +#[label(slug("..."))] +//~^ ERROR no nested attribute expected here +//~| ERROR diagnostic slug must be first argument +struct K { + #[primary_span] + span: Span, + var: String, +} + +#[derive(Subdiagnostic)] +#[label()] +//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute +struct M { + #[primary_span] + span: Span, + var: String, +} + +#[derive(Subdiagnostic)] +#[label("example message", code = "...")] +//~^ ERROR no nested attribute expected here +struct N { + #[primary_span] + span: Span, + var: String, +} + +#[derive(Subdiagnostic)] +#[label("example message", applicability = "machine-applicable")] +//~^ ERROR no nested attribute expected here +struct O { + #[primary_span] + span: Span, + var: String, +} + +#[derive(Subdiagnostic)] +#[foo] +//~^ ERROR cannot find attribute `foo` in this scope +//~^^ ERROR unsupported type attribute for subdiagnostic enum +enum P { + #[label("example message")] + A { + #[primary_span] + span: Span, + var: String, + }, +} + +#[derive(Subdiagnostic)] +enum Q { + #[bar] + //~^ ERROR `#[bar]` is not a valid attribute + //~^^ ERROR cannot find attribute `bar` in this scope + A { + #[primary_span] + span: Span, + var: String, + }, +} + +#[derive(Subdiagnostic)] +enum R { + #[bar = "..."] + //~^ ERROR `#[bar = ...]` is not a valid attribute + //~^^ ERROR cannot find attribute `bar` in this scope + A { + #[primary_span] + span: Span, + var: String, + }, +} + +#[derive(Subdiagnostic)] +enum S { + #[bar = 4] + //~^ ERROR `#[bar = ...]` is not a valid attribute + //~^^ ERROR cannot find attribute `bar` in this scope + A { + #[primary_span] + span: Span, + var: String, + }, +} + +#[derive(Subdiagnostic)] +enum T { + #[bar("...")] + //~^ ERROR `#[bar(...)]` is not a valid attribute + //~^^ ERROR cannot find attribute `bar` in this scope + A { + #[primary_span] + span: Span, + var: String, + }, +} + +#[derive(Subdiagnostic)] +enum U { + #[label(code = "...")] + //~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute + //~| ERROR no nested attribute expected here + A { + #[primary_span] + span: Span, + var: String, + }, +} + +#[derive(Subdiagnostic)] +enum V { + #[label("example message")] + A { + #[primary_span] + span: Span, + var: String, + }, + B { + #[primary_span] + span: Span, + var: String, + }, +} + +#[derive(Subdiagnostic)] +#[label("example message")] +//~^ ERROR label without `#[primary_span]` field +struct W { + #[primary_span] + //~^ ERROR the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` + span: String, +} + +#[derive(Subdiagnostic)] +#[label("example message")] +struct X { + #[primary_span] + span: Span, + #[applicability] + //~^ ERROR `#[applicability]` is only valid on suggestions + applicability: Applicability, +} + +#[derive(Subdiagnostic)] +#[label("example message")] +struct Y { + #[primary_span] + span: Span, + #[bar] + //~^ ERROR `#[bar]` is not a valid attribute + //~^^ ERROR cannot find attribute `bar` in this scope + bar: String, +} + +#[derive(Subdiagnostic)] +#[label("example message")] +struct Z { + #[primary_span] + span: Span, + #[bar = "..."] + //~^ ERROR `#[bar = ...]` is not a valid attribute + //~^^ ERROR cannot find attribute `bar` in this scope + bar: String, +} + +#[derive(Subdiagnostic)] +#[label("example message")] +struct AA { + #[primary_span] + span: Span, + #[bar("...")] + //~^ ERROR `#[bar(...)]` is not a valid attribute + //~^^ ERROR cannot find attribute `bar` in this scope + bar: String, +} + +#[derive(Subdiagnostic)] +#[label("example message")] +struct AB { + #[primary_span] + span: Span, + #[skip_arg] + z: Z, +} + +#[derive(Subdiagnostic)] +union AC { + //~^ ERROR unexpected unsupported untagged union + span: u32, + b: u64, +} + +#[derive(Subdiagnostic)] +#[label("example message")] +#[label("example message")] +struct AD { + #[primary_span] + span: Span, +} + +#[derive(Subdiagnostic)] +#[label("example message", no_crate::example)] +//~^ ERROR a diagnostic slug must be the first argument to the attribute +struct AE { + #[primary_span] + span: Span, +} + +#[derive(Subdiagnostic)] +#[label("example message")] +struct AF { + #[primary_span] + //~^ NOTE previously specified here + span_a: Span, + #[primary_span] + //~^ ERROR specified multiple times + span_b: Span, +} + +#[derive(Subdiagnostic)] +struct AG { + //~^ ERROR subdiagnostic kind not specified + #[primary_span] + span: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "...")] +struct AH { + #[primary_span] + span: Span, + #[applicability] + applicability: Applicability, + var: String, +} + +#[derive(Subdiagnostic)] +enum AI { + #[suggestion("example message", code = "...")] + A { + #[primary_span] + span: Span, + #[applicability] + applicability: Applicability, + var: String, + }, + #[suggestion("example message", code = "...")] + B { + #[primary_span] + span: Span, + #[applicability] + applicability: Applicability, + var: String, + }, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "...", code = "...")] +//~^ ERROR specified multiple times +//~^^ NOTE previously specified here +struct AJ { + #[primary_span] + span: Span, + #[applicability] + applicability: Applicability, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "...")] +struct AK { + #[primary_span] + span: Span, + #[applicability] + //~^ NOTE previously specified here + applicability_a: Applicability, + #[applicability] + //~^ ERROR specified multiple times + applicability_b: Applicability, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "...")] +struct AL { + #[primary_span] + span: Span, + #[applicability] + //~^ ERROR the `#[applicability]` attribute can only be applied to fields of type `Applicability` + applicability: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "...")] +struct AM { + #[primary_span] + span: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message")] +//~^ ERROR suggestion without `code = "..."` +struct AN { + #[primary_span] + span: Span, + #[applicability] + applicability: Applicability, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "...", applicability = "foo")] +//~^ ERROR invalid applicability +struct AO { + #[primary_span] + span: Span, +} + +#[derive(Subdiagnostic)] +#[help("example message")] +struct AP { + var: String, +} + +#[derive(Subdiagnostic)] +#[note("example message")] +struct AQ; + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "...")] +//~^ ERROR suggestion without `#[primary_span]` field +struct AR { + var: String, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "...", applicability = "machine-applicable")] +struct AS { + #[primary_span] + span: Span, +} + +#[derive(Subdiagnostic)] +#[label] +//~^ ERROR unsupported type attribute for subdiagnostic enum +enum AT { + #[label("example message")] + A { + #[primary_span] + span: Span, + var: String, + }, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "{var}", applicability = "machine-applicable")] +struct AU { + #[primary_span] + span: Span, + var: String, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "{var}", applicability = "machine-applicable")] +//~^ ERROR `var` doesn't refer to a field on this type +struct AV { + #[primary_span] + span: Span, +} + +#[derive(Subdiagnostic)] +enum AW { + #[suggestion("example message", code = "{var}", applicability = "machine-applicable")] + A { + #[primary_span] + span: Span, + var: String, + }, +} + +#[derive(Subdiagnostic)] +enum AX { + #[suggestion("example message", code = "{var}", applicability = "machine-applicable")] + //~^ ERROR `var` doesn't refer to a field on this type + A { + #[primary_span] + span: Span, + }, +} + +#[derive(Subdiagnostic)] +#[warning("example message")] +struct AY {} + +#[derive(Subdiagnostic)] +#[warning("example message")] +struct AZ { + #[primary_span] + span: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "...")] +//~^ ERROR suggestion without `#[primary_span]` field +struct BA { + #[suggestion_part] + //~^ ERROR `#[suggestion_part]` is not a valid attribute + span: Span, + #[suggestion_part(code = "...")] + //~^ ERROR `#[suggestion_part(...)]` is not a valid attribute + span2: Span, + #[applicability] + applicability: Applicability, + var: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("example message", code = "...", applicability = "machine-applicable")] +//~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields +//~| ERROR invalid nested attribute +struct BBa { + var: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("example message", applicability = "machine-applicable")] +struct BBb { + #[suggestion_part] + //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` + span1: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("example message", applicability = "machine-applicable")] +struct BBc { + #[suggestion_part()] + //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` + span1: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("example message")] +//~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields +struct BC { + #[primary_span] + //~^ ERROR `#[primary_span]` is not a valid attribute + span: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("example message")] +struct BD { + #[suggestion_part] + //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` + span1: Span, + #[suggestion_part()] + //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` + span2: Span, + #[suggestion_part(foo = "bar")] + //~^ ERROR `code` is the only valid nested attribute + //~| ERROR expected `,` + span4: Span, + #[suggestion_part(code = "...")] + //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` + s1: String, + #[suggestion_part()] + //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` + s2: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("example message", applicability = "machine-applicable")] +struct BE { + #[suggestion_part(code = "...", code = ",,,")] + //~^ ERROR specified multiple times + //~| NOTE previously specified here + span: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("example message", applicability = "machine-applicable")] +struct BF { + #[suggestion_part(code = "(")] + first: Span, + #[suggestion_part(code = ")")] + second: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("example message")] +struct BG { + #[applicability] + appl: Applicability, + #[suggestion_part(code = "(")] + first: Span, + #[suggestion_part(code = ")")] + second: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("example message", applicability = "machine-applicable")] +struct BH { + #[applicability] + //~^ ERROR `#[applicability]` has no effect + appl: Applicability, + #[suggestion_part(code = "(")] + first: Span, + #[suggestion_part(code = ")")] + second: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("example message", applicability = "machine-applicable")] +struct BI { + #[suggestion_part(code = "")] + spans: Vec, +} + +#[derive(Subdiagnostic)] +#[label("example message")] +struct BJ { + #[primary_span] + span: Span, + r#type: String, +} + +/// with a doc comment on the type.. +#[derive(Subdiagnostic)] +#[label("example message")] +struct BK { + /// ..and the field + #[primary_span] + span: Span, +} + +/// with a doc comment on the type.. +#[derive(Subdiagnostic)] +enum BL { + /// ..and the variant.. + #[label("example message")] + Foo { + /// ..and the field + #[primary_span] + span: Span, + }, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("example message")] +struct BM { + #[suggestion_part(code("foo"))] + //~^ ERROR expected exactly one string literal for `code = ...` + //~| ERROR unexpected token, expected `)` + span: Span, + r#type: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("example message")] +struct BN { + #[suggestion_part(code("foo", "bar"))] + //~^ ERROR expected exactly one string literal for `code = ...` + //~| ERROR unexpected token, expected `)` + span: Span, + r#type: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("example message")] +struct BO { + #[suggestion_part(code(3))] + //~^ ERROR expected exactly one string literal for `code = ...` + //~| ERROR unexpected token, expected `)` + span: Span, + r#type: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("example message")] +struct BP { + #[suggestion_part(code())] + //~^ ERROR expected exactly one string literal for `code = ...` + span: Span, + r#type: String, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("example message")] +struct BQ { + #[suggestion_part(code = 3)] + //~^ ERROR expected string literal + span: Span, + r#type: String, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "")] +struct SuggestionStyleDefault { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "", style = "short")] +struct SuggestionStyleShort { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "", style = "hidden")] +struct SuggestionStyleHidden { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "", style = "verbose")] +struct SuggestionStyleVerbose { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "", style = "tool-only")] +struct SuggestionStyleToolOnly { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "", style = "hidden", style = "normal")] +//~^ ERROR specified multiple times +//~| NOTE previously specified here +struct SuggestionStyleTwice { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion_hidden("example message", code = "")] +//~^ ERROR #[suggestion_hidden(...)]` is not a valid attribute +struct SuggestionStyleOldSyntax { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion_hidden("example message", code = "", style = "normal")] +//~^ ERROR #[suggestion_hidden(...)]` is not a valid attribute +struct SuggestionStyleOldAndNewSyntax { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "", style = "foo")] +//~^ ERROR invalid suggestion style +struct SuggestionStyleInvalid1 { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "", style = 42)] +//~^ ERROR expected string literal +struct SuggestionStyleInvalid2 { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "", style)] +//~^ ERROR a diagnostic slug must be the first argument to the attribute +struct SuggestionStyleInvalid3 { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "", style("foo"))] +//~^ ERROR expected `=` +struct SuggestionStyleInvalid4 { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion("example message", code = "")] +//~^ ERROR suggestion without `#[primary_span]` field +struct PrimarySpanOnVec { + #[primary_span] + //~^ ERROR `#[primary_span]` is not a valid attribute + //~| NOTE there must be exactly one primary span + sub: Vec, +} + +#[derive(Subdiagnostic)] +struct NestedParent { + #[subdiagnostic] + single_sub: A, + #[subdiagnostic] + option_sub: Option, + #[subdiagnostic] + vec_sub: Vec, +} diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr new file mode 100644 index 000000000000..11753b949bc7 --- /dev/null +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr @@ -0,0 +1,549 @@ +error: derive(Diagnostic): label without `#[primary_span]` field + --> $DIR/subdiagnostic-derive-inline.rs:50:1 + | +LL | #[label("example message")] + | ^ + +error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive-inline.rs:57:1 + | +LL | #[label] + | ^ + +error: derive(Diagnostic): `#[foo]` is not a valid attribute + --> $DIR/subdiagnostic-derive-inline.rs:66:1 + | +LL | #[foo] + | ^ + +error: derive(Diagnostic): `#[label = ...]` is not a valid attribute + --> $DIR/subdiagnostic-derive-inline.rs:76:1 + | +LL | #[label = "..."] + | ^ + +error: derive(Diagnostic): no nested attribute expected here + --> $DIR/subdiagnostic-derive-inline.rs:85:9 + | +LL | #[label(bug = "...")] + | ^^^ + +error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive-inline.rs:85:1 + | +LL | #[label(bug = "...")] + | ^ + +error: derive(Diagnostic): no nested attribute expected here + --> $DIR/subdiagnostic-derive-inline.rs:95:9 + | +LL | #[label(slug = 4)] + | ^^^^ + +error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive-inline.rs:95:1 + | +LL | #[label(slug = 4)] + | ^ + +error: derive(Diagnostic): no nested attribute expected here + --> $DIR/subdiagnostic-derive-inline.rs:105:9 + | +LL | #[label(slug("..."))] + | ^^^^ + +error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive-inline.rs:105:1 + | +LL | #[label(slug("..."))] + | ^ + +error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive-inline.rs:115:1 + | +LL | #[label()] + | ^ + +error: derive(Diagnostic): no nested attribute expected here + --> $DIR/subdiagnostic-derive-inline.rs:124:28 + | +LL | #[label("example message", code = "...")] + | ^^^^ + +error: derive(Diagnostic): no nested attribute expected here + --> $DIR/subdiagnostic-derive-inline.rs:133:28 + | +LL | #[label("example message", applicability = "machine-applicable")] + | ^^^^^^^^^^^^^ + +error: derive(Diagnostic): unsupported type attribute for subdiagnostic enum + --> $DIR/subdiagnostic-derive-inline.rs:142:1 + | +LL | #[foo] + | ^ + +error: derive(Diagnostic): `#[bar]` is not a valid attribute + --> $DIR/subdiagnostic-derive-inline.rs:156:5 + | +LL | #[bar] + | ^ + +error: derive(Diagnostic): `#[bar = ...]` is not a valid attribute + --> $DIR/subdiagnostic-derive-inline.rs:168:5 + | +LL | #[bar = "..."] + | ^ + +error: derive(Diagnostic): `#[bar = ...]` is not a valid attribute + --> $DIR/subdiagnostic-derive-inline.rs:180:5 + | +LL | #[bar = 4] + | ^ + +error: derive(Diagnostic): `#[bar(...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive-inline.rs:192:5 + | +LL | #[bar("...")] + | ^ + +error: derive(Diagnostic): no nested attribute expected here + --> $DIR/subdiagnostic-derive-inline.rs:204:13 + | +LL | #[label(code = "...")] + | ^^^^ + +error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive-inline.rs:204:5 + | +LL | #[label(code = "...")] + | ^ + +error: derive(Diagnostic): the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` + --> $DIR/subdiagnostic-derive-inline.rs:233:5 + | +LL | #[primary_span] + | ^ + +error: derive(Diagnostic): label without `#[primary_span]` field + --> $DIR/subdiagnostic-derive-inline.rs:230:1 + | +LL | #[label("example message")] + | ^ + +error: derive(Diagnostic): `#[applicability]` is only valid on suggestions + --> $DIR/subdiagnostic-derive-inline.rs:243:5 + | +LL | #[applicability] + | ^ + +error: derive(Diagnostic): `#[bar]` is not a valid attribute + --> $DIR/subdiagnostic-derive-inline.rs:253:5 + | +LL | #[bar] + | ^ + | + = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes + +error: derive(Diagnostic): `#[bar = ...]` is not a valid attribute + --> $DIR/subdiagnostic-derive-inline.rs:264:5 + | +LL | #[bar = "..."] + | ^ + +error: derive(Diagnostic): `#[bar(...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive-inline.rs:275:5 + | +LL | #[bar("...")] + | ^ + | + = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes + +error: unexpected unsupported untagged union + --> $DIR/subdiagnostic-derive-inline.rs:291:1 + | +LL | / union AC { +LL | | +LL | | span: u32, +LL | | b: u64, +LL | | } + | |_^ + +error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute + --> $DIR/subdiagnostic-derive-inline.rs:306:28 + | +LL | #[label("example message", no_crate::example)] + | ^^^^^^^^ + +error: derive(Diagnostic): attribute specified multiple times + --> $DIR/subdiagnostic-derive-inline.rs:319:5 + | +LL | #[primary_span] + | ^ + | +note: previously specified here + --> $DIR/subdiagnostic-derive-inline.rs:316:5 + | +LL | #[primary_span] + | ^ + +error: derive(Diagnostic): subdiagnostic kind not specified + --> $DIR/subdiagnostic-derive-inline.rs:325:8 + | +LL | struct AG { + | ^^ + +error: derive(Diagnostic): attribute specified multiple times + --> $DIR/subdiagnostic-derive-inline.rs:362:47 + | +LL | #[suggestion("example message", code = "...", code = "...")] + | ^^^^ + | +note: previously specified here + --> $DIR/subdiagnostic-derive-inline.rs:362:33 + | +LL | #[suggestion("example message", code = "...", code = "...")] + | ^^^^ + +error: derive(Diagnostic): attribute specified multiple times + --> $DIR/subdiagnostic-derive-inline.rs:380:5 + | +LL | #[applicability] + | ^ + | +note: previously specified here + --> $DIR/subdiagnostic-derive-inline.rs:377:5 + | +LL | #[applicability] + | ^ + +error: derive(Diagnostic): the `#[applicability]` attribute can only be applied to fields of type `Applicability` + --> $DIR/subdiagnostic-derive-inline.rs:390:5 + | +LL | #[applicability] + | ^ + +error: derive(Diagnostic): suggestion without `code = "..."` + --> $DIR/subdiagnostic-derive-inline.rs:403:1 + | +LL | #[suggestion("example message")] + | ^ + +error: derive(Diagnostic): invalid applicability + --> $DIR/subdiagnostic-derive-inline.rs:413:63 + | +LL | #[suggestion("example message", code = "...", applicability = "foo")] + | ^^^^^ + +error: derive(Diagnostic): suggestion without `#[primary_span]` field + --> $DIR/subdiagnostic-derive-inline.rs:431:1 + | +LL | #[suggestion("example message", code = "...")] + | ^ + +error: derive(Diagnostic): unsupported type attribute for subdiagnostic enum + --> $DIR/subdiagnostic-derive-inline.rs:445:1 + | +LL | #[label] + | ^ + +error: derive(Diagnostic): `var` doesn't refer to a field on this type + --> $DIR/subdiagnostic-derive-inline.rs:465:40 + | +LL | #[suggestion("example message", code = "{var}", applicability = "machine-applicable")] + | ^^^^^^^ + +error: derive(Diagnostic): `var` doesn't refer to a field on this type + --> $DIR/subdiagnostic-derive-inline.rs:484:44 + | +LL | #[suggestion("example message", code = "{var}", applicability = "machine-applicable")] + | ^^^^^^^ + +error: derive(Diagnostic): `#[suggestion_part]` is not a valid attribute + --> $DIR/subdiagnostic-derive-inline.rs:507:5 + | +LL | #[suggestion_part] + | ^ + | + = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead + +error: derive(Diagnostic): `#[suggestion_part(...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive-inline.rs:510:5 + | +LL | #[suggestion_part(code = "...")] + | ^ + | + = help: `#[suggestion_part(...)]` is only valid in multipart suggestions + +error: derive(Diagnostic): suggestion without `#[primary_span]` field + --> $DIR/subdiagnostic-derive-inline.rs:504:1 + | +LL | #[suggestion("example message", code = "...")] + | ^ + +error: derive(Diagnostic): invalid nested attribute + --> $DIR/subdiagnostic-derive-inline.rs:519:43 + | +LL | #[multipart_suggestion("example message", code = "...", applicability = "machine-applicable")] + | ^^^^ + | + = help: only `style` and `applicability` are valid nested attributes + +error: derive(Diagnostic): multipart suggestion without any `#[suggestion_part(...)]` fields + --> $DIR/subdiagnostic-derive-inline.rs:519:1 + | +LL | #[multipart_suggestion("example message", code = "...", applicability = "machine-applicable")] + | ^ + +error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` + --> $DIR/subdiagnostic-derive-inline.rs:529:5 + | +LL | #[suggestion_part] + | ^ + +error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` + --> $DIR/subdiagnostic-derive-inline.rs:537:5 + | +LL | #[suggestion_part()] + | ^ + +error: derive(Diagnostic): `#[primary_span]` is not a valid attribute + --> $DIR/subdiagnostic-derive-inline.rs:546:5 + | +LL | #[primary_span] + | ^ + | + = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]` + +error: derive(Diagnostic): multipart suggestion without any `#[suggestion_part(...)]` fields + --> $DIR/subdiagnostic-derive-inline.rs:543:1 + | +LL | #[multipart_suggestion("example message")] + | ^ + +error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` + --> $DIR/subdiagnostic-derive-inline.rs:554:5 + | +LL | #[suggestion_part] + | ^ + +error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` + --> $DIR/subdiagnostic-derive-inline.rs:557:5 + | +LL | #[suggestion_part()] + | ^ + +error: derive(Diagnostic): `code` is the only valid nested attribute + --> $DIR/subdiagnostic-derive-inline.rs:560:23 + | +LL | #[suggestion_part(foo = "bar")] + | ^^^ + +error: derive(Diagnostic): the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` + --> $DIR/subdiagnostic-derive-inline.rs:564:5 + | +LL | #[suggestion_part(code = "...")] + | ^ + +error: derive(Diagnostic): the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` + --> $DIR/subdiagnostic-derive-inline.rs:567:5 + | +LL | #[suggestion_part()] + | ^ + +error: expected `,` + --> $DIR/subdiagnostic-derive-inline.rs:560:27 + | +LL | #[suggestion_part(foo = "bar")] + | ^ + +error: derive(Diagnostic): attribute specified multiple times + --> $DIR/subdiagnostic-derive-inline.rs:575:37 + | +LL | #[suggestion_part(code = "...", code = ",,,")] + | ^^^^ + | +note: previously specified here + --> $DIR/subdiagnostic-derive-inline.rs:575:23 + | +LL | #[suggestion_part(code = "...", code = ",,,")] + | ^^^^ + +error: derive(Diagnostic): `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."` + --> $DIR/subdiagnostic-derive-inline.rs:604:5 + | +LL | #[applicability] + | ^ + +error: derive(Diagnostic): expected exactly one string literal for `code = ...` + --> $DIR/subdiagnostic-derive-inline.rs:652:28 + | +LL | #[suggestion_part(code("foo"))] + | ^^^^^ + +error: unexpected token, expected `)` + --> $DIR/subdiagnostic-derive-inline.rs:652:28 + | +LL | #[suggestion_part(code("foo"))] + | ^^^^^ + +error: derive(Diagnostic): expected exactly one string literal for `code = ...` + --> $DIR/subdiagnostic-derive-inline.rs:662:28 + | +LL | #[suggestion_part(code("foo", "bar"))] + | ^^^^^ + +error: unexpected token, expected `)` + --> $DIR/subdiagnostic-derive-inline.rs:662:28 + | +LL | #[suggestion_part(code("foo", "bar"))] + | ^^^^^ + +error: derive(Diagnostic): expected exactly one string literal for `code = ...` + --> $DIR/subdiagnostic-derive-inline.rs:672:28 + | +LL | #[suggestion_part(code(3))] + | ^ + +error: unexpected token, expected `)` + --> $DIR/subdiagnostic-derive-inline.rs:672:28 + | +LL | #[suggestion_part(code(3))] + | ^ + +error: derive(Diagnostic): expected exactly one string literal for `code = ...` + --> $DIR/subdiagnostic-derive-inline.rs:682:28 + | +LL | #[suggestion_part(code())] + | ^ + +error: expected string literal + --> $DIR/subdiagnostic-derive-inline.rs:691:30 + | +LL | #[suggestion_part(code = 3)] + | ^ + +error: derive(Diagnostic): attribute specified multiple times + --> $DIR/subdiagnostic-derive-inline.rs:733:1 + | +LL | #[suggestion("example message", code = "", style = "hidden", style = "normal")] + | ^ + | +note: previously specified here + --> $DIR/subdiagnostic-derive-inline.rs:733:1 + | +LL | #[suggestion("example message", code = "", style = "hidden", style = "normal")] + | ^ + +error: derive(Diagnostic): `#[suggestion_hidden(...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive-inline.rs:742:1 + | +LL | #[suggestion_hidden("example message", code = "")] + | ^ + | + = help: Use `#[suggestion(..., style = "hidden")]` instead + +error: derive(Diagnostic): `#[suggestion_hidden(...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive-inline.rs:750:1 + | +LL | #[suggestion_hidden("example message", code = "", style = "normal")] + | ^ + | + = help: Use `#[suggestion(..., style = "hidden")]` instead + +error: derive(Diagnostic): invalid suggestion style + --> $DIR/subdiagnostic-derive-inline.rs:758:52 + | +LL | #[suggestion("example message", code = "", style = "foo")] + | ^^^^^ + | + = help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only` + +error: expected string literal + --> $DIR/subdiagnostic-derive-inline.rs:766:52 + | +LL | #[suggestion("example message", code = "", style = 42)] + | ^^ + +error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute + --> $DIR/subdiagnostic-derive-inline.rs:774:44 + | +LL | #[suggestion("example message", code = "", style)] + | ^^^^^ + +error: expected `=` + --> $DIR/subdiagnostic-derive-inline.rs:782:49 + | +LL | #[suggestion("example message", code = "", style("foo"))] + | ^ + +error: derive(Diagnostic): `#[primary_span]` is not a valid attribute + --> $DIR/subdiagnostic-derive-inline.rs:793:5 + | +LL | #[primary_span] + | ^ + | + = note: there must be exactly one primary span + = help: to create a suggestion with multiple spans, use `#[multipart_suggestion]` instead + +error: derive(Diagnostic): suggestion without `#[primary_span]` field + --> $DIR/subdiagnostic-derive-inline.rs:790:1 + | +LL | #[suggestion("example message", code = "")] + | ^ + +error: cannot find attribute `foo` in this scope + --> $DIR/subdiagnostic-derive-inline.rs:66:3 + | +LL | #[foo] + | ^^^ + +error: cannot find attribute `foo` in this scope + --> $DIR/subdiagnostic-derive-inline.rs:142:3 + | +LL | #[foo] + | ^^^ + +error: cannot find attribute `bar` in this scope + --> $DIR/subdiagnostic-derive-inline.rs:156:7 + | +LL | #[bar] + | ^^^ + +error: cannot find attribute `bar` in this scope + --> $DIR/subdiagnostic-derive-inline.rs:168:7 + | +LL | #[bar = "..."] + | ^^^ + +error: cannot find attribute `bar` in this scope + --> $DIR/subdiagnostic-derive-inline.rs:180:7 + | +LL | #[bar = 4] + | ^^^ + +error: cannot find attribute `bar` in this scope + --> $DIR/subdiagnostic-derive-inline.rs:192:7 + | +LL | #[bar("...")] + | ^^^ + +error: cannot find attribute `bar` in this scope + --> $DIR/subdiagnostic-derive-inline.rs:253:7 + | +LL | #[bar] + | ^^^ + +error: cannot find attribute `bar` in this scope + --> $DIR/subdiagnostic-derive-inline.rs:264:7 + | +LL | #[bar = "..."] + | ^^^ + +error: cannot find attribute `bar` in this scope + --> $DIR/subdiagnostic-derive-inline.rs:275:7 + | +LL | #[bar("...")] + | ^^^ + +error: aborting due to 82 previous errors + diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index b2e7b4c61daa..c06ea451b9bf 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -93,15 +93,6 @@ struct G { var: String, } -#[derive(Subdiagnostic)] -#[label("...")] -//~^ ERROR expected identifier -struct H { - #[primary_span] - span: Span, - var: String, -} - #[derive(Subdiagnostic)] #[label(slug = 4)] //~^ ERROR no nested attribute expected here diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index 63634741e934..9f18f7ffabcc 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -34,116 +34,110 @@ error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label( LL | #[label(bug = "...")] | ^ -error: expected identifier +error: derive(Diagnostic): no nested attribute expected here --> $DIR/subdiagnostic-derive.rs:97:9 | -LL | #[label("...")] - | ^^^^^ - -error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive.rs:106:9 - | LL | #[label(slug = 4)] | ^^^^ error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:106:1 + --> $DIR/subdiagnostic-derive.rs:97:1 | LL | #[label(slug = 4)] | ^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive.rs:116:9 + --> $DIR/subdiagnostic-derive.rs:107:9 | LL | #[label(slug("..."))] | ^^^^ error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:116:1 + --> $DIR/subdiagnostic-derive.rs:107:1 | LL | #[label(slug("..."))] | ^ error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:126:1 + --> $DIR/subdiagnostic-derive.rs:117:1 | LL | #[label()] | ^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive.rs:135:27 + --> $DIR/subdiagnostic-derive.rs:126:27 | LL | #[label(no_crate_example, code = "...")] | ^^^^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive.rs:144:27 + --> $DIR/subdiagnostic-derive.rs:135:27 | LL | #[label(no_crate_example, applicability = "machine-applicable")] | ^^^^^^^^^^^^^ error: derive(Diagnostic): unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:153:1 + --> $DIR/subdiagnostic-derive.rs:144:1 | LL | #[foo] | ^ error: derive(Diagnostic): `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:167:5 + --> $DIR/subdiagnostic-derive.rs:158:5 | LL | #[bar] | ^ error: derive(Diagnostic): `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:179:5 + --> $DIR/subdiagnostic-derive.rs:170:5 | LL | #[bar = "..."] | ^ error: derive(Diagnostic): `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:191:5 + --> $DIR/subdiagnostic-derive.rs:182:5 | LL | #[bar = 4] | ^ error: derive(Diagnostic): `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:203:5 + --> $DIR/subdiagnostic-derive.rs:194:5 | LL | #[bar("...")] | ^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive.rs:215:13 + --> $DIR/subdiagnostic-derive.rs:206:13 | LL | #[label(code = "...")] | ^^^^ error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:215:5 + --> $DIR/subdiagnostic-derive.rs:206:5 | LL | #[label(code = "...")] | ^ error: derive(Diagnostic): the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:244:5 + --> $DIR/subdiagnostic-derive.rs:235:5 | LL | #[primary_span] | ^ error: derive(Diagnostic): label without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:241:1 + --> $DIR/subdiagnostic-derive.rs:232:1 | LL | #[label(no_crate_example)] | ^ error: derive(Diagnostic): `#[applicability]` is only valid on suggestions - --> $DIR/subdiagnostic-derive.rs:254:5 + --> $DIR/subdiagnostic-derive.rs:245:5 | LL | #[applicability] | ^ error: derive(Diagnostic): `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:264:5 + --> $DIR/subdiagnostic-derive.rs:255:5 | LL | #[bar] | ^ @@ -151,13 +145,13 @@ LL | #[bar] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: derive(Diagnostic): `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:275:5 + --> $DIR/subdiagnostic-derive.rs:266:5 | LL | #[bar = "..."] | ^ error: derive(Diagnostic): `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:286:5 + --> $DIR/subdiagnostic-derive.rs:277:5 | LL | #[bar("...")] | ^ @@ -165,7 +159,7 @@ LL | #[bar("...")] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: unexpected unsupported untagged union - --> $DIR/subdiagnostic-derive.rs:302:1 + --> $DIR/subdiagnostic-derive.rs:293:1 | LL | / union AC { LL | | @@ -175,97 +169,97 @@ LL | | } | |_^ error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute - --> $DIR/subdiagnostic-derive.rs:317:27 + --> $DIR/subdiagnostic-derive.rs:308:27 | LL | #[label(no_crate_example, no_crate::example)] | ^^^^^^^^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive.rs:330:5 + --> $DIR/subdiagnostic-derive.rs:321:5 | LL | #[primary_span] | ^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:327:5 + --> $DIR/subdiagnostic-derive.rs:318:5 | LL | #[primary_span] | ^ error: derive(Diagnostic): subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:336:8 + --> $DIR/subdiagnostic-derive.rs:327:8 | LL | struct AG { | ^^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive.rs:373:46 + --> $DIR/subdiagnostic-derive.rs:364:46 | LL | #[suggestion(no_crate_example, code = "...", code = "...")] | ^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:373:32 + --> $DIR/subdiagnostic-derive.rs:364:32 | LL | #[suggestion(no_crate_example, code = "...", code = "...")] | ^^^^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive.rs:391:5 + --> $DIR/subdiagnostic-derive.rs:382:5 | LL | #[applicability] | ^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:388:5 + --> $DIR/subdiagnostic-derive.rs:379:5 | LL | #[applicability] | ^ error: derive(Diagnostic): the `#[applicability]` attribute can only be applied to fields of type `Applicability` - --> $DIR/subdiagnostic-derive.rs:401:5 + --> $DIR/subdiagnostic-derive.rs:392:5 | LL | #[applicability] | ^ error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:414:1 + --> $DIR/subdiagnostic-derive.rs:405:1 | LL | #[suggestion(no_crate_example)] | ^ error: derive(Diagnostic): invalid applicability - --> $DIR/subdiagnostic-derive.rs:424:62 + --> $DIR/subdiagnostic-derive.rs:415:62 | LL | #[suggestion(no_crate_example, code = "...", applicability = "foo")] | ^^^^^ error: derive(Diagnostic): suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:442:1 + --> $DIR/subdiagnostic-derive.rs:433:1 | LL | #[suggestion(no_crate_example, code = "...")] | ^ error: derive(Diagnostic): unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:456:1 + --> $DIR/subdiagnostic-derive.rs:447:1 | LL | #[label] | ^ error: derive(Diagnostic): `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:476:39 + --> $DIR/subdiagnostic-derive.rs:467:39 | LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")] | ^^^^^^^ error: derive(Diagnostic): `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:495:43 + --> $DIR/subdiagnostic-derive.rs:486:43 | LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")] | ^^^^^^^ error: derive(Diagnostic): `#[suggestion_part]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:518:5 + --> $DIR/subdiagnostic-derive.rs:509:5 | LL | #[suggestion_part] | ^ @@ -273,7 +267,7 @@ LL | #[suggestion_part] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead error: derive(Diagnostic): `#[suggestion_part(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:521:5 + --> $DIR/subdiagnostic-derive.rs:512:5 | LL | #[suggestion_part(code = "...")] | ^ @@ -281,13 +275,13 @@ LL | #[suggestion_part(code = "...")] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions error: derive(Diagnostic): suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:515:1 + --> $DIR/subdiagnostic-derive.rs:506:1 | LL | #[suggestion(no_crate_example, code = "...")] | ^ error: derive(Diagnostic): invalid nested attribute - --> $DIR/subdiagnostic-derive.rs:530:42 + --> $DIR/subdiagnostic-derive.rs:521:42 | LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] | ^^^^ @@ -295,25 +289,25 @@ LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "mac = help: only `style` and `applicability` are valid nested attributes error: derive(Diagnostic): multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:530:1 + --> $DIR/subdiagnostic-derive.rs:521:1 | LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] | ^ error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:540:5 + --> $DIR/subdiagnostic-derive.rs:531:5 | LL | #[suggestion_part] | ^ error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:548:5 + --> $DIR/subdiagnostic-derive.rs:539:5 | LL | #[suggestion_part()] | ^ error: derive(Diagnostic): `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:557:5 + --> $DIR/subdiagnostic-derive.rs:548:5 | LL | #[primary_span] | ^ @@ -321,127 +315,127 @@ LL | #[primary_span] = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]` error: derive(Diagnostic): multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:554:1 + --> $DIR/subdiagnostic-derive.rs:545:1 | LL | #[multipart_suggestion(no_crate_example)] | ^ error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:565:5 + --> $DIR/subdiagnostic-derive.rs:556:5 | LL | #[suggestion_part] | ^ error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:568:5 + --> $DIR/subdiagnostic-derive.rs:559:5 | LL | #[suggestion_part()] | ^ error: derive(Diagnostic): `code` is the only valid nested attribute - --> $DIR/subdiagnostic-derive.rs:571:23 + --> $DIR/subdiagnostic-derive.rs:562:23 | LL | #[suggestion_part(foo = "bar")] | ^^^ error: derive(Diagnostic): the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:575:5 + --> $DIR/subdiagnostic-derive.rs:566:5 | LL | #[suggestion_part(code = "...")] | ^ error: derive(Diagnostic): the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:578:5 + --> $DIR/subdiagnostic-derive.rs:569:5 | LL | #[suggestion_part()] | ^ error: expected `,` - --> $DIR/subdiagnostic-derive.rs:571:27 + --> $DIR/subdiagnostic-derive.rs:562:27 | LL | #[suggestion_part(foo = "bar")] | ^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive.rs:586:37 + --> $DIR/subdiagnostic-derive.rs:577:37 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:586:23 + --> $DIR/subdiagnostic-derive.rs:577:23 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^ error: derive(Diagnostic): `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."` - --> $DIR/subdiagnostic-derive.rs:615:5 + --> $DIR/subdiagnostic-derive.rs:606:5 | LL | #[applicability] | ^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:663:28 + --> $DIR/subdiagnostic-derive.rs:654:28 | LL | #[suggestion_part(code("foo"))] | ^^^^^ error: unexpected token, expected `)` - --> $DIR/subdiagnostic-derive.rs:663:28 + --> $DIR/subdiagnostic-derive.rs:654:28 | LL | #[suggestion_part(code("foo"))] | ^^^^^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:673:28 + --> $DIR/subdiagnostic-derive.rs:664:28 | LL | #[suggestion_part(code("foo", "bar"))] | ^^^^^ error: unexpected token, expected `)` - --> $DIR/subdiagnostic-derive.rs:673:28 + --> $DIR/subdiagnostic-derive.rs:664:28 | LL | #[suggestion_part(code("foo", "bar"))] | ^^^^^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:683:28 + --> $DIR/subdiagnostic-derive.rs:674:28 | LL | #[suggestion_part(code(3))] | ^ error: unexpected token, expected `)` - --> $DIR/subdiagnostic-derive.rs:683:28 + --> $DIR/subdiagnostic-derive.rs:674:28 | LL | #[suggestion_part(code(3))] | ^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:693:28 + --> $DIR/subdiagnostic-derive.rs:684:28 | LL | #[suggestion_part(code())] | ^ error: expected string literal - --> $DIR/subdiagnostic-derive.rs:702:30 + --> $DIR/subdiagnostic-derive.rs:693:30 | LL | #[suggestion_part(code = 3)] | ^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive.rs:744:1 + --> $DIR/subdiagnostic-derive.rs:735:1 | LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")] | ^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:744:1 + --> $DIR/subdiagnostic-derive.rs:735:1 | LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")] | ^ error: derive(Diagnostic): `#[suggestion_hidden(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:753:1 + --> $DIR/subdiagnostic-derive.rs:744:1 | LL | #[suggestion_hidden(no_crate_example, code = "")] | ^ @@ -449,7 +443,7 @@ LL | #[suggestion_hidden(no_crate_example, code = "")] = help: Use `#[suggestion(..., style = "hidden")]` instead error: derive(Diagnostic): `#[suggestion_hidden(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:761:1 + --> $DIR/subdiagnostic-derive.rs:752:1 | LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")] | ^ @@ -457,7 +451,7 @@ LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")] = help: Use `#[suggestion(..., style = "hidden")]` instead error: derive(Diagnostic): invalid suggestion style - --> $DIR/subdiagnostic-derive.rs:769:51 + --> $DIR/subdiagnostic-derive.rs:760:51 | LL | #[suggestion(no_crate_example, code = "", style = "foo")] | ^^^^^ @@ -465,25 +459,25 @@ LL | #[suggestion(no_crate_example, code = "", style = "foo")] = help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only` error: expected string literal - --> $DIR/subdiagnostic-derive.rs:777:51 + --> $DIR/subdiagnostic-derive.rs:768:51 | LL | #[suggestion(no_crate_example, code = "", style = 42)] | ^^ error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute - --> $DIR/subdiagnostic-derive.rs:785:43 + --> $DIR/subdiagnostic-derive.rs:776:43 | LL | #[suggestion(no_crate_example, code = "", style)] | ^^^^^ error: expected `=` - --> $DIR/subdiagnostic-derive.rs:793:48 + --> $DIR/subdiagnostic-derive.rs:784:48 | LL | #[suggestion(no_crate_example, code = "", style("foo"))] | ^ error: derive(Diagnostic): `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:804:5 + --> $DIR/subdiagnostic-derive.rs:795:5 | LL | #[primary_span] | ^ @@ -492,7 +486,7 @@ LL | #[primary_span] = help: to create a suggestion with multiple spans, use `#[multipart_suggestion]` instead error: derive(Diagnostic): suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:801:1 + --> $DIR/subdiagnostic-derive.rs:792:1 | LL | #[suggestion(no_crate_example, code = "")] | ^ @@ -504,52 +498,52 @@ LL | #[foo] | ^^^ error: cannot find attribute `foo` in this scope - --> $DIR/subdiagnostic-derive.rs:153:3 + --> $DIR/subdiagnostic-derive.rs:144:3 | LL | #[foo] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:167:7 + --> $DIR/subdiagnostic-derive.rs:158:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:179:7 + --> $DIR/subdiagnostic-derive.rs:170:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:191:7 + --> $DIR/subdiagnostic-derive.rs:182:7 | LL | #[bar = 4] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:203:7 + --> $DIR/subdiagnostic-derive.rs:194:7 | LL | #[bar("...")] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:264:7 + --> $DIR/subdiagnostic-derive.rs:255:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:275:7 + --> $DIR/subdiagnostic-derive.rs:266:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:286:7 + --> $DIR/subdiagnostic-derive.rs:277:7 | LL | #[bar("...")] | ^^^ -error: aborting due to 83 previous errors +error: aborting due to 82 previous errors From ca2be71a18487405d72ae87d84e8fc75bb366b82 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 30 Jan 2026 21:23:40 +0100 Subject: [PATCH 349/978] Add verification for inline fluent messages --- Cargo.lock | 2 + compiler/rustc_macros/Cargo.toml | 2 + .../src/diagnostics/diagnostic.rs | 53 ++------ .../src/diagnostics/diagnostic_builder.rs | 38 ++++-- .../rustc_macros/src/diagnostics/message.rs | 127 ++++++++++++++++-- .../src/diagnostics/subdiagnostic.rs | 9 +- .../rustc_macros/src/diagnostics/utils.rs | 2 +- .../diagnostic-derive-inline.rs | 13 ++ .../diagnostic-derive-inline.stderr | 10 +- 9 files changed, 183 insertions(+), 73 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6be4565374af..9acb62b234ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4229,6 +4229,8 @@ dependencies = [ name = "rustc_macros" version = "0.0.0" dependencies = [ + "fluent-bundle", + "fluent-syntax", "proc-macro2", "quote", "syn 2.0.110", diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml index f9d3b7583590..f097aee54abb 100644 --- a/compiler/rustc_macros/Cargo.toml +++ b/compiler/rustc_macros/Cargo.toml @@ -8,6 +8,8 @@ proc-macro = true [dependencies] # tidy-alphabetical-start +fluent-bundle = "0.16" +fluent-syntax = "0.12" proc-macro2 = "1" quote = "1" syn = { version = "2.0.9", features = ["full"] } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 1ae6393b2860..b4270f45422e 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -22,7 +22,7 @@ impl<'a> DiagnosticDerive<'a> { pub(crate) fn into_tokens(self) -> TokenStream { let DiagnosticDerive { mut structure } = self; let kind = DiagnosticDeriveKind::Diagnostic; - let slugs = RefCell::new(Vec::new()); + let messages = RefCell::new(Vec::new()); let implementation = kind.each_variant(&mut structure, |mut builder, variant| { let preamble = builder.preamble(variant); let body = builder.body(variant); @@ -30,8 +30,8 @@ impl<'a> DiagnosticDerive<'a> { let Some(message) = builder.primary_message() else { return DiagnosticDeriveError::ErrorHandled.to_compile_error(); }; - slugs.borrow_mut().extend(message.slug().cloned()); - let message = message.diag_message(); + messages.borrow_mut().push(message.clone()); + let message = message.diag_message(variant); let init = quote! { let mut diag = rustc_errors::Diag::new( @@ -68,7 +68,7 @@ impl<'a> DiagnosticDerive<'a> { } } }); - for test in slugs.borrow().iter().map(|s| generate_test(s, &structure)) { + for test in messages.borrow().iter().map(|s| s.generate_test(&structure)) { imp.extend(test); } imp @@ -88,7 +88,7 @@ impl<'a> LintDiagnosticDerive<'a> { pub(crate) fn into_tokens(self) -> TokenStream { let LintDiagnosticDerive { mut structure } = self; let kind = DiagnosticDeriveKind::LintDiagnostic; - let slugs = RefCell::new(Vec::new()); + let messages = RefCell::new(Vec::new()); let implementation = kind.each_variant(&mut structure, |mut builder, variant| { let preamble = builder.preamble(variant); let body = builder.body(variant); @@ -96,8 +96,8 @@ impl<'a> LintDiagnosticDerive<'a> { let Some(message) = builder.primary_message() else { return DiagnosticDeriveError::ErrorHandled.to_compile_error(); }; - slugs.borrow_mut().extend(message.slug().cloned()); - let message = message.diag_message(); + messages.borrow_mut().push(message.clone()); + let message = message.diag_message(variant); let primary_message = quote! { diag.primary_message(#message); }; @@ -125,47 +125,10 @@ impl<'a> LintDiagnosticDerive<'a> { } } }); - for test in slugs.borrow().iter().map(|s| generate_test(s, &structure)) { + for test in messages.borrow().iter().map(|s| s.generate_test(&structure)) { imp.extend(test); } imp } } - -/// Generates a `#[test]` that verifies that all referenced variables -/// exist on this structure. -fn generate_test(slug: &syn::Path, structure: &Structure<'_>) -> TokenStream { - // FIXME: We can't identify variables in a subdiagnostic - for field in structure.variants().iter().flat_map(|v| v.ast().fields.iter()) { - for attr_name in field.attrs.iter().filter_map(|at| at.path().get_ident()) { - if attr_name == "subdiagnostic" { - return quote!(); - } - } - } - 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. - 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)); - let ref_slug = quote::format_ident!("{slug}_refs"); - let struct_name = &structure.ast().ident; - let variables: Vec<_> = structure - .variants() - .iter() - .flat_map(|v| v.ast().fields.iter().filter_map(|f| f.ident.as_ref().map(|i| i.to_string()))) - .collect(); - // tidy errors on `#[test]` outside of test files, so we use `#[test ]` to work around this - quote! { - #[cfg(test)] - #[test ] - fn #ident() { - let variables = [#(#variables),*]; - for vref in crate::fluent_generated::#ref_slug { - assert!(variables.contains(vref), "{}: variable `{vref}` not found ({})", stringify!(#struct_name), stringify!(#slug)); - } - } - } -} diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 14eda017970f..e6d9409a1fa3 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -137,7 +137,8 @@ impl DiagnosticDeriveVariantBuilder { let ast = variant.ast(); let attrs = &ast.attrs; let preamble = attrs.iter().map(|attr| { - self.generate_structure_code_for_attr(attr).unwrap_or_else(|v| v.to_compile_error()) + self.generate_structure_code_for_attr(attr, variant) + .unwrap_or_else(|v| v.to_compile_error()) }); quote! { @@ -155,7 +156,7 @@ impl DiagnosticDeriveVariantBuilder { } // ..and then subdiagnostic additions. for binding in variant.bindings().iter().filter(|bi| !should_generate_arg(bi.ast())) { - body.extend(self.generate_field_attrs_code(binding)); + body.extend(self.generate_field_attrs_code(binding, variant)); } body } @@ -199,6 +200,7 @@ impl DiagnosticDeriveVariantBuilder { fn generate_structure_code_for_attr( &mut self, attr: &Attribute, + variant: &VariantInfo<'_>, ) -> Result { // Always allow documentation comments. if is_doc_comment(attr) { @@ -224,7 +226,7 @@ impl DiagnosticDeriveVariantBuilder { ) .emit(); } - self.message = Some(Message::Inline(message.value())); + self.message = Some(Message::Inline(message.span(), message.value())); } else { // Parse a slug let slug = input.parse::()?; @@ -285,7 +287,7 @@ impl DiagnosticDeriveVariantBuilder { | SubdiagnosticKind::NoteOnce | SubdiagnosticKind::Help | SubdiagnosticKind::HelpOnce - | SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, slug)), + | SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, slug, variant)), SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => { throw_invalid_attr!(attr, |diag| diag .help("`#[label]` and `#[suggestion]` can only be applied to fields")); @@ -313,7 +315,11 @@ impl DiagnosticDeriveVariantBuilder { } } - fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { + fn generate_field_attrs_code( + &mut self, + binding_info: &BindingInfo<'_>, + variant: &VariantInfo<'_>, + ) -> TokenStream { let field = binding_info.ast(); let field_binding = &binding_info.binding; @@ -352,6 +358,7 @@ impl DiagnosticDeriveVariantBuilder { attr, FieldInfo { binding: binding_info, ty: inner_ty, span: &field.span() }, binding, + variant ) .unwrap_or_else(|v| v.to_compile_error()); @@ -369,6 +376,7 @@ impl DiagnosticDeriveVariantBuilder { attr: &Attribute, info: FieldInfo<'_>, binding: TokenStream, + variant: &VariantInfo<'_>, ) -> Result { let ident = &attr.path().segments.last().unwrap().ident; let name = ident.to_string(); @@ -407,7 +415,7 @@ impl DiagnosticDeriveVariantBuilder { match subdiag { SubdiagnosticKind::Label => { report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug)) + Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug, variant)) } SubdiagnosticKind::Note | SubdiagnosticKind::NoteOnce @@ -418,11 +426,11 @@ impl DiagnosticDeriveVariantBuilder { if type_matches_path(inner, &["rustc_span", "Span"]) || type_matches_path(inner, &["rustc_span", "MultiSpan"]) { - Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug)) + Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug, variant)) } else if type_is_unit(inner) || (matches!(info.ty, FieldInnerTy::Plain(_)) && type_is_bool(inner)) { - Ok(self.add_subdiagnostic(&fn_ident, slug)) + Ok(self.add_subdiagnostic(&fn_ident, slug, variant)) } else { report_type_error(attr, "`Span`, `MultiSpan`, `bool` or `()`")? } @@ -448,7 +456,7 @@ impl DiagnosticDeriveVariantBuilder { applicability.set_once(quote! { #static_applicability }, span); } - let message = slug.diag_message(); + let message = slug.diag_message(variant); let applicability = applicability .value() .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified }); @@ -476,9 +484,10 @@ impl DiagnosticDeriveVariantBuilder { field_binding: TokenStream, kind: &Ident, message: Message, + variant: &VariantInfo<'_>, ) -> TokenStream { let fn_name = format_ident!("span_{}", kind); - let message = message.diag_message(); + let message = message.diag_message(variant); quote! { diag.#fn_name( #field_binding, @@ -489,8 +498,13 @@ impl DiagnosticDeriveVariantBuilder { /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug /// and `fluent_attr_identifier`. - fn add_subdiagnostic(&self, kind: &Ident, message: Message) -> TokenStream { - let message = message.diag_message(); + fn add_subdiagnostic( + &self, + kind: &Ident, + message: Message, + variant: &VariantInfo<'_>, + ) -> TokenStream { + let message = message.diag_message(variant); quote! { diag.#kind(#message); } diff --git a/compiler/rustc_macros/src/diagnostics/message.rs b/compiler/rustc_macros/src/diagnostics/message.rs index cfce252fbdd8..153abecf8937 100644 --- a/compiler/rustc_macros/src/diagnostics/message.rs +++ b/compiler/rustc_macros/src/diagnostics/message.rs @@ -1,28 +1,133 @@ -use proc_macro2::TokenStream; +use fluent_bundle::FluentResource; +use fluent_syntax::ast::{Expression, InlineExpression, Pattern, PatternElement}; +use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::Path; +use synstructure::{Structure, VariantInfo}; +use crate::diagnostics::error::span_err; + +#[derive(Clone)] pub(crate) enum Message { Slug(Path), - Inline(String), + Inline(Span, String), } impl Message { - pub(crate) fn slug(&self) -> Option<&Path> { - match self { - Message::Slug(slug) => Some(slug), - Message::Inline(_) => None, - } - } - - pub(crate) fn diag_message(&self) -> TokenStream { + pub(crate) fn diag_message(&self, variant: &VariantInfo<'_>) -> TokenStream { match self { Message::Slug(slug) => { quote! { crate::fluent_generated::#slug } } - Message::Inline(message) => { + Message::Inline(message_span, message) => { + verify_fluent_message(*message_span, &message, variant); quote! { rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed(#message)) } } } } + + /// Generates a `#[test]` that verifies that all referenced variables + /// exist on this structure. + pub(crate) fn generate_test(&self, structure: &Structure<'_>) -> TokenStream { + match self { + Message::Slug(slug) => { + // FIXME: We can't identify variables in a subdiagnostic + for field in structure.variants().iter().flat_map(|v| v.ast().fields.iter()) { + for attr_name in field.attrs.iter().filter_map(|at| at.path().get_ident()) { + if attr_name == "subdiagnostic" { + return quote!(); + } + } + } + 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. + 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) + ); + let ref_slug = quote::format_ident!("{slug}_refs"); + let struct_name = &structure.ast().ident; + let variables: Vec<_> = structure + .variants() + .iter() + .flat_map(|v| { + v.ast() + .fields + .iter() + .filter_map(|f| f.ident.as_ref().map(|i| i.to_string())) + }) + .collect(); + // tidy errors on `#[test]` outside of test files, so we use `#[test ]` to work around this + quote! { + #[cfg(test)] + #[test ] + fn #ident() { + let variables = [#(#variables),*]; + for vref in crate::fluent_generated::#ref_slug { + assert!(variables.contains(vref), "{}: variable `{vref}` not found ({})", stringify!(#struct_name), stringify!(#slug)); + } + } + } + } + Message::Inline(..) => { + // We don't generate a test for inline diagnostics, we can verify these at compile-time! + // This verification is done in the `diag_message` function above + quote! {} + } + } + } +} + +fn verify_fluent_message(msg_span: Span, message: &str, variant: &VariantInfo<'_>) { + // Parse the fluent message + const GENERATED_MSG_ID: &str = "generated_msg"; + let resource = FluentResource::try_new(format!("{GENERATED_MSG_ID} = {message}\n")).unwrap(); + assert_eq!(resource.entries().count(), 1); + let Some(fluent_syntax::ast::Entry::Message(message)) = resource.get_entry(0) else { + panic!("Did not parse into a message") + }; + + // Check if all variables are used + let fields: Vec = variant + .bindings() + .iter() + .flat_map(|b| b.ast().ident.as_ref()) + .map(|id| id.to_string()) + .collect(); + for variable in variable_references(&message) { + if !fields.iter().any(|f| f == variable) { + span_err(msg_span.unwrap(), format!("Variable `{variable}` not found in diagnostic ")) + .help(format!("Available fields: {:?}", fields.join(", "))) + .emit(); + } + // assert!(, ); + } +} + +fn variable_references<'a>(msg: &fluent_syntax::ast::Message<&'a str>) -> Vec<&'a str> { + let mut refs = vec![]; + if let Some(Pattern { elements }) = &msg.value { + for elt in elements { + if let PatternElement::Placeable { + expression: Expression::Inline(InlineExpression::VariableReference { id }), + } = elt + { + refs.push(id.name); + } + } + } + for attr in &msg.attributes { + for elt in &attr.value.elements { + if let PatternElement::Placeable { + expression: Expression::Inline(InlineExpression::VariableReference { id }), + } = elt + { + refs.push(id.name); + } + } + } + refs } diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 61a234f96d12..adc968dacd5c 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -75,7 +75,7 @@ impl SubdiagnosticDerive { has_subdiagnostic: false, is_enum, }; - builder.into_tokens().unwrap_or_else(|v| v.to_compile_error()) + builder.into_tokens(variant).unwrap_or_else(|v| v.to_compile_error()) }); quote! { @@ -497,7 +497,10 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } } - pub(crate) fn into_tokens(&mut self) -> Result { + pub(crate) fn into_tokens( + &mut self, + variant: &VariantInfo<'_>, + ) -> Result { let kind_slugs = self.identify_kind()?; let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect(); @@ -535,7 +538,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let mut calls = TokenStream::new(); for (kind, slug) in kind_slugs { let message = format_ident!("__message"); - let message_stream = slug.diag_message(); + let message_stream = slug.diag_message(variant); calls.extend(quote! { let #message = #diag.eagerly_translate(#message_stream); }); let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 0718448a0513..a5265a847a9c 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -708,7 +708,7 @@ impl SubdiagnosticVariant { } if !input.is_empty() { input.parse::()?; } if is_first { - slug = Some(Message::Inline(message.value())); + slug = Some(Message::Inline(message.span(), message.value())); is_first = false; } else { span_err(message.span().unwrap(), "a diagnostic message must be the first argument to the attribute").emit(); diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs index 7d9af0522f63..babe3813e40b 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs @@ -762,3 +762,16 @@ struct SuggestionOnVec { //~^ ERROR `#[suggestion(...)]` is not a valid attribute sub: Vec, } + +#[derive(Diagnostic)] +#[diag("exists: {$sub}")] +struct VariableExists { + sub: String, +} + +#[derive(Diagnostic)] +#[diag("does not exist: {$nosub}")] +//~^ ERROR Variable `nosub` not found in diagnostic +struct VariableDoesNotExist { + sub: String, +} diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr index bec07a425762..2ba307940280 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr @@ -508,6 +508,14 @@ LL | #[suggestion("with a suggestion", code = "")] = help: to show a suggestion consisting of multiple parts, use a `Subdiagnostic` annotated with `#[multipart_suggestion(...)]` = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]` +error: derive(Diagnostic): Variable `nosub` not found in diagnostic + --> $DIR/diagnostic-derive-inline.rs:773:8 + | +LL | #[diag("does not exist: {$nosub}")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: Available fields: "sub" + error: cannot find attribute `nonsense` in this scope --> $DIR/diagnostic-derive-inline.rs:61:3 | @@ -622,6 +630,6 @@ note: required by a bound in `Diag::<'a, G>::arg` = note: in this macro invocation = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 79 previous errors +error: aborting due to 80 previous errors For more information about this error, try `rustc --explain E0277`. From 24a28332582ac25470c20079f0fdacf2c2e1b871 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 30 Jan 2026 20:22:18 +0100 Subject: [PATCH 350/978] test the `vld1*` functions --- .../crates/core_arch/src/aarch64/neon/mod.rs | 864 ++++++++++++++++++ 1 file changed, 864 insertions(+) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs index bac45742393c..feaf94a7f9e0 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs @@ -993,6 +993,870 @@ mod tests { assert_eq!(vals[1], 1.); assert_eq!(vals[2], 2.); } + + #[simd_test(enable = "neon,fp16")] + #[cfg(not(target_arch = "arm64ec"))] + unsafe fn test_vld1_f16_x2() { + let vals: [f16; 8] = crate::array::from_fn(|i| i as f16); + let a: float16x4x2_t = transmute(vals); + let mut tmp = [0_f16; 8]; + vst1_f16_x2(tmp.as_mut_ptr().cast(), a); + let r: float16x4x2_t = vld1_f16_x2(tmp.as_ptr().cast()); + let out: [f16; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,fp16")] + #[cfg(not(target_arch = "arm64ec"))] + unsafe fn test_vld1_f16_x3() { + let vals: [f16; 12] = crate::array::from_fn(|i| i as f16); + let a: float16x4x3_t = transmute(vals); + let mut tmp = [0_f16; 12]; + vst1_f16_x3(tmp.as_mut_ptr().cast(), a); + let r: float16x4x3_t = vld1_f16_x3(tmp.as_ptr().cast()); + let out: [f16; 12] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,fp16")] + #[cfg(not(target_arch = "arm64ec"))] + unsafe fn test_vld1_f16_x4() { + let vals: [f16; 16] = crate::array::from_fn(|i| i as f16); + let a: float16x4x4_t = transmute(vals); + let mut tmp = [0_f16; 16]; + vst1_f16_x4(tmp.as_mut_ptr().cast(), a); + let r: float16x4x4_t = vld1_f16_x4(tmp.as_ptr().cast()); + let out: [f16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,fp16")] + #[cfg(not(target_arch = "arm64ec"))] + unsafe fn test_vld1q_f16_x2() { + let vals: [f16; 16] = crate::array::from_fn(|i| i as f16); + let a: float16x8x2_t = transmute(vals); + let mut tmp = [0_f16; 16]; + vst1q_f16_x2(tmp.as_mut_ptr().cast(), a); + let r: float16x8x2_t = vld1q_f16_x2(tmp.as_ptr().cast()); + let out: [f16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,fp16")] + #[cfg(not(target_arch = "arm64ec"))] + unsafe fn test_vld1q_f16_x3() { + let vals: [f16; 24] = crate::array::from_fn(|i| i as f16); + let a: float16x8x3_t = transmute(vals); + let mut tmp = [0_f16; 24]; + vst1q_f16_x3(tmp.as_mut_ptr().cast(), a); + let r: float16x8x3_t = vld1q_f16_x3(tmp.as_ptr().cast()); + let out: [f16; 24] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,fp16")] + #[cfg(not(target_arch = "arm64ec"))] + unsafe fn test_vld1q_f16_x4() { + let vals: [f16; 32] = crate::array::from_fn(|i| i as f16); + let a: float16x8x4_t = transmute(vals); + let mut tmp = [0_f16; 32]; + vst1q_f16_x4(tmp.as_mut_ptr().cast(), a); + let r: float16x8x4_t = vld1q_f16_x4(tmp.as_ptr().cast()); + let out: [f16; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_f32_x2() { + let vals: [f32; 4] = crate::array::from_fn(|i| i as f32); + let a: float32x2x2_t = transmute(vals); + let mut tmp = [0_f32; 4]; + vst1_f32_x2(tmp.as_mut_ptr().cast(), a); + let r: float32x2x2_t = vld1_f32_x2(tmp.as_ptr().cast()); + let out: [f32; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_f32_x3() { + let vals: [f32; 6] = crate::array::from_fn(|i| i as f32); + let a: float32x2x3_t = transmute(vals); + let mut tmp = [0_f32; 6]; + vst1_f32_x3(tmp.as_mut_ptr().cast(), a); + let r: float32x2x3_t = vld1_f32_x3(tmp.as_ptr().cast()); + let out: [f32; 6] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_f32_x4() { + let vals: [f32; 8] = crate::array::from_fn(|i| i as f32); + let a: float32x2x4_t = transmute(vals); + let mut tmp = [0_f32; 8]; + vst1_f32_x4(tmp.as_mut_ptr().cast(), a); + let r: float32x2x4_t = vld1_f32_x4(tmp.as_ptr().cast()); + let out: [f32; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_f32_x2() { + let vals: [f32; 8] = crate::array::from_fn(|i| i as f32); + let a: float32x4x2_t = transmute(vals); + let mut tmp = [0_f32; 8]; + vst1q_f32_x2(tmp.as_mut_ptr().cast(), a); + let r: float32x4x2_t = vld1q_f32_x2(tmp.as_ptr().cast()); + let out: [f32; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_f32_x3() { + let vals: [f32; 12] = crate::array::from_fn(|i| i as f32); + let a: float32x4x3_t = transmute(vals); + let mut tmp = [0_f32; 12]; + vst1q_f32_x3(tmp.as_mut_ptr().cast(), a); + let r: float32x4x3_t = vld1q_f32_x3(tmp.as_ptr().cast()); + let out: [f32; 12] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_f32_x4() { + let vals: [f32; 16] = crate::array::from_fn(|i| i as f32); + let a: float32x4x4_t = transmute(vals); + let mut tmp = [0_f32; 16]; + vst1q_f32_x4(tmp.as_mut_ptr().cast(), a); + let r: float32x4x4_t = vld1q_f32_x4(tmp.as_ptr().cast()); + let out: [f32; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1_p64_x2() { + let vals: [p64; 2] = crate::array::from_fn(|i| i as p64); + let a: poly64x1x2_t = transmute(vals); + let mut tmp = [0 as p64; 2]; + vst1_p64_x2(tmp.as_mut_ptr().cast(), a); + let r: poly64x1x2_t = vld1_p64_x2(tmp.as_ptr().cast()); + let out: [p64; 2] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1_p64_x3() { + let vals: [p64; 3] = crate::array::from_fn(|i| i as p64); + let a: poly64x1x3_t = transmute(vals); + let mut tmp = [0 as p64; 3]; + vst1_p64_x3(tmp.as_mut_ptr().cast(), a); + let r: poly64x1x3_t = vld1_p64_x3(tmp.as_ptr().cast()); + let out: [p64; 3] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1_p64_x4() { + let vals: [p64; 4] = crate::array::from_fn(|i| i as p64); + let a: poly64x1x4_t = transmute(vals); + let mut tmp = [0 as p64; 4]; + vst1_p64_x4(tmp.as_mut_ptr().cast(), a); + let r: poly64x1x4_t = vld1_p64_x4(tmp.as_ptr().cast()); + let out: [p64; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1q_p64_x2() { + let vals: [p64; 4] = crate::array::from_fn(|i| i as p64); + let a: poly64x2x2_t = transmute(vals); + let mut tmp = [0 as p64; 4]; + vst1q_p64_x2(tmp.as_mut_ptr().cast(), a); + let r: poly64x2x2_t = vld1q_p64_x2(tmp.as_ptr().cast()); + let out: [p64; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1q_p64_x3() { + let vals: [p64; 6] = crate::array::from_fn(|i| i as p64); + let a: poly64x2x3_t = transmute(vals); + let mut tmp = [0 as p64; 6]; + vst1q_p64_x3(tmp.as_mut_ptr().cast(), a); + let r: poly64x2x3_t = vld1q_p64_x3(tmp.as_ptr().cast()); + let out: [p64; 6] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon,aes")] + unsafe fn test_vld1q_p64_x4() { + let vals: [p64; 8] = crate::array::from_fn(|i| i as p64); + let a: poly64x2x4_t = transmute(vals); + let mut tmp = [0 as p64; 8]; + vst1q_p64_x4(tmp.as_mut_ptr().cast(), a); + let r: poly64x2x4_t = vld1q_p64_x4(tmp.as_ptr().cast()); + let out: [p64; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s8_x2() { + let vals: [i8; 16] = crate::array::from_fn(|i| i as i8); + let a: int8x8x2_t = transmute(vals); + let mut tmp = [0_i8; 16]; + vst1_s8_x2(tmp.as_mut_ptr().cast(), a); + let r: int8x8x2_t = vld1_s8_x2(tmp.as_ptr().cast()); + let out: [i8; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s8_x3() { + let vals: [i8; 24] = crate::array::from_fn(|i| i as i8); + let a: int8x8x3_t = transmute(vals); + let mut tmp = [0_i8; 24]; + vst1_s8_x3(tmp.as_mut_ptr().cast(), a); + let r: int8x8x3_t = vld1_s8_x3(tmp.as_ptr().cast()); + let out: [i8; 24] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s8_x4() { + let vals: [i8; 32] = crate::array::from_fn(|i| i as i8); + let a: int8x8x4_t = transmute(vals); + let mut tmp = [0_i8; 32]; + vst1_s8_x4(tmp.as_mut_ptr().cast(), a); + let r: int8x8x4_t = vld1_s8_x4(tmp.as_ptr().cast()); + let out: [i8; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s8_x2() { + let vals: [i8; 32] = crate::array::from_fn(|i| i as i8); + let a: int8x16x2_t = transmute(vals); + let mut tmp = [0_i8; 32]; + vst1q_s8_x2(tmp.as_mut_ptr().cast(), a); + let r: int8x16x2_t = vld1q_s8_x2(tmp.as_ptr().cast()); + let out: [i8; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s8_x3() { + let vals: [i8; 48] = crate::array::from_fn(|i| i as i8); + let a: int8x16x3_t = transmute(vals); + let mut tmp = [0_i8; 48]; + vst1q_s8_x3(tmp.as_mut_ptr().cast(), a); + let r: int8x16x3_t = vld1q_s8_x3(tmp.as_ptr().cast()); + let out: [i8; 48] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s8_x4() { + let vals: [i8; 64] = crate::array::from_fn(|i| i as i8); + let a: int8x16x4_t = transmute(vals); + let mut tmp = [0_i8; 64]; + vst1q_s8_x4(tmp.as_mut_ptr().cast(), a); + let r: int8x16x4_t = vld1q_s8_x4(tmp.as_ptr().cast()); + let out: [i8; 64] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s16_x2() { + let vals: [i16; 8] = crate::array::from_fn(|i| i as i16); + let a: int16x4x2_t = transmute(vals); + let mut tmp = [0_i16; 8]; + vst1_s16_x2(tmp.as_mut_ptr().cast(), a); + let r: int16x4x2_t = vld1_s16_x2(tmp.as_ptr().cast()); + let out: [i16; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s16_x3() { + let vals: [i16; 12] = crate::array::from_fn(|i| i as i16); + let a: int16x4x3_t = transmute(vals); + let mut tmp = [0_i16; 12]; + vst1_s16_x3(tmp.as_mut_ptr().cast(), a); + let r: int16x4x3_t = vld1_s16_x3(tmp.as_ptr().cast()); + let out: [i16; 12] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s16_x4() { + let vals: [i16; 16] = crate::array::from_fn(|i| i as i16); + let a: int16x4x4_t = transmute(vals); + let mut tmp = [0_i16; 16]; + vst1_s16_x4(tmp.as_mut_ptr().cast(), a); + let r: int16x4x4_t = vld1_s16_x4(tmp.as_ptr().cast()); + let out: [i16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s16_x2() { + let vals: [i16; 16] = crate::array::from_fn(|i| i as i16); + let a: int16x8x2_t = transmute(vals); + let mut tmp = [0_i16; 16]; + vst1q_s16_x2(tmp.as_mut_ptr().cast(), a); + let r: int16x8x2_t = vld1q_s16_x2(tmp.as_ptr().cast()); + let out: [i16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s16_x3() { + let vals: [i16; 24] = crate::array::from_fn(|i| i as i16); + let a: int16x8x3_t = transmute(vals); + let mut tmp = [0_i16; 24]; + vst1q_s16_x3(tmp.as_mut_ptr().cast(), a); + let r: int16x8x3_t = vld1q_s16_x3(tmp.as_ptr().cast()); + let out: [i16; 24] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s16_x4() { + let vals: [i16; 32] = crate::array::from_fn(|i| i as i16); + let a: int16x8x4_t = transmute(vals); + let mut tmp = [0_i16; 32]; + vst1q_s16_x4(tmp.as_mut_ptr().cast(), a); + let r: int16x8x4_t = vld1q_s16_x4(tmp.as_ptr().cast()); + let out: [i16; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s32_x2() { + let vals: [i32; 4] = crate::array::from_fn(|i| i as i32); + let a: int32x2x2_t = transmute(vals); + let mut tmp = [0_i32; 4]; + vst1_s32_x2(tmp.as_mut_ptr().cast(), a); + let r: int32x2x2_t = vld1_s32_x2(tmp.as_ptr().cast()); + let out: [i32; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s32_x3() { + let vals: [i32; 6] = crate::array::from_fn(|i| i as i32); + let a: int32x2x3_t = transmute(vals); + let mut tmp = [0_i32; 6]; + vst1_s32_x3(tmp.as_mut_ptr().cast(), a); + let r: int32x2x3_t = vld1_s32_x3(tmp.as_ptr().cast()); + let out: [i32; 6] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s32_x4() { + let vals: [i32; 8] = crate::array::from_fn(|i| i as i32); + let a: int32x2x4_t = transmute(vals); + let mut tmp = [0_i32; 8]; + vst1_s32_x4(tmp.as_mut_ptr().cast(), a); + let r: int32x2x4_t = vld1_s32_x4(tmp.as_ptr().cast()); + let out: [i32; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s32_x2() { + let vals: [i32; 8] = crate::array::from_fn(|i| i as i32); + let a: int32x4x2_t = transmute(vals); + let mut tmp = [0_i32; 8]; + vst1q_s32_x2(tmp.as_mut_ptr().cast(), a); + let r: int32x4x2_t = vld1q_s32_x2(tmp.as_ptr().cast()); + let out: [i32; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s32_x3() { + let vals: [i32; 12] = crate::array::from_fn(|i| i as i32); + let a: int32x4x3_t = transmute(vals); + let mut tmp = [0_i32; 12]; + vst1q_s32_x3(tmp.as_mut_ptr().cast(), a); + let r: int32x4x3_t = vld1q_s32_x3(tmp.as_ptr().cast()); + let out: [i32; 12] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s32_x4() { + let vals: [i32; 16] = crate::array::from_fn(|i| i as i32); + let a: int32x4x4_t = transmute(vals); + let mut tmp = [0_i32; 16]; + vst1q_s32_x4(tmp.as_mut_ptr().cast(), a); + let r: int32x4x4_t = vld1q_s32_x4(tmp.as_ptr().cast()); + let out: [i32; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s64_x2() { + let vals: [i64; 2] = crate::array::from_fn(|i| i as i64); + let a: int64x1x2_t = transmute(vals); + let mut tmp = [0_i64; 2]; + vst1_s64_x2(tmp.as_mut_ptr().cast(), a); + let r: int64x1x2_t = vld1_s64_x2(tmp.as_ptr().cast()); + let out: [i64; 2] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s64_x3() { + let vals: [i64; 3] = crate::array::from_fn(|i| i as i64); + let a: int64x1x3_t = transmute(vals); + let mut tmp = [0_i64; 3]; + vst1_s64_x3(tmp.as_mut_ptr().cast(), a); + let r: int64x1x3_t = vld1_s64_x3(tmp.as_ptr().cast()); + let out: [i64; 3] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_s64_x4() { + let vals: [i64; 4] = crate::array::from_fn(|i| i as i64); + let a: int64x1x4_t = transmute(vals); + let mut tmp = [0_i64; 4]; + vst1_s64_x4(tmp.as_mut_ptr().cast(), a); + let r: int64x1x4_t = vld1_s64_x4(tmp.as_ptr().cast()); + let out: [i64; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s64_x2() { + let vals: [i64; 4] = crate::array::from_fn(|i| i as i64); + let a: int64x2x2_t = transmute(vals); + let mut tmp = [0_i64; 4]; + vst1q_s64_x2(tmp.as_mut_ptr().cast(), a); + let r: int64x2x2_t = vld1q_s64_x2(tmp.as_ptr().cast()); + let out: [i64; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s64_x3() { + let vals: [i64; 6] = crate::array::from_fn(|i| i as i64); + let a: int64x2x3_t = transmute(vals); + let mut tmp = [0_i64; 6]; + vst1q_s64_x3(tmp.as_mut_ptr().cast(), a); + let r: int64x2x3_t = vld1q_s64_x3(tmp.as_ptr().cast()); + let out: [i64; 6] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_s64_x4() { + let vals: [i64; 8] = crate::array::from_fn(|i| i as i64); + let a: int64x2x4_t = transmute(vals); + let mut tmp = [0_i64; 8]; + vst1q_s64_x4(tmp.as_mut_ptr().cast(), a); + let r: int64x2x4_t = vld1q_s64_x4(tmp.as_ptr().cast()); + let out: [i64; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u8_x2() { + let vals: [u8; 16] = crate::array::from_fn(|i| i as u8); + let a: uint8x8x2_t = transmute(vals); + let mut tmp = [0_u8; 16]; + vst1_u8_x2(tmp.as_mut_ptr().cast(), a); + let r: uint8x8x2_t = vld1_u8_x2(tmp.as_ptr().cast()); + let out: [u8; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u8_x3() { + let vals: [u8; 24] = crate::array::from_fn(|i| i as u8); + let a: uint8x8x3_t = transmute(vals); + let mut tmp = [0_u8; 24]; + vst1_u8_x3(tmp.as_mut_ptr().cast(), a); + let r: uint8x8x3_t = vld1_u8_x3(tmp.as_ptr().cast()); + let out: [u8; 24] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u8_x4() { + let vals: [u8; 32] = crate::array::from_fn(|i| i as u8); + let a: uint8x8x4_t = transmute(vals); + let mut tmp = [0_u8; 32]; + vst1_u8_x4(tmp.as_mut_ptr().cast(), a); + let r: uint8x8x4_t = vld1_u8_x4(tmp.as_ptr().cast()); + let out: [u8; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u8_x2() { + let vals: [u8; 32] = crate::array::from_fn(|i| i as u8); + let a: uint8x16x2_t = transmute(vals); + let mut tmp = [0_u8; 32]; + vst1q_u8_x2(tmp.as_mut_ptr().cast(), a); + let r: uint8x16x2_t = vld1q_u8_x2(tmp.as_ptr().cast()); + let out: [u8; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u8_x3() { + let vals: [u8; 48] = crate::array::from_fn(|i| i as u8); + let a: uint8x16x3_t = transmute(vals); + let mut tmp = [0_u8; 48]; + vst1q_u8_x3(tmp.as_mut_ptr().cast(), a); + let r: uint8x16x3_t = vld1q_u8_x3(tmp.as_ptr().cast()); + let out: [u8; 48] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u8_x4() { + let vals: [u8; 64] = crate::array::from_fn(|i| i as u8); + let a: uint8x16x4_t = transmute(vals); + let mut tmp = [0_u8; 64]; + vst1q_u8_x4(tmp.as_mut_ptr().cast(), a); + let r: uint8x16x4_t = vld1q_u8_x4(tmp.as_ptr().cast()); + let out: [u8; 64] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u16_x2() { + let vals: [u16; 8] = crate::array::from_fn(|i| i as u16); + let a: uint16x4x2_t = transmute(vals); + let mut tmp = [0_u16; 8]; + vst1_u16_x2(tmp.as_mut_ptr().cast(), a); + let r: uint16x4x2_t = vld1_u16_x2(tmp.as_ptr().cast()); + let out: [u16; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u16_x3() { + let vals: [u16; 12] = crate::array::from_fn(|i| i as u16); + let a: uint16x4x3_t = transmute(vals); + let mut tmp = [0_u16; 12]; + vst1_u16_x3(tmp.as_mut_ptr().cast(), a); + let r: uint16x4x3_t = vld1_u16_x3(tmp.as_ptr().cast()); + let out: [u16; 12] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u16_x4() { + let vals: [u16; 16] = crate::array::from_fn(|i| i as u16); + let a: uint16x4x4_t = transmute(vals); + let mut tmp = [0_u16; 16]; + vst1_u16_x4(tmp.as_mut_ptr().cast(), a); + let r: uint16x4x4_t = vld1_u16_x4(tmp.as_ptr().cast()); + let out: [u16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u16_x2() { + let vals: [u16; 16] = crate::array::from_fn(|i| i as u16); + let a: uint16x8x2_t = transmute(vals); + let mut tmp = [0_u16; 16]; + vst1q_u16_x2(tmp.as_mut_ptr().cast(), a); + let r: uint16x8x2_t = vld1q_u16_x2(tmp.as_ptr().cast()); + let out: [u16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u16_x3() { + let vals: [u16; 24] = crate::array::from_fn(|i| i as u16); + let a: uint16x8x3_t = transmute(vals); + let mut tmp = [0_u16; 24]; + vst1q_u16_x3(tmp.as_mut_ptr().cast(), a); + let r: uint16x8x3_t = vld1q_u16_x3(tmp.as_ptr().cast()); + let out: [u16; 24] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u16_x4() { + let vals: [u16; 32] = crate::array::from_fn(|i| i as u16); + let a: uint16x8x4_t = transmute(vals); + let mut tmp = [0_u16; 32]; + vst1q_u16_x4(tmp.as_mut_ptr().cast(), a); + let r: uint16x8x4_t = vld1q_u16_x4(tmp.as_ptr().cast()); + let out: [u16; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u32_x2() { + let vals: [u32; 4] = crate::array::from_fn(|i| i as u32); + let a: uint32x2x2_t = transmute(vals); + let mut tmp = [0_u32; 4]; + vst1_u32_x2(tmp.as_mut_ptr().cast(), a); + let r: uint32x2x2_t = vld1_u32_x2(tmp.as_ptr().cast()); + let out: [u32; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u32_x3() { + let vals: [u32; 6] = crate::array::from_fn(|i| i as u32); + let a: uint32x2x3_t = transmute(vals); + let mut tmp = [0_u32; 6]; + vst1_u32_x3(tmp.as_mut_ptr().cast(), a); + let r: uint32x2x3_t = vld1_u32_x3(tmp.as_ptr().cast()); + let out: [u32; 6] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u32_x4() { + let vals: [u32; 8] = crate::array::from_fn(|i| i as u32); + let a: uint32x2x4_t = transmute(vals); + let mut tmp = [0_u32; 8]; + vst1_u32_x4(tmp.as_mut_ptr().cast(), a); + let r: uint32x2x4_t = vld1_u32_x4(tmp.as_ptr().cast()); + let out: [u32; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u32_x2() { + let vals: [u32; 8] = crate::array::from_fn(|i| i as u32); + let a: uint32x4x2_t = transmute(vals); + let mut tmp = [0_u32; 8]; + vst1q_u32_x2(tmp.as_mut_ptr().cast(), a); + let r: uint32x4x2_t = vld1q_u32_x2(tmp.as_ptr().cast()); + let out: [u32; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u32_x3() { + let vals: [u32; 12] = crate::array::from_fn(|i| i as u32); + let a: uint32x4x3_t = transmute(vals); + let mut tmp = [0_u32; 12]; + vst1q_u32_x3(tmp.as_mut_ptr().cast(), a); + let r: uint32x4x3_t = vld1q_u32_x3(tmp.as_ptr().cast()); + let out: [u32; 12] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u32_x4() { + let vals: [u32; 16] = crate::array::from_fn(|i| i as u32); + let a: uint32x4x4_t = transmute(vals); + let mut tmp = [0_u32; 16]; + vst1q_u32_x4(tmp.as_mut_ptr().cast(), a); + let r: uint32x4x4_t = vld1q_u32_x4(tmp.as_ptr().cast()); + let out: [u32; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u64_x2() { + let vals: [u64; 2] = crate::array::from_fn(|i| i as u64); + let a: uint64x1x2_t = transmute(vals); + let mut tmp = [0_u64; 2]; + vst1_u64_x2(tmp.as_mut_ptr().cast(), a); + let r: uint64x1x2_t = vld1_u64_x2(tmp.as_ptr().cast()); + let out: [u64; 2] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u64_x3() { + let vals: [u64; 3] = crate::array::from_fn(|i| i as u64); + let a: uint64x1x3_t = transmute(vals); + let mut tmp = [0_u64; 3]; + vst1_u64_x3(tmp.as_mut_ptr().cast(), a); + let r: uint64x1x3_t = vld1_u64_x3(tmp.as_ptr().cast()); + let out: [u64; 3] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_u64_x4() { + let vals: [u64; 4] = crate::array::from_fn(|i| i as u64); + let a: uint64x1x4_t = transmute(vals); + let mut tmp = [0_u64; 4]; + vst1_u64_x4(tmp.as_mut_ptr().cast(), a); + let r: uint64x1x4_t = vld1_u64_x4(tmp.as_ptr().cast()); + let out: [u64; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u64_x2() { + let vals: [u64; 4] = crate::array::from_fn(|i| i as u64); + let a: uint64x2x2_t = transmute(vals); + let mut tmp = [0_u64; 4]; + vst1q_u64_x2(tmp.as_mut_ptr().cast(), a); + let r: uint64x2x2_t = vld1q_u64_x2(tmp.as_ptr().cast()); + let out: [u64; 4] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u64_x3() { + let vals: [u64; 6] = crate::array::from_fn(|i| i as u64); + let a: uint64x2x3_t = transmute(vals); + let mut tmp = [0_u64; 6]; + vst1q_u64_x3(tmp.as_mut_ptr().cast(), a); + let r: uint64x2x3_t = vld1q_u64_x3(tmp.as_ptr().cast()); + let out: [u64; 6] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_u64_x4() { + let vals: [u64; 8] = crate::array::from_fn(|i| i as u64); + let a: uint64x2x4_t = transmute(vals); + let mut tmp = [0_u64; 8]; + vst1q_u64_x4(tmp.as_mut_ptr().cast(), a); + let r: uint64x2x4_t = vld1q_u64_x4(tmp.as_ptr().cast()); + let out: [u64; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_p8_x2() { + let vals: [p8; 16] = crate::array::from_fn(|i| i as p8); + let a: poly8x8x2_t = transmute(vals); + let mut tmp = [0 as p8; 16]; + vst1_p8_x2(tmp.as_mut_ptr().cast(), a); + let r: poly8x8x2_t = vld1_p8_x2(tmp.as_ptr().cast()); + let out: [p8; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_p8_x3() { + let vals: [p8; 24] = crate::array::from_fn(|i| i as p8); + let a: poly8x8x3_t = transmute(vals); + let mut tmp = [0 as p8; 24]; + vst1_p8_x3(tmp.as_mut_ptr().cast(), a); + let r: poly8x8x3_t = vld1_p8_x3(tmp.as_ptr().cast()); + let out: [p8; 24] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_p8_x4() { + let vals: [p8; 32] = crate::array::from_fn(|i| i as p8); + let a: poly8x8x4_t = transmute(vals); + let mut tmp = [0 as p8; 32]; + vst1_p8_x4(tmp.as_mut_ptr().cast(), a); + let r: poly8x8x4_t = vld1_p8_x4(tmp.as_ptr().cast()); + let out: [p8; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_p8_x2() { + let vals: [p8; 32] = crate::array::from_fn(|i| i as p8); + let a: poly8x16x2_t = transmute(vals); + let mut tmp = [0 as p8; 32]; + vst1q_p8_x2(tmp.as_mut_ptr().cast(), a); + let r: poly8x16x2_t = vld1q_p8_x2(tmp.as_ptr().cast()); + let out: [p8; 32] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_p8_x3() { + let vals: [p8; 48] = crate::array::from_fn(|i| i as p8); + let a: poly8x16x3_t = transmute(vals); + let mut tmp = [0 as p8; 48]; + vst1q_p8_x3(tmp.as_mut_ptr().cast(), a); + let r: poly8x16x3_t = vld1q_p8_x3(tmp.as_ptr().cast()); + let out: [p8; 48] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_p8_x4() { + let vals: [p8; 64] = crate::array::from_fn(|i| i as p8); + let a: poly8x16x4_t = transmute(vals); + let mut tmp = [0 as p8; 64]; + vst1q_p8_x4(tmp.as_mut_ptr().cast(), a); + let r: poly8x16x4_t = vld1q_p8_x4(tmp.as_ptr().cast()); + let out: [p8; 64] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_p16_x2() { + let vals: [p16; 8] = crate::array::from_fn(|i| i as p16); + let a: poly16x4x2_t = transmute(vals); + let mut tmp = [0 as p16; 8]; + vst1_p16_x2(tmp.as_mut_ptr().cast(), a); + let r: poly16x4x2_t = vld1_p16_x2(tmp.as_ptr().cast()); + let out: [p16; 8] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_p16_x3() { + let vals: [p16; 12] = crate::array::from_fn(|i| i as p16); + let a: poly16x4x3_t = transmute(vals); + let mut tmp = [0 as p16; 12]; + vst1_p16_x3(tmp.as_mut_ptr().cast(), a); + let r: poly16x4x3_t = vld1_p16_x3(tmp.as_ptr().cast()); + let out: [p16; 12] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1_p16_x4() { + let vals: [p16; 16] = crate::array::from_fn(|i| i as p16); + let a: poly16x4x4_t = transmute(vals); + let mut tmp = [0 as p16; 16]; + vst1_p16_x4(tmp.as_mut_ptr().cast(), a); + let r: poly16x4x4_t = vld1_p16_x4(tmp.as_ptr().cast()); + let out: [p16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_p16_x2() { + let vals: [p16; 16] = crate::array::from_fn(|i| i as p16); + let a: poly16x8x2_t = transmute(vals); + let mut tmp = [0 as p16; 16]; + vst1q_p16_x2(tmp.as_mut_ptr().cast(), a); + let r: poly16x8x2_t = vld1q_p16_x2(tmp.as_ptr().cast()); + let out: [p16; 16] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_p16_x3() { + let vals: [p16; 24] = crate::array::from_fn(|i| i as p16); + let a: poly16x8x3_t = transmute(vals); + let mut tmp = [0 as p16; 24]; + vst1q_p16_x3(tmp.as_mut_ptr().cast(), a); + let r: poly16x8x3_t = vld1q_p16_x3(tmp.as_ptr().cast()); + let out: [p16; 24] = transmute(r); + assert_eq!(out, vals); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vld1q_p16_x4() { + let vals: [p16; 32] = crate::array::from_fn(|i| i as p16); + let a: poly16x8x4_t = transmute(vals); + let mut tmp = [0 as p16; 32]; + vst1q_p16_x4(tmp.as_mut_ptr().cast(), a); + let r: poly16x8x4_t = vld1q_p16_x4(tmp.as_ptr().cast()); + let out: [p16; 32] = transmute(r); + assert_eq!(out, vals); + } } #[cfg(test)] From a208e6c8874c471ffa1a3d96fc7dd8913798f4c9 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 30 Jan 2026 21:35:56 +0100 Subject: [PATCH 351/978] maybe fix aarch64be unsigned vector tuple loads --- .../src/arm_shared/neon/generated.rs | 1152 ----------------- .../spec/neon/arm_shared.spec.yml | 2 + 2 files changed, 2 insertions(+), 1152 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs index 3b67208182cb..2f52e3b52b07 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs @@ -17067,7 +17067,6 @@ pub unsafe fn vld1_p64_x4(a: *const p64) -> poly64x1x4_t { #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] @@ -17087,38 +17086,10 @@ pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t { transmute(vld1q_s64_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon,aes")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t { - let mut ret_val: poly64x2x2_t = transmute(vld1q_s64_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] @@ -17138,39 +17109,10 @@ pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { transmute(vld1q_s64_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon,aes")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { - let mut ret_val: poly64x2x3_t = transmute(vld1q_s64_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] @@ -17189,35 +17131,6 @@ pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { pub unsafe fn vld1q_p64_x4(a: *const p64) -> poly64x2x4_t { transmute(vld1q_s64_x4(transmute(a))) } -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon,aes")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p64_x4(a: *const p64) -> poly64x2x4_t { - let mut ret_val: poly64x2x4_t = transmute(vld1q_s64_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [1, 0]) }; - ret_val -} #[doc = "Load multiple single-element structures to one, two, three, or four registers."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s8)"] #[doc = "## Safety"] @@ -18071,7 +17984,6 @@ pub unsafe fn vld1q_s64_x4(a: *const i64) -> int64x2x4_t { #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18091,38 +18003,10 @@ pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t { transmute(vld1_s8_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t { - let mut ret_val: uint8x8x2_t = transmute(vld1_s8_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18142,39 +18026,10 @@ pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { transmute(vld1_s8_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { - let mut ret_val: uint8x8x3_t = transmute(vld1_s8_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18194,40 +18049,10 @@ pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { transmute(vld1_s8_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { - let mut ret_val: uint8x8x4_t = transmute(vld1_s8_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18247,50 +18072,10 @@ pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { transmute(vld1q_s8_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { - let mut ret_val: uint8x16x2_t = transmute(vld1q_s8_x2(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18310,57 +18095,10 @@ pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { transmute(vld1q_s8_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { - let mut ret_val: uint8x16x3_t = transmute(vld1q_s8_x3(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.2 = unsafe { - simd_shuffle!( - ret_val.2, - ret_val.2, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18380,64 +18118,10 @@ pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { transmute(vld1q_s8_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { - let mut ret_val: uint8x16x4_t = transmute(vld1q_s8_x4(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.2 = unsafe { - simd_shuffle!( - ret_val.2, - ret_val.2, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.3 = unsafe { - simd_shuffle!( - ret_val.3, - ret_val.3, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18457,38 +18141,10 @@ pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { transmute(vld1_s16_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { - let mut ret_val: uint16x4x2_t = transmute(vld1_s16_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18508,39 +18164,10 @@ pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t { transmute(vld1_s16_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t { - let mut ret_val: uint16x4x3_t = transmute(vld1_s16_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18560,40 +18187,10 @@ pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t { transmute(vld1_s16_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t { - let mut ret_val: uint16x4x4_t = transmute(vld1_s16_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18613,38 +18210,10 @@ pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t { transmute(vld1q_s16_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t { - let mut ret_val: uint16x8x2_t = transmute(vld1q_s16_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18664,39 +18233,10 @@ pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t { transmute(vld1q_s16_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t { - let mut ret_val: uint16x8x3_t = transmute(vld1q_s16_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18716,40 +18256,10 @@ pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t { transmute(vld1q_s16_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t { - let mut ret_val: uint16x8x4_t = transmute(vld1q_s16_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18769,38 +18279,10 @@ pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t { transmute(vld1_s32_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t { - let mut ret_val: uint32x2x2_t = transmute(vld1_s32_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18820,39 +18302,10 @@ pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t { transmute(vld1_s32_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t { - let mut ret_val: uint32x2x3_t = transmute(vld1_s32_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18872,40 +18325,10 @@ pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t { transmute(vld1_s32_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t { - let mut ret_val: uint32x2x4_t = transmute(vld1_s32_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18925,38 +18348,10 @@ pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t { transmute(vld1q_s32_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t { - let mut ret_val: uint32x4x2_t = transmute(vld1q_s32_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -18976,39 +18371,10 @@ pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t { transmute(vld1q_s32_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t { - let mut ret_val: uint32x4x3_t = transmute(vld1q_s32_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19028,35 +18394,6 @@ pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t { transmute(vld1q_s32_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t { - let mut ret_val: uint32x4x4_t = transmute(vld1q_s32_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u64_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] @@ -19130,7 +18467,6 @@ pub unsafe fn vld1_u64_x4(a: *const u64) -> uint64x1x4_t { #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19150,38 +18486,10 @@ pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t { transmute(vld1q_s64_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t { - let mut ret_val: uint64x2x2_t = transmute(vld1q_s64_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19201,39 +18509,10 @@ pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t { transmute(vld1q_s64_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t { - let mut ret_val: uint64x2x3_t = transmute(vld1q_s64_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19253,40 +18532,10 @@ pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t { transmute(vld1q_s64_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t { - let mut ret_val: uint64x2x4_t = transmute(vld1q_s64_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19306,38 +18555,10 @@ pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t { transmute(vld1_s8_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t { - let mut ret_val: poly8x8x2_t = transmute(vld1_s8_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19357,39 +18578,10 @@ pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { transmute(vld1_s8_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { - let mut ret_val: poly8x8x3_t = transmute(vld1_s8_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19409,40 +18601,10 @@ pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { transmute(vld1_s8_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { - let mut ret_val: poly8x8x4_t = transmute(vld1_s8_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19462,50 +18624,10 @@ pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { transmute(vld1q_s8_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { - let mut ret_val: poly8x16x2_t = transmute(vld1q_s8_x2(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19525,57 +18647,10 @@ pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { transmute(vld1q_s8_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { - let mut ret_val: poly8x16x3_t = transmute(vld1q_s8_x3(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.2 = unsafe { - simd_shuffle!( - ret_val.2, - ret_val.2, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19595,64 +18670,10 @@ pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { transmute(vld1q_s8_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { - let mut ret_val: poly8x16x4_t = transmute(vld1q_s8_x4(transmute(a))); - ret_val.0 = unsafe { - simd_shuffle!( - ret_val.0, - ret_val.0, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.1 = unsafe { - simd_shuffle!( - ret_val.1, - ret_val.1, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.2 = unsafe { - simd_shuffle!( - ret_val.2, - ret_val.2, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val.3 = unsafe { - simd_shuffle!( - ret_val.3, - ret_val.3, - [15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - ) - }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19672,38 +18693,10 @@ pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { transmute(vld1_s16_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { - let mut ret_val: poly16x4x2_t = transmute(vld1_s16_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19723,39 +18716,10 @@ pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { transmute(vld1_s16_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { - let mut ret_val: poly16x4x3_t = transmute(vld1_s16_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19775,40 +18739,10 @@ pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { transmute(vld1_s16_x4(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { - let mut ret_val: poly16x4x4_t = transmute(vld1_s16_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x2)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19828,38 +18762,10 @@ pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { transmute(vld1q_s16_x2(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x2)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { - let mut ret_val: poly16x8x2_t = transmute(vld1q_s16_x2(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x3)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19879,39 +18785,10 @@ pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { transmute(vld1q_s16_x3(transmute(a))) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x3)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { - let mut ret_val: poly16x8x3_t = transmute(vld1q_s16_x3(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x4)"] #[doc = "## Safety"] #[doc = " * Neon intrinsic unsafe"] #[inline(always)] -#[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] @@ -19930,35 +18807,6 @@ pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { pub unsafe fn vld1q_p16_x4(a: *const p16) -> poly16x8x4_t { transmute(vld1q_s16_x4(transmute(a))) } -#[doc = "Load multiple single-element structures to one, two, three, or four registers"] -#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x4)"] -#[doc = "## Safety"] -#[doc = " * Neon intrinsic unsafe"] -#[inline(always)] -#[cfg(target_endian = "big")] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] -#[cfg_attr( - all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) -)] -#[cfg_attr( - not(target_arch = "arm"), - stable(feature = "neon_intrinsics", since = "1.59.0") -)] -#[cfg_attr( - target_arch = "arm", - unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") -)] -pub unsafe fn vld1q_p16_x4(a: *const p16) -> poly16x8x4_t { - let mut ret_val: poly16x8x4_t = transmute(vld1q_s16_x4(transmute(a))); - ret_val.0 = unsafe { simd_shuffle!(ret_val.0, ret_val.0, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.1 = unsafe { simd_shuffle!(ret_val.1, ret_val.1, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.2 = unsafe { simd_shuffle!(ret_val.2, ret_val.2, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val.3 = unsafe { simd_shuffle!(ret_val.3, ret_val.3, [7, 6, 5, 4, 3, 2, 1, 0]) }; - ret_val -} #[inline(always)] #[rustc_legacy_const_generics(1)] #[cfg(target_arch = "arm")] diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml index 52748a4cc056..3ec7ba8814e5 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml @@ -2681,6 +2681,7 @@ intrinsics: - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] - *neon-not-arm-stable - *neon-cfg-arm-unstable + big_endian_inverse: false safety: unsafe: [neon] types: @@ -2740,6 +2741,7 @@ intrinsics: - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] - *neon-not-arm-stable - *neon-cfg-arm-unstable + big_endian_inverse: false safety: unsafe: [neon] types: From ac159dd9bd2fbec369d5231c49a068c343737dee Mon Sep 17 00:00:00 2001 From: Muhtasim-Rasheed Date: Sun, 1 Feb 2026 19:01:19 +0600 Subject: [PATCH 352/978] Add help message suggesting explicit reference cast for From/TryFrom Make fmt check happy --- .../traits/fulfillment_errors.rs | 85 +++++++++++++++++++ tests/ui/traits/explicit-reference-cast.rs | 50 +++++++++++ .../ui/traits/explicit-reference-cast.stderr | 68 +++++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 tests/ui/traits/explicit-reference-cast.rs create mode 100644 tests/ui/traits/explicit-reference-cast.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 6872d038fb7f..d888c767203a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -277,6 +277,28 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; let mut err = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg); + + let trait_def_id = main_trait_predicate.def_id(); + if self.tcx.is_diagnostic_item(sym::From, trait_def_id) + || self.tcx.is_diagnostic_item(sym::TryFrom, trait_def_id) + { + let found_ty = leaf_trait_predicate.skip_binder().trait_ref.args.type_at(1); + let ty = main_trait_predicate.skip_binder().self_ty(); + if let Some(cast_ty) = self.find_explicit_cast_type( + obligation.param_env, + found_ty, + ty, + ) { + let found_ty_str = self.tcx.short_string(found_ty, &mut long_ty_file); + let cast_ty_str = self.tcx.short_string(cast_ty, &mut long_ty_file); + err.help( + format!( + "consider casting the `{found_ty_str}` value to `{cast_ty_str}`", + ), + ); + } + } + *err.long_ty_path() = long_ty_file; let mut suggested = false; @@ -2930,6 +2952,69 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }) } + /// If `found_ty` is a reference that can be explicitly cast to another reference type for which + /// a `From` / `TryFrom` impl exists for `self_ty`, return that type. + fn find_explicit_cast_type( + &self, + param_env: ty::ParamEnv<'tcx>, + found_ty: Ty<'tcx>, + self_ty: Ty<'tcx>, + ) -> Option> { + let ty::Ref(region, inner_ty, mutbl) = *found_ty.kind() else { + return None; + }; + + let mut derefs = (self.autoderef_steps)(inner_ty).into_iter(); + derefs.next(); // skip the first one, which is inner_ty itself + let deref_target = derefs.into_iter().next()?.0; + + let cast_ty = Ty::new_ref(self.tcx, region, deref_target, mutbl); + + let Some(from_def_id) = self.tcx.get_diagnostic_item(sym::From) else { + return None; + }; + let Some(try_from_def_id) = self.tcx.get_diagnostic_item(sym::TryFrom) else { + return None; + }; + + if self.has_impl_for_type( + param_env, + ty::TraitRef::new( + self.tcx, + from_def_id, + self.tcx.mk_args(&[self_ty.into(), cast_ty.into()]), + ), + ) { + Some(cast_ty) + } else if self.has_impl_for_type( + param_env, + ty::TraitRef::new( + self.tcx, + try_from_def_id, + self.tcx.mk_args(&[self_ty.into(), cast_ty.into()]), + ), + ) { + Some(cast_ty) + } else { + None + } + } + + fn has_impl_for_type( + &self, + param_env: ty::ParamEnv<'tcx>, + trait_ref: ty::TraitRef<'tcx>, + ) -> bool { + let obligation = Obligation::new( + self.tcx, + ObligationCause::dummy(), + param_env, + ty::TraitPredicate { trait_ref, polarity: ty::PredicatePolarity::Positive }, + ); + + self.predicate_must_hold_modulo_regions(&obligation) + } + fn add_tuple_trait_message( &self, obligation_cause_code: &ObligationCauseCode<'tcx>, diff --git a/tests/ui/traits/explicit-reference-cast.rs b/tests/ui/traits/explicit-reference-cast.rs new file mode 100644 index 000000000000..efb4f10bea67 --- /dev/null +++ b/tests/ui/traits/explicit-reference-cast.rs @@ -0,0 +1,50 @@ +// compile-fail + +use std::convert::TryFrom; +use std::path::{Path, PathBuf}; + +pub struct ToolA(PathBuf); +//~^ HELP the trait `From<&PathBuf>` is not implemented for `ToolA` + +impl From<&Path> for ToolA { + //~^ HELP the following other types implement trait `From` + fn from(p: &Path) -> ToolA { + ToolA(p.to_path_buf()) + } +} + +// Add a different From impl to ensure we suggest the correct cast +impl From<&str> for ToolA { + fn from(s: &str) -> ToolA { + ToolA(PathBuf::from(s)) + } +} + +pub struct ToolB(PathBuf); +//~^ HELP the trait `From<&PathBuf>` is not implemented for `ToolB` +//~| HELP the trait `From<&PathBuf>` is not implemented for `ToolB` + +impl TryFrom<&Path> for ToolB { + //~^ HELP the trait `TryFrom<&PathBuf>` is not implemented for `ToolB` + //~| HELP the trait `TryFrom<&PathBuf>` is not implemented for `ToolB` + type Error = (); + + fn try_from(p: &Path) -> Result { + Ok(ToolB(p.to_path_buf())) + } +} + +fn main() { + let path = PathBuf::new(); + + let _ = ToolA::from(&path); + //~^ ERROR the trait bound `ToolA: From<&PathBuf>` is not satisfied + //~| HELP consider casting the `&PathBuf` value to `&Path` + let _ = ToolB::try_from(&path); + //~^ ERROR the trait bound `ToolB: TryFrom<&PathBuf>` is not satisfied + //~| ERROR the trait bound `ToolB: From<&PathBuf>` is not satisfied + //~| HELP consider casting the `&PathBuf` value to `&Path` + //~| HELP consider casting the `&PathBuf` value to `&Path` + //~| HELP for that trait implementation, expected `Path`, found `PathBuf` + //~| HELP for that trait implementation, expected `Path`, found `PathBuf` +} diff --git a/tests/ui/traits/explicit-reference-cast.stderr b/tests/ui/traits/explicit-reference-cast.stderr new file mode 100644 index 000000000000..924de3d5bbe3 --- /dev/null +++ b/tests/ui/traits/explicit-reference-cast.stderr @@ -0,0 +1,68 @@ +error[E0277]: the trait bound `ToolA: From<&PathBuf>` is not satisfied + --> $DIR/explicit-reference-cast.rs:40:13 + | +LL | let _ = ToolA::from(&path); + | ^^^^^ unsatisfied trait bound + | + = help: consider casting the `&PathBuf` value to `&Path` +help: the trait `From<&PathBuf>` is not implemented for `ToolA` + --> $DIR/explicit-reference-cast.rs:6:1 + | +LL | pub struct ToolA(PathBuf); + | ^^^^^^^^^^^^^^^^ +help: the following other types implement trait `From` + --> $DIR/explicit-reference-cast.rs:9:1 + | +LL | impl From<&Path> for ToolA { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `ToolA` implements `From<&Path>` +... +LL | impl From<&str> for ToolA { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `ToolA` implements `From<&str>` + +error[E0277]: the trait bound `ToolB: TryFrom<&PathBuf>` is not satisfied + --> $DIR/explicit-reference-cast.rs:43:13 + | +LL | let _ = ToolB::try_from(&path); + | ^^^^^ unsatisfied trait bound + | + = help: consider casting the `&PathBuf` value to `&Path` +help: the trait `From<&PathBuf>` is not implemented for `ToolB` + --> $DIR/explicit-reference-cast.rs:23:1 + | +LL | pub struct ToolB(PathBuf); + | ^^^^^^^^^^^^^^^^ +help: the trait `TryFrom<&PathBuf>` is not implemented for `ToolB` + but trait `TryFrom<&Path>` is implemented for it + --> $DIR/explicit-reference-cast.rs:27:1 + | +LL | impl TryFrom<&Path> for ToolB { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: for that trait implementation, expected `Path`, found `PathBuf` + = note: required for `&PathBuf` to implement `Into` + = note: required for `ToolB` to implement `TryFrom<&PathBuf>` + +error[E0277]: the trait bound `ToolB: From<&PathBuf>` is not satisfied + --> $DIR/explicit-reference-cast.rs:43:13 + | +LL | let _ = ToolB::try_from(&path); + | ^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | + = help: consider casting the `&PathBuf` value to `&Path` +help: the trait `From<&PathBuf>` is not implemented for `ToolB` + --> $DIR/explicit-reference-cast.rs:23:1 + | +LL | pub struct ToolB(PathBuf); + | ^^^^^^^^^^^^^^^^ +help: the trait `TryFrom<&PathBuf>` is not implemented for `ToolB` + but trait `TryFrom<&Path>` is implemented for it + --> $DIR/explicit-reference-cast.rs:27:1 + | +LL | impl TryFrom<&Path> for ToolB { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: for that trait implementation, expected `Path`, found `PathBuf` + = note: required for `&PathBuf` to implement `Into` + = note: required for `ToolB` to implement `TryFrom<&PathBuf>` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. From 2bab7a02f2caf77f53637838ef3cbf67bb718f6f Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 31 Jan 2026 02:06:47 +0000 Subject: [PATCH 353/978] Handle unbalanced delimiters gracefully in make_attr_token_stream --- compiler/rustc_ast/src/tokenstream.rs | 8 +- .../ui/macros/tokenstream-ice-issue-149954.rs | 22 ++++ .../tokenstream-ice-issue-149954.stderr | 110 ++++++++++++++++++ 3 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 tests/ui/macros/tokenstream-ice-issue-149954.rs create mode 100644 tests/ui/macros/tokenstream-ice-issue-149954.stderr diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index e346a56bcf40..8d8e8ffc562f 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -354,7 +354,13 @@ fn make_attr_token_stream( FrameData { open_delim_sp: Some((delim, span, spacing)), inner: vec![] }, )); } else if let Some(delim) = kind.close_delim() { - let frame_data = mem::replace(&mut stack_top, stack_rest.pop().unwrap()); + // If there's no matching opening delimiter, the token stream is malformed, + // likely due to a improper delimiter positions in the source code. + // It's not delimiter mismatch, and lexer can not detect it, so we just ignore it here. + let Some(frame) = stack_rest.pop() else { + return AttrTokenStream::new(stack_top.inner); + }; + let frame_data = mem::replace(&mut stack_top, frame); let (open_delim, open_sp, open_spacing) = frame_data.open_delim_sp.unwrap(); assert!( open_delim.eq_ignoring_invisible_origin(&delim), diff --git a/tests/ui/macros/tokenstream-ice-issue-149954.rs b/tests/ui/macros/tokenstream-ice-issue-149954.rs new file mode 100644 index 000000000000..958a86cbde8b --- /dev/null +++ b/tests/ui/macros/tokenstream-ice-issue-149954.rs @@ -0,0 +1,22 @@ +// Regression test for ICE https://github.com/rust-lang/rust/issues/149954 +//@ edition: 2024 + +enum A { + A + const A: A = { //~ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found keyword `const` + #[derive(Debug)] + struct A + where + A: A<{ struct A> ; enum A } + //~^ ERROR malformed `cfg` attribute input + //~| ERROR malformed `cfg` attribute input + //~| ERROR expected trait, found struct `A` + //~| ERROR expected trait, found type parameter `A` + //~| ERROR expected trait, found struct `A` + //~| ERROR expected trait, found type parameter `A` + //~| ERROR expected one of `<`, `where`, or `{`, found `}` + //~| ERROR expected one of `<`, `where`, or `{`, found `}` + //~| ERROR expected one of `,`, `>`, or `}`, found `` + } + >; +}; //~ ERROR `main` function not found in crate diff --git a/tests/ui/macros/tokenstream-ice-issue-149954.stderr b/tests/ui/macros/tokenstream-ice-issue-149954.stderr new file mode 100644 index 000000000000..750f3efcc612 --- /dev/null +++ b/tests/ui/macros/tokenstream-ice-issue-149954.stderr @@ -0,0 +1,110 @@ +error: expected one of `(`, `,`, `=`, `{`, or `}`, found keyword `const` + --> $DIR/tokenstream-ice-issue-149954.rs:6:5 + | +LL | A + | - expected one of `(`, `,`, `=`, `{`, or `}` +LL | const A: A = { + | ^^^^^ unexpected token + | + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` + +error: expected one of `<`, `where`, or `{`, found `}` + --> $DIR/tokenstream-ice-issue-149954.rs:10:60 + | +LL | A: A<{ struct A> ; enum A } + | - ^ expected one of `<`, `where`, or `{` + | | + | while parsing this enum + +error: expected one of `<`, `where`, or `{`, found `}` + --> $DIR/tokenstream-ice-issue-149954.rs:10:60 + | +LL | A: A<{ struct A> ; enum A } + | - ^ expected one of `<`, `where`, or `{` + | | + | while parsing this enum + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: expected one of `,`, `>`, or `}`, found `` + --> $DIR/tokenstream-ice-issue-149954.rs:10:60 + | +LL | A: A<{ struct A> ; enum A } + | ^ expected one of `,`, `>`, or `}` + | +help: you might have meant to end the type parameters here + | +LL | A: A<{ struct A> ; enum A }> + | + + +error[E0539]: malformed `cfg` attribute input + --> $DIR/tokenstream-ice-issue-149954.rs:10:36 + | +LL | A: A<{ struct A> ; enum A } + | ^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[cfg(predicate)]` + | + = note: for more information, visit + +error[E0539]: malformed `cfg` attribute input + --> $DIR/tokenstream-ice-issue-149954.rs:10:36 + | +LL | A: A<{ struct A> ; enum A } + | ^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[cfg(predicate)]` + | + = note: for more information, visit + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0404]: expected trait, found struct `A` + --> $DIR/tokenstream-ice-issue-149954.rs:10:16 + | +LL | A: A<{ struct A> ; enum A } + | ________________^ +... | +LL | | >; + | |_________^ not a trait + +error[E0404]: expected trait, found type parameter `A` + --> $DIR/tokenstream-ice-issue-149954.rs:10:32 + | +LL | A: A<{ struct A> ; enum A } + | - ^^^^^^^^^^^^^^^^ not a trait + | | + | found this type parameter + +error[E0404]: expected trait, found struct `A` + --> $DIR/tokenstream-ice-issue-149954.rs:10:16 + | +LL | A: A<{ struct A> ; enum A } + | ________________^ +... | +LL | | >; + | |_________^ not a trait + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0404]: expected trait, found type parameter `A` + --> $DIR/tokenstream-ice-issue-149954.rs:10:32 + | +LL | A: A<{ struct A> ; enum A } + | - ^^^^^^^^^^^^^^^^ not a trait + | | + | found this type parameter + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0601]: `main` function not found in crate `tokenstream_ice_issue_149954` + --> $DIR/tokenstream-ice-issue-149954.rs:22:3 + | +LL | }; + | ^ consider adding a `main` function to `$DIR/tokenstream-ice-issue-149954.rs` + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0404, E0539, E0601. +For more information about an error, try `rustc --explain E0404`. From 0306275849b28f23ebf9d7883317937c9aac0991 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 1 Feb 2026 13:50:20 +0100 Subject: [PATCH 354/978] use macro for wide store/load roundtrip tests --- .../crates/core_arch/src/aarch64/neon/mod.rs | 636 +++--------------- 1 file changed, 90 insertions(+), 546 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs index feaf94a7f9e0..ee27bef9738c 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs @@ -994,868 +994,412 @@ mod tests { assert_eq!(vals[2], 2.); } + macro_rules! wide_store_load_roundtrip { + ($elem_ty:ty, $len:expr, $vec_ty:ty, $store:expr, $load:expr) => { + let vals: [$elem_ty; $len] = crate::array::from_fn(|i| i as $elem_ty); + let a: $vec_ty = transmute(vals); + let mut tmp = [0 as $elem_ty; $len]; + $store(tmp.as_mut_ptr().cast(), a); + let r: $vec_ty = $load(tmp.as_ptr().cast()); + let out: [$elem_ty; $len] = transmute(r); + assert_eq!(out, vals); + }; + } + #[simd_test(enable = "neon,fp16")] #[cfg(not(target_arch = "arm64ec"))] unsafe fn test_vld1_f16_x2() { - let vals: [f16; 8] = crate::array::from_fn(|i| i as f16); - let a: float16x4x2_t = transmute(vals); - let mut tmp = [0_f16; 8]; - vst1_f16_x2(tmp.as_mut_ptr().cast(), a); - let r: float16x4x2_t = vld1_f16_x2(tmp.as_ptr().cast()); - let out: [f16; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f16, 8, float16x4x2_t, vst1_f16_x2, vld1_f16_x2); } #[simd_test(enable = "neon,fp16")] #[cfg(not(target_arch = "arm64ec"))] unsafe fn test_vld1_f16_x3() { - let vals: [f16; 12] = crate::array::from_fn(|i| i as f16); - let a: float16x4x3_t = transmute(vals); - let mut tmp = [0_f16; 12]; - vst1_f16_x3(tmp.as_mut_ptr().cast(), a); - let r: float16x4x3_t = vld1_f16_x3(tmp.as_ptr().cast()); - let out: [f16; 12] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f16, 12, float16x4x3_t, vst1_f16_x3, vld1_f16_x3); } #[simd_test(enable = "neon,fp16")] #[cfg(not(target_arch = "arm64ec"))] unsafe fn test_vld1_f16_x4() { - let vals: [f16; 16] = crate::array::from_fn(|i| i as f16); - let a: float16x4x4_t = transmute(vals); - let mut tmp = [0_f16; 16]; - vst1_f16_x4(tmp.as_mut_ptr().cast(), a); - let r: float16x4x4_t = vld1_f16_x4(tmp.as_ptr().cast()); - let out: [f16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f16, 16, float16x4x4_t, vst1_f16_x4, vld1_f16_x4); } #[simd_test(enable = "neon,fp16")] #[cfg(not(target_arch = "arm64ec"))] unsafe fn test_vld1q_f16_x2() { - let vals: [f16; 16] = crate::array::from_fn(|i| i as f16); - let a: float16x8x2_t = transmute(vals); - let mut tmp = [0_f16; 16]; - vst1q_f16_x2(tmp.as_mut_ptr().cast(), a); - let r: float16x8x2_t = vld1q_f16_x2(tmp.as_ptr().cast()); - let out: [f16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f16, 16, float16x8x2_t, vst1q_f16_x2, vld1q_f16_x2); } #[simd_test(enable = "neon,fp16")] #[cfg(not(target_arch = "arm64ec"))] unsafe fn test_vld1q_f16_x3() { - let vals: [f16; 24] = crate::array::from_fn(|i| i as f16); - let a: float16x8x3_t = transmute(vals); - let mut tmp = [0_f16; 24]; - vst1q_f16_x3(tmp.as_mut_ptr().cast(), a); - let r: float16x8x3_t = vld1q_f16_x3(tmp.as_ptr().cast()); - let out: [f16; 24] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f16, 24, float16x8x3_t, vst1q_f16_x3, vld1q_f16_x3); } #[simd_test(enable = "neon,fp16")] #[cfg(not(target_arch = "arm64ec"))] unsafe fn test_vld1q_f16_x4() { - let vals: [f16; 32] = crate::array::from_fn(|i| i as f16); - let a: float16x8x4_t = transmute(vals); - let mut tmp = [0_f16; 32]; - vst1q_f16_x4(tmp.as_mut_ptr().cast(), a); - let r: float16x8x4_t = vld1q_f16_x4(tmp.as_ptr().cast()); - let out: [f16; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f16, 32, float16x8x4_t, vst1q_f16_x4, vld1q_f16_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_f32_x2() { - let vals: [f32; 4] = crate::array::from_fn(|i| i as f32); - let a: float32x2x2_t = transmute(vals); - let mut tmp = [0_f32; 4]; - vst1_f32_x2(tmp.as_mut_ptr().cast(), a); - let r: float32x2x2_t = vld1_f32_x2(tmp.as_ptr().cast()); - let out: [f32; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f32, 4, float32x2x2_t, vst1_f32_x2, vld1_f32_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_f32_x3() { - let vals: [f32; 6] = crate::array::from_fn(|i| i as f32); - let a: float32x2x3_t = transmute(vals); - let mut tmp = [0_f32; 6]; - vst1_f32_x3(tmp.as_mut_ptr().cast(), a); - let r: float32x2x3_t = vld1_f32_x3(tmp.as_ptr().cast()); - let out: [f32; 6] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f32, 6, float32x2x3_t, vst1_f32_x3, vld1_f32_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_f32_x4() { - let vals: [f32; 8] = crate::array::from_fn(|i| i as f32); - let a: float32x2x4_t = transmute(vals); - let mut tmp = [0_f32; 8]; - vst1_f32_x4(tmp.as_mut_ptr().cast(), a); - let r: float32x2x4_t = vld1_f32_x4(tmp.as_ptr().cast()); - let out: [f32; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f32, 8, float32x2x4_t, vst1_f32_x4, vld1_f32_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_f32_x2() { - let vals: [f32; 8] = crate::array::from_fn(|i| i as f32); - let a: float32x4x2_t = transmute(vals); - let mut tmp = [0_f32; 8]; - vst1q_f32_x2(tmp.as_mut_ptr().cast(), a); - let r: float32x4x2_t = vld1q_f32_x2(tmp.as_ptr().cast()); - let out: [f32; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f32, 8, float32x4x2_t, vst1q_f32_x2, vld1q_f32_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_f32_x3() { - let vals: [f32; 12] = crate::array::from_fn(|i| i as f32); - let a: float32x4x3_t = transmute(vals); - let mut tmp = [0_f32; 12]; - vst1q_f32_x3(tmp.as_mut_ptr().cast(), a); - let r: float32x4x3_t = vld1q_f32_x3(tmp.as_ptr().cast()); - let out: [f32; 12] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f32, 12, float32x4x3_t, vst1q_f32_x3, vld1q_f32_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_f32_x4() { - let vals: [f32; 16] = crate::array::from_fn(|i| i as f32); - let a: float32x4x4_t = transmute(vals); - let mut tmp = [0_f32; 16]; - vst1q_f32_x4(tmp.as_mut_ptr().cast(), a); - let r: float32x4x4_t = vld1q_f32_x4(tmp.as_ptr().cast()); - let out: [f32; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(f32, 16, float32x4x4_t, vst1q_f32_x4, vld1q_f32_x4); } #[simd_test(enable = "neon,aes")] unsafe fn test_vld1_p64_x2() { - let vals: [p64; 2] = crate::array::from_fn(|i| i as p64); - let a: poly64x1x2_t = transmute(vals); - let mut tmp = [0 as p64; 2]; - vst1_p64_x2(tmp.as_mut_ptr().cast(), a); - let r: poly64x1x2_t = vld1_p64_x2(tmp.as_ptr().cast()); - let out: [p64; 2] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p64, 2, poly64x1x2_t, vst1_p64_x2, vld1_p64_x2); } #[simd_test(enable = "neon,aes")] unsafe fn test_vld1_p64_x3() { - let vals: [p64; 3] = crate::array::from_fn(|i| i as p64); - let a: poly64x1x3_t = transmute(vals); - let mut tmp = [0 as p64; 3]; - vst1_p64_x3(tmp.as_mut_ptr().cast(), a); - let r: poly64x1x3_t = vld1_p64_x3(tmp.as_ptr().cast()); - let out: [p64; 3] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p64, 3, poly64x1x3_t, vst1_p64_x3, vld1_p64_x3); } #[simd_test(enable = "neon,aes")] unsafe fn test_vld1_p64_x4() { - let vals: [p64; 4] = crate::array::from_fn(|i| i as p64); - let a: poly64x1x4_t = transmute(vals); - let mut tmp = [0 as p64; 4]; - vst1_p64_x4(tmp.as_mut_ptr().cast(), a); - let r: poly64x1x4_t = vld1_p64_x4(tmp.as_ptr().cast()); - let out: [p64; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p64, 4, poly64x1x4_t, vst1_p64_x4, vld1_p64_x4); } #[simd_test(enable = "neon,aes")] unsafe fn test_vld1q_p64_x2() { - let vals: [p64; 4] = crate::array::from_fn(|i| i as p64); - let a: poly64x2x2_t = transmute(vals); - let mut tmp = [0 as p64; 4]; - vst1q_p64_x2(tmp.as_mut_ptr().cast(), a); - let r: poly64x2x2_t = vld1q_p64_x2(tmp.as_ptr().cast()); - let out: [p64; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p64, 4, poly64x2x2_t, vst1q_p64_x2, vld1q_p64_x2); } #[simd_test(enable = "neon,aes")] unsafe fn test_vld1q_p64_x3() { - let vals: [p64; 6] = crate::array::from_fn(|i| i as p64); - let a: poly64x2x3_t = transmute(vals); - let mut tmp = [0 as p64; 6]; - vst1q_p64_x3(tmp.as_mut_ptr().cast(), a); - let r: poly64x2x3_t = vld1q_p64_x3(tmp.as_ptr().cast()); - let out: [p64; 6] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p64, 6, poly64x2x3_t, vst1q_p64_x3, vld1q_p64_x3); } #[simd_test(enable = "neon,aes")] unsafe fn test_vld1q_p64_x4() { - let vals: [p64; 8] = crate::array::from_fn(|i| i as p64); - let a: poly64x2x4_t = transmute(vals); - let mut tmp = [0 as p64; 8]; - vst1q_p64_x4(tmp.as_mut_ptr().cast(), a); - let r: poly64x2x4_t = vld1q_p64_x4(tmp.as_ptr().cast()); - let out: [p64; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p64, 8, poly64x2x4_t, vst1q_p64_x4, vld1q_p64_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s8_x2() { - let vals: [i8; 16] = crate::array::from_fn(|i| i as i8); - let a: int8x8x2_t = transmute(vals); - let mut tmp = [0_i8; 16]; - vst1_s8_x2(tmp.as_mut_ptr().cast(), a); - let r: int8x8x2_t = vld1_s8_x2(tmp.as_ptr().cast()); - let out: [i8; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i8, 16, int8x8x2_t, vst1_s8_x2, vld1_s8_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s8_x3() { - let vals: [i8; 24] = crate::array::from_fn(|i| i as i8); - let a: int8x8x3_t = transmute(vals); - let mut tmp = [0_i8; 24]; - vst1_s8_x3(tmp.as_mut_ptr().cast(), a); - let r: int8x8x3_t = vld1_s8_x3(tmp.as_ptr().cast()); - let out: [i8; 24] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i8, 24, int8x8x3_t, vst1_s8_x3, vld1_s8_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s8_x4() { - let vals: [i8; 32] = crate::array::from_fn(|i| i as i8); - let a: int8x8x4_t = transmute(vals); - let mut tmp = [0_i8; 32]; - vst1_s8_x4(tmp.as_mut_ptr().cast(), a); - let r: int8x8x4_t = vld1_s8_x4(tmp.as_ptr().cast()); - let out: [i8; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i8, 32, int8x8x4_t, vst1_s8_x4, vld1_s8_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s8_x2() { - let vals: [i8; 32] = crate::array::from_fn(|i| i as i8); - let a: int8x16x2_t = transmute(vals); - let mut tmp = [0_i8; 32]; - vst1q_s8_x2(tmp.as_mut_ptr().cast(), a); - let r: int8x16x2_t = vld1q_s8_x2(tmp.as_ptr().cast()); - let out: [i8; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i8, 32, int8x16x2_t, vst1q_s8_x2, vld1q_s8_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s8_x3() { - let vals: [i8; 48] = crate::array::from_fn(|i| i as i8); - let a: int8x16x3_t = transmute(vals); - let mut tmp = [0_i8; 48]; - vst1q_s8_x3(tmp.as_mut_ptr().cast(), a); - let r: int8x16x3_t = vld1q_s8_x3(tmp.as_ptr().cast()); - let out: [i8; 48] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i8, 48, int8x16x3_t, vst1q_s8_x3, vld1q_s8_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s8_x4() { - let vals: [i8; 64] = crate::array::from_fn(|i| i as i8); - let a: int8x16x4_t = transmute(vals); - let mut tmp = [0_i8; 64]; - vst1q_s8_x4(tmp.as_mut_ptr().cast(), a); - let r: int8x16x4_t = vld1q_s8_x4(tmp.as_ptr().cast()); - let out: [i8; 64] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i8, 64, int8x16x4_t, vst1q_s8_x4, vld1q_s8_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s16_x2() { - let vals: [i16; 8] = crate::array::from_fn(|i| i as i16); - let a: int16x4x2_t = transmute(vals); - let mut tmp = [0_i16; 8]; - vst1_s16_x2(tmp.as_mut_ptr().cast(), a); - let r: int16x4x2_t = vld1_s16_x2(tmp.as_ptr().cast()); - let out: [i16; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i16, 8, int16x4x2_t, vst1_s16_x2, vld1_s16_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s16_x3() { - let vals: [i16; 12] = crate::array::from_fn(|i| i as i16); - let a: int16x4x3_t = transmute(vals); - let mut tmp = [0_i16; 12]; - vst1_s16_x3(tmp.as_mut_ptr().cast(), a); - let r: int16x4x3_t = vld1_s16_x3(tmp.as_ptr().cast()); - let out: [i16; 12] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i16, 12, int16x4x3_t, vst1_s16_x3, vld1_s16_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s16_x4() { - let vals: [i16; 16] = crate::array::from_fn(|i| i as i16); - let a: int16x4x4_t = transmute(vals); - let mut tmp = [0_i16; 16]; - vst1_s16_x4(tmp.as_mut_ptr().cast(), a); - let r: int16x4x4_t = vld1_s16_x4(tmp.as_ptr().cast()); - let out: [i16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i16, 16, int16x4x4_t, vst1_s16_x4, vld1_s16_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s16_x2() { - let vals: [i16; 16] = crate::array::from_fn(|i| i as i16); - let a: int16x8x2_t = transmute(vals); - let mut tmp = [0_i16; 16]; - vst1q_s16_x2(tmp.as_mut_ptr().cast(), a); - let r: int16x8x2_t = vld1q_s16_x2(tmp.as_ptr().cast()); - let out: [i16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i16, 16, int16x8x2_t, vst1q_s16_x2, vld1q_s16_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s16_x3() { - let vals: [i16; 24] = crate::array::from_fn(|i| i as i16); - let a: int16x8x3_t = transmute(vals); - let mut tmp = [0_i16; 24]; - vst1q_s16_x3(tmp.as_mut_ptr().cast(), a); - let r: int16x8x3_t = vld1q_s16_x3(tmp.as_ptr().cast()); - let out: [i16; 24] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i16, 24, int16x8x3_t, vst1q_s16_x3, vld1q_s16_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s16_x4() { - let vals: [i16; 32] = crate::array::from_fn(|i| i as i16); - let a: int16x8x4_t = transmute(vals); - let mut tmp = [0_i16; 32]; - vst1q_s16_x4(tmp.as_mut_ptr().cast(), a); - let r: int16x8x4_t = vld1q_s16_x4(tmp.as_ptr().cast()); - let out: [i16; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i16, 32, int16x8x4_t, vst1q_s16_x4, vld1q_s16_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s32_x2() { - let vals: [i32; 4] = crate::array::from_fn(|i| i as i32); - let a: int32x2x2_t = transmute(vals); - let mut tmp = [0_i32; 4]; - vst1_s32_x2(tmp.as_mut_ptr().cast(), a); - let r: int32x2x2_t = vld1_s32_x2(tmp.as_ptr().cast()); - let out: [i32; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i32, 4, int32x2x2_t, vst1_s32_x2, vld1_s32_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s32_x3() { - let vals: [i32; 6] = crate::array::from_fn(|i| i as i32); - let a: int32x2x3_t = transmute(vals); - let mut tmp = [0_i32; 6]; - vst1_s32_x3(tmp.as_mut_ptr().cast(), a); - let r: int32x2x3_t = vld1_s32_x3(tmp.as_ptr().cast()); - let out: [i32; 6] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i32, 6, int32x2x3_t, vst1_s32_x3, vld1_s32_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s32_x4() { - let vals: [i32; 8] = crate::array::from_fn(|i| i as i32); - let a: int32x2x4_t = transmute(vals); - let mut tmp = [0_i32; 8]; - vst1_s32_x4(tmp.as_mut_ptr().cast(), a); - let r: int32x2x4_t = vld1_s32_x4(tmp.as_ptr().cast()); - let out: [i32; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i32, 8, int32x2x4_t, vst1_s32_x4, vld1_s32_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s32_x2() { - let vals: [i32; 8] = crate::array::from_fn(|i| i as i32); - let a: int32x4x2_t = transmute(vals); - let mut tmp = [0_i32; 8]; - vst1q_s32_x2(tmp.as_mut_ptr().cast(), a); - let r: int32x4x2_t = vld1q_s32_x2(tmp.as_ptr().cast()); - let out: [i32; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i32, 8, int32x4x2_t, vst1q_s32_x2, vld1q_s32_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s32_x3() { - let vals: [i32; 12] = crate::array::from_fn(|i| i as i32); - let a: int32x4x3_t = transmute(vals); - let mut tmp = [0_i32; 12]; - vst1q_s32_x3(tmp.as_mut_ptr().cast(), a); - let r: int32x4x3_t = vld1q_s32_x3(tmp.as_ptr().cast()); - let out: [i32; 12] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i32, 12, int32x4x3_t, vst1q_s32_x3, vld1q_s32_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s32_x4() { - let vals: [i32; 16] = crate::array::from_fn(|i| i as i32); - let a: int32x4x4_t = transmute(vals); - let mut tmp = [0_i32; 16]; - vst1q_s32_x4(tmp.as_mut_ptr().cast(), a); - let r: int32x4x4_t = vld1q_s32_x4(tmp.as_ptr().cast()); - let out: [i32; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i32, 16, int32x4x4_t, vst1q_s32_x4, vld1q_s32_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s64_x2() { - let vals: [i64; 2] = crate::array::from_fn(|i| i as i64); - let a: int64x1x2_t = transmute(vals); - let mut tmp = [0_i64; 2]; - vst1_s64_x2(tmp.as_mut_ptr().cast(), a); - let r: int64x1x2_t = vld1_s64_x2(tmp.as_ptr().cast()); - let out: [i64; 2] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i64, 2, int64x1x2_t, vst1_s64_x2, vld1_s64_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s64_x3() { - let vals: [i64; 3] = crate::array::from_fn(|i| i as i64); - let a: int64x1x3_t = transmute(vals); - let mut tmp = [0_i64; 3]; - vst1_s64_x3(tmp.as_mut_ptr().cast(), a); - let r: int64x1x3_t = vld1_s64_x3(tmp.as_ptr().cast()); - let out: [i64; 3] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i64, 3, int64x1x3_t, vst1_s64_x3, vld1_s64_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_s64_x4() { - let vals: [i64; 4] = crate::array::from_fn(|i| i as i64); - let a: int64x1x4_t = transmute(vals); - let mut tmp = [0_i64; 4]; - vst1_s64_x4(tmp.as_mut_ptr().cast(), a); - let r: int64x1x4_t = vld1_s64_x4(tmp.as_ptr().cast()); - let out: [i64; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i64, 4, int64x1x4_t, vst1_s64_x4, vld1_s64_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s64_x2() { - let vals: [i64; 4] = crate::array::from_fn(|i| i as i64); - let a: int64x2x2_t = transmute(vals); - let mut tmp = [0_i64; 4]; - vst1q_s64_x2(tmp.as_mut_ptr().cast(), a); - let r: int64x2x2_t = vld1q_s64_x2(tmp.as_ptr().cast()); - let out: [i64; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i64, 4, int64x2x2_t, vst1q_s64_x2, vld1q_s64_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s64_x3() { - let vals: [i64; 6] = crate::array::from_fn(|i| i as i64); - let a: int64x2x3_t = transmute(vals); - let mut tmp = [0_i64; 6]; - vst1q_s64_x3(tmp.as_mut_ptr().cast(), a); - let r: int64x2x3_t = vld1q_s64_x3(tmp.as_ptr().cast()); - let out: [i64; 6] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i64, 6, int64x2x3_t, vst1q_s64_x3, vld1q_s64_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_s64_x4() { - let vals: [i64; 8] = crate::array::from_fn(|i| i as i64); - let a: int64x2x4_t = transmute(vals); - let mut tmp = [0_i64; 8]; - vst1q_s64_x4(tmp.as_mut_ptr().cast(), a); - let r: int64x2x4_t = vld1q_s64_x4(tmp.as_ptr().cast()); - let out: [i64; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(i64, 8, int64x2x4_t, vst1q_s64_x4, vld1q_s64_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u8_x2() { - let vals: [u8; 16] = crate::array::from_fn(|i| i as u8); - let a: uint8x8x2_t = transmute(vals); - let mut tmp = [0_u8; 16]; - vst1_u8_x2(tmp.as_mut_ptr().cast(), a); - let r: uint8x8x2_t = vld1_u8_x2(tmp.as_ptr().cast()); - let out: [u8; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u8, 16, uint8x8x2_t, vst1_u8_x2, vld1_u8_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u8_x3() { - let vals: [u8; 24] = crate::array::from_fn(|i| i as u8); - let a: uint8x8x3_t = transmute(vals); - let mut tmp = [0_u8; 24]; - vst1_u8_x3(tmp.as_mut_ptr().cast(), a); - let r: uint8x8x3_t = vld1_u8_x3(tmp.as_ptr().cast()); - let out: [u8; 24] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u8, 24, uint8x8x3_t, vst1_u8_x3, vld1_u8_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u8_x4() { - let vals: [u8; 32] = crate::array::from_fn(|i| i as u8); - let a: uint8x8x4_t = transmute(vals); - let mut tmp = [0_u8; 32]; - vst1_u8_x4(tmp.as_mut_ptr().cast(), a); - let r: uint8x8x4_t = vld1_u8_x4(tmp.as_ptr().cast()); - let out: [u8; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u8, 32, uint8x8x4_t, vst1_u8_x4, vld1_u8_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u8_x2() { - let vals: [u8; 32] = crate::array::from_fn(|i| i as u8); - let a: uint8x16x2_t = transmute(vals); - let mut tmp = [0_u8; 32]; - vst1q_u8_x2(tmp.as_mut_ptr().cast(), a); - let r: uint8x16x2_t = vld1q_u8_x2(tmp.as_ptr().cast()); - let out: [u8; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u8, 32, uint8x16x2_t, vst1q_u8_x2, vld1q_u8_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u8_x3() { - let vals: [u8; 48] = crate::array::from_fn(|i| i as u8); - let a: uint8x16x3_t = transmute(vals); - let mut tmp = [0_u8; 48]; - vst1q_u8_x3(tmp.as_mut_ptr().cast(), a); - let r: uint8x16x3_t = vld1q_u8_x3(tmp.as_ptr().cast()); - let out: [u8; 48] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u8, 48, uint8x16x3_t, vst1q_u8_x3, vld1q_u8_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u8_x4() { - let vals: [u8; 64] = crate::array::from_fn(|i| i as u8); - let a: uint8x16x4_t = transmute(vals); - let mut tmp = [0_u8; 64]; - vst1q_u8_x4(tmp.as_mut_ptr().cast(), a); - let r: uint8x16x4_t = vld1q_u8_x4(tmp.as_ptr().cast()); - let out: [u8; 64] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u8, 64, uint8x16x4_t, vst1q_u8_x4, vld1q_u8_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u16_x2() { - let vals: [u16; 8] = crate::array::from_fn(|i| i as u16); - let a: uint16x4x2_t = transmute(vals); - let mut tmp = [0_u16; 8]; - vst1_u16_x2(tmp.as_mut_ptr().cast(), a); - let r: uint16x4x2_t = vld1_u16_x2(tmp.as_ptr().cast()); - let out: [u16; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u16, 8, uint16x4x2_t, vst1_u16_x2, vld1_u16_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u16_x3() { - let vals: [u16; 12] = crate::array::from_fn(|i| i as u16); - let a: uint16x4x3_t = transmute(vals); - let mut tmp = [0_u16; 12]; - vst1_u16_x3(tmp.as_mut_ptr().cast(), a); - let r: uint16x4x3_t = vld1_u16_x3(tmp.as_ptr().cast()); - let out: [u16; 12] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u16, 12, uint16x4x3_t, vst1_u16_x3, vld1_u16_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u16_x4() { - let vals: [u16; 16] = crate::array::from_fn(|i| i as u16); - let a: uint16x4x4_t = transmute(vals); - let mut tmp = [0_u16; 16]; - vst1_u16_x4(tmp.as_mut_ptr().cast(), a); - let r: uint16x4x4_t = vld1_u16_x4(tmp.as_ptr().cast()); - let out: [u16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u16, 16, uint16x4x4_t, vst1_u16_x4, vld1_u16_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u16_x2() { - let vals: [u16; 16] = crate::array::from_fn(|i| i as u16); - let a: uint16x8x2_t = transmute(vals); - let mut tmp = [0_u16; 16]; - vst1q_u16_x2(tmp.as_mut_ptr().cast(), a); - let r: uint16x8x2_t = vld1q_u16_x2(tmp.as_ptr().cast()); - let out: [u16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u16, 16, uint16x8x2_t, vst1q_u16_x2, vld1q_u16_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u16_x3() { - let vals: [u16; 24] = crate::array::from_fn(|i| i as u16); - let a: uint16x8x3_t = transmute(vals); - let mut tmp = [0_u16; 24]; - vst1q_u16_x3(tmp.as_mut_ptr().cast(), a); - let r: uint16x8x3_t = vld1q_u16_x3(tmp.as_ptr().cast()); - let out: [u16; 24] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u16, 24, uint16x8x3_t, vst1q_u16_x3, vld1q_u16_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u16_x4() { - let vals: [u16; 32] = crate::array::from_fn(|i| i as u16); - let a: uint16x8x4_t = transmute(vals); - let mut tmp = [0_u16; 32]; - vst1q_u16_x4(tmp.as_mut_ptr().cast(), a); - let r: uint16x8x4_t = vld1q_u16_x4(tmp.as_ptr().cast()); - let out: [u16; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u16, 32, uint16x8x4_t, vst1q_u16_x4, vld1q_u16_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u32_x2() { - let vals: [u32; 4] = crate::array::from_fn(|i| i as u32); - let a: uint32x2x2_t = transmute(vals); - let mut tmp = [0_u32; 4]; - vst1_u32_x2(tmp.as_mut_ptr().cast(), a); - let r: uint32x2x2_t = vld1_u32_x2(tmp.as_ptr().cast()); - let out: [u32; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u32, 4, uint32x2x2_t, vst1_u32_x2, vld1_u32_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u32_x3() { - let vals: [u32; 6] = crate::array::from_fn(|i| i as u32); - let a: uint32x2x3_t = transmute(vals); - let mut tmp = [0_u32; 6]; - vst1_u32_x3(tmp.as_mut_ptr().cast(), a); - let r: uint32x2x3_t = vld1_u32_x3(tmp.as_ptr().cast()); - let out: [u32; 6] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u32, 6, uint32x2x3_t, vst1_u32_x3, vld1_u32_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u32_x4() { - let vals: [u32; 8] = crate::array::from_fn(|i| i as u32); - let a: uint32x2x4_t = transmute(vals); - let mut tmp = [0_u32; 8]; - vst1_u32_x4(tmp.as_mut_ptr().cast(), a); - let r: uint32x2x4_t = vld1_u32_x4(tmp.as_ptr().cast()); - let out: [u32; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u32, 8, uint32x2x4_t, vst1_u32_x4, vld1_u32_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u32_x2() { - let vals: [u32; 8] = crate::array::from_fn(|i| i as u32); - let a: uint32x4x2_t = transmute(vals); - let mut tmp = [0_u32; 8]; - vst1q_u32_x2(tmp.as_mut_ptr().cast(), a); - let r: uint32x4x2_t = vld1q_u32_x2(tmp.as_ptr().cast()); - let out: [u32; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u32, 8, uint32x4x2_t, vst1q_u32_x2, vld1q_u32_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u32_x3() { - let vals: [u32; 12] = crate::array::from_fn(|i| i as u32); - let a: uint32x4x3_t = transmute(vals); - let mut tmp = [0_u32; 12]; - vst1q_u32_x3(tmp.as_mut_ptr().cast(), a); - let r: uint32x4x3_t = vld1q_u32_x3(tmp.as_ptr().cast()); - let out: [u32; 12] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u32, 12, uint32x4x3_t, vst1q_u32_x3, vld1q_u32_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u32_x4() { - let vals: [u32; 16] = crate::array::from_fn(|i| i as u32); - let a: uint32x4x4_t = transmute(vals); - let mut tmp = [0_u32; 16]; - vst1q_u32_x4(tmp.as_mut_ptr().cast(), a); - let r: uint32x4x4_t = vld1q_u32_x4(tmp.as_ptr().cast()); - let out: [u32; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u32, 16, uint32x4x4_t, vst1q_u32_x4, vld1q_u32_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u64_x2() { - let vals: [u64; 2] = crate::array::from_fn(|i| i as u64); - let a: uint64x1x2_t = transmute(vals); - let mut tmp = [0_u64; 2]; - vst1_u64_x2(tmp.as_mut_ptr().cast(), a); - let r: uint64x1x2_t = vld1_u64_x2(tmp.as_ptr().cast()); - let out: [u64; 2] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u64, 2, uint64x1x2_t, vst1_u64_x2, vld1_u64_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u64_x3() { - let vals: [u64; 3] = crate::array::from_fn(|i| i as u64); - let a: uint64x1x3_t = transmute(vals); - let mut tmp = [0_u64; 3]; - vst1_u64_x3(tmp.as_mut_ptr().cast(), a); - let r: uint64x1x3_t = vld1_u64_x3(tmp.as_ptr().cast()); - let out: [u64; 3] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u64, 3, uint64x1x3_t, vst1_u64_x3, vld1_u64_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_u64_x4() { - let vals: [u64; 4] = crate::array::from_fn(|i| i as u64); - let a: uint64x1x4_t = transmute(vals); - let mut tmp = [0_u64; 4]; - vst1_u64_x4(tmp.as_mut_ptr().cast(), a); - let r: uint64x1x4_t = vld1_u64_x4(tmp.as_ptr().cast()); - let out: [u64; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u64, 4, uint64x1x4_t, vst1_u64_x4, vld1_u64_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u64_x2() { - let vals: [u64; 4] = crate::array::from_fn(|i| i as u64); - let a: uint64x2x2_t = transmute(vals); - let mut tmp = [0_u64; 4]; - vst1q_u64_x2(tmp.as_mut_ptr().cast(), a); - let r: uint64x2x2_t = vld1q_u64_x2(tmp.as_ptr().cast()); - let out: [u64; 4] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u64, 4, uint64x2x2_t, vst1q_u64_x2, vld1q_u64_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u64_x3() { - let vals: [u64; 6] = crate::array::from_fn(|i| i as u64); - let a: uint64x2x3_t = transmute(vals); - let mut tmp = [0_u64; 6]; - vst1q_u64_x3(tmp.as_mut_ptr().cast(), a); - let r: uint64x2x3_t = vld1q_u64_x3(tmp.as_ptr().cast()); - let out: [u64; 6] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u64, 6, uint64x2x3_t, vst1q_u64_x3, vld1q_u64_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_u64_x4() { - let vals: [u64; 8] = crate::array::from_fn(|i| i as u64); - let a: uint64x2x4_t = transmute(vals); - let mut tmp = [0_u64; 8]; - vst1q_u64_x4(tmp.as_mut_ptr().cast(), a); - let r: uint64x2x4_t = vld1q_u64_x4(tmp.as_ptr().cast()); - let out: [u64; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(u64, 8, uint64x2x4_t, vst1q_u64_x4, vld1q_u64_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_p8_x2() { - let vals: [p8; 16] = crate::array::from_fn(|i| i as p8); - let a: poly8x8x2_t = transmute(vals); - let mut tmp = [0 as p8; 16]; - vst1_p8_x2(tmp.as_mut_ptr().cast(), a); - let r: poly8x8x2_t = vld1_p8_x2(tmp.as_ptr().cast()); - let out: [p8; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p8, 16, poly8x8x2_t, vst1_p8_x2, vld1_p8_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_p8_x3() { - let vals: [p8; 24] = crate::array::from_fn(|i| i as p8); - let a: poly8x8x3_t = transmute(vals); - let mut tmp = [0 as p8; 24]; - vst1_p8_x3(tmp.as_mut_ptr().cast(), a); - let r: poly8x8x3_t = vld1_p8_x3(tmp.as_ptr().cast()); - let out: [p8; 24] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p8, 24, poly8x8x3_t, vst1_p8_x3, vld1_p8_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_p8_x4() { - let vals: [p8; 32] = crate::array::from_fn(|i| i as p8); - let a: poly8x8x4_t = transmute(vals); - let mut tmp = [0 as p8; 32]; - vst1_p8_x4(tmp.as_mut_ptr().cast(), a); - let r: poly8x8x4_t = vld1_p8_x4(tmp.as_ptr().cast()); - let out: [p8; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p8, 32, poly8x8x4_t, vst1_p8_x4, vld1_p8_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_p8_x2() { - let vals: [p8; 32] = crate::array::from_fn(|i| i as p8); - let a: poly8x16x2_t = transmute(vals); - let mut tmp = [0 as p8; 32]; - vst1q_p8_x2(tmp.as_mut_ptr().cast(), a); - let r: poly8x16x2_t = vld1q_p8_x2(tmp.as_ptr().cast()); - let out: [p8; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p8, 32, poly8x16x2_t, vst1q_p8_x2, vld1q_p8_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_p8_x3() { - let vals: [p8; 48] = crate::array::from_fn(|i| i as p8); - let a: poly8x16x3_t = transmute(vals); - let mut tmp = [0 as p8; 48]; - vst1q_p8_x3(tmp.as_mut_ptr().cast(), a); - let r: poly8x16x3_t = vld1q_p8_x3(tmp.as_ptr().cast()); - let out: [p8; 48] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p8, 48, poly8x16x3_t, vst1q_p8_x3, vld1q_p8_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_p8_x4() { - let vals: [p8; 64] = crate::array::from_fn(|i| i as p8); - let a: poly8x16x4_t = transmute(vals); - let mut tmp = [0 as p8; 64]; - vst1q_p8_x4(tmp.as_mut_ptr().cast(), a); - let r: poly8x16x4_t = vld1q_p8_x4(tmp.as_ptr().cast()); - let out: [p8; 64] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p8, 64, poly8x16x4_t, vst1q_p8_x4, vld1q_p8_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1_p16_x2() { - let vals: [p16; 8] = crate::array::from_fn(|i| i as p16); - let a: poly16x4x2_t = transmute(vals); - let mut tmp = [0 as p16; 8]; - vst1_p16_x2(tmp.as_mut_ptr().cast(), a); - let r: poly16x4x2_t = vld1_p16_x2(tmp.as_ptr().cast()); - let out: [p16; 8] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p16, 8, poly16x4x2_t, vst1_p16_x2, vld1_p16_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1_p16_x3() { - let vals: [p16; 12] = crate::array::from_fn(|i| i as p16); - let a: poly16x4x3_t = transmute(vals); - let mut tmp = [0 as p16; 12]; - vst1_p16_x3(tmp.as_mut_ptr().cast(), a); - let r: poly16x4x3_t = vld1_p16_x3(tmp.as_ptr().cast()); - let out: [p16; 12] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p16, 12, poly16x4x3_t, vst1_p16_x3, vld1_p16_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1_p16_x4() { - let vals: [p16; 16] = crate::array::from_fn(|i| i as p16); - let a: poly16x4x4_t = transmute(vals); - let mut tmp = [0 as p16; 16]; - vst1_p16_x4(tmp.as_mut_ptr().cast(), a); - let r: poly16x4x4_t = vld1_p16_x4(tmp.as_ptr().cast()); - let out: [p16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p16, 16, poly16x4x4_t, vst1_p16_x4, vld1_p16_x4); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_p16_x2() { - let vals: [p16; 16] = crate::array::from_fn(|i| i as p16); - let a: poly16x8x2_t = transmute(vals); - let mut tmp = [0 as p16; 16]; - vst1q_p16_x2(tmp.as_mut_ptr().cast(), a); - let r: poly16x8x2_t = vld1q_p16_x2(tmp.as_ptr().cast()); - let out: [p16; 16] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p16, 16, poly16x8x2_t, vst1q_p16_x2, vld1q_p16_x2); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_p16_x3() { - let vals: [p16; 24] = crate::array::from_fn(|i| i as p16); - let a: poly16x8x3_t = transmute(vals); - let mut tmp = [0 as p16; 24]; - vst1q_p16_x3(tmp.as_mut_ptr().cast(), a); - let r: poly16x8x3_t = vld1q_p16_x3(tmp.as_ptr().cast()); - let out: [p16; 24] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p16, 24, poly16x8x3_t, vst1q_p16_x3, vld1q_p16_x3); } #[simd_test(enable = "neon")] unsafe fn test_vld1q_p16_x4() { - let vals: [p16; 32] = crate::array::from_fn(|i| i as p16); - let a: poly16x8x4_t = transmute(vals); - let mut tmp = [0 as p16; 32]; - vst1q_p16_x4(tmp.as_mut_ptr().cast(), a); - let r: poly16x8x4_t = vld1q_p16_x4(tmp.as_ptr().cast()); - let out: [p16; 32] = transmute(r); - assert_eq!(out, vals); + wide_store_load_roundtrip!(p16, 32, poly16x8x4_t, vst1q_p16_x4, vld1q_p16_x4); } } From 794810f897559a86d2de36344e13ad3c065d5217 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 1 Feb 2026 14:17:35 +0100 Subject: [PATCH 355/978] use more capable macro for wide store/load roundtrip tests --- .../crates/core_arch/src/aarch64/neon/mod.rs | 532 +++++------------- 1 file changed, 140 insertions(+), 392 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs index ee27bef9738c..580f203ef066 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs @@ -1006,400 +1006,148 @@ mod tests { }; } - #[simd_test(enable = "neon,fp16")] - #[cfg(not(target_arch = "arm64ec"))] - unsafe fn test_vld1_f16_x2() { - wide_store_load_roundtrip!(f16, 8, float16x4x2_t, vst1_f16_x2, vld1_f16_x2); - } - - #[simd_test(enable = "neon,fp16")] - #[cfg(not(target_arch = "arm64ec"))] - unsafe fn test_vld1_f16_x3() { - wide_store_load_roundtrip!(f16, 12, float16x4x3_t, vst1_f16_x3, vld1_f16_x3); - } - - #[simd_test(enable = "neon,fp16")] - #[cfg(not(target_arch = "arm64ec"))] - unsafe fn test_vld1_f16_x4() { - wide_store_load_roundtrip!(f16, 16, float16x4x4_t, vst1_f16_x4, vld1_f16_x4); - } - - #[simd_test(enable = "neon,fp16")] - #[cfg(not(target_arch = "arm64ec"))] - unsafe fn test_vld1q_f16_x2() { - wide_store_load_roundtrip!(f16, 16, float16x8x2_t, vst1q_f16_x2, vld1q_f16_x2); - } - - #[simd_test(enable = "neon,fp16")] - #[cfg(not(target_arch = "arm64ec"))] - unsafe fn test_vld1q_f16_x3() { - wide_store_load_roundtrip!(f16, 24, float16x8x3_t, vst1q_f16_x3, vld1q_f16_x3); - } - - #[simd_test(enable = "neon,fp16")] - #[cfg(not(target_arch = "arm64ec"))] - unsafe fn test_vld1q_f16_x4() { - wide_store_load_roundtrip!(f16, 32, float16x8x4_t, vst1q_f16_x4, vld1q_f16_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_f32_x2() { - wide_store_load_roundtrip!(f32, 4, float32x2x2_t, vst1_f32_x2, vld1_f32_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_f32_x3() { - wide_store_load_roundtrip!(f32, 6, float32x2x3_t, vst1_f32_x3, vld1_f32_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_f32_x4() { - wide_store_load_roundtrip!(f32, 8, float32x2x4_t, vst1_f32_x4, vld1_f32_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_f32_x2() { - wide_store_load_roundtrip!(f32, 8, float32x4x2_t, vst1q_f32_x2, vld1q_f32_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_f32_x3() { - wide_store_load_roundtrip!(f32, 12, float32x4x3_t, vst1q_f32_x3, vld1q_f32_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_f32_x4() { - wide_store_load_roundtrip!(f32, 16, float32x4x4_t, vst1q_f32_x4, vld1q_f32_x4); - } - - #[simd_test(enable = "neon,aes")] - unsafe fn test_vld1_p64_x2() { - wide_store_load_roundtrip!(p64, 2, poly64x1x2_t, vst1_p64_x2, vld1_p64_x2); - } - - #[simd_test(enable = "neon,aes")] - unsafe fn test_vld1_p64_x3() { - wide_store_load_roundtrip!(p64, 3, poly64x1x3_t, vst1_p64_x3, vld1_p64_x3); - } - - #[simd_test(enable = "neon,aes")] - unsafe fn test_vld1_p64_x4() { - wide_store_load_roundtrip!(p64, 4, poly64x1x4_t, vst1_p64_x4, vld1_p64_x4); - } - - #[simd_test(enable = "neon,aes")] - unsafe fn test_vld1q_p64_x2() { - wide_store_load_roundtrip!(p64, 4, poly64x2x2_t, vst1q_p64_x2, vld1q_p64_x2); - } - - #[simd_test(enable = "neon,aes")] - unsafe fn test_vld1q_p64_x3() { - wide_store_load_roundtrip!(p64, 6, poly64x2x3_t, vst1q_p64_x3, vld1q_p64_x3); - } - - #[simd_test(enable = "neon,aes")] - unsafe fn test_vld1q_p64_x4() { - wide_store_load_roundtrip!(p64, 8, poly64x2x4_t, vst1q_p64_x4, vld1q_p64_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s8_x2() { - wide_store_load_roundtrip!(i8, 16, int8x8x2_t, vst1_s8_x2, vld1_s8_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s8_x3() { - wide_store_load_roundtrip!(i8, 24, int8x8x3_t, vst1_s8_x3, vld1_s8_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s8_x4() { - wide_store_load_roundtrip!(i8, 32, int8x8x4_t, vst1_s8_x4, vld1_s8_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s8_x2() { - wide_store_load_roundtrip!(i8, 32, int8x16x2_t, vst1q_s8_x2, vld1q_s8_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s8_x3() { - wide_store_load_roundtrip!(i8, 48, int8x16x3_t, vst1q_s8_x3, vld1q_s8_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s8_x4() { - wide_store_load_roundtrip!(i8, 64, int8x16x4_t, vst1q_s8_x4, vld1q_s8_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s16_x2() { - wide_store_load_roundtrip!(i16, 8, int16x4x2_t, vst1_s16_x2, vld1_s16_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s16_x3() { - wide_store_load_roundtrip!(i16, 12, int16x4x3_t, vst1_s16_x3, vld1_s16_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s16_x4() { - wide_store_load_roundtrip!(i16, 16, int16x4x4_t, vst1_s16_x4, vld1_s16_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s16_x2() { - wide_store_load_roundtrip!(i16, 16, int16x8x2_t, vst1q_s16_x2, vld1q_s16_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s16_x3() { - wide_store_load_roundtrip!(i16, 24, int16x8x3_t, vst1q_s16_x3, vld1q_s16_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s16_x4() { - wide_store_load_roundtrip!(i16, 32, int16x8x4_t, vst1q_s16_x4, vld1q_s16_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s32_x2() { - wide_store_load_roundtrip!(i32, 4, int32x2x2_t, vst1_s32_x2, vld1_s32_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s32_x3() { - wide_store_load_roundtrip!(i32, 6, int32x2x3_t, vst1_s32_x3, vld1_s32_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s32_x4() { - wide_store_load_roundtrip!(i32, 8, int32x2x4_t, vst1_s32_x4, vld1_s32_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s32_x2() { - wide_store_load_roundtrip!(i32, 8, int32x4x2_t, vst1q_s32_x2, vld1q_s32_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s32_x3() { - wide_store_load_roundtrip!(i32, 12, int32x4x3_t, vst1q_s32_x3, vld1q_s32_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s32_x4() { - wide_store_load_roundtrip!(i32, 16, int32x4x4_t, vst1q_s32_x4, vld1q_s32_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s64_x2() { - wide_store_load_roundtrip!(i64, 2, int64x1x2_t, vst1_s64_x2, vld1_s64_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s64_x3() { - wide_store_load_roundtrip!(i64, 3, int64x1x3_t, vst1_s64_x3, vld1_s64_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_s64_x4() { - wide_store_load_roundtrip!(i64, 4, int64x1x4_t, vst1_s64_x4, vld1_s64_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s64_x2() { - wide_store_load_roundtrip!(i64, 4, int64x2x2_t, vst1q_s64_x2, vld1q_s64_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s64_x3() { - wide_store_load_roundtrip!(i64, 6, int64x2x3_t, vst1q_s64_x3, vld1q_s64_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_s64_x4() { - wide_store_load_roundtrip!(i64, 8, int64x2x4_t, vst1q_s64_x4, vld1q_s64_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u8_x2() { - wide_store_load_roundtrip!(u8, 16, uint8x8x2_t, vst1_u8_x2, vld1_u8_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u8_x3() { - wide_store_load_roundtrip!(u8, 24, uint8x8x3_t, vst1_u8_x3, vld1_u8_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u8_x4() { - wide_store_load_roundtrip!(u8, 32, uint8x8x4_t, vst1_u8_x4, vld1_u8_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u8_x2() { - wide_store_load_roundtrip!(u8, 32, uint8x16x2_t, vst1q_u8_x2, vld1q_u8_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u8_x3() { - wide_store_load_roundtrip!(u8, 48, uint8x16x3_t, vst1q_u8_x3, vld1q_u8_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u8_x4() { - wide_store_load_roundtrip!(u8, 64, uint8x16x4_t, vst1q_u8_x4, vld1q_u8_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u16_x2() { - wide_store_load_roundtrip!(u16, 8, uint16x4x2_t, vst1_u16_x2, vld1_u16_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u16_x3() { - wide_store_load_roundtrip!(u16, 12, uint16x4x3_t, vst1_u16_x3, vld1_u16_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u16_x4() { - wide_store_load_roundtrip!(u16, 16, uint16x4x4_t, vst1_u16_x4, vld1_u16_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u16_x2() { - wide_store_load_roundtrip!(u16, 16, uint16x8x2_t, vst1q_u16_x2, vld1q_u16_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u16_x3() { - wide_store_load_roundtrip!(u16, 24, uint16x8x3_t, vst1q_u16_x3, vld1q_u16_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u16_x4() { - wide_store_load_roundtrip!(u16, 32, uint16x8x4_t, vst1q_u16_x4, vld1q_u16_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u32_x2() { - wide_store_load_roundtrip!(u32, 4, uint32x2x2_t, vst1_u32_x2, vld1_u32_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u32_x3() { - wide_store_load_roundtrip!(u32, 6, uint32x2x3_t, vst1_u32_x3, vld1_u32_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u32_x4() { - wide_store_load_roundtrip!(u32, 8, uint32x2x4_t, vst1_u32_x4, vld1_u32_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u32_x2() { - wide_store_load_roundtrip!(u32, 8, uint32x4x2_t, vst1q_u32_x2, vld1q_u32_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u32_x3() { - wide_store_load_roundtrip!(u32, 12, uint32x4x3_t, vst1q_u32_x3, vld1q_u32_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u32_x4() { - wide_store_load_roundtrip!(u32, 16, uint32x4x4_t, vst1q_u32_x4, vld1q_u32_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u64_x2() { - wide_store_load_roundtrip!(u64, 2, uint64x1x2_t, vst1_u64_x2, vld1_u64_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u64_x3() { - wide_store_load_roundtrip!(u64, 3, uint64x1x3_t, vst1_u64_x3, vld1_u64_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_u64_x4() { - wide_store_load_roundtrip!(u64, 4, uint64x1x4_t, vst1_u64_x4, vld1_u64_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u64_x2() { - wide_store_load_roundtrip!(u64, 4, uint64x2x2_t, vst1q_u64_x2, vld1q_u64_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u64_x3() { - wide_store_load_roundtrip!(u64, 6, uint64x2x3_t, vst1q_u64_x3, vld1q_u64_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_u64_x4() { - wide_store_load_roundtrip!(u64, 8, uint64x2x4_t, vst1q_u64_x4, vld1q_u64_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_p8_x2() { - wide_store_load_roundtrip!(p8, 16, poly8x8x2_t, vst1_p8_x2, vld1_p8_x2); - } + macro_rules! wide_store_load_roundtrip_fp16 { + ($( $name:ident $args:tt);* $(;)?) => { + $( + #[simd_test(enable = "neon,fp16")] + #[cfg(not(target_arch = "arm64ec"))] + unsafe fn $name() { + wide_store_load_roundtrip! $args; + } + )* + }; + } + + wide_store_load_roundtrip_fp16! { + test_vld1_f16_x2(f16, 8, float16x4x2_t, vst1_f16_x2, vld1_f16_x2); + test_vld1_f16_x3(f16, 12, float16x4x3_t, vst1_f16_x3, vld1_f16_x3); + test_vld1_f16_x4(f16, 16, float16x4x4_t, vst1_f16_x4, vld1_f16_x4); + + test_vld1q_f16_x2(f16, 16, float16x8x2_t, vst1q_f16_x2, vld1q_f16_x2); + test_vld1q_f16_x3(f16, 24, float16x8x3_t, vst1q_f16_x3, vld1q_f16_x3); + test_vld1q_f16_x4(f16, 32, float16x8x4_t, vst1q_f16_x4, vld1q_f16_x4); + } + + macro_rules! wide_store_load_roundtrip_aes { + ($( $name:ident $args:tt);* $(;)?) => { + $( + #[simd_test(enable = "neon,aes")] + unsafe fn $name() { + wide_store_load_roundtrip! $args; + } + )* + }; + } + + wide_store_load_roundtrip_aes! { + test_vld1_p64_x2(p64, 2, poly64x1x2_t, vst1_p64_x2, vld1_p64_x2); + test_vld1_p64_x3(p64, 3, poly64x1x3_t, vst1_p64_x3, vld1_p64_x3); + test_vld1_p64_x4(p64, 4, poly64x1x4_t, vst1_p64_x4, vld1_p64_x4); + + test_vld1q_p64_x2(p64, 4, poly64x2x2_t, vst1q_p64_x2, vld1q_p64_x2); + test_vld1q_p64_x3(p64, 6, poly64x2x3_t, vst1q_p64_x3, vld1q_p64_x3); + test_vld1q_p64_x4(p64, 8, poly64x2x4_t, vst1q_p64_x4, vld1q_p64_x4); + } + + macro_rules! wide_store_load_roundtrip_neon { + ($( $name:ident $args:tt);* $(;)?) => { + $( + #[simd_test(enable = "neon")] + unsafe fn $name() { + wide_store_load_roundtrip! $args; + } + )* + }; + } + + wide_store_load_roundtrip_neon! { + test_vld1_f32_x2(f32, 4, float32x2x2_t, vst1_f32_x2, vld1_f32_x2); + test_vld1_f32_x3(f32, 6, float32x2x3_t, vst1_f32_x3, vld1_f32_x3); + test_vld1_f32_x4(f32, 8, float32x2x4_t, vst1_f32_x4, vld1_f32_x4); + + test_vld1q_f32_x2(f32, 8, float32x4x2_t, vst1q_f32_x2, vld1q_f32_x2); + test_vld1q_f32_x3(f32, 12, float32x4x3_t, vst1q_f32_x3, vld1q_f32_x3); + test_vld1q_f32_x4(f32, 16, float32x4x4_t, vst1q_f32_x4, vld1q_f32_x4); + + test_vld1_s8_x2(i8, 16, int8x8x2_t, vst1_s8_x2, vld1_s8_x2); + test_vld1_s8_x3(i8, 24, int8x8x3_t, vst1_s8_x3, vld1_s8_x3); + test_vld1_s8_x4(i8, 32, int8x8x4_t, vst1_s8_x4, vld1_s8_x4); + + test_vld1q_s8_x2(i8, 32, int8x16x2_t, vst1q_s8_x2, vld1q_s8_x2); + test_vld1q_s8_x3(i8, 48, int8x16x3_t, vst1q_s8_x3, vld1q_s8_x3); + test_vld1q_s8_x4(i8, 64, int8x16x4_t, vst1q_s8_x4, vld1q_s8_x4); + + test_vld1_s16_x2(i16, 8, int16x4x2_t, vst1_s16_x2, vld1_s16_x2); + test_vld1_s16_x3(i16, 12, int16x4x3_t, vst1_s16_x3, vld1_s16_x3); + test_vld1_s16_x4(i16, 16, int16x4x4_t, vst1_s16_x4, vld1_s16_x4); + + test_vld1q_s16_x2(i16, 16, int16x8x2_t, vst1q_s16_x2, vld1q_s16_x2); + test_vld1q_s16_x3(i16, 24, int16x8x3_t, vst1q_s16_x3, vld1q_s16_x3); + test_vld1q_s16_x4(i16, 32, int16x8x4_t, vst1q_s16_x4, vld1q_s16_x4); + + test_vld1_s32_x2(i32, 4, int32x2x2_t, vst1_s32_x2, vld1_s32_x2); + test_vld1_s32_x3(i32, 6, int32x2x3_t, vst1_s32_x3, vld1_s32_x3); + test_vld1_s32_x4(i32, 8, int32x2x4_t, vst1_s32_x4, vld1_s32_x4); + + test_vld1q_s32_x2(i32, 8, int32x4x2_t, vst1q_s32_x2, vld1q_s32_x2); + test_vld1q_s32_x3(i32, 12, int32x4x3_t, vst1q_s32_x3, vld1q_s32_x3); + test_vld1q_s32_x4(i32, 16, int32x4x4_t, vst1q_s32_x4, vld1q_s32_x4); + + test_vld1_s64_x2(i64, 2, int64x1x2_t, vst1_s64_x2, vld1_s64_x2); + test_vld1_s64_x3(i64, 3, int64x1x3_t, vst1_s64_x3, vld1_s64_x3); + test_vld1_s64_x4(i64, 4, int64x1x4_t, vst1_s64_x4, vld1_s64_x4); + + test_vld1q_s64_x2(i64, 4, int64x2x2_t, vst1q_s64_x2, vld1q_s64_x2); + test_vld1q_s64_x3(i64, 6, int64x2x3_t, vst1q_s64_x3, vld1q_s64_x3); + test_vld1q_s64_x4(i64, 8, int64x2x4_t, vst1q_s64_x4, vld1q_s64_x4); + + test_vld1_u8_x2(u8, 16, uint8x8x2_t, vst1_u8_x2, vld1_u8_x2); + test_vld1_u8_x3(u8, 24, uint8x8x3_t, vst1_u8_x3, vld1_u8_x3); + test_vld1_u8_x4(u8, 32, uint8x8x4_t, vst1_u8_x4, vld1_u8_x4); + + test_vld1q_u8_x2(u8, 32, uint8x16x2_t, vst1q_u8_x2, vld1q_u8_x2); + test_vld1q_u8_x3(u8, 48, uint8x16x3_t, vst1q_u8_x3, vld1q_u8_x3); + test_vld1q_u8_x4(u8, 64, uint8x16x4_t, vst1q_u8_x4, vld1q_u8_x4); + + test_vld1_u16_x2(u16, 8, uint16x4x2_t, vst1_u16_x2, vld1_u16_x2); + test_vld1_u16_x3(u16, 12, uint16x4x3_t, vst1_u16_x3, vld1_u16_x3); + test_vld1_u16_x4(u16, 16, uint16x4x4_t, vst1_u16_x4, vld1_u16_x4); + + test_vld1q_u16_x2(u16, 16, uint16x8x2_t, vst1q_u16_x2, vld1q_u16_x2); + test_vld1q_u16_x3(u16, 24, uint16x8x3_t, vst1q_u16_x3, vld1q_u16_x3); + test_vld1q_u16_x4(u16, 32, uint16x8x4_t, vst1q_u16_x4, vld1q_u16_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1_p8_x3() { - wide_store_load_roundtrip!(p8, 24, poly8x8x3_t, vst1_p8_x3, vld1_p8_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_p8_x4() { - wide_store_load_roundtrip!(p8, 32, poly8x8x4_t, vst1_p8_x4, vld1_p8_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p8_x2() { - wide_store_load_roundtrip!(p8, 32, poly8x16x2_t, vst1q_p8_x2, vld1q_p8_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p8_x3() { - wide_store_load_roundtrip!(p8, 48, poly8x16x3_t, vst1q_p8_x3, vld1q_p8_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p8_x4() { - wide_store_load_roundtrip!(p8, 64, poly8x16x4_t, vst1q_p8_x4, vld1q_p8_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_p16_x2() { - wide_store_load_roundtrip!(p16, 8, poly16x4x2_t, vst1_p16_x2, vld1_p16_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_p16_x3() { - wide_store_load_roundtrip!(p16, 12, poly16x4x3_t, vst1_p16_x3, vld1_p16_x3); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1_p16_x4() { - wide_store_load_roundtrip!(p16, 16, poly16x4x4_t, vst1_p16_x4, vld1_p16_x4); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p16_x2() { - wide_store_load_roundtrip!(p16, 16, poly16x8x2_t, vst1q_p16_x2, vld1q_p16_x2); - } - - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p16_x3() { - wide_store_load_roundtrip!(p16, 24, poly16x8x3_t, vst1q_p16_x3, vld1q_p16_x3); - } + test_vld1_u32_x2(u32, 4, uint32x2x2_t, vst1_u32_x2, vld1_u32_x2); + test_vld1_u32_x3(u32, 6, uint32x2x3_t, vst1_u32_x3, vld1_u32_x3); + test_vld1_u32_x4(u32, 8, uint32x2x4_t, vst1_u32_x4, vld1_u32_x4); + + test_vld1q_u32_x2(u32, 8, uint32x4x2_t, vst1q_u32_x2, vld1q_u32_x2); + test_vld1q_u32_x3(u32, 12, uint32x4x3_t, vst1q_u32_x3, vld1q_u32_x3); + test_vld1q_u32_x4(u32, 16, uint32x4x4_t, vst1q_u32_x4, vld1q_u32_x4); + + test_vld1_u64_x2(u64, 2, uint64x1x2_t, vst1_u64_x2, vld1_u64_x2); + test_vld1_u64_x3(u64, 3, uint64x1x3_t, vst1_u64_x3, vld1_u64_x3); + test_vld1_u64_x4(u64, 4, uint64x1x4_t, vst1_u64_x4, vld1_u64_x4); + + test_vld1q_u64_x2(u64, 4, uint64x2x2_t, vst1q_u64_x2, vld1q_u64_x2); + test_vld1q_u64_x3(u64, 6, uint64x2x3_t, vst1q_u64_x3, vld1q_u64_x3); + test_vld1q_u64_x4(u64, 8, uint64x2x4_t, vst1q_u64_x4, vld1q_u64_x4); + + test_vld1_p8_x2(p8, 16, poly8x8x2_t, vst1_p8_x2, vld1_p8_x2); + test_vld1_p8_x3(p8, 24, poly8x8x3_t, vst1_p8_x3, vld1_p8_x3); + test_vld1_p8_x4(p8, 32, poly8x8x4_t, vst1_p8_x4, vld1_p8_x4); - #[simd_test(enable = "neon")] - unsafe fn test_vld1q_p16_x4() { - wide_store_load_roundtrip!(p16, 32, poly16x8x4_t, vst1q_p16_x4, vld1q_p16_x4); + test_vld1q_p8_x2(p8, 32, poly8x16x2_t, vst1q_p8_x2, vld1q_p8_x2); + test_vld1q_p8_x3(p8, 48, poly8x16x3_t, vst1q_p8_x3, vld1q_p8_x3); + test_vld1q_p8_x4(p8, 64, poly8x16x4_t, vst1q_p8_x4, vld1q_p8_x4); + + test_vld1_p16_x2(p16, 8, poly16x4x2_t, vst1_p16_x2, vld1_p16_x2); + test_vld1_p16_x3(p16, 12, poly16x4x3_t, vst1_p16_x3, vld1_p16_x3); + test_vld1_p16_x4(p16, 16, poly16x4x4_t, vst1_p16_x4, vld1_p16_x4); + + test_vld1q_p16_x2(p16, 16, poly16x8x2_t, vst1q_p16_x2, vld1q_p16_x2); + test_vld1q_p16_x3(p16, 24, poly16x8x3_t, vst1q_p16_x3, vld1q_p16_x3); + test_vld1q_p16_x4(p16, 32, poly16x8x4_t, vst1q_p16_x4, vld1q_p16_x4); } } From 141a867b02e090c432895779812948f2c354efa7 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 1 Feb 2026 01:40:06 +0100 Subject: [PATCH 356/978] Revert "Use LLVM intrinsics for `madd` intrinsics" This reverts commit 32146718741ee22ff0d54d21b9ab60353014c980. --- .../stdarch/crates/core_arch/src/x86/avx2.rs | 26 +++----- .../crates/core_arch/src/x86/avx512bw.rs | 64 ++++++++++--------- .../stdarch/crates/core_arch/src/x86/sse2.rs | 26 +++----- 3 files changed, 53 insertions(+), 63 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index 83aef753c9d9..8e9a56bb8518 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -1841,20 +1841,14 @@ pub const fn _mm256_inserti128_si256(a: __m256i, b: __m128i) -> #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpmaddwd))] #[stable(feature = "simd_x86", since = "1.27.0")] -pub fn _mm256_madd_epi16(a: __m256i, b: __m256i) -> __m256i { - // It's a trick used in the Adler-32 algorithm to perform a widening addition. - // - // ```rust - // #[target_feature(enable = "avx2")] - // unsafe fn widening_add(mad: __m256i) -> __m256i { - // _mm256_madd_epi16(mad, _mm256_set1_epi16(1)) - // } - // ``` - // - // If we implement this using generic vector intrinsics, the optimizer - // will eliminate this pattern, and `vpmaddwd` will no longer be emitted. - // For this reason, we use x86 intrinsics. - unsafe { transmute(pmaddwd(a.as_i16x16(), b.as_i16x16())) } +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm256_madd_epi16(a: __m256i, b: __m256i) -> __m256i { + unsafe { + let r: i32x16 = simd_mul(simd_cast(a.as_i16x16()), simd_cast(b.as_i16x16())); + let even: i32x8 = simd_shuffle!(r, r, [0, 2, 4, 6, 8, 10, 12, 14]); + let odd: i32x8 = simd_shuffle!(r, r, [1, 3, 5, 7, 9, 11, 13, 15]); + simd_add(even, odd).as_m256i() + } } /// Vertically multiplies each unsigned 8-bit integer from `a` with the @@ -3819,8 +3813,6 @@ pub const fn _mm256_extract_epi16(a: __m256i) -> i32 { #[allow(improper_ctypes)] unsafe extern "C" { - #[link_name = "llvm.x86.avx2.pmadd.wd"] - fn pmaddwd(a: i16x16, b: i16x16) -> i32x8; #[link_name = "llvm.x86.avx2.pmadd.ub.sw"] fn pmaddubsw(a: u8x32, b: i8x32) -> i16x16; #[link_name = "llvm.x86.avx2.mpsadbw"] @@ -4669,7 +4661,7 @@ mod tests { } #[simd_test(enable = "avx2")] - fn test_mm256_madd_epi16() { + const fn test_mm256_madd_epi16() { let a = _mm256_set1_epi16(2); let b = _mm256_set1_epi16(4); let r = _mm256_madd_epi16(a, b); diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs index 8e074fdcfa48..e2d12cd97264 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs @@ -6321,20 +6321,22 @@ pub const unsafe fn _mm_mask_storeu_epi8(mem_addr: *mut i8, mask: __mmask16, a: #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -pub fn _mm512_madd_epi16(a: __m512i, b: __m512i) -> __m512i { - // It's a trick used in the Adler-32 algorithm to perform a widening addition. - // - // ```rust - // #[target_feature(enable = "avx512bw")] - // unsafe fn widening_add(mad: __m512i) -> __m512i { - // _mm512_madd_epi16(mad, _mm512_set1_epi16(1)) - // } - // ``` - // - // If we implement this using generic vector intrinsics, the optimizer - // will eliminate this pattern, and `vpmaddwd` will no longer be emitted. - // For this reason, we use x86 intrinsics. - unsafe { transmute(vpmaddwd(a.as_i16x32(), b.as_i16x32())) } +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm512_madd_epi16(a: __m512i, b: __m512i) -> __m512i { + unsafe { + let r: i32x32 = simd_mul(simd_cast(a.as_i16x32()), simd_cast(b.as_i16x32())); + let even: i32x16 = simd_shuffle!( + r, + r, + [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30] + ); + let odd: i32x16 = simd_shuffle!( + r, + r, + [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31] + ); + simd_add(even, odd).as_m512i() + } } /// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -6344,7 +6346,8 @@ pub fn _mm512_madd_epi16(a: __m512i, b: __m512i) -> __m512i { #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -pub fn _mm512_mask_madd_epi16(src: __m512i, k: __mmask16, a: __m512i, b: __m512i) -> __m512i { +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm512_mask_madd_epi16(src: __m512i, k: __mmask16, a: __m512i, b: __m512i) -> __m512i { unsafe { let madd = _mm512_madd_epi16(a, b).as_i32x16(); transmute(simd_select_bitmask(k, madd, src.as_i32x16())) @@ -6358,7 +6361,8 @@ pub fn _mm512_mask_madd_epi16(src: __m512i, k: __mmask16, a: __m512i, b: __m512i #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -pub fn _mm512_maskz_madd_epi16(k: __mmask16, a: __m512i, b: __m512i) -> __m512i { +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm512_maskz_madd_epi16(k: __mmask16, a: __m512i, b: __m512i) -> __m512i { unsafe { let madd = _mm512_madd_epi16(a, b).as_i32x16(); transmute(simd_select_bitmask(k, madd, i32x16::ZERO)) @@ -6372,7 +6376,8 @@ pub fn _mm512_maskz_madd_epi16(k: __mmask16, a: __m512i, b: __m512i) -> __m512i #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -pub fn _mm256_mask_madd_epi16(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm256_mask_madd_epi16(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { unsafe { let madd = _mm256_madd_epi16(a, b).as_i32x8(); transmute(simd_select_bitmask(k, madd, src.as_i32x8())) @@ -6386,7 +6391,8 @@ pub fn _mm256_mask_madd_epi16(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -pub fn _mm256_maskz_madd_epi16(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm256_maskz_madd_epi16(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { unsafe { let madd = _mm256_madd_epi16(a, b).as_i32x8(); transmute(simd_select_bitmask(k, madd, i32x8::ZERO)) @@ -6400,7 +6406,8 @@ pub fn _mm256_maskz_madd_epi16(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -pub fn _mm_mask_madd_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm_mask_madd_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { unsafe { let madd = _mm_madd_epi16(a, b).as_i32x4(); transmute(simd_select_bitmask(k, madd, src.as_i32x4())) @@ -6414,7 +6421,8 @@ pub fn _mm_mask_madd_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -pub fn _mm_maskz_madd_epi16(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm_maskz_madd_epi16(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { unsafe { let madd = _mm_madd_epi16(a, b).as_i32x4(); transmute(simd_select_bitmask(k, madd, i32x4::ZERO)) @@ -12574,8 +12582,6 @@ unsafe extern "C" { #[link_name = "llvm.x86.avx512.pmul.hr.sw.512"] fn vpmulhrsw(a: i16x32, b: i16x32) -> i16x32; - #[link_name = "llvm.x86.avx512.pmaddw.d.512"] - fn vpmaddwd(a: i16x32, b: i16x32) -> i32x16; #[link_name = "llvm.x86.avx512.pmaddubs.w.512"] fn vpmaddubsw(a: u8x64, b: i8x64) -> i16x32; @@ -17500,7 +17506,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - fn test_mm512_madd_epi16() { + const fn test_mm512_madd_epi16() { let a = _mm512_set1_epi16(1); let b = _mm512_set1_epi16(1); let r = _mm512_madd_epi16(a, b); @@ -17509,7 +17515,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - fn test_mm512_mask_madd_epi16() { + const fn test_mm512_mask_madd_epi16() { let a = _mm512_set1_epi16(1); let b = _mm512_set1_epi16(1); let r = _mm512_mask_madd_epi16(a, 0, a, b); @@ -17537,7 +17543,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - fn test_mm512_maskz_madd_epi16() { + const fn test_mm512_maskz_madd_epi16() { let a = _mm512_set1_epi16(1); let b = _mm512_set1_epi16(1); let r = _mm512_maskz_madd_epi16(0, a, b); @@ -17548,7 +17554,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - fn test_mm256_mask_madd_epi16() { + const fn test_mm256_mask_madd_epi16() { let a = _mm256_set1_epi16(1); let b = _mm256_set1_epi16(1); let r = _mm256_mask_madd_epi16(a, 0, a, b); @@ -17568,7 +17574,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - fn test_mm256_maskz_madd_epi16() { + const fn test_mm256_maskz_madd_epi16() { let a = _mm256_set1_epi16(1); let b = _mm256_set1_epi16(1); let r = _mm256_maskz_madd_epi16(0, a, b); @@ -17579,7 +17585,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - fn test_mm_mask_madd_epi16() { + const fn test_mm_mask_madd_epi16() { let a = _mm_set1_epi16(1); let b = _mm_set1_epi16(1); let r = _mm_mask_madd_epi16(a, 0, a, b); @@ -17590,7 +17596,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - fn test_mm_maskz_madd_epi16() { + const fn test_mm_maskz_madd_epi16() { let a = _mm_set1_epi16(1); let b = _mm_set1_epi16(1); let r = _mm_maskz_madd_epi16(0, a, b); diff --git a/library/stdarch/crates/core_arch/src/x86/sse2.rs b/library/stdarch/crates/core_arch/src/x86/sse2.rs index f339a003df4d..ecd478511b06 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse2.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse2.rs @@ -210,20 +210,14 @@ pub const fn _mm_avg_epu16(a: __m128i, b: __m128i) -> __m128i { #[target_feature(enable = "sse2")] #[cfg_attr(test, assert_instr(pmaddwd))] #[stable(feature = "simd_x86", since = "1.27.0")] -pub fn _mm_madd_epi16(a: __m128i, b: __m128i) -> __m128i { - // It's a trick used in the Adler-32 algorithm to perform a widening addition. - // - // ```rust - // #[target_feature(enable = "sse2")] - // unsafe fn widening_add(mad: __m128i) -> __m128i { - // _mm_madd_epi16(mad, _mm_set1_epi16(1)) - // } - // ``` - // - // If we implement this using generic vector intrinsics, the optimizer - // will eliminate this pattern, and `pmaddwd` will no longer be emitted. - // For this reason, we use x86 intrinsics. - unsafe { transmute(pmaddwd(a.as_i16x8(), b.as_i16x8())) } +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm_madd_epi16(a: __m128i, b: __m128i) -> __m128i { + unsafe { + let r: i32x8 = simd_mul(simd_cast(a.as_i16x8()), simd_cast(b.as_i16x8())); + let even: i32x4 = simd_shuffle!(r, r, [0, 2, 4, 6]); + let odd: i32x4 = simd_shuffle!(r, r, [1, 3, 5, 7]); + simd_add(even, odd).as_m128i() + } } /// Compares packed 16-bit integers in `a` and `b`, and returns the packed @@ -3193,8 +3187,6 @@ unsafe extern "C" { fn lfence(); #[link_name = "llvm.x86.sse2.mfence"] fn mfence(); - #[link_name = "llvm.x86.sse2.pmadd.wd"] - fn pmaddwd(a: i16x8, b: i16x8) -> i32x4; #[link_name = "llvm.x86.sse2.psad.bw"] fn psadbw(a: u8x16, b: u8x16) -> u64x2; #[link_name = "llvm.x86.sse2.psll.w"] @@ -3473,7 +3465,7 @@ mod tests { } #[simd_test(enable = "sse2")] - fn test_mm_madd_epi16() { + const fn test_mm_madd_epi16() { let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8); let b = _mm_setr_epi16(9, 10, 11, 12, 13, 14, 15, 16); let r = _mm_madd_epi16(a, b); From 55e3d2206a21aeb291cbaf6535579e2994d98d4a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 1 Feb 2026 15:05:57 +0100 Subject: [PATCH 357/978] Improve new proc-macro methods name --- library/proc_macro/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 2a75c4489095..18ab470f89d6 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -1445,9 +1445,9 @@ impl Literal { }) } - /// Returns the unescaped char value if the current literal is a char. + /// Returns the unescaped character value if the current literal is a byte character literal. #[unstable(feature = "proc_macro_value", issue = "136652")] - pub fn byte_value(&self) -> Result { + pub fn byte_character_value(&self) -> Result { self.0.symbol.with(|symbol| match self.0.kind { bridge::LitKind::Char => { unescape_byte(symbol).map_err(ConversionErrorKind::FailedToUnescape) @@ -1456,9 +1456,9 @@ impl Literal { }) } - /// Returns the unescaped char value if the current literal is a char. + /// Returns the unescaped character value if the current literal is a character literal. #[unstable(feature = "proc_macro_value", issue = "136652")] - pub fn char_value(&self) -> Result { + pub fn character_value(&self) -> Result { self.0.symbol.with(|symbol| match self.0.kind { bridge::LitKind::Char => { unescape_char(symbol).map_err(ConversionErrorKind::FailedToUnescape) From 990c55801ec129a1781c1b3915ff74bb85f9cdf1 Mon Sep 17 00:00:00 2001 From: mu001999 Date: Sun, 1 Feb 2026 19:17:28 +0800 Subject: [PATCH 358/978] Include assoc const projections in CFI trait object --- .../cfi/typeid/itanium_cxx_abi/transform.rs | 24 +++++++++---------- .../assoc-const-projection-issue-151878.rs | 20 ++++++++++++++++ 2 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index 9cea681fcb57..971ac9348fc4 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -243,24 +243,24 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc .flat_map(|super_poly_trait_ref| { tcx.associated_items(super_poly_trait_ref.def_id()) .in_definition_order() - .filter(|item| item.is_type()) + .filter(|item| item.is_type() || item.is_const()) .filter(|item| !tcx.generics_require_sized_self(item.def_id)) - .map(move |assoc_ty| { + .map(move |assoc_item| { super_poly_trait_ref.map_bound(|super_trait_ref| { - let alias_ty = - ty::AliasTy::new_from_args(tcx, assoc_ty.def_id, super_trait_ref.args); - let resolved = tcx.normalize_erasing_regions( - ty::TypingEnv::fully_monomorphized(), - alias_ty.to_ty(tcx), + let projection_term = ty::AliasTerm::new_from_args( + tcx, + assoc_item.def_id, + super_trait_ref.args, ); - debug!("Resolved {:?} -> {resolved}", alias_ty.to_ty(tcx)); + let term = tcx.normalize_erasing_regions( + ty::TypingEnv::fully_monomorphized(), + projection_term.to_term(tcx), + ); + debug!("Projection {:?} -> {term}", projection_term.to_term(tcx),); ty::ExistentialPredicate::Projection( ty::ExistentialProjection::erase_self_ty( tcx, - ty::ProjectionPredicate { - projection_term: alias_ty.into(), - term: resolved.into(), - }, + ty::ProjectionPredicate { projection_term, term }, ), ) }) diff --git a/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs b/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs new file mode 100644 index 000000000000..50530e4f0db0 --- /dev/null +++ b/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs @@ -0,0 +1,20 @@ +//@ compile-flags: -Zsanitizer=cfi -Cunsafe-allow-abi-mismatch=sanitizer -Ccodegen-units=1 -Clto +//@ needs-rustc-debug-assertions +//@ needs-sanitizer-cfi +//@ build-pass +//@ no-prefer-dynamic + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +trait Trait { + #[type_const] + const N: usize = 0; + fn process(&self, _: [u8; Self::N]) {} +} + +impl Trait for () {} + +fn main() { + let _x: &dyn Trait = &(); +} From f5540adde9c7a731b1a5bac4b8157975910a54d6 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 1 Feb 2026 01:52:52 +0100 Subject: [PATCH 359/978] add test for multiply by one pattern --- library/stdarch/crates/core_arch/src/x86/avx2.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index 8e9a56bb8518..e9463d433180 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -4669,6 +4669,16 @@ mod tests { assert_eq_m256i(r, e); } + #[target_feature(enable = "avx2")] + #[cfg_attr(test, assert_instr(vpmaddwd))] + unsafe fn test_mm256_madd_epi16_mul_one(mad: __m256i) -> __m256i { + // This is a trick used in the adler32 algorithm to get a widening addition. The + // multiplication by 1 is trivial, but must not be optimized out because then the vpmaddwd + // instruction is no longer selected. The assert_instr verifies that this is the case. + let one_v = _mm256_set1_epi16(1); + _mm256_madd_epi16(mad, one_v) + } + #[simd_test(enable = "avx2")] const fn test_mm256_inserti128_si256() { let a = _mm256_setr_epi64x(1, 2, 3, 4); From 2292d53b7b5dc3989167e753d3ac4422b321b426 Mon Sep 17 00:00:00 2001 From: ritik chahar Date: Sun, 1 Feb 2026 21:41:43 +0530 Subject: [PATCH 360/978] Add codegen test for SLP vectorization --- tests/codegen-llvm/slp-vectorization-mul3.rs | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tests/codegen-llvm/slp-vectorization-mul3.rs diff --git a/tests/codegen-llvm/slp-vectorization-mul3.rs b/tests/codegen-llvm/slp-vectorization-mul3.rs new file mode 100644 index 000000000000..a414192e6a1a --- /dev/null +++ b/tests/codegen-llvm/slp-vectorization-mul3.rs @@ -0,0 +1,23 @@ +// compile-flags: -O +#![crate_type = "lib"] + +// CHECK-LABEL: mul3 +// CHECK: %[[C_BPP:.*]] = phi <4 x i8> +// CHECK: %[[V:.*]] = load <4 x i8>, ptr +// CHECK: %[[ADD:.*]] = add <4 x i8> %[[V]], %[[C_BPP]] +// CHECK: store {{<4 x i8>|i32}} {{.*}}, ptr + +pub fn mul3(previous: &[u8], current: &mut [u8]) { + let mut c_bpp = [0u8; 4]; + + for (chunk, b_bpp) in current.chunks_exact_mut(4).zip(previous.chunks_exact(4)) { + let new_chunk = [ + chunk[0].wrapping_add(c_bpp[0]), + chunk[1].wrapping_add(c_bpp[1]), + chunk[2].wrapping_add(c_bpp[2]), + chunk[3].wrapping_add(c_bpp[3]), + ]; + chunk.copy_from_slice(&new_chunk); + c_bpp.copy_from_slice(b_bpp); + } +} \ No newline at end of file From 0a60bd653d3bd42752e4e454567ae5fcb96a2b49 Mon Sep 17 00:00:00 2001 From: ritik chahar Date: Sun, 1 Feb 2026 22:09:05 +0530 Subject: [PATCH 361/978] fix: remove trailing newline for tidy --- tests/codegen-llvm/slp-vectorization-mul3.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codegen-llvm/slp-vectorization-mul3.rs b/tests/codegen-llvm/slp-vectorization-mul3.rs index a414192e6a1a..7a69be5cafb7 100644 --- a/tests/codegen-llvm/slp-vectorization-mul3.rs +++ b/tests/codegen-llvm/slp-vectorization-mul3.rs @@ -20,4 +20,4 @@ pub fn mul3(previous: &[u8], current: &mut [u8]) { chunk.copy_from_slice(&new_chunk); c_bpp.copy_from_slice(b_bpp); } -} \ No newline at end of file +} From 1c396d24ddf97d556d41487234f6216b67461b7c Mon Sep 17 00:00:00 2001 From: ritik chahar Date: Sun, 1 Feb 2026 22:14:13 +0530 Subject: [PATCH 362/978] Restrict test to x86_64 per reviewer feedback --- tests/codegen-llvm/slp-vectorization-mul3.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/codegen-llvm/slp-vectorization-mul3.rs b/tests/codegen-llvm/slp-vectorization-mul3.rs index 7a69be5cafb7..bb4965c46bc0 100644 --- a/tests/codegen-llvm/slp-vectorization-mul3.rs +++ b/tests/codegen-llvm/slp-vectorization-mul3.rs @@ -1,4 +1,6 @@ -// compile-flags: -O +//@ only-x86_64 +//@ compile-flags: -O + #![crate_type = "lib"] // CHECK-LABEL: mul3 From caaee92855a64ae1f1e6cf93ce7ad29f1bd12241 Mon Sep 17 00:00:00 2001 From: Joshua Rayton Date: Tue, 23 Sep 2025 15:31:58 +0100 Subject: [PATCH 363/978] more float constants: sqrt(5), 1/sqrt(5) --- library/core/src/num/f128.rs | 11 +++++++++++ library/core/src/num/f16.rs | 10 ++++++++++ library/core/src/num/f32.rs | 8 ++++++++ library/core/src/num/f64.rs | 8 ++++++++ 4 files changed, 37 insertions(+) diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index cc142fab8e82..4630fd729c6a 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -108,6 +108,17 @@ pub mod consts { pub const FRAC_1_SQRT_3: f128 = 0.577350269189625764509148780501957455647601751270126876018602_f128; + /// sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + // Also, #[unstable(feature = "f128", issue = "116909")] + pub const SQRT_5: f128 = 2.23606797749978969640917366873127623544061835961152572427089_f128; + + /// 1/sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + // Also, #[unstable(feature = "f128", issue = "116909")] + pub const FRAC_1_SQRT_5: f128 = + 0.447213595499957939281834733746255247088123671922305144854179_f128; + /// Euler's number (e) #[unstable(feature = "f128", issue = "116909")] pub const E: f128 = 2.71828182845904523536028747135266249775724709369995957496697_f128; diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index e97a44e991f6..21ba8f1f2828 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -103,6 +103,16 @@ pub mod consts { // Also, #[unstable(feature = "more_float_constants", issue = "146939")] pub const FRAC_1_SQRT_3: f16 = 0.577350269189625764509148780501957456_f16; + /// sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + // Also, #[unstable(feature = "f16", issue = "116909")] + pub const SQRT_5: f16 = 2.23606797749978969640917366873127623_f16; + + /// 1/sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + // Also, #[unstable(feature = "f16", issue = "116909")] + pub const FRAC_1_SQRT_5: f16 = 0.44721359549995793928183473374625524_f16; + /// Euler's number (e) #[unstable(feature = "f16", issue = "116909")] pub const E: f16 = 2.71828182845904523536028747135266250_f16; diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 3d8249631037..c4ec774f5956 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -356,6 +356,14 @@ pub mod consts { #[unstable(feature = "more_float_constants", issue = "146939")] pub const FRAC_1_SQRT_3: f32 = 0.577350269189625764509148780501957456_f32; + /// sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + pub const SQRT_5: f32 = 2.23606797749978969640917366873127623_f32; + + /// 1/sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + pub const FRAC_1_SQRT_5: f32 = 0.44721359549995793928183473374625524_f32; + /// Euler's number (e) #[stable(feature = "rust1", since = "1.0.0")] pub const E: f32 = 2.71828182845904523536028747135266250_f32; diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 566a6a7ec947..0bb881323577 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -356,6 +356,14 @@ pub mod consts { #[unstable(feature = "more_float_constants", issue = "146939")] pub const FRAC_1_SQRT_3: f64 = 0.577350269189625764509148780501957456_f64; + /// sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + pub const SQRT_5: f64 = 2.23606797749978969640917366873127623_f64; + + /// 1/sqrt(5) + #[unstable(feature = "more_float_constants", issue = "146939")] + pub const FRAC_1_SQRT_5: f64 = 0.44721359549995793928183473374625524_f64; + /// Euler's number (e) #[stable(feature = "rust1", since = "1.0.0")] pub const E: f64 = 2.71828182845904523536028747135266250_f64; From 7b62d97abdd38850621153e806cc7b0ee6ab4289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 17 Jan 2026 00:19:20 +0000 Subject: [PATCH 364/978] Mention implicit bounds from `#[derive(Clone)]` on moved value When encountering a value that has a borrow checker error where the type was previously moved, when suggesting cloning verify that it is not already being derived. If it is, explain why the `derive(Clone)` doesn't apply: ``` note: if `TypedAddress` implemented `Clone`, you could clone the value --> $DIR/derive-clone-implicit-bound.rs:6:1 | LL | #[derive(Clone, Copy)] | ----- derived `Clone` adds implicit bounds on type parameters LL | pub struct TypedAddress{ | ^^^^^^^^^^^^^^^^^^^^^^^^-^ | | | | | introduces an implicit `T: Clone` bound | consider manually implementing `Clone` for this type ... LL | let old = self.return_value(offset); | ------ you could clone this value ``` --- .../src/diagnostics/conflict_errors.rs | 37 +++++++++++++++++- .../borrowck/derive-clone-implicit-bound.rs | 32 ++++++++++++++++ .../derive-clone-implicit-bound.stderr | 38 +++++++++++++++++++ 3 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 tests/ui/borrowck/derive-clone-implicit-bound.rs create mode 100644 tests/ui/borrowck/derive-clone-implicit-bound.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index caf6a86af098..692ce240e36f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1256,7 +1256,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning_inner(err, ty, expr); } } else if let ty::Adt(def, args) = ty.kind() - && def.did().as_local().is_some() + && let Some(local_did) = def.did().as_local() && def.variants().iter().all(|variant| { variant .fields @@ -1266,7 +1266,40 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { { let ty_span = self.infcx.tcx.def_span(def.did()); let mut span: MultiSpan = ty_span.into(); - span.push_span_label(ty_span, "consider implementing `Clone` for this type"); + let mut derive_clone = false; + self.infcx.tcx.for_each_relevant_impl( + self.infcx.tcx.lang_items().clone_trait().unwrap(), + ty, + |def_id| { + if self.infcx.tcx.is_automatically_derived(def_id) { + derive_clone = true; + span.push_span_label( + self.infcx.tcx.def_span(def_id), + "derived `Clone` adds implicit bounds on type parameters", + ); + if let Some(generics) = self.infcx.tcx.hir_get_generics(local_did) { + for param in generics.params { + if let hir::GenericParamKind::Type { .. } = param.kind { + span.push_span_label( + param.span, + format!( + "introduces an implicit `{}: Clone` bound", + param.name.ident() + ), + ); + } + } + } + } + }, + ); + span.push_span_label( + ty_span, + format!( + "consider {}implementing `Clone` for this type", + if derive_clone { "manually " } else { "" } + ), + ); span.push_span_label(expr.span, "you could clone this value"); err.span_note( span, diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.rs b/tests/ui/borrowck/derive-clone-implicit-bound.rs new file mode 100644 index 000000000000..a20e04d3afdc --- /dev/null +++ b/tests/ui/borrowck/derive-clone-implicit-bound.rs @@ -0,0 +1,32 @@ +// Issue #108894 + +use std::marker::PhantomData; + +#[derive(Clone, Copy)] //~ NOTE derived `Clone` adds implicit bounds on type parameters +pub struct TypedAddress{ +//~^ NOTE if `TypedAddress` implemented `Clone`, you could clone the value +//~| NOTE consider manually implementing `Clone` for this type +//~| NOTE introduces an implicit `T: Clone` bound + inner: u64, + phantom: PhantomData, +} + +pub trait Memory { + fn write_value(&self, offset: TypedAddress, value: &T); + fn return_value(&self, offset: TypedAddress) -> T; + //~^ NOTE consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary + //~| NOTE in this method + //~| NOTE this parameter takes ownership of the value + fn update_value(&self, offset: TypedAddress, update: F) + //~^ NOTE move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait + where F: FnOnce(T) -> T + { + let old = self.return_value(offset); //~ NOTE value moved here + //~^ NOTE you could clone this value + let new = update(old); + self.write_value(offset, &new); //~ ERROR use of moved value: `offset` + //~^ NOTE value used here after move + } +} + +fn main() {} diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.stderr b/tests/ui/borrowck/derive-clone-implicit-bound.stderr new file mode 100644 index 000000000000..b10e3a92c96b --- /dev/null +++ b/tests/ui/borrowck/derive-clone-implicit-bound.stderr @@ -0,0 +1,38 @@ +error[E0382]: use of moved value: `offset` + --> $DIR/derive-clone-implicit-bound.rs:27:26 + | +LL | fn update_value(&self, offset: TypedAddress, update: F) + | ------ move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait +... +LL | let old = self.return_value(offset); + | ------ value moved here +... +LL | self.write_value(offset, &new); + | ^^^^^^ value used here after move + | +note: consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary + --> $DIR/derive-clone-implicit-bound.rs:16:39 + | +LL | fn return_value(&self, offset: TypedAddress) -> T; + | ------------ in this method ^^^^^^^^^^^^^^^ this parameter takes ownership of the value +note: if `TypedAddress` implemented `Clone`, you could clone the value + --> $DIR/derive-clone-implicit-bound.rs:6:1 + | +LL | #[derive(Clone, Copy)] + | ----- derived `Clone` adds implicit bounds on type parameters +LL | pub struct TypedAddress{ + | ^^^^^^^^^^^^^^^^^^^^^^^^-^ + | | | + | | introduces an implicit `T: Clone` bound + | consider manually implementing `Clone` for this type +... +LL | let old = self.return_value(offset); + | ------ you could clone this value +help: consider further restricting type parameter `T` with trait `Copy` + | +LL | where F: FnOnce(T) -> T, T: Copy + | +++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. From 679f38c1259d96463c5f04f175846501fbca2a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 02:29:33 +0000 Subject: [PATCH 365/978] On E0277 pointing at bound in derive, suggest manual impl When encountering a bound coming from a derive macro, suggest manual impl of the trait. Use the span for the specific param when adding bounds in builtin derive macros, so the diagnostic will point at them as well as the derive macro itself. ``` error[E0277]: can't compare `SomeNode` with `SomeNode` --> f29.rs:24:15 | 24 | accept_eq(&node); | --------- ^^^^^ no implementation for `SomeNode == SomeNode` | | | required by a bound introduced by this call | = note: -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs:279:39 = help: the trait `PartialEq` is not implemented for `SomeNode` note: required for `Id` to implement `PartialEq` --> f29.rs:3:10 | 3 | #[derive(PartialEq, Eq)] | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro 4 | pub struct Id(PhantomData); | - = help: consider manually implementing `PartialEq` to avoid undesired bounds note: required by a bound in `accept_eq` --> f29.rs:15:23 | 15 | fn accept_eq(_: &impl PartialEq) { } | ^^^^^^^^^ required by this bound in `accept_eq` help: consider annotating `SomeNode` with `#[derive(PartialEq)]` | 13 + #[derive(PartialEq)] 14 | struct SomeNode(); | ``` --- .../src/deriving/generic/mod.rs | 18 +++++----- compiler/rustc_hir/src/hir.rs | 11 ++++-- compiler/rustc_middle/src/ty/diagnostics.rs | 15 ++++---- .../src/error_reporting/traits/suggestions.rs | 8 +++++ tests/ui/associated-types/issue-38821.stderr | 3 ++ .../unsizing-wfcheck-issue-126272.stderr | 6 +++- .../ui/consts/const-blocks/trait-error.stderr | 5 ++- tests/ui/derives/deriving-copyclone.stderr | 15 ++++++-- .../impl_bounds.stderr | 10 ++++-- .../issue-104884-trait-impl-sugg-err.stderr | 6 +++- ...missing-bound-in-derive-copy-impl-2.stderr | 2 ++ .../missing-bound-in-derive-copy-impl.stderr | 2 ++ tests/ui/traits/derive-implicit-bound.rs | 34 +++++++++++++++++++ tests/ui/traits/derive-implicit-bound.stderr | 31 +++++++++++++++++ 14 files changed, 140 insertions(+), 26 deletions(-) create mode 100644 tests/ui/traits/derive-implicit-bound.rs create mode 100644 tests/ui/traits/derive-implicit-bound.stderr diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index c2260a459097..665e0ddab194 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -638,27 +638,27 @@ impl<'a> TraitDef<'a> { GenericParamKind::Type { .. } => { // Extra restrictions on the generics parameters to the // type being derived upon. + let span = param.ident.span.with_ctxt(ctxt); let bounds: Vec<_> = self .additional_bounds .iter() .map(|p| { - cx.trait_bound( - p.to_path(cx, self.span, type_ident, generics), - self.is_const, - ) + cx.trait_bound(p.to_path(cx, span, type_ident, generics), self.is_const) }) .chain( // Add a bound for the current trait. - self.skip_path_as_bound - .not() - .then(|| cx.trait_bound(trait_path.clone(), self.is_const)), + self.skip_path_as_bound.not().then(|| { + let mut trait_path = trait_path.clone(); + trait_path.span = span; + cx.trait_bound(trait_path, self.is_const) + }), ) .chain({ // Add a `Copy` bound if required. if is_packed && self.needs_copy_as_bound_if_packed { let p = deriving::path_std!(marker::Copy); Some(cx.trait_bound( - p.to_path(cx, self.span, type_ident, generics), + p.to_path(cx, span, type_ident, generics), self.is_const, )) } else { @@ -671,7 +671,7 @@ impl<'a> TraitDef<'a> { ) .collect(); - cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, bounds, None) + cx.typaram(span, param.ident, bounds, None) } GenericParamKind::Const { ty, span, .. } => { let const_nodefault_kind = GenericParamKind::Const { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4c1bcffa1cf4..b117fa832729 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,6 +1,7 @@ // ignore-tidy-filelength use std::borrow::Cow; use std::fmt; +use std::ops::Not; use rustc_abi::ExternAbi; use rustc_ast::attr::AttributeExt; @@ -1012,10 +1013,14 @@ impl<'hir> Generics<'hir> { span_for_parentheses.map_or_else( || { - // We include bounds that come from a `#[derive(_)]` but point at the user's code, - // as we use this method to get a span appropriate for suggestions. + // We include bounds that come from a `#[derive(_)]` but point at the user's + // code, as we use this method to get a span appropriate for suggestions. let bs = bound.span(); - bs.can_be_used_for_suggestions().then(|| (bs.shrink_to_hi(), None)) + // We use `from_expansion` instead of `can_be_used_for_suggestions` because + // the trait bound from imperfect derives do point at the type parameter, + // but expanded to a where clause, so we want to ignore those. This is only + // true for derive intrinsics. + bs.from_expansion().not().then(|| (bs.shrink_to_hi(), None)) }, |span| Some((span.shrink_to_hi(), Some(span.shrink_to_lo()))), ) diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 279c34cb275d..b3b06314e1a0 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -526,12 +526,15 @@ pub fn suggest_constraining_type_params<'a>( // // fn foo(t: T) { ... } // - help: consider restricting this type parameter with `T: Foo` - suggestions.push(( - param.span.shrink_to_hi(), - post, - format!(": {constraint}"), - SuggestChangingConstraintsMessage::RestrictType { ty: param_name }, - )); + let span = param.span.shrink_to_hi(); + if span.can_be_used_for_suggestions() { + suggestions.push(( + span, + post, + format!(": {constraint}"), + SuggestChangingConstraintsMessage::RestrictType { ty: param_name }, + )); + } } // FIXME: remove the suggestions that are from derive, as the span is not correct diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index d54f3812350d..94876c6dd89f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3586,6 +3586,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } spans.push(self_ty.span); let mut spans: MultiSpan = spans.into(); + let mut derived = false; if matches!( self_ty.span.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _) @@ -3593,6 +3594,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { of_trait.map(|t| t.trait_ref.path.span.ctxt().outer_expn_data().kind), Some(ExpnKind::Macro(MacroKind::Derive, _)) ) { + derived = true; spans.push_span_label( data.span, "unsatisfied trait bound introduced in this `derive` macro", @@ -3621,6 +3623,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } err.span_note(spans, msg); + if derived { + err.help(format!( + "consider manually implementing `{trait_name}` to avoid undesired \ + bounds", + )); + } point_at_assoc_type_restriction( tcx, err, diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 01329f69c3be..3c5f67fee26a 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -102,6 +102,7 @@ LL | #[derive(Debug, Copy, Clone)] ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Debug` to avoid undesired bounds help: consider further restricting the associated type | LL | Expr: Expression::Nullable>, ::SqlType: NotNull, @@ -146,6 +147,7 @@ LL | #[derive(Debug, Copy, Clone)] ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds help: consider further restricting the associated type | LL | Expr: Expression::Nullable>, ::SqlType: NotNull, @@ -219,6 +221,7 @@ LL | #[derive(Debug, Copy, Clone)] ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting the associated type | LL | Expr: Expression::Nullable>, ::SqlType: NotNull, diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index aecd97ef7763..ea411741536f 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -65,6 +65,7 @@ LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] | ^^^^^ LL | struct Bar(T); | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Debug` to avoid undesired bounds = note: 2 redundant requirements hidden = note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug` = note: required for the cast from `&&&'static Bar<(dyn Debug + 'static)>` to `&dyn Debug` @@ -96,7 +97,10 @@ note: required for `Bar` to implement `Eq` --> $DIR/unsizing-wfcheck-issue-126272.rs:19:28 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^ unsatisfied trait bound introduced in this `derive` macro + | ^^ +LL | struct Bar(T); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Eq` to avoid undesired bounds = note: 1 redundant requirement hidden = note: required for `&'static Bar` to implement `Eq` note: required by a bound in `std::cmp::AssertParamIsEq` diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 601d067e3d84..1e66daa7132d 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -8,7 +8,10 @@ note: required for `Foo` to implement `Copy` --> $DIR/trait-error.rs:1:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ +LL | struct Foo(T); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block | diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index befff8802804..f4cd4cff7f44 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -10,7 +10,10 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ +LL | struct B { + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 | @@ -33,7 +36,10 @@ note: required for `B` to implement `Clone` --> $DIR/deriving-copyclone.rs:9:16 | LL | #[derive(Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ +LL | struct B { + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Clone` to avoid undesired bounds note: required by a bound in `is_clone` --> $DIR/deriving-copyclone.rs:19:16 | @@ -56,7 +62,10 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ +LL | struct B { + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 | diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index 7847bbd813cd..d6a794fa0b19 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -32,7 +32,10 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ +LL | struct Fooy(T); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 | @@ -56,7 +59,10 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ +LL | struct Fooy(T); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 | diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index b7aed4a8485a..93fd2df0398e 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -37,7 +37,11 @@ note: required for `PriorityQueue` to implement `PartialOrd` --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^^^^^^ +... +LL | struct PriorityQueue(BinaryHeap>); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `PartialOrd` to avoid undesired bounds note: required by a bound in `Ord` --> $SRC_DIR/core/src/cmp.rs:LL:COL diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index a48dd30d008a..2b8c6baeeafe 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -30,6 +30,7 @@ LL | #[derive(Debug, Copy, Clone)] | ^^^^^ LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider further restricting type parameter `K` with trait `Copy` | @@ -71,6 +72,7 @@ LL | #[derive(Debug, Copy, Clone)] | ^^^^^ LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 645d6ebb3961..2bd56b7688f4 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -65,6 +65,7 @@ LL | #[derive(Debug, Copy, Clone)] | ^^^^^ LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider restricting type parameter `K` with trait `Copy` | @@ -134,6 +135,7 @@ LL | #[derive(Debug, Copy, Clone)] | ^^^^^ LL | pub struct Vector2 { | ---- unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `Clone` to avoid undesired bounds help: consider restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { diff --git a/tests/ui/traits/derive-implicit-bound.rs b/tests/ui/traits/derive-implicit-bound.rs new file mode 100644 index 000000000000..22fb68f37c5c --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound.rs @@ -0,0 +1,34 @@ +// Second case reported in issue #108894. + +use std::marker::PhantomData; + +#[derive(PartialEq, Eq)] +pub struct Id(PhantomData); + +// manual implementation which would break the usage of const patterns +// impl PartialEq for Id { fn eq(&self, _: &Id) -> bool { true } } +// impl Eq for Id {} + +// This derive is undesired but cannot be removed without +// breaking the usages below +// #[derive(PartialEq, Eq)] +struct SomeNode(); + +fn accept_eq(_: &impl PartialEq) { } + +fn main() { + let node = Id::(PhantomData); + + // this will only work if + // - `Partial/Eq` is implemented manually, or + // - `SomeNode` also needlessly(?) implements `Partial/Eq` + accept_eq(&node); //~ ERROR can't compare `SomeNode` with `SomeNode` + + const CONST_ID: Id:: = Id::(PhantomData); + // this will work only when `Partial/Eq` is being derived + // otherwise: error: to use a constant of type `Id` in a pattern, + // `Id` must be annotated with `#[derive(PartialEq, Eq)]` + match node { + CONST_ID => {} + } +} diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr new file mode 100644 index 000000000000..9805835bb07f --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -0,0 +1,31 @@ +error[E0277]: can't compare `SomeNode` with `SomeNode` + --> $DIR/derive-implicit-bound.rs:25:15 + | +LL | accept_eq(&node); + | --------- ^^^^^ no implementation for `SomeNode == SomeNode` + | | + | required by a bound introduced by this call + | + = help: the trait `PartialEq` is not implemented for `SomeNode` +note: required for `Id` to implement `PartialEq` + --> $DIR/derive-implicit-bound.rs:5:10 + | +LL | #[derive(PartialEq, Eq)] + | ^^^^^^^^^ +LL | pub struct Id(PhantomData); + | - unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing `PartialEq` to avoid undesired bounds +note: required by a bound in `accept_eq` + --> $DIR/derive-implicit-bound.rs:17:23 + | +LL | fn accept_eq(_: &impl PartialEq) { } + | ^^^^^^^^^ required by this bound in `accept_eq` +help: consider annotating `SomeNode` with `#[derive(PartialEq)]` + | +LL + #[derive(PartialEq)] +LL | struct SomeNode(); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 54fe73fd6d3d0b2935977016039ded8d6a0d4772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 05:43:19 +0000 Subject: [PATCH 366/978] Tweak span labels caused by trait bound coming from derive expansion ``` note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct B { | - would need to be `Copy` ``` --- .../src/error_reporting/traits/suggestions.rs | 12 +++++++++++- tests/ui/associated-types/issue-38821.stderr | 12 ++++++------ .../unsizing-wfcheck-issue-126272.stderr | 8 ++++---- tests/ui/consts/const-blocks/trait-error.stderr | 4 ++-- tests/ui/derives/deriving-copyclone.stderr | 12 ++++++------ tests/ui/generic-associated-types/impl_bounds.stderr | 8 ++++---- .../issue-104884-trait-impl-sugg-err.stderr | 4 ++-- .../missing-bound-in-derive-copy-impl-2.stderr | 8 ++++---- .../missing-bound-in-derive-copy-impl.stderr | 8 ++++---- tests/ui/traits/derive-implicit-bound.stderr | 4 ++-- 10 files changed, 45 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 94876c6dd89f..c9dc390ea0be 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3595,9 +3595,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Some(ExpnKind::Macro(MacroKind::Derive, _)) ) { derived = true; + spans.push_span_label( + data.span.ctxt().outer_expn_data().call_site, + format!( + "unsatisfied trait bound introduced in this `derive` macro" + ), + ); spans.push_span_label( data.span, - "unsatisfied trait bound introduced in this `derive` macro", + if data.span.in_derive_expansion() { + format!("would need to be `{trait_name}`") + } else { + format!("") + }, ); } else if !data.span.is_dummy() && !data.span.overlaps(self_ty.span) { // `Sized` may be an explicit or implicit trait bound. If it is diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 3c5f67fee26a..11d0c9d514ff 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -98,10 +98,10 @@ note: required for `ColumnInsertValue` to implement `Debug` --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + | ------------------------------------------------ = help: consider manually implementing `Debug` to avoid undesired bounds help: consider further restricting the associated type | @@ -143,10 +143,10 @@ note: required for `ColumnInsertValue` to implement `Copy` --> $DIR/issue-38821.rs:23:17 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + | ------------------------------------------------ = help: consider manually implementing `Copy` to avoid undesired bounds help: consider further restricting the associated type | @@ -217,10 +217,10 @@ note: required for `ColumnInsertValue` to implement `Clone` --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + | ------------------------------------------------ = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting the associated type | diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index ea411741536f..1aaa7591a7be 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -62,9 +62,9 @@ note: required for `Bar<(dyn Debug + 'static)>` to implement `Debug` --> $DIR/unsizing-wfcheck-issue-126272.rs:19:10 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct Bar(T); - | - unsatisfied trait bound introduced in this `derive` macro + | - = help: consider manually implementing `Debug` to avoid undesired bounds = note: 2 redundant requirements hidden = note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug` @@ -97,9 +97,9 @@ note: required for `Bar` to implement `Eq` --> $DIR/unsizing-wfcheck-issue-126272.rs:19:28 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^ + | ^^ unsatisfied trait bound introduced in this `derive` macro LL | struct Bar(T); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Eq` = help: consider manually implementing `Eq` to avoid undesired bounds = note: 1 redundant requirement hidden = note: required for `&'static Bar` to implement `Eq` diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 1e66daa7132d..991a48917efb 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -8,9 +8,9 @@ note: required for `Foo` to implement `Copy` --> $DIR/trait-error.rs:1:10 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct Foo(T); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index f4cd4cff7f44..1baacf85f6a2 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -10,9 +10,9 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct B { - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 @@ -36,9 +36,9 @@ note: required for `B` to implement `Clone` --> $DIR/deriving-copyclone.rs:9:16 | LL | #[derive(Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct B { - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Clone` = help: consider manually implementing `Clone` to avoid undesired bounds note: required by a bound in `is_clone` --> $DIR/deriving-copyclone.rs:19:16 @@ -62,9 +62,9 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct B { - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index d6a794fa0b19..fd7dd774cf08 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -32,9 +32,9 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct Fooy(T); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 @@ -59,9 +59,9 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ^^^^ unsatisfied trait bound introduced in this `derive` macro LL | struct Fooy(T); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index 93fd2df0398e..c3513e19981f 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -37,10 +37,10 @@ note: required for `PriorityQueue` to implement `PartialOrd` --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ + | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro ... LL | struct PriorityQueue(BinaryHeap>); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `PartialOrd` = help: consider manually implementing `PartialOrd` to avoid undesired bounds note: required by a bound in `Ord` --> $SRC_DIR/core/src/cmp.rs:LL:COL diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index 2b8c6baeeafe..800f07054af7 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -27,9 +27,9 @@ note: required for `Vector2` to implement `Debug` --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ---- = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider further restricting type parameter `K` with trait `Copy` @@ -69,9 +69,9 @@ note: required for `Vector2` to implement `Clone` --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ---- = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 2bd56b7688f4..3f889f31484b 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -62,9 +62,9 @@ note: required for `Vector2` to implement `Debug` --> $DIR/missing-bound-in-derive-copy-impl.rs:3:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ---- = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider restricting type parameter `K` with trait `Copy` @@ -132,9 +132,9 @@ note: required for `Vector2` to implement `Clone` --> $DIR/missing-bound-in-derive-copy-impl.rs:3:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ---- = help: consider manually implementing `Clone` to avoid undesired bounds help: consider restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr index 9805835bb07f..275cef7a94fd 100644 --- a/tests/ui/traits/derive-implicit-bound.stderr +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -11,9 +11,9 @@ note: required for `Id` to implement `PartialEq` --> $DIR/derive-implicit-bound.rs:5:10 | LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro LL | pub struct Id(PhantomData); - | - unsatisfied trait bound introduced in this `derive` macro + | - would need to be `PartialEq` = help: consider manually implementing `PartialEq` to avoid undesired bounds note: required by a bound in `accept_eq` --> $DIR/derive-implicit-bound.rs:17:23 From b88fb8a0b0422697a8fe1573598795d7052e936c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 07:22:00 +0000 Subject: [PATCH 367/978] Mention that the trait could be manually impld in E0599 --- compiler/rustc_hir_typeck/src/method/suggest.rs | 5 +++++ tests/ui/derives/derive-assoc-type-not-impl.stderr | 1 + tests/ui/derives/deriving-with-repr-packed-2.stderr | 1 + tests/ui/union/union-derive-clone.stderr | 1 + 4 files changed, 8 insertions(+) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index cd25b866b098..f5ef5adff6bd 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1748,6 +1748,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Find all the requirements that come from a local `impl` block. let mut skip_list: UnordSet<_> = Default::default(); let mut spanned_predicates = FxIndexMap::default(); + let mut manually_impl = false; for (p, parent_p, cause) in unsatisfied_predicates { // Extract the predicate span and parent def id of the cause, // if we have one. @@ -1798,6 +1799,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); entry.2.push(p); skip_list.insert(p); + manually_impl = true; } // Unmet obligation coming from an `impl`. @@ -2083,6 +2085,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { *suggested_derive = self.suggest_derive(err, unsatisfied_predicates); *unsatisfied_bounds = true; } + if manually_impl { + err.help("consider manually implementing the trait to avoid undesired bounds"); + } } /// If an appropriate error source is not found, check method chain for possible candidates diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr index 13ba80243a5e..e239ad4ef209 100644 --- a/tests/ui/derives/derive-assoc-type-not-impl.stderr +++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr @@ -15,6 +15,7 @@ note: trait bound `NotClone: Clone` was not satisfied | LL | #[derive(Clone)] | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `NotClone` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/derives/deriving-with-repr-packed-2.stderr b/tests/ui/derives/deriving-with-repr-packed-2.stderr index b62c67d9a9da..fff6269472bd 100644 --- a/tests/ui/derives/deriving-with-repr-packed-2.stderr +++ b/tests/ui/derives/deriving-with-repr-packed-2.stderr @@ -25,6 +25,7 @@ note: the following trait bounds were not satisfied: | LL | #[derive(Copy, Clone, Default, PartialEq, Eq)] | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `NonCopy` with `#[derive(Clone, Copy)]` | LL + #[derive(Clone, Copy)] diff --git a/tests/ui/union/union-derive-clone.stderr b/tests/ui/union/union-derive-clone.stderr index 18f862aaa7d6..65488629b629 100644 --- a/tests/ui/union/union-derive-clone.stderr +++ b/tests/ui/union/union-derive-clone.stderr @@ -29,6 +29,7 @@ note: trait bound `CloneNoCopy: Copy` was not satisfied | LL | #[derive(Clone, Copy)] | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]` | LL + #[derive(Clone, Copy)] From 085da0cee4e6de6408c401ea2a807eff6b701307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 20:23:18 +0000 Subject: [PATCH 368/978] On E0308 caused by cloning a reference due to missing bounds, account for derive On type errors where the difference is expecting an owned type and getting a reference, if the expression is a `.clone()` call and the type is annotated with `#[derive(Clone)]`, we now explain implicit bounds and suggest manually implementing `Clone`. ``` error[E0308]: mismatched types --> $DIR/derive-implicit-bound-on-clone.rs:10:5 | LL | fn clone_me(x: &ContainsRc) -> ContainsRc { | ---------------- expected `ContainsRc` because of return type LL | x.clone() | ^^^^^^^^^ expected `ContainsRc`, found `&ContainsRc` | = note: expected struct `ContainsRc<_, _>` found reference `&ContainsRc<_, _>` note: `ContainsRc` does not implement `Clone`, so `&ContainsRc` was cloned instead --> $DIR/derive-implicit-bound-on-clone.rs:10:5 | LL | x.clone() | ^ help: `Clone` is not implemented because the some trait bounds could not be satisfied --> $DIR/derive-implicit-bound-on-clone.rs:5:19 | LL | #[derive(Clone)] | ----- in this derive macro expansion LL | struct ContainsRc { | ^ ^ derive introduces an implicit unsatisfied trait bound `K: Clone` | | | derive introduces an implicit unsatisfied trait bound `T: Clone` = help: consider manually implementing `Clone` to avoid the implict type parameter bounds ``` --- .../src/fn_ctxt/suggestions.rs | 97 ++++++++++++++++--- ...on-ref-due-to-missing-bound.current.stderr | 3 +- ...ll-on-ref-due-to-missing-bound.next.stderr | 3 +- .../traits/derive-implicit-bound-on-clone.rs | 24 +++++ .../derive-implicit-bound-on-clone.stderr | 53 ++++++++++ 5 files changed, 166 insertions(+), 14 deletions(-) create mode 100644 tests/ui/traits/derive-implicit-bound-on-clone.rs create mode 100644 tests/ui/traits/derive-implicit-bound-on-clone.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 3e4c194147f9..285288e87ee0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1932,25 +1932,96 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, ); } else { + let mut suggest_derive = true; if let Some(errors) = self.type_implements_trait_shallow(clone_trait_did, expected_ty, self.param_env) { + let manually_impl = "consider manually implementing `Clone` to avoid the \ + implict type parameter bounds"; match &errors[..] { [] => {} [error] => { - diag.help(format!( - "`Clone` is not implemented because the trait bound `{}` is \ - not satisfied", - error.obligation.predicate, - )); + // diag.note("{error:#?}"); + // diag.note(format!("{:#?} {:#?} {:#?}", error.obligation, error.obligation.cause, error.obligation.cause.code())); + let msg = "`Clone` is not implemented because a trait bound is not \ + satisfied"; + if let traits::ObligationCauseCode::ImplDerived(data) = + error.obligation.cause.code() + { + let mut span: MultiSpan = data.span.into(); + if self.tcx.is_automatically_derived(data.impl_or_alias_def_id) { + span.push_span_label( + data.span, + format!( + "derive introduces an implicit `{}` bound", + error.obligation.predicate + ), + ); + } + diag.span_help(span, msg); + if self.tcx.is_automatically_derived(data.impl_or_alias_def_id) + && data.impl_or_alias_def_id.is_local() + { + diag.help(manually_impl); + suggest_derive = false; + } + } else { + diag.help(msg); + } } _ => { - diag.help(format!( - "`Clone` is not implemented because the following trait bounds \ - could not be satisfied: {}", - listify(&errors, |e| format!("`{}`", e.obligation.predicate)) - .unwrap(), - )); + let unsatisfied_bounds: Vec<_> = errors + .iter() + .filter_map(|error| match error.obligation.cause.code() { + traits::ObligationCauseCode::ImplDerived(data) => { + let pre = if self + .tcx + .is_automatically_derived(data.impl_or_alias_def_id) + { + "derive introduces an implicit " + } else { + "" + }; + Some(( + data.span, + format!( + "{pre}unsatisfied trait bound `{}`", + error.obligation.predicate + ), + )) + } + _ => None, + }) + .collect(); + let msg = "`Clone` is not implemented because the some trait bounds \ + could not be satisfied"; + if errors.len() == unsatisfied_bounds.len() { + let mut unsatisfied_bounds_spans: MultiSpan = unsatisfied_bounds + .iter() + .map(|(span, _)| *span) + .collect::>() + .into(); + for (span, label) in unsatisfied_bounds { + unsatisfied_bounds_spans.push_span_label(span, label); + } + diag.span_help(unsatisfied_bounds_spans, msg); + if errors.iter().all(|error| match error.obligation.cause.code() { + traits::ObligationCauseCode::ImplDerived(data) => { + self.tcx.is_automatically_derived(data.impl_or_alias_def_id) + && data.impl_or_alias_def_id.is_local() + } + _ => false, + }) { + diag.help(manually_impl); + suggest_derive = false; + } + } else { + diag.help(format!( + "{msg}: {}", + listify(&errors, |e| format!("`{}`", e.obligation.predicate)) + .unwrap(), + )); + } } } for error in errors { @@ -1968,7 +2039,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - self.suggest_derive(diag, &vec![(trait_ref.upcast(self.tcx), None, None)]); + if suggest_derive { + self.suggest_derive(diag, &vec![(trait_ref.upcast(self.tcx), None, None)]); + } } } } diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr index 301f3c3a458d..5de99cc6ca6a 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr @@ -13,7 +13,8 @@ note: `HashSet` does not implement `Clone`, so `&HashSet` was cloned i | LL | let mut x: HashSet = v.clone(); | ^ - = help: `Clone` is not implemented because the trait bound `Day: Clone` is not satisfied +help: `Clone` is not implemented because a trait bound is not satisfied + --> $SRC_DIR/std/src/collections/hash/set.rs:LL:COL help: consider annotating `Day` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr index 301f3c3a458d..5de99cc6ca6a 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr @@ -13,7 +13,8 @@ note: `HashSet` does not implement `Clone`, so `&HashSet` was cloned i | LL | let mut x: HashSet = v.clone(); | ^ - = help: `Clone` is not implemented because the trait bound `Day: Clone` is not satisfied +help: `Clone` is not implemented because a trait bound is not satisfied + --> $SRC_DIR/std/src/collections/hash/set.rs:LL:COL help: consider annotating `Day` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/traits/derive-implicit-bound-on-clone.rs b/tests/ui/traits/derive-implicit-bound-on-clone.rs new file mode 100644 index 000000000000..a4c9e88ef576 --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound-on-clone.rs @@ -0,0 +1,24 @@ +// Issue #146515 +use std::rc::Rc; + +#[derive(Clone)] +struct ContainsRc { //~ HELP `Clone` is not implemented + value: Rc<(T, K)>, +} + +fn clone_me(x: &ContainsRc) -> ContainsRc { + x.clone() //~ ERROR E0308 + //~^ HELP consider manually implementing `Clone` +} + +#[derive(Clone)] +struct ContainsRcSingle { //~ HELP `Clone` is not implemented + value: Rc, +} + +fn clone_me_single(x: &ContainsRcSingle) -> ContainsRcSingle { + x.clone() //~ ERROR E0308 + //~^ HELP consider manually implementing `Clone` +} + +fn main() {} diff --git a/tests/ui/traits/derive-implicit-bound-on-clone.stderr b/tests/ui/traits/derive-implicit-bound-on-clone.stderr new file mode 100644 index 000000000000..0cec4ef7c609 --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound-on-clone.stderr @@ -0,0 +1,53 @@ +error[E0308]: mismatched types + --> $DIR/derive-implicit-bound-on-clone.rs:10:5 + | +LL | fn clone_me(x: &ContainsRc) -> ContainsRc { + | ---------------- expected `ContainsRc` because of return type +LL | x.clone() + | ^^^^^^^^^ expected `ContainsRc`, found `&ContainsRc` + | + = note: expected struct `ContainsRc<_, _>` + found reference `&ContainsRc<_, _>` +note: `ContainsRc` does not implement `Clone`, so `&ContainsRc` was cloned instead + --> $DIR/derive-implicit-bound-on-clone.rs:10:5 + | +LL | x.clone() + | ^ +help: `Clone` is not implemented because the some trait bounds could not be satisfied + --> $DIR/derive-implicit-bound-on-clone.rs:5:19 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct ContainsRc { + | ^ ^ derive introduces an implicit unsatisfied trait bound `K: Clone` + | | + | derive introduces an implicit unsatisfied trait bound `T: Clone` + = help: consider manually implementing `Clone` to avoid the implict type parameter bounds + +error[E0308]: mismatched types + --> $DIR/derive-implicit-bound-on-clone.rs:20:5 + | +LL | fn clone_me_single(x: &ContainsRcSingle) -> ContainsRcSingle { + | ------------------- expected `ContainsRcSingle` because of return type +LL | x.clone() + | ^^^^^^^^^ expected `ContainsRcSingle`, found `&ContainsRcSingle` + | + = note: expected struct `ContainsRcSingle<_>` + found reference `&ContainsRcSingle<_>` +note: `ContainsRcSingle` does not implement `Clone`, so `&ContainsRcSingle` was cloned instead + --> $DIR/derive-implicit-bound-on-clone.rs:20:5 + | +LL | x.clone() + | ^ +help: `Clone` is not implemented because a trait bound is not satisfied + --> $DIR/derive-implicit-bound-on-clone.rs:15:25 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct ContainsRcSingle { + | ^ derive introduces an implicit `T: Clone` bound + = help: consider manually implementing `Clone` to avoid the implict type parameter bounds + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From aebf1fdcf9c3b1e7b674499ce10aee43960569a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 20:40:29 +0000 Subject: [PATCH 369/978] Keep span of type in builtin derive macros expansions --- .../src/deriving/generic/mod.rs | 3 +- tests/ui/associated-types/issue-38821.rs | 6 +-- tests/ui/associated-types/issue-38821.stderr | 47 +++++++++++++++---- .../const_param_ty_impl_bad_field.rs | 4 +- .../const_param_ty_impl_bad_field.stderr | 7 ++- .../const_param_ty_impl_no_structural_eq.rs | 8 ++-- ...onst_param_ty_impl_no_structural_eq.stderr | 14 ++++-- .../nested_bad_const_param_ty.rs | 6 +-- .../nested_bad_const_param_ty.stderr | 27 +++++------ .../adt_const_params/unsized_field-1.rs | 6 +-- .../adt_const_params/unsized_field-1.stderr | 27 +++++------ .../unsizing-wfcheck-issue-126272.rs | 2 +- .../unsizing-wfcheck-issue-126272.stderr | 22 ++++++--- .../ui/consts/const-blocks/trait-error.stderr | 7 ++- .../derives/copy-drop-mutually-exclusive.rs | 8 ++-- .../copy-drop-mutually-exclusive.stderr | 12 +++-- tests/ui/derives/deriving-copyclone.stderr | 21 ++++++--- tests/ui/derives/issue-97343.stderr | 9 ++-- ...ith-same-name-and-derive-default-133965.rs | 12 ++--- ...same-name-and-derive-default-133965.stderr | 23 ++++----- ...ultiple-types-with-same-name-and-derive.rs | 12 ++--- ...ple-types-with-same-name-and-derive.stderr | 40 ++++++++-------- tests/ui/error-codes/E0184.rs | 4 +- tests/ui/error-codes/E0184.stderr | 6 ++- .../impl_bounds.stderr | 14 ++++-- tests/ui/issues/issue-27340.rs | 4 +- tests/ui/issues/issue-27340.stderr | 10 ++-- tests/ui/malformed/malformed-derive-entry.rs | 10 ++-- .../malformed/malformed-derive-entry.stderr | 14 ++++-- .../issue-104884-trait-impl-sugg-err.rs | 13 +++-- .../issue-104884-trait-impl-sugg-err.stderr | 20 +++++--- tests/ui/range/range_traits-2.rs | 4 +- tests/ui/range/range_traits-2.stderr | 6 +-- tests/ui/range/range_traits-3.rs | 4 +- tests/ui/range/range_traits-3.stderr | 6 +-- tests/ui/range/range_traits-6.rs | 4 +- tests/ui/range/range_traits-6.stderr | 6 +-- tests/ui/span/E0204.rs | 8 ++-- tests/ui/span/E0204.stderr | 10 ++-- .../ui/suggestions/derive-clone-for-eq.fixed | 4 +- tests/ui/suggestions/derive-clone-for-eq.rs | 4 +- .../ui/suggestions/derive-clone-for-eq.stderr | 6 ++- ...missing-bound-in-derive-copy-impl-2.stderr | 14 ++++-- .../missing-bound-in-derive-copy-impl-3.fixed | 4 +- .../missing-bound-in-derive-copy-impl-3.rs | 4 +- ...missing-bound-in-derive-copy-impl-3.stderr | 17 +++---- .../missing-bound-in-derive-copy-impl.rs | 4 +- .../missing-bound-in-derive-copy-impl.stderr | 19 +++++--- tests/ui/traits/derive-implicit-bound.stderr | 7 ++- tests/ui/traits/issue-106072.rs | 8 ++-- tests/ui/traits/issue-106072.stderr | 15 ++++-- tests/ui/traits/issue-50480.rs | 11 ++--- tests/ui/traits/issue-50480.stderr | 35 +++++++------- .../global-cache-and-parallel-frontend.rs | 4 +- .../global-cache-and-parallel-frontend.stderr | 6 ++- 55 files changed, 356 insertions(+), 272 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 665e0ddab194..bc86cdbc9f7e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -791,7 +791,8 @@ impl<'a> TraitDef<'a> { .collect(); // Create the type of `self`. - let path = cx.path_all(self.span, false, vec![type_ident], self_params); + let path = + cx.path_all(type_ident.span.with_ctxt(ctxt), false, vec![type_ident], self_params); let self_type = cx.ty_path(path); let rustc_const_unstable = cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span)); diff --git a/tests/ui/associated-types/issue-38821.rs b/tests/ui/associated-types/issue-38821.rs index 5212bc886f0d..35c371235e64 100644 --- a/tests/ui/associated-types/issue-38821.rs +++ b/tests/ui/associated-types/issue-38821.rs @@ -34,11 +34,11 @@ pub trait Column: Expression {} //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied -//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied -//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied -//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied pub enum ColumnInsertValue where //~^ ERROR the trait bound `::SqlType: NotNull` is not satisfied +//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied +//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied +//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied Col: Column, Expr: Expression::Nullable>, //~^ ERROR the trait bound `::SqlType: IntoNullable` is not satisfied diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 11d0c9d514ff..58d06860fe30 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:40:1 + --> $DIR/issue-38821.rs:37:1 | LL | pub enum ColumnInsertValue where | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` @@ -82,10 +82,13 @@ LL | impl IntoNullable for T { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:10 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ----- in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -98,7 +101,13 @@ note: required for `ColumnInsertValue` to implement `Debug` --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ @@ -127,10 +136,13 @@ LL | Expr: Expression::Nullable>, ::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:17 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ---- in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -143,7 +155,13 @@ note: required for `ColumnInsertValue` to implement `Copy` --> $DIR/issue-38821.rs:23:17 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ @@ -201,10 +219,13 @@ LL | impl IntoNullable for T { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:23 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ----- in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -217,7 +238,13 @@ note: required for `ColumnInsertValue` to implement `Clone` --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs index 0614ea97b1ad..1900931b3f35 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs @@ -8,10 +8,10 @@ struct NotParam; struct CantParam(NotParam); impl std::marker::ConstParamTy_ for CantParam {} -//~^ error: the trait `ConstParamTy_` cannot be implemented for this type +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type #[derive(std::marker::ConstParamTy, Eq, PartialEq)] -//~^ error: the trait `ConstParamTy_` cannot be implemented for this type struct CantParamDerive(NotParam); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr index fd1836802c4a..084c64d27335 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr @@ -8,13 +8,12 @@ LL | impl std::marker::ConstParamTy_ for CantParam {} | ^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/const_param_ty_impl_bad_field.rs:13:10 + --> $DIR/const_param_ty_impl_bad_field.rs:14:8 | LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | + | ------------------------- in this derive macro expansion LL | struct CantParamDerive(NotParam); - | -------- this field does not implement `ConstParamTy_` + | ^^^^^^^^^^^^^^^ -------- this field does not implement `ConstParamTy_` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs index a1c8eccfb095..a8f190609c04 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs @@ -8,13 +8,13 @@ impl std::marker::ConstParamTy_ for ImplementsConstParamTy {} struct CantParam(ImplementsConstParamTy); impl std::marker::ConstParamTy_ for CantParam {} -//~^ error: the type `CantParam` does not `#[derive(PartialEq)]` -//~| ERROR the trait bound `CantParam: Eq` is not satisfied +//~^ ERROR: the type `CantParam` does not `#[derive(PartialEq)]` +//~| ERROR: the trait bound `CantParam: Eq` is not satisfied #[derive(std::marker::ConstParamTy)] -//~^ error: the type `CantParamDerive` does not `#[derive(PartialEq)]` -//~| ERROR the trait bound `CantParamDerive: Eq` is not satisfied struct CantParamDerive(ImplementsConstParamTy); +//~^ ERROR: the type `CantParamDerive` does not `#[derive(PartialEq)]` +//~| ERROR: the trait bound `CantParamDerive: Eq` is not satisfied fn check() {} diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr index ca2a693d48ce..1219d5f04380 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr @@ -27,10 +27,12 @@ note: required by a bound in `ConstParamTy_` --> $SRC_DIR/core/src/marker.rs:LL:COL error[E0277]: the trait bound `CantParamDerive: Eq` is not satisfied - --> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10 + --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:8 | LL | #[derive(std::marker::ConstParamTy)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `CantParamDerive` + | ------------------------- in this derive macro expansion +LL | struct CantParamDerive(ImplementsConstParamTy); + | ^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `CantParamDerive` | note: required by a bound in `ConstParamTy_` --> $SRC_DIR/core/src/marker.rs:LL:COL @@ -41,13 +43,15 @@ LL | struct CantParamDerive(ImplementsConstParamTy); | error[E0277]: the type `CantParamDerive` does not `#[derive(PartialEq)]` - --> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10 + --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:8 | LL | #[derive(std::marker::ConstParamTy)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | ------------------------- in this derive macro expansion +LL | struct CantParamDerive(ImplementsConstParamTy); + | ^^^^^^^^^^^^^^^ unsatisfied trait bound | help: the nightly-only, unstable trait `StructuralPartialEq` is not implemented for `CantParamDerive` - --> $DIR/const_param_ty_impl_no_structural_eq.rs:17:1 + --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:1 | LL | struct CantParamDerive(ImplementsConstParamTy); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs index d42ef90e1b18..e8a16be2197b 100644 --- a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs +++ b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs @@ -4,15 +4,15 @@ use std::marker::ConstParamTy; #[derive(ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty struct Foo([*const u8; 1]); +//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty #[derive(ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty struct Foo2([*mut u8; 1]); +//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty #[derive(ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty struct Foo3([fn(); 1]); +//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr index 442ec6b96cef..6c8a506d1f40 100644 --- a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr +++ b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr @@ -1,44 +1,41 @@ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/nested_bad_const_param_ty.rs:6:10 + --> $DIR/nested_bad_const_param_ty.rs:7:8 | LL | #[derive(ConstParamTy)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct Foo([*const u8; 1]); - | -------------- this field does not implement `ConstParamTy_` + | ^^^ -------------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[*const u8; 1]` requires that `*const u8: ConstParamTy_` - --> $DIR/nested_bad_const_param_ty.rs:8:12 + --> $DIR/nested_bad_const_param_ty.rs:7:12 | LL | struct Foo([*const u8; 1]); | ^^^^^^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/nested_bad_const_param_ty.rs:10:10 + --> $DIR/nested_bad_const_param_ty.rs:11:8 | LL | #[derive(ConstParamTy)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct Foo2([*mut u8; 1]); - | ------------ this field does not implement `ConstParamTy_` + | ^^^^ ------------ this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[*mut u8; 1]` requires that `*mut u8: ConstParamTy_` - --> $DIR/nested_bad_const_param_ty.rs:12:13 + --> $DIR/nested_bad_const_param_ty.rs:11:13 | LL | struct Foo2([*mut u8; 1]); | ^^^^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/nested_bad_const_param_ty.rs:14:10 + --> $DIR/nested_bad_const_param_ty.rs:15:8 | LL | #[derive(ConstParamTy)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct Foo3([fn(); 1]); - | --------- this field does not implement `ConstParamTy_` + | ^^^^ --------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[fn(); 1]` requires that `fn(): ConstParamTy_` - --> $DIR/nested_bad_const_param_ty.rs:16:13 + --> $DIR/nested_bad_const_param_ty.rs:15:13 | LL | struct Foo3([fn(); 1]); | ^^^^^^^^^ diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-1.rs b/tests/ui/const-generics/adt_const_params/unsized_field-1.rs index 5db031cb900f..f2d972612dc6 100644 --- a/tests/ui/const-generics/adt_const_params/unsized_field-1.rs +++ b/tests/ui/const-generics/adt_const_params/unsized_field-1.rs @@ -6,18 +6,18 @@ extern crate unsized_const_param; use std::marker::ConstParamTy; #[derive(ConstParamTy, Eq, PartialEq)] -//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type struct A([u8]); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type #[derive(ConstParamTy, Eq, PartialEq)] -//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type struct B(&'static [u8]); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type #[derive(ConstParamTy, Eq, PartialEq)] struct C(unsized_const_param::Foo); #[derive(std::marker::ConstParamTy, Eq, PartialEq)] -//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type struct D(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr b/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr index 134dbba0d63a..2538b811618b 100644 --- a/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr +++ b/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr @@ -1,44 +1,41 @@ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsized_field-1.rs:8:10 + --> $DIR/unsized_field-1.rs:9:8 | LL | #[derive(ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct A([u8]); - | ---- this field does not implement `ConstParamTy_` + | ^ ---- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[u8]` requires that `feature(unsized_const_params) is enabled` - --> $DIR/unsized_field-1.rs:10:10 + --> $DIR/unsized_field-1.rs:9:10 | LL | struct A([u8]); | ^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsized_field-1.rs:12:10 + --> $DIR/unsized_field-1.rs:13:8 | LL | #[derive(ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct B(&'static [u8]); - | ------------- this field does not implement `ConstParamTy_` + | ^ ------------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `&'static [u8]` requires that `feature(unsized_const_params) is enabled` - --> $DIR/unsized_field-1.rs:14:10 + --> $DIR/unsized_field-1.rs:13:10 | LL | struct B(&'static [u8]); | ^^^^^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsized_field-1.rs:19:10 + --> $DIR/unsized_field-1.rs:20:8 | LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | + | ------------------------- in this derive macro expansion LL | struct D(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>); - | ---------------------------------------------------------- this field does not implement `ConstParamTy_` + | ^ ---------------------------------------------------------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `GenericNotUnsizedParam<&'static [u8]>` requires that `feature(unsized_const_params) is enabled` - --> $DIR/unsized_field-1.rs:21:10 + --> $DIR/unsized_field-1.rs:20:10 | LL | struct D(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs index 500e8e22b0e3..71ac662cf580 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs @@ -6,8 +6,8 @@ use std::marker::ConstParamTy; #[derive(Debug, PartialEq, Eq, ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` struct Foo { +//~^ ERROR the trait `ConstParamTy_` nested: &'static Bar, //~^ ERROR the size for values //~| ERROR the size for values diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index 1aaa7591a7be..f90f0b45d967 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -19,11 +19,13 @@ LL | struct Bar(T); | this could be changed to `T: ?Sized`... error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsizing-wfcheck-issue-126272.rs:8:32 + --> $DIR/unsizing-wfcheck-issue-126272.rs:9:8 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^^^^^^^^^^^ -... + | ------------ in this derive macro expansion +LL | struct Foo { + | ^^^ +LL | LL | nested: &'static Bar, | ----------------------------------------- this field does not implement `ConstParamTy_` | @@ -62,9 +64,12 @@ note: required for `Bar<(dyn Debug + 'static)>` to implement `Debug` --> $DIR/unsizing-wfcheck-issue-126272.rs:19:10 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct Bar(T); - | - + | ^^^ - = help: consider manually implementing `Debug` to avoid undesired bounds = note: 2 redundant requirements hidden = note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug` @@ -97,9 +102,12 @@ note: required for `Bar` to implement `Eq` --> $DIR/unsizing-wfcheck-issue-126272.rs:19:28 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^ unsatisfied trait bound introduced in this `derive` macro + | ^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct Bar(T); - | - would need to be `Eq` + | ^^^ - would need to be `Eq` = help: consider manually implementing `Eq` to avoid undesired bounds = note: 1 redundant requirement hidden = note: required for `&'static Bar` to implement `Eq` diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 991a48917efb..aa9177d2b017 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -8,9 +8,12 @@ note: required for `Foo` to implement `Copy` --> $DIR/trait-error.rs:1:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct Foo(T); - | - would need to be `Copy` + | ^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block diff --git a/tests/ui/derives/copy-drop-mutually-exclusive.rs b/tests/ui/derives/copy-drop-mutually-exclusive.rs index 5147605910d7..64cd5bf594b0 100644 --- a/tests/ui/derives/copy-drop-mutually-exclusive.rs +++ b/tests/ui/derives/copy-drop-mutually-exclusive.rs @@ -1,14 +1,14 @@ //! Regression test for issue #20126: Copy and Drop traits are mutually exclusive -#[derive(Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented -struct Foo; +#[derive(Copy, Clone)] +struct Foo; //~ ERROR the trait `Copy` cannot be implemented impl Drop for Foo { fn drop(&mut self) {} } -#[derive(Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented -struct Bar(::std::marker::PhantomData); +#[derive(Copy, Clone)] +struct Bar(::std::marker::PhantomData); //~ ERROR the trait `Copy` cannot be implemented impl Drop for Bar { fn drop(&mut self) {} diff --git a/tests/ui/derives/copy-drop-mutually-exclusive.stderr b/tests/ui/derives/copy-drop-mutually-exclusive.stderr index 771bbc925695..f17d33ffbfed 100644 --- a/tests/ui/derives/copy-drop-mutually-exclusive.stderr +++ b/tests/ui/derives/copy-drop-mutually-exclusive.stderr @@ -1,14 +1,18 @@ error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor - --> $DIR/copy-drop-mutually-exclusive.rs:3:10 + --> $DIR/copy-drop-mutually-exclusive.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ `Copy` not allowed on types with destructors + | ---- in this derive macro expansion +LL | struct Foo; + | ^^^ `Copy` not allowed on types with destructors error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor - --> $DIR/copy-drop-mutually-exclusive.rs:10:10 + --> $DIR/copy-drop-mutually-exclusive.rs:11:8 | LL | #[derive(Copy, Clone)] - | ^^^^ `Copy` not allowed on types with destructors + | ---- in this derive macro expansion +LL | struct Bar(::std::marker::PhantomData); + | ^^^ `Copy` not allowed on types with destructors error: aborting due to 2 previous errors diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index 1baacf85f6a2..226163474482 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -10,9 +10,12 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct B { - | - would need to be `Copy` + | ^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 @@ -36,9 +39,12 @@ note: required for `B` to implement `Clone` --> $DIR/deriving-copyclone.rs:9:16 | LL | #[derive(Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct B { - | - would need to be `Clone` + | ^ - would need to be `Clone` = help: consider manually implementing `Clone` to avoid undesired bounds note: required by a bound in `is_clone` --> $DIR/deriving-copyclone.rs:19:16 @@ -62,9 +68,12 @@ note: required for `B` to implement `Copy` --> $DIR/deriving-copyclone.rs:9:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct B { - | - would need to be `Copy` + | ^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 diff --git a/tests/ui/derives/issue-97343.stderr b/tests/ui/derives/issue-97343.stderr index 27691f571884..c033a3d227c1 100644 --- a/tests/ui/derives/issue-97343.stderr +++ b/tests/ui/derives/issue-97343.stderr @@ -2,12 +2,11 @@ error[E0109]: type arguments are not allowed on type parameter `Irrelevant` --> $DIR/issue-97343.rs:4:23 | LL | #[derive(Debug)] - | ----- - | | - | not allowed on type parameter `Irrelevant` - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Irrelevant { - | ^^^^^^^^^^ type argument not allowed + | ---------- ^^^^^^^^^^ type argument not allowed + | | + | not allowed on type parameter `Irrelevant` | note: type parameter `Irrelevant` defined here --> $DIR/issue-97343.rs:4:23 diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs index 8e5cd4248f14..f4193f18352d 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs @@ -3,12 +3,12 @@ struct NonGeneric {} #[derive(Default)] -//~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied -//~^^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied -//~^^^ ERROR struct takes 0 generic arguments but 1 generic argument was supplied -//~^^^^ ERROR struct takes 0 generic arguments but 1 generic argument was supplied +//~^ ERROR: struct takes 0 lifetime arguments but 1 lifetime argument was supplied +//~| ERROR: struct takes 0 generic arguments but 1 generic argument was supplied struct NonGeneric<'a, const N: usize> {} -//~^ ERROR lifetime parameter `'a` is never used -//~^^ ERROR the name `NonGeneric` is defined multiple times +//~^ ERROR: struct takes 0 lifetime arguments but 1 lifetime argument was supplied +//~| ERROR: struct takes 0 generic arguments but 1 generic argument was supplied +//~| ERROR: lifetime parameter `'a` is never used +//~| ERROR: the name `NonGeneric` is defined multiple times pub fn main() {} diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr index cf9c0d0ad3be..0d6aaaf5186d 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `NonGeneric` is defined multiple times - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:10:1 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:1 | LL | struct NonGeneric {} | ----------------- previous definition of the type `NonGeneric` here @@ -37,7 +37,7 @@ LL | struct NonGeneric {} | ^^^^^^^^^^ error[E0392]: lifetime parameter `'a` is never used - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:10:19 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:19 | LL | struct NonGeneric<'a, const N: usize> {} | ^^ unused lifetime parameter @@ -45,29 +45,26 @@ LL | struct NonGeneric<'a, const N: usize> {} = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:5:10 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:8 | -LL | #[derive(Default)] - | ^^^^^^^ expected 0 lifetime arguments -... LL | struct NonGeneric<'a, const N: usize> {} - | -- help: remove the lifetime argument + | ^^^^^^^^^^ -- help: remove the lifetime argument + | | + | expected 0 lifetime arguments | note: struct defined here, with 0 lifetime parameters --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 | LL | struct NonGeneric {} | ^^^^^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:5:10 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:8 | -LL | #[derive(Default)] - | ^^^^^^^ expected 0 generic arguments -... LL | struct NonGeneric<'a, const N: usize> {} - | - help: remove the unnecessary generic argument + | ^^^^^^^^^^ - help: remove the unnecessary generic argument + | | + | expected 0 generic arguments | note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs index f3bf299aa65f..e946c0c5350e 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs @@ -8,12 +8,12 @@ struct NotSM; #[derive(PartialEq, Eq)] -//~^ ERROR struct takes 0 generic arguments -//~| ERROR struct takes 0 generic arguments -//~| ERROR struct takes 0 generic arguments -//~| ERROR struct takes 0 generic arguments +//~^ ERROR: struct takes 0 generic arguments struct NotSM(T); -//~^ ERROR the name `NotSM` is defined multiple times -//~| ERROR no field `0` +//~^ ERROR: struct takes 0 generic arguments +//~| ERROR: struct takes 0 generic arguments +//~| ERROR: struct takes 0 generic arguments +//~| ERROR: the name `NotSM` is defined multiple times +//~| ERROR: no field `0` fn main() {} diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr index 32c3cf440316..e80cf35d81e1 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `NotSM` is defined multiple times - --> $DIR/multiple-types-with-same-name-and-derive.rs:15:1 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:1 | LL | struct NotSM; | ------------- previous definition of the type `NotSM` here @@ -10,10 +10,10 @@ LL | struct NotSM(T); = note: `NotSM` must be defined only once in the type namespace of this module error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:10:10 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:8 | -LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ expected 0 generic arguments +LL | struct NotSM(T); + | ^^^^^ expected 0 generic arguments | note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 @@ -30,27 +30,27 @@ LL | #[derive(PartialEq, Eq)] note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 | +LL | struct NotSM; + | ^^^^^ + +error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:8 + | +LL | struct NotSM(T); + | ^^^^^ expected 0 generic arguments + | +note: struct defined here, with 0 generic parameters + --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 + | LL | struct NotSM; | ^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:10:21 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:8 | -LL | #[derive(PartialEq, Eq)] - | ^^ expected 0 generic arguments - | -note: struct defined here, with 0 generic parameters - --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 - | -LL | struct NotSM; - | ^^^^^ - -error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:10:10 - | -LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ expected 0 generic arguments +LL | struct NotSM(T); + | ^^^^^ expected 0 generic arguments | note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 @@ -60,7 +60,7 @@ LL | struct NotSM; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0609]: no field `0` on type `&NotSM` - --> $DIR/multiple-types-with-same-name-and-derive.rs:15:17 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:17 | LL | struct NotSM(T); | ^ unknown field diff --git a/tests/ui/error-codes/E0184.rs b/tests/ui/error-codes/E0184.rs index 0c448e4ad8bc..64cc1f0d1538 100644 --- a/tests/ui/error-codes/E0184.rs +++ b/tests/ui/error-codes/E0184.rs @@ -1,5 +1,5 @@ -#[derive(Copy)] //~ ERROR E0184 -struct Foo; +#[derive(Copy)] +struct Foo; //~ ERROR E0184 impl Drop for Foo { fn drop(&mut self) { diff --git a/tests/ui/error-codes/E0184.stderr b/tests/ui/error-codes/E0184.stderr index 1a7df9ac095a..98b5305ad0dc 100644 --- a/tests/ui/error-codes/E0184.stderr +++ b/tests/ui/error-codes/E0184.stderr @@ -1,8 +1,10 @@ error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor - --> $DIR/E0184.rs:1:10 + --> $DIR/E0184.rs:2:8 | LL | #[derive(Copy)] - | ^^^^ `Copy` not allowed on types with destructors + | ---- in this derive macro expansion +LL | struct Foo; + | ^^^ `Copy` not allowed on types with destructors error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index fd7dd774cf08..d918bd62c2d7 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -32,9 +32,12 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct Fooy(T); - | - would need to be `Copy` + | ^^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 @@ -59,9 +62,12 @@ note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | struct Fooy(T); - | - would need to be `Copy` + | ^^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 diff --git a/tests/ui/issues/issue-27340.rs b/tests/ui/issues/issue-27340.rs index 53ca2bc973ff..9966c24a7441 100644 --- a/tests/ui/issues/issue-27340.rs +++ b/tests/ui/issues/issue-27340.rs @@ -1,7 +1,7 @@ struct Foo; #[derive(Copy, Clone)] -//~^ ERROR the trait `Copy` cannot be implemented for this type struct Bar(Foo); -//~^ ERROR `Foo: Clone` is not satisfied +//~^ ERROR: the trait `Copy` cannot be implemented for this type +//~| ERROR: `Foo: Clone` is not satisfied fn main() {} diff --git a/tests/ui/issues/issue-27340.stderr b/tests/ui/issues/issue-27340.stderr index 7cde901ffd95..3b4ad58b1f08 100644 --- a/tests/ui/issues/issue-27340.stderr +++ b/tests/ui/issues/issue-27340.stderr @@ -1,18 +1,16 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-27340.rs:2:10 + --> $DIR/issue-27340.rs:3:8 | LL | #[derive(Copy, Clone)] - | ^^^^ -LL | + | ---- in this derive macro expansion LL | struct Bar(Foo); - | --- this field does not implement `Copy` + | ^^^ --- this field does not implement `Copy` error[E0277]: the trait bound `Foo: Clone` is not satisfied - --> $DIR/issue-27340.rs:4:12 + --> $DIR/issue-27340.rs:3:12 | LL | #[derive(Copy, Clone)] | ----- in this derive macro expansion -LL | LL | struct Bar(Foo); | ^^^ the trait `Clone` is not implemented for `Foo` | diff --git a/tests/ui/malformed/malformed-derive-entry.rs b/tests/ui/malformed/malformed-derive-entry.rs index 77fa2f566a8f..f9dc98d9d270 100644 --- a/tests/ui/malformed/malformed-derive-entry.rs +++ b/tests/ui/malformed/malformed-derive-entry.rs @@ -1,14 +1,14 @@ #[derive(Copy(Bad))] -//~^ ERROR traits in `#[derive(...)]` don't accept arguments -//~| ERROR the trait bound +//~^ ERROR: traits in `#[derive(...)]` don't accept arguments struct Test1; +//~^ ERROR: the trait bound #[derive(Copy="bad")] -//~^ ERROR traits in `#[derive(...)]` don't accept values -//~| ERROR the trait bound +//~^ ERROR: traits in `#[derive(...)]` don't accept values struct Test2; +//~^ ERROR: the trait bound -#[derive] //~ ERROR malformed `derive` attribute input +#[derive] //~ ERROR: malformed `derive` attribute input struct Test4; fn main() {} diff --git a/tests/ui/malformed/malformed-derive-entry.stderr b/tests/ui/malformed/malformed-derive-entry.stderr index 02036e8d4c90..a5d7c3a4f8aa 100644 --- a/tests/ui/malformed/malformed-derive-entry.stderr +++ b/tests/ui/malformed/malformed-derive-entry.stderr @@ -17,10 +17,13 @@ LL | #[derive] | ^^^^^^^^^ help: must be of the form: `#[derive(Trait1, Trait2, ...)]` error[E0277]: the trait bound `Test1: Clone` is not satisfied - --> $DIR/malformed-derive-entry.rs:1:10 + --> $DIR/malformed-derive-entry.rs:3:8 | LL | #[derive(Copy(Bad))] - | ^^^^ the trait `Clone` is not implemented for `Test1` + | ---- in this derive macro expansion +LL | +LL | struct Test1; + | ^^^^^ the trait `Clone` is not implemented for `Test1` | note: required by a bound in `Copy` --> $SRC_DIR/core/src/marker.rs:LL:COL @@ -31,10 +34,13 @@ LL | struct Test1; | error[E0277]: the trait bound `Test2: Clone` is not satisfied - --> $DIR/malformed-derive-entry.rs:6:10 + --> $DIR/malformed-derive-entry.rs:8:8 | LL | #[derive(Copy="bad")] - | ^^^^ the trait `Clone` is not implemented for `Test2` + | ---- in this derive macro expansion +LL | +LL | struct Test2; + | ^^^^^ the trait `Clone` is not implemented for `Test2` | note: required by a bound in `Copy` --> $SRC_DIR/core/src/marker.rs:LL:COL diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs index d420f2641daf..0c66b47b3941 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs @@ -12,12 +12,11 @@ struct PriorityQueueEntry { } #[derive(PartialOrd, AddImpl)] -//~^ ERROR can't compare `PriorityQueue` with `PriorityQueue` -//~| ERROR the trait bound `PriorityQueue: Eq` is not satisfied -//~| ERROR can't compare `T` with `T` -//~| ERROR no method named `cmp` found for struct `BinaryHeap>` -//~| ERROR no field `height` on type `&PriorityQueue` - +//~^ ERROR: the trait bound `PriorityQueue: Eq` is not satisfied +//~| ERROR: can't compare `T` with `T` +//~| ERROR: no method named `cmp` found for struct `BinaryHeap>` +//~| ERROR: no field `height` on type `&PriorityQueue` struct PriorityQueue(BinaryHeap>); -//~^ ERROR can't compare `BinaryHeap>` with `_` +//~^ ERROR: can't compare `PriorityQueue` with `PriorityQueue` +//~| ERROR: can't compare `BinaryHeap>` with `_` fn main() {} diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index c3513e19981f..e49cf6256cb2 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -1,11 +1,14 @@ error[E0277]: can't compare `PriorityQueue` with `PriorityQueue` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:8 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ no implementation for `PriorityQueue == PriorityQueue` + | ---------- in this derive macro expansion +... +LL | struct PriorityQueue(BinaryHeap>); + | ^^^^^^^^^^^^^ no implementation for `PriorityQueue == PriorityQueue` | help: the trait `PartialEq` is not implemented for `PriorityQueue` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:21:1 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:1 | LL | struct PriorityQueue(BinaryHeap>); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +22,7 @@ LL | #[derive(PartialOrd, AddImpl)] | ^^^^^^^ unsatisfied trait bound | help: the trait `Eq` is not implemented for `PriorityQueue` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:21:1 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:1 | LL | struct PriorityQueue(BinaryHeap>); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,16 +40,19 @@ note: required for `PriorityQueue` to implement `PartialOrd` --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion ... LL | struct PriorityQueue(BinaryHeap>); - | - would need to be `PartialOrd` + | ^^^^^^^^^^^^^ - would need to be `PartialOrd` = help: consider manually implementing `PartialOrd` to avoid undesired bounds note: required by a bound in `Ord` --> $SRC_DIR/core/src/cmp.rs:LL:COL error[E0277]: can't compare `BinaryHeap>` with `_` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:21:25 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:25 | LL | #[derive(PartialOrd, AddImpl)] | ---------- in this derive macro expansion diff --git a/tests/ui/range/range_traits-2.rs b/tests/ui/range/range_traits-2.rs index 234d7a64dc8b..7dd91243082c 100644 --- a/tests/ui/range/range_traits-2.rs +++ b/tests/ui/range/range_traits-2.rs @@ -1,6 +1,6 @@ use std::ops::*; -#[derive(Copy, Clone)] //~ ERROR Copy -struct R(Range); +#[derive(Copy, Clone)] +struct R(Range); //~ ERROR Copy fn main() {} diff --git a/tests/ui/range/range_traits-2.stderr b/tests/ui/range/range_traits-2.stderr index 2001c85c4348..f38539cc648c 100644 --- a/tests/ui/range/range_traits-2.stderr +++ b/tests/ui/range/range_traits-2.stderr @@ -1,10 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/range_traits-2.rs:3:10 + --> $DIR/range_traits-2.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | struct R(Range); - | ------------ this field does not implement `Copy` + | ^ ------------ this field does not implement `Copy` error: aborting due to 1 previous error diff --git a/tests/ui/range/range_traits-3.rs b/tests/ui/range/range_traits-3.rs index 2d597cce5ad5..79ba1842f62f 100644 --- a/tests/ui/range/range_traits-3.rs +++ b/tests/ui/range/range_traits-3.rs @@ -1,6 +1,6 @@ use std::ops::*; -#[derive(Copy, Clone)] //~ ERROR Copy -struct R(RangeFrom); +#[derive(Copy, Clone)] +struct R(RangeFrom); //~ ERROR Copy fn main() {} diff --git a/tests/ui/range/range_traits-3.stderr b/tests/ui/range/range_traits-3.stderr index 71210379c79c..1f3768ad8d84 100644 --- a/tests/ui/range/range_traits-3.stderr +++ b/tests/ui/range/range_traits-3.stderr @@ -1,10 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/range_traits-3.rs:3:10 + --> $DIR/range_traits-3.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | struct R(RangeFrom); - | ---------------- this field does not implement `Copy` + | ^ ---------------- this field does not implement `Copy` error: aborting due to 1 previous error diff --git a/tests/ui/range/range_traits-6.rs b/tests/ui/range/range_traits-6.rs index bce106bbfe79..72c6cecc88d6 100644 --- a/tests/ui/range/range_traits-6.rs +++ b/tests/ui/range/range_traits-6.rs @@ -1,6 +1,6 @@ use std::ops::*; -#[derive(Copy, Clone)] //~ ERROR Copy -struct R(RangeInclusive); +#[derive(Copy, Clone)] +struct R(RangeInclusive); //~ ERROR Copy fn main() {} diff --git a/tests/ui/range/range_traits-6.stderr b/tests/ui/range/range_traits-6.stderr index a58022ef7e4f..53fe2fed0a61 100644 --- a/tests/ui/range/range_traits-6.stderr +++ b/tests/ui/range/range_traits-6.stderr @@ -1,10 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/range_traits-6.rs:3:10 + --> $DIR/range_traits-6.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | struct R(RangeInclusive); - | --------------------- this field does not implement `Copy` + | ^ --------------------- this field does not implement `Copy` error: aborting due to 1 previous error diff --git a/tests/ui/span/E0204.rs b/tests/ui/span/E0204.rs index 8793a05c8a85..841bd5e32b8a 100644 --- a/tests/ui/span/E0204.rs +++ b/tests/ui/span/E0204.rs @@ -4,8 +4,8 @@ struct Foo { impl Copy for Foo { } //~ ERROR cannot be implemented for this type -#[derive(Copy)] //~ ERROR cannot be implemented for this type -struct Foo2<'a> { +#[derive(Copy)] +struct Foo2<'a> { //~ ERROR cannot be implemented for this type ty: &'a mut bool, } @@ -16,8 +16,8 @@ enum EFoo { impl Copy for EFoo { } //~ ERROR cannot be implemented for this type -#[derive(Copy)] //~ ERROR cannot be implemented for this type -enum EFoo2<'a> { +#[derive(Copy)] +enum EFoo2<'a> { //~ ERROR cannot be implemented for this type Bar(&'a mut bool), Baz, } diff --git a/tests/ui/span/E0204.stderr b/tests/ui/span/E0204.stderr index fe375b94781b..a0b51be17863 100644 --- a/tests/ui/span/E0204.stderr +++ b/tests/ui/span/E0204.stderr @@ -8,11 +8,12 @@ LL | impl Copy for Foo { } | ^^^ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/E0204.rs:7:10 + --> $DIR/E0204.rs:8:8 | LL | #[derive(Copy)] - | ^^^^ + | ---- in this derive macro expansion LL | struct Foo2<'a> { + | ^^^^ LL | ty: &'a mut bool, | ---------------- this field does not implement `Copy` @@ -26,11 +27,12 @@ LL | impl Copy for EFoo { } | ^^^^ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/E0204.rs:19:10 + --> $DIR/E0204.rs:20:6 | LL | #[derive(Copy)] - | ^^^^ + | ---- in this derive macro expansion LL | enum EFoo2<'a> { + | ^^^^^ LL | Bar(&'a mut bool), | ------------ this field does not implement `Copy` diff --git a/tests/ui/suggestions/derive-clone-for-eq.fixed b/tests/ui/suggestions/derive-clone-for-eq.fixed index 4dc362f94787..17259dd687c6 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.fixed +++ b/tests/ui/suggestions/derive-clone-for-eq.fixed @@ -1,8 +1,8 @@ //@ run-rustfix // https://github.com/rust-lang/rust/issues/79076 -#[derive(Clone, Eq)] //~ ERROR [E0277] -pub struct Struct(T); +#[derive(Clone, Eq)] +pub struct Struct(T); //~ ERROR [E0277] impl PartialEq for Struct where diff --git a/tests/ui/suggestions/derive-clone-for-eq.rs b/tests/ui/suggestions/derive-clone-for-eq.rs index b3635000f165..3e4331745be8 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.rs +++ b/tests/ui/suggestions/derive-clone-for-eq.rs @@ -1,8 +1,8 @@ //@ run-rustfix // https://github.com/rust-lang/rust/issues/79076 -#[derive(Clone, Eq)] //~ ERROR [E0277] -pub struct Struct(T); +#[derive(Clone, Eq)] +pub struct Struct(T); //~ ERROR [E0277] impl PartialEq for Struct where diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr index eb0355853daa..bed5ff90c194 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.stderr +++ b/tests/ui/suggestions/derive-clone-for-eq.stderr @@ -1,8 +1,10 @@ error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/derive-clone-for-eq.rs:4:17 + --> $DIR/derive-clone-for-eq.rs:5:12 | LL | #[derive(Clone, Eq)] - | ^^ the trait `Clone` is not implemented for `T` + | -- in this derive macro expansion +LL | pub struct Struct(T); + | ^^^^^^ the trait `Clone` is not implemented for `T` | note: required for `Struct` to implement `PartialEq` --> $DIR/derive-clone-for-eq.rs:7:19 diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index 800f07054af7..872ce7105ce8 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -27,9 +27,12 @@ note: required for `Vector2` to implement `Debug` --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | pub struct Vector2 { - | ---- + | ^^^^^^^ ---- = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider further restricting type parameter `K` with trait `Copy` @@ -69,9 +72,12 @@ note: required for `Vector2` to implement `Clone` --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | pub struct Vector2 { - | ---- + | ^^^^^^^ ---- = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed index 74df1d7c7cfd..bd1785e35112 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed @@ -7,8 +7,8 @@ pub struct Vector2{ pub y: T } -#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type -pub struct AABB{ +#[derive(Debug, Copy, Clone)] +pub struct AABB { //~ ERROR the trait `Copy` cannot be implemented for this type pub loc: Vector2, //~ ERROR `K` doesn't implement `Debug` //~^ ERROR `K` doesn't implement `Debug` pub size: Vector2 //~ ERROR `K` doesn't implement `Debug` diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs index 8550a4d72476..36502044bd46 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs @@ -7,8 +7,8 @@ pub struct Vector2{ pub y: T } -#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type -pub struct AABB{ +#[derive(Debug, Copy, Clone)] +pub struct AABB { //~ ERROR the trait `Copy` cannot be implemented for this type pub loc: Vector2, //~ ERROR `K` doesn't implement `Debug` //~^ ERROR `K` doesn't implement `Debug` pub size: Vector2 //~ ERROR `K` doesn't implement `Debug` diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr index e3375b67c86d..cc80e7297e48 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -1,9 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/missing-bound-in-derive-copy-impl-3.rs:10:17 + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:11:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ -LL | pub struct AABB{ + | ---- in this derive macro expansion +LL | pub struct AABB { + | ^^^^ LL | pub loc: Vector2, | ------------------- this field does not implement `Copy` | @@ -14,7 +15,7 @@ LL | pub loc: Vector2, | ^^^^^^^^^^ help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++ error[E0277]: `K` doesn't implement `Debug` @@ -30,7 +31,7 @@ LL | pub struct Vector2{ | ^^^^^ required by this bound in `Vector2` help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++++++++++++ error[E0277]: `K` doesn't implement `Debug` @@ -38,13 +39,13 @@ error[E0277]: `K` doesn't implement `Debug` | LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion -LL | pub struct AABB{ +LL | pub struct AABB { LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `K` | help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++++++++++++ error[E0277]: `K` doesn't implement `Debug` @@ -58,7 +59,7 @@ LL | pub size: Vector2 | help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++++++++++++ error: aborting due to 4 previous errors diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs index 0ffc1b8f7a25..60a9074e5c0d 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs @@ -6,8 +6,8 @@ pub struct Vector2 { pub y: T, } -#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type -pub struct AABB { +#[derive(Debug, Copy, Clone)] +pub struct AABB { //~ ERROR the trait `Copy` cannot be implemented for this type pub loc: Vector2, //~^ ERROR doesn't implement `Debug` //~| ERROR `K: Copy` is not satisfied diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 3f889f31484b..f843fb0d6d7e 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -1,9 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/missing-bound-in-derive-copy-impl.rs:9:17 + --> $DIR/missing-bound-in-derive-copy-impl.rs:10:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | pub struct AABB { + | ^^^^ LL | pub loc: Vector2, | ------------------- this field does not implement `Copy` | @@ -62,9 +63,12 @@ note: required for `Vector2` to implement `Debug` --> $DIR/missing-bound-in-derive-copy-impl.rs:3:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | pub struct Vector2 { - | ---- + | ^^^^^^^ ---- = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider restricting type parameter `K` with trait `Copy` @@ -132,9 +136,12 @@ note: required for `Vector2` to implement `Clone` --> $DIR/missing-bound-in-derive-copy-impl.rs:3:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | pub struct Vector2 { - | ---- + | ^^^^^^^ ---- = help: consider manually implementing `Clone` to avoid undesired bounds help: consider restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr index 275cef7a94fd..02c7fe9e689e 100644 --- a/tests/ui/traits/derive-implicit-bound.stderr +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -11,9 +11,12 @@ note: required for `Id` to implement `PartialEq` --> $DIR/derive-implicit-bound.rs:5:10 | LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^^^^^ + | | + | unsatisfied trait bound introduced in this `derive` macro + | in this derive macro expansion LL | pub struct Id(PhantomData); - | - would need to be `PartialEq` + | ^^ - would need to be `PartialEq` = help: consider manually implementing `PartialEq` to avoid undesired bounds note: required by a bound in `accept_eq` --> $DIR/derive-implicit-bound.rs:17:23 diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs index d45668312218..6b04004621d8 100644 --- a/tests/ui/traits/issue-106072.rs +++ b/tests/ui/traits/issue-106072.rs @@ -1,6 +1,4 @@ -#[derive(Clone)] -//~^ ERROR expected a type, found a trait -//~| ERROR expected a type, found a trait -struct Foo; -trait Foo {} //~ ERROR the name `Foo` is defined multiple times +#[derive(Clone)] //~ ERROR: expected a type, found a trait +struct Foo; //~ ERROR: expected a type, found a trait +trait Foo {} //~ ERROR: the name `Foo` is defined multiple times fn main() {} diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr index 815787c3bfec..ebb22cb9cd74 100644 --- a/tests/ui/traits/issue-106072.stderr +++ b/tests/ui/traits/issue-106072.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `Foo` is defined multiple times - --> $DIR/issue-106072.rs:5:1 + --> $DIR/issue-106072.rs:3:1 | LL | struct Foo; | ----------- previous definition of the type `Foo` here @@ -9,18 +9,23 @@ LL | trait Foo {} = note: `Foo` must be defined only once in the type namespace of this module error[E0782]: expected a type, found a trait - --> $DIR/issue-106072.rs:1:10 + --> $DIR/issue-106072.rs:2:8 | LL | #[derive(Clone)] - | ^^^^^ + | ----- in this derive macro expansion +LL | struct Foo; + | ^^^ + | +help: you can add the `dyn` keyword if you want a trait object + | +LL | struct dyn Foo; + | +++ error[E0782]: expected a type, found a trait --> $DIR/issue-106072.rs:1:10 | LL | #[derive(Clone)] | ^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/traits/issue-50480.rs b/tests/ui/traits/issue-50480.rs index ccd35a850f2d..2f62906e9df3 100644 --- a/tests/ui/traits/issue-50480.rs +++ b/tests/ui/traits/issue-50480.rs @@ -1,18 +1,17 @@ #[derive(Clone, Copy)] -//~^ ERROR the trait `Copy` cannot be implemented for this type struct Foo(N, NotDefined, ::Item, Vec, String); -//~^ ERROR cannot find type `NotDefined` in this scope +//~^ ERROR the trait `Copy` cannot be implemented for this type +//~| ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `N` in this scope //~| ERROR cannot find type `N` in this scope //~| ERROR `i32` is not an iterator //~| ERROR `i32` is not an iterator -#[derive(Clone, Copy)] -//~^ ERROR the trait `Copy` cannot be implemented for this type -//~| ERROR `i32` is not an iterator +#[derive(Clone, Copy)] //~ ERROR `i32` is not an iterator struct Bar(T, N, NotDefined, ::Item, Vec, String); -//~^ ERROR cannot find type `NotDefined` in this scope +//~^ ERROR the trait `Copy` cannot be implemented for this type +//~| ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `N` in this scope //~| ERROR `i32` is not an iterator //~| ERROR `i32` is not an iterator diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr index 32c8b2cf3ac1..1fb5e8b00783 100644 --- a/tests/ui/traits/issue-50480.stderr +++ b/tests/ui/traits/issue-50480.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find type `N` in this scope - --> $DIR/issue-50480.rs:3:12 + --> $DIR/issue-50480.rs:2:12 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^ not found in this scope @@ -10,13 +10,13 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); | +++ error[E0425]: cannot find type `NotDefined` in this scope - --> $DIR/issue-50480.rs:3:15 + --> $DIR/issue-50480.rs:2:15 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope error[E0425]: cannot find type `N` in this scope - --> $DIR/issue-50480.rs:3:12 + --> $DIR/issue-50480.rs:2:12 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^ not found in this scope @@ -27,7 +27,7 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); | +++ error[E0425]: cannot find type `NotDefined` in this scope - --> $DIR/issue-50480.rs:3:15 + --> $DIR/issue-50480.rs:2:15 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope @@ -38,7 +38,7 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, St | ++++++++++++ error[E0425]: cannot find type `N` in this scope - --> $DIR/issue-50480.rs:14:18 + --> $DIR/issue-50480.rs:12:18 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | - ^ @@ -56,13 +56,13 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, Strin | +++ error[E0425]: cannot find type `NotDefined` in this scope - --> $DIR/issue-50480.rs:14:21 + --> $DIR/issue-50480.rs:12:21 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:3:27 + --> $DIR/issue-50480.rs:2:27 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator @@ -70,29 +70,27 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); = help: the trait `Iterator` is not implemented for `i32` error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-50480.rs:1:17 + --> $DIR/issue-50480.rs:2:8 | LL | #[derive(Clone, Copy)] - | ^^^^ -LL | + | ---- in this derive macro expansion LL | struct Foo(N, NotDefined, ::Item, Vec, String); - | -------- ------ this field does not implement `Copy` + | ^^^ -------- ------ this field does not implement `Copy` | | | this field does not implement `Copy` error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-50480.rs:11:17 + --> $DIR/issue-50480.rs:12:8 | LL | #[derive(Clone, Copy)] - | ^^^^ -... + | ---- in this derive macro expansion LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); - | -------- ------ this field does not implement `Copy` + | ^^^ -------- ------ this field does not implement `Copy` | | | this field does not implement `Copy` error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:14:33 + --> $DIR/issue-50480.rs:12:33 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator @@ -100,7 +98,7 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); = help: the trait `Iterator` is not implemented for `i32` error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:3:28 + --> $DIR/issue-50480.rs:2:28 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^ `i32` is not an iterator @@ -116,11 +114,10 @@ LL | #[derive(Clone, Copy)] = help: the trait `Iterator` is not implemented for `i32` error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:14:33 + --> $DIR/issue-50480.rs:12:33 | LL | #[derive(Clone, Copy)] | ----- in this derive macro expansion -... LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator | diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs index 2b4f7ba9fa29..ceef87d76abb 100644 --- a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs +++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs @@ -12,8 +12,8 @@ // we already face this difficulty, probably. If we need to fix this by reducing the error margin, // we should improve compiletest. -#[derive(Clone, Eq)] //~ ERROR [E0277] -pub struct Struct(T); +#[derive(Clone, Eq)] +pub struct Struct(T); //~ ERROR [E0277] impl PartialEq for Struct where diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr index 290b1df1665d..912286a48faf 100644 --- a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr +++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr @@ -1,8 +1,10 @@ error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/global-cache-and-parallel-frontend.rs:15:17 + --> $DIR/global-cache-and-parallel-frontend.rs:16:12 | LL | #[derive(Clone, Eq)] - | ^^ the trait `Clone` is not implemented for `T` + | -- in this derive macro expansion +LL | pub struct Struct(T); + | ^^^^^^ the trait `Clone` is not implemented for `T` | note: required for `Struct` to implement `PartialEq` --> $DIR/global-cache-and-parallel-frontend.rs:18:19 From b9e5cf7806b824c1080b66755701840f9d88f80b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 20:57:27 +0000 Subject: [PATCH 370/978] Fix incorrect suggestion caused by change in derive expansion Span --- .../rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs | 6 +++++- tests/ui/traits/issue-106072.stderr | 5 ----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index 29f29761b605..57defac577d8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -592,7 +592,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if span.can_be_used_for_suggestions() && poly_trait_ref.trait_ref.trait_def_id().is_some() && !self.maybe_suggest_impl_trait(span, hir_id, hir_bounds, &mut diag) - && !self.maybe_suggest_dyn_trait(hir_id, sugg, &mut diag) + && !self.maybe_suggest_dyn_trait(hir_id, span, sugg, &mut diag) { self.maybe_suggest_add_generic_impl_trait(span, hir_id, &mut diag); } @@ -750,10 +750,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn maybe_suggest_dyn_trait( &self, hir_id: hir::HirId, + span: Span, sugg: Vec<(Span, String)>, diag: &mut Diag<'_>, ) -> bool { let tcx = self.tcx(); + if span.in_derive_expansion() { + return false; + } // Look at the direct HIR parent, since we care about the relationship between // the type and the thing that directly encloses it. diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr index ebb22cb9cd74..57661fda7307 100644 --- a/tests/ui/traits/issue-106072.stderr +++ b/tests/ui/traits/issue-106072.stderr @@ -15,11 +15,6 @@ LL | #[derive(Clone)] | ----- in this derive macro expansion LL | struct Foo; | ^^^ - | -help: you can add the `dyn` keyword if you want a trait object - | -LL | struct dyn Foo; - | +++ error[E0782]: expected a type, found a trait --> $DIR/issue-106072.rs:1:10 From dd8148373fa376541b40e24129251153e0bf5271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 21:16:39 +0000 Subject: [PATCH 371/978] Tweak span labels --- .../src/error_reporting/traits/suggestions.rs | 12 +++------ tests/ui/associated-types/issue-38821.stderr | 27 +++++++------------ .../unsizing-wfcheck-issue-126272.stderr | 16 ++++------- .../ui/consts/const-blocks/trait-error.stderr | 7 ++--- tests/ui/derives/deriving-copyclone.stderr | 21 +++++---------- .../impl_bounds.stderr | 14 +++------- .../issue-104884-trait-impl-sugg-err.stderr | 7 ++--- ...missing-bound-in-derive-copy-impl-2.stderr | 18 +++++-------- .../missing-bound-in-derive-copy-impl.stderr | 18 +++++-------- tests/ui/traits/derive-implicit-bound.stderr | 7 ++--- 10 files changed, 46 insertions(+), 101 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index c9dc390ea0be..70a16b23d276 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3581,7 +3581,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .. })) => { let mut spans = Vec::with_capacity(2); - if let Some(of_trait) = of_trait { + if let Some(of_trait) = of_trait + && !of_trait.trait_ref.path.span.in_derive_expansion() + { spans.push(of_trait.trait_ref.path.span); } spans.push(self_ty.span); @@ -3595,18 +3597,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Some(ExpnKind::Macro(MacroKind::Derive, _)) ) { derived = true; - spans.push_span_label( - data.span.ctxt().outer_expn_data().call_site, - format!( - "unsatisfied trait bound introduced in this `derive` macro" - ), - ); spans.push_span_label( data.span, if data.span.in_derive_expansion() { format!("would need to be `{trait_name}`") } else { - format!("") + format!("unsatisfied trait bound") }, ); } else if !data.span.is_dummy() && !data.span.overlaps(self_ty.span) { diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 58d06860fe30..fae388c98d36 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -98,19 +98,16 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Debug` - --> $DIR/issue-38821.rs:23:10 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion ... LL | pub enum ColumnInsertValue where | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ + | ------------------------------------------------ unsatisfied trait bound = help: consider manually implementing `Debug` to avoid undesired bounds help: consider further restricting the associated type | @@ -152,19 +149,16 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Copy` - --> $DIR/issue-38821.rs:23:17 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion ... LL | pub enum ColumnInsertValue where | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ + | ------------------------------------------------ unsatisfied trait bound = help: consider manually implementing `Copy` to avoid undesired bounds help: consider further restricting the associated type | @@ -235,19 +229,16 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Clone` - --> $DIR/issue-38821.rs:23:23 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion ... LL | pub enum ColumnInsertValue where | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ + | ------------------------------------------------ unsatisfied trait bound = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting the associated type | diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index f90f0b45d967..fc681e655e1a 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -61,15 +61,12 @@ help: the trait `Debug` is implemented for `Bar` LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] | ^^^^^ note: required for `Bar<(dyn Debug + 'static)>` to implement `Debug` - --> $DIR/unsizing-wfcheck-issue-126272.rs:19:10 + --> $DIR/unsizing-wfcheck-issue-126272.rs:20:8 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | struct Bar(T); - | ^^^ - + | ^^^ - unsatisfied trait bound = help: consider manually implementing `Debug` to avoid undesired bounds = note: 2 redundant requirements hidden = note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug` @@ -99,13 +96,10 @@ help: the trait `Eq` is implemented for `Bar` LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] | ^^ note: required for `Bar` to implement `Eq` - --> $DIR/unsizing-wfcheck-issue-126272.rs:19:28 + --> $DIR/unsizing-wfcheck-issue-126272.rs:20:8 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | -- in this derive macro expansion LL | struct Bar(T); | ^^^ - would need to be `Eq` = help: consider manually implementing `Eq` to avoid undesired bounds diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index aa9177d2b017..60402a412362 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -5,13 +5,10 @@ LL | [Foo(String::new()); 4]; | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | note: required for `Foo` to implement `Copy` - --> $DIR/trait-error.rs:1:10 + --> $DIR/trait-error.rs:2:8 | LL | #[derive(Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion LL | struct Foo(T); | ^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index 226163474482..f8d2859f211e 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -7,13 +7,10 @@ LL | is_copy(B { a: 1, b: C }); | required by a bound introduced by this call | note: required for `B` to implement `Copy` - --> $DIR/deriving-copyclone.rs:9:10 + --> $DIR/deriving-copyclone.rs:10:8 | LL | #[derive(Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion LL | struct B { | ^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds @@ -36,13 +33,10 @@ LL | is_clone(B { a: 1, b: C }); | required by a bound introduced by this call | note: required for `B` to implement `Clone` - --> $DIR/deriving-copyclone.rs:9:16 + --> $DIR/deriving-copyclone.rs:10:8 | LL | #[derive(Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | struct B { | ^ - would need to be `Clone` = help: consider manually implementing `Clone` to avoid undesired bounds @@ -65,13 +59,10 @@ LL | is_copy(B { a: 1, b: D }); | required by a bound introduced by this call | note: required for `B` to implement `Copy` - --> $DIR/deriving-copyclone.rs:9:10 + --> $DIR/deriving-copyclone.rs:10:8 | LL | #[derive(Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion LL | struct B { | ^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index d918bd62c2d7..f65675686532 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -29,13 +29,10 @@ LL | type C = String where Self: Copy; | ^^^^ the trait `Copy` is not implemented for `T` | note: required for `Fooy` to implement `Copy` - --> $DIR/impl_bounds.rs:10:10 + --> $DIR/impl_bounds.rs:11:8 | LL | #[derive(Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion LL | struct Fooy(T); | ^^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds @@ -59,13 +56,10 @@ LL | fn d() where Self: Copy {} | ^^^^ the trait `Copy` is not implemented for `T` | note: required for `Fooy` to implement `Copy` - --> $DIR/impl_bounds.rs:10:10 + --> $DIR/impl_bounds.rs:11:8 | LL | #[derive(Copy, Clone)] - | ^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---- in this derive macro expansion LL | struct Fooy(T); | ^^^^ - would need to be `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index e49cf6256cb2..d14f9eae6950 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -37,13 +37,10 @@ LL | #[derive(PartialOrd, AddImpl)] | ^^^^^^^ no implementation for `T < T` and `T > T` | note: required for `PriorityQueue` to implement `PartialOrd` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:8 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ---------- in this derive macro expansion ... LL | struct PriorityQueue(BinaryHeap>); | ^^^^^^^^^^^^^ - would need to be `PartialOrd` diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index 872ce7105ce8..791e2d19f2f9 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -24,15 +24,12 @@ LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Debug` - --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:10 + --> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ^^^^^^^ ---- + | ^^^^^^^ ---- unsatisfied trait bound = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider further restricting type parameter `K` with trait `Copy` @@ -69,15 +66,12 @@ LL | pub size: Vector2, | ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Clone` - --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:23 + --> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ^^^^^^^ ---- + | ^^^^^^^ ---- unsatisfied trait bound = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index f843fb0d6d7e..55d6391f975e 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -60,15 +60,12 @@ LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Debug` - --> $DIR/missing-bound-in-derive-copy-impl.rs:3:10 + --> $DIR/missing-bound-in-derive-copy-impl.rs:4:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ^^^^^^^ ---- + | ^^^^^^^ ---- unsatisfied trait bound = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider restricting type parameter `K` with trait `Copy` @@ -133,15 +130,12 @@ LL | pub size: Vector2, | ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Clone` - --> $DIR/missing-bound-in-derive-copy-impl.rs:3:23 + --> $DIR/missing-bound-in-derive-copy-impl.rs:4:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ^^^^^^^ ---- + | ^^^^^^^ ---- unsatisfied trait bound = help: consider manually implementing `Clone` to avoid undesired bounds help: consider restricting type parameter `K` with trait `Copy` | diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr index 02c7fe9e689e..ee78cba5af27 100644 --- a/tests/ui/traits/derive-implicit-bound.stderr +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -8,13 +8,10 @@ LL | accept_eq(&node); | = help: the trait `PartialEq` is not implemented for `SomeNode` note: required for `Id` to implement `PartialEq` - --> $DIR/derive-implicit-bound.rs:5:10 + --> $DIR/derive-implicit-bound.rs:6:12 | LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ - | | - | unsatisfied trait bound introduced in this `derive` macro - | in this derive macro expansion + | --------- in this derive macro expansion LL | pub struct Id(PhantomData); | ^^ - would need to be `PartialEq` = help: consider manually implementing `PartialEq` to avoid undesired bounds From 20000ca25a90c1704e02e349b9583b0bb00086b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 21:28:58 +0000 Subject: [PATCH 372/978] Point at destructor when denying deriving `Copy` --- compiler/rustc_hir_analysis/messages.ftl | 1 + compiler/rustc_hir_analysis/src/coherence/builtin.rs | 5 +++-- compiler/rustc_hir_analysis/src/errors.rs | 2 ++ compiler/rustc_trait_selection/src/traits/misc.rs | 6 +++--- tests/ui/derives/copy-drop-mutually-exclusive.stderr | 12 ++++++++++++ tests/ui/error-codes/E0184.stderr | 6 ++++++ 6 files changed, 27 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index d9f8eba65c4a..611aa070124a 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -142,6 +142,7 @@ hir_analysis_copy_impl_on_non_adt = hir_analysis_copy_impl_on_type_with_dtor = the trait `Copy` cannot be implemented for this type; the type has a destructor .label = `Copy` not allowed on types with destructors + .note = destructor declared here hir_analysis_cross_crate_traits = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type, not `{$self_ty}` .label = can't implement cross-crate trait with a default impl for non-struct/enum type diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 61562cc1e4f3..558d2ec84e4b 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -121,9 +121,10 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; Err(tcx.dcx().emit_err(errors::CopyImplOnNonAdt { span })) } - Err(CopyImplementationError::HasDestructor) => { + Err(CopyImplementationError::HasDestructor(did)) => { let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; - Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span })) + let impl_ = tcx.def_span(did); + Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span, impl_ })) } Err(CopyImplementationError::HasUnsafeFields) => { let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 2a77d0b997e2..b90ccc6716d0 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -278,6 +278,8 @@ pub(crate) struct CopyImplOnTypeWithDtor { #[primary_span] #[label] pub span: Span, + #[note] + pub impl_: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index f33196bab647..2fd3a6e738cf 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -13,7 +13,7 @@ use crate::traits::{self, FulfillmentError, Obligation, ObligationCause}; pub enum CopyImplementationError<'tcx> { InfringingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>), NotAnAdt, - HasDestructor, + HasDestructor(hir::def_id::DefId), HasUnsafeFields, } @@ -76,8 +76,8 @@ pub fn type_allowed_to_implement_copy<'tcx>( ) .map_err(CopyImplementationError::InfringingFields)?; - if adt.has_dtor(tcx) { - return Err(CopyImplementationError::HasDestructor); + if let Some(did) = adt.destructor(tcx).map(|dtor| dtor.did) { + return Err(CopyImplementationError::HasDestructor(did)); } if impl_safety.is_safe() && self_type.has_unsafe_fields() { diff --git a/tests/ui/derives/copy-drop-mutually-exclusive.stderr b/tests/ui/derives/copy-drop-mutually-exclusive.stderr index f17d33ffbfed..ab2d086c7f5f 100644 --- a/tests/ui/derives/copy-drop-mutually-exclusive.stderr +++ b/tests/ui/derives/copy-drop-mutually-exclusive.stderr @@ -5,6 +5,12 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Foo; | ^^^ `Copy` not allowed on types with destructors + | +note: destructor declared here + --> $DIR/copy-drop-mutually-exclusive.rs:7:5 + | +LL | fn drop(&mut self) {} + | ^^^^^^^^^^^^^^^^^^ error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor --> $DIR/copy-drop-mutually-exclusive.rs:11:8 @@ -13,6 +19,12 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Bar(::std::marker::PhantomData); | ^^^ `Copy` not allowed on types with destructors + | +note: destructor declared here + --> $DIR/copy-drop-mutually-exclusive.rs:14:5 + | +LL | fn drop(&mut self) {} + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/E0184.stderr b/tests/ui/error-codes/E0184.stderr index 98b5305ad0dc..13294959bc3c 100644 --- a/tests/ui/error-codes/E0184.stderr +++ b/tests/ui/error-codes/E0184.stderr @@ -5,6 +5,12 @@ LL | #[derive(Copy)] | ---- in this derive macro expansion LL | struct Foo; | ^^^ `Copy` not allowed on types with destructors + | +note: destructor declared here + --> $DIR/E0184.rs:5:5 + | +LL | fn drop(&mut self) { + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error From 23b766ce631dc90c89f1c71878058a2618b7b8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Jan 2026 21:43:18 +0000 Subject: [PATCH 373/978] fix typo --- compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 2 +- tests/ui/traits/derive-implicit-bound-on-clone.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 285288e87ee0..349b2c756b64 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1937,7 +1937,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.type_implements_trait_shallow(clone_trait_did, expected_ty, self.param_env) { let manually_impl = "consider manually implementing `Clone` to avoid the \ - implict type parameter bounds"; + implicit type parameter bounds"; match &errors[..] { [] => {} [error] => { diff --git a/tests/ui/traits/derive-implicit-bound-on-clone.stderr b/tests/ui/traits/derive-implicit-bound-on-clone.stderr index 0cec4ef7c609..2fb039f96528 100644 --- a/tests/ui/traits/derive-implicit-bound-on-clone.stderr +++ b/tests/ui/traits/derive-implicit-bound-on-clone.stderr @@ -22,7 +22,7 @@ LL | struct ContainsRc { | ^ ^ derive introduces an implicit unsatisfied trait bound `K: Clone` | | | derive introduces an implicit unsatisfied trait bound `T: Clone` - = help: consider manually implementing `Clone` to avoid the implict type parameter bounds + = help: consider manually implementing `Clone` to avoid the implicit type parameter bounds error[E0308]: mismatched types --> $DIR/derive-implicit-bound-on-clone.rs:20:5 @@ -46,7 +46,7 @@ LL | #[derive(Clone)] | ----- in this derive macro expansion LL | struct ContainsRcSingle { | ^ derive introduces an implicit `T: Clone` bound - = help: consider manually implementing `Clone` to avoid the implict type parameter bounds + = help: consider manually implementing `Clone` to avoid the implicit type parameter bounds error: aborting due to 2 previous errors From b534229a3ace7e39381efb8941d8277d17a985f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 19 Jan 2026 18:49:12 +0000 Subject: [PATCH 374/978] remove commented out code --- compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 349b2c756b64..b8f99bbd7e17 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1941,8 +1941,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match &errors[..] { [] => {} [error] => { - // diag.note("{error:#?}"); - // diag.note(format!("{:#?} {:#?} {:#?}", error.obligation, error.obligation.cause, error.obligation.cause.code())); let msg = "`Clone` is not implemented because a trait bound is not \ satisfied"; if let traits::ObligationCauseCode::ImplDerived(data) = From 6c8eee82970d4b1659329a8ff1f9bad7ac66e152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 19 Jan 2026 18:59:32 +0000 Subject: [PATCH 375/978] reword span label --- .../src/error_reporting/traits/suggestions.rs | 2 +- .../adt_const_params/unsizing-wfcheck-issue-126272.stderr | 2 +- tests/ui/consts/const-blocks/trait-error.stderr | 2 +- tests/ui/derives/deriving-copyclone.stderr | 6 +++--- tests/ui/generic-associated-types/impl_bounds.stderr | 4 ++-- tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr | 2 +- tests/ui/traits/derive-implicit-bound.stderr | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 70a16b23d276..1880465eff54 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3600,7 +3600,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { spans.push_span_label( data.span, if data.span.in_derive_expansion() { - format!("would need to be `{trait_name}`") + format!("type parameter would need to implement `{trait_name}`") } else { format!("unsatisfied trait bound") }, diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index fc681e655e1a..f520413927c3 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -101,7 +101,7 @@ note: required for `Bar` to implement `Eq` LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] | -- in this derive macro expansion LL | struct Bar(T); - | ^^^ - would need to be `Eq` + | ^^^ - type parameter would need to implement `Eq` = help: consider manually implementing `Eq` to avoid undesired bounds = note: 1 redundant requirement hidden = note: required for `&'static Bar` to implement `Eq` diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 60402a412362..853e10e0b35a 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -10,7 +10,7 @@ note: required for `Foo` to implement `Copy` LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Foo(T); - | ^^^ - would need to be `Copy` + | ^^^ - type parameter would need to implement `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index f8d2859f211e..40f96919121f 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -12,7 +12,7 @@ note: required for `B` to implement `Copy` LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct B { - | ^ - would need to be `Copy` + | ^ - type parameter would need to implement `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 @@ -38,7 +38,7 @@ note: required for `B` to implement `Clone` LL | #[derive(Copy, Clone)] | ----- in this derive macro expansion LL | struct B { - | ^ - would need to be `Clone` + | ^ - type parameter would need to implement `Clone` = help: consider manually implementing `Clone` to avoid undesired bounds note: required by a bound in `is_clone` --> $DIR/deriving-copyclone.rs:19:16 @@ -64,7 +64,7 @@ note: required for `B` to implement `Copy` LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct B { - | ^ - would need to be `Copy` + | ^ - type parameter would need to implement `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index f65675686532..63c4ba900829 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -34,7 +34,7 @@ note: required for `Fooy` to implement `Copy` LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Fooy(T); - | ^^^^ - would need to be `Copy` + | ^^^^ - type parameter would need to implement `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 @@ -61,7 +61,7 @@ note: required for `Fooy` to implement `Copy` LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Fooy(T); - | ^^^^ - would need to be `Copy` + | ^^^^ - type parameter would need to implement `Copy` = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index d14f9eae6950..b53ebe9f7271 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -43,7 +43,7 @@ LL | #[derive(PartialOrd, AddImpl)] | ---------- in this derive macro expansion ... LL | struct PriorityQueue(BinaryHeap>); - | ^^^^^^^^^^^^^ - would need to be `PartialOrd` + | ^^^^^^^^^^^^^ - type parameter would need to implement `PartialOrd` = help: consider manually implementing `PartialOrd` to avoid undesired bounds note: required by a bound in `Ord` --> $SRC_DIR/core/src/cmp.rs:LL:COL diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr index ee78cba5af27..fe2bc77b9529 100644 --- a/tests/ui/traits/derive-implicit-bound.stderr +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -13,7 +13,7 @@ note: required for `Id` to implement `PartialEq` LL | #[derive(PartialEq, Eq)] | --------- in this derive macro expansion LL | pub struct Id(PhantomData); - | ^^ - would need to be `PartialEq` + | ^^ - type parameter would need to implement `PartialEq` = help: consider manually implementing `PartialEq` to avoid undesired bounds note: required by a bound in `accept_eq` --> $DIR/derive-implicit-bound.rs:17:23 From 879633f97b3affafd87a8726240b8109a7bc8363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 19 Jan 2026 19:24:10 +0000 Subject: [PATCH 376/978] Change note to help --- .../src/diagnostics/conflict_errors.rs | 2 +- tests/ui/associated-types/issue-25700.stderr | 2 +- .../closure-shim-borrowck-error.stderr | 2 +- .../async-closures/move-out-of-ref.stderr | 2 +- .../borrowck-move-out-of-static-item.stderr | 2 +- .../borrowck-move-subcomponent.stderr | 2 +- .../borrowck/borrowck-overloaded-call.stderr | 2 +- tests/ui/borrowck/clone-on-ref.stderr | 2 +- .../borrowck/derive-clone-implicit-bound.rs | 4 ++-- .../derive-clone-implicit-bound.stderr | 2 +- tests/ui/borrowck/issue-103624.stderr | 2 +- .../issue-119915-bad-clone-suggestion.stderr | 2 +- .../borrowck/issue-17718-static-move.stderr | 2 +- tests/ui/borrowck/issue-20801.stderr | 8 +++---- .../borrowck/move-error-in-promoted-2.stderr | 2 +- tests/ui/borrowck/move-error-snippets.stderr | 2 +- ...e-in-static-initializer-issue-38520.stderr | 4 ++-- tests/ui/box/leak-alloc.stderr | 2 +- .../closure-move-use-after-move-diagnostic.rs | 2 +- ...sure-move-use-after-move-diagnostic.stderr | 2 +- tests/ui/coroutine/moved-twice.stderr | 2 +- .../derives/deriving-with-repr-packed.stderr | 2 +- tests/ui/error-codes/E0504.stderr | 2 +- tests/ui/error-codes/E0505.stderr | 2 +- tests/ui/error-codes/E0507.stderr | 2 +- tests/ui/error-codes/E0508-fail.stderr | 2 +- tests/ui/error-codes/E0508.stderr | 2 +- tests/ui/error-codes/E0509.stderr | 2 +- tests/ui/mir/issue-102389.stderr | 2 +- tests/ui/moves/issue-72649-uninit-in-loop.rs | 10 ++++---- .../moves/issue-72649-uninit-in-loop.stderr | 15 ++++++------ .../issue-75904-move-closure-loop.stderr | 2 +- ...atching-partially-moved-value-17385.stderr | 4 ++-- tests/ui/moves/move-fn-self-receiver.stderr | 2 +- tests/ui/moves/move-out-of-array-1.stderr | 2 +- .../ui/moves/moved-value-on-as-ref-arg.stderr | 4 ++-- .../issue-21232-partial-init-and-use.stderr | 4 ++-- tests/ui/nll/move-errors.stderr | 12 +++++----- .../pin-ergonomics/borrow-unpin.pinned.stderr | 24 +++++++++---------- .../pin-ergonomics/borrow-unpin.unpin.stderr | 6 ++--- tests/ui/pin-macro/pin_move.stderr | 4 ++-- .../non_copy_move_out_of_tuple.stderr | 2 +- .../suggestions/option-content-move3.stderr | 4 ++-- .../union-borrow-move-parent-sibling.stderr | 2 +- tests/ui/union/union-move.stderr | 4 ++-- tests/ui/variance/variance-issue-20533.stderr | 8 +++---- 46 files changed, 90 insertions(+), 87 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 692ce240e36f..72a35de73f32 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1301,7 +1301,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ), ); span.push_span_label(expr.span, "you could clone this value"); - err.span_note( + err.span_help( span, format!("if `{ty}` implemented `Clone`, you could clone the value"), ); diff --git a/tests/ui/associated-types/issue-25700.stderr b/tests/ui/associated-types/issue-25700.stderr index 8d40e6905e07..595aefc9a215 100644 --- a/tests/ui/associated-types/issue-25700.stderr +++ b/tests/ui/associated-types/issue-25700.stderr @@ -8,7 +8,7 @@ LL | drop(t); LL | drop(t); | ^ value used here after move | -note: if `S<()>` implemented `Clone`, you could clone the value +help: if `S<()>` implemented `Clone`, you could clone the value --> $DIR/issue-25700.rs:1:1 | LL | struct S(#[allow(dead_code)] Option<&'static T>); diff --git a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr index 3fe1431fda71..a4d239090830 100644 --- a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr +++ b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr @@ -9,7 +9,7 @@ LL | LL | x.hello(); | - variable moved due to use in coroutine | -note: if `Ty` implemented `Clone`, you could clone the value +help: if `Ty` implemented `Clone`, you could clone the value --> $DIR/closure-shim-borrowck-error.rs:17:1 | LL | x.hello(); diff --git a/tests/ui/async-await/async-closures/move-out-of-ref.stderr b/tests/ui/async-await/async-closures/move-out-of-ref.stderr index d443dc9d4831..c516597c81f9 100644 --- a/tests/ui/async-await/async-closures/move-out-of-ref.stderr +++ b/tests/ui/async-await/async-closures/move-out-of-ref.stderr @@ -7,7 +7,7 @@ LL | let c = async || { LL | *x; | ^^ `*x` is moved here | -note: if `Ty` implemented `Clone`, you could clone the value +help: if `Ty` implemented `Clone`, you could clone the value --> $DIR/move-out-of-ref.rs:5:1 | LL | struct Ty; diff --git a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr index b4b60d40d914..9eb90e169fd3 100644 --- a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr +++ b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of static item `BAR` LL | test(BAR); | ^^^ move occurs because `BAR` has type `Foo`, which does not implement the `Copy` trait | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrowck-move-out-of-static-item.rs:3:1 | LL | struct Foo { diff --git a/tests/ui/borrowck/borrowck-move-subcomponent.stderr b/tests/ui/borrowck/borrowck-move-subcomponent.stderr index b5dc01f180b2..8dcb81273f89 100644 --- a/tests/ui/borrowck/borrowck-move-subcomponent.stderr +++ b/tests/ui/borrowck/borrowck-move-subcomponent.stderr @@ -10,7 +10,7 @@ LL | let S { x: ax } = a; LL | f(pb); | -- borrow later used here | -note: if `S` implemented `Clone`, you could clone the value +help: if `S` implemented `Clone`, you could clone the value --> $DIR/borrowck-move-subcomponent.rs:6:1 | LL | struct S { diff --git a/tests/ui/borrowck/borrowck-overloaded-call.stderr b/tests/ui/borrowck/borrowck-overloaded-call.stderr index c3b7b0b6080c..c838c6512bc4 100644 --- a/tests/ui/borrowck/borrowck-overloaded-call.stderr +++ b/tests/ui/borrowck/borrowck-overloaded-call.stderr @@ -30,7 +30,7 @@ LL | s(" world".to_string()); LL | s(" world".to_string()); | ^ value used here after move | -note: if `SFnOnce` implemented `Clone`, you could clone the value +help: if `SFnOnce` implemented `Clone`, you could clone the value --> $DIR/borrowck-overloaded-call.rs:41:1 | LL | struct SFnOnce { diff --git a/tests/ui/borrowck/clone-on-ref.stderr b/tests/ui/borrowck/clone-on-ref.stderr index 72580e7464b7..535550409dd8 100644 --- a/tests/ui/borrowck/clone-on-ref.stderr +++ b/tests/ui/borrowck/clone-on-ref.stderr @@ -59,7 +59,7 @@ LL | LL | println!("{b:?}"); | - borrow later used here | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/clone-on-ref.rs:19:1 | LL | struct A; diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.rs b/tests/ui/borrowck/derive-clone-implicit-bound.rs index a20e04d3afdc..12fd2129331b 100644 --- a/tests/ui/borrowck/derive-clone-implicit-bound.rs +++ b/tests/ui/borrowck/derive-clone-implicit-bound.rs @@ -4,7 +4,7 @@ use std::marker::PhantomData; #[derive(Clone, Copy)] //~ NOTE derived `Clone` adds implicit bounds on type parameters pub struct TypedAddress{ -//~^ NOTE if `TypedAddress` implemented `Clone`, you could clone the value +//~^ HELP if `TypedAddress` implemented `Clone`, you could clone the value //~| NOTE consider manually implementing `Clone` for this type //~| NOTE introduces an implicit `T: Clone` bound inner: u64, @@ -19,7 +19,7 @@ pub trait Memory { //~| NOTE this parameter takes ownership of the value fn update_value(&self, offset: TypedAddress, update: F) //~^ NOTE move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait - where F: FnOnce(T) -> T + where F: FnOnce(T) -> T //~ HELP consider further restricting type parameter `T` { let old = self.return_value(offset); //~ NOTE value moved here //~^ NOTE you could clone this value diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.stderr b/tests/ui/borrowck/derive-clone-implicit-bound.stderr index b10e3a92c96b..31a55b448eb6 100644 --- a/tests/ui/borrowck/derive-clone-implicit-bound.stderr +++ b/tests/ui/borrowck/derive-clone-implicit-bound.stderr @@ -15,7 +15,7 @@ note: consider changing this parameter type in method `return_value` to borrow i | LL | fn return_value(&self, offset: TypedAddress) -> T; | ------------ in this method ^^^^^^^^^^^^^^^ this parameter takes ownership of the value -note: if `TypedAddress` implemented `Clone`, you could clone the value +help: if `TypedAddress` implemented `Clone`, you could clone the value --> $DIR/derive-clone-implicit-bound.rs:6:1 | LL | #[derive(Clone, Copy)] diff --git a/tests/ui/borrowck/issue-103624.stderr b/tests/ui/borrowck/issue-103624.stderr index bd6c1c44bfb3..85769e187691 100644 --- a/tests/ui/borrowck/issue-103624.stderr +++ b/tests/ui/borrowck/issue-103624.stderr @@ -18,7 +18,7 @@ help: `Fn` and `FnMut` closures require captured values to be able to be consume | LL | async fn spawn_blocking(f: impl (Fn() -> T) + Send + Sync + 'static) -> T { | ^^^^^^^^^^^ -note: if `StructB` implemented `Clone`, you could clone the value +help: if `StructB` implemented `Clone`, you could clone the value --> $DIR/issue-103624.rs:23:1 | LL | self.b; diff --git a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr index dde17d1f6523..a5a218a0641d 100644 --- a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr +++ b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr @@ -11,7 +11,7 @@ note: `Example::::change` takes ownership of the receiver `self`, | LL | unsafe fn change(self) -> Example { | ^^^^ -note: if `Example` implemented `Clone`, you could clone the value +help: if `Example` implemented `Clone`, you could clone the value --> $DIR/issue-119915-bad-clone-suggestion.rs:3:1 | LL | struct Example(PhantomData<(fn(E), fn(FakeParam))>); diff --git a/tests/ui/borrowck/issue-17718-static-move.stderr b/tests/ui/borrowck/issue-17718-static-move.stderr index 057ac6d7e3df..959b1d1a3b84 100644 --- a/tests/ui/borrowck/issue-17718-static-move.stderr +++ b/tests/ui/borrowck/issue-17718-static-move.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of static item `FOO` LL | let _a = FOO; | ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/issue-17718-static-move.rs:1:1 | LL | struct Foo; diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr index 5fda92634d8f..5336352e0dbd 100644 --- a/tests/ui/borrowck/issue-20801.stderr +++ b/tests/ui/borrowck/issue-20801.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of a mutable reference LL | let a = unsafe { *mut_ref() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -note: if `T` implemented `Clone`, you could clone the value +help: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -24,7 +24,7 @@ error[E0507]: cannot move out of a shared reference LL | let b = unsafe { *imm_ref() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -note: if `T` implemented `Clone`, you could clone the value +help: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -44,7 +44,7 @@ error[E0507]: cannot move out of a raw pointer LL | let c = unsafe { *mut_ptr() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -note: if `T` implemented `Clone`, you could clone the value +help: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -59,7 +59,7 @@ error[E0507]: cannot move out of a raw pointer LL | let d = unsafe { *const_ptr() }; | ^^^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -note: if `T` implemented `Clone`, you could clone the value +help: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); diff --git a/tests/ui/borrowck/move-error-in-promoted-2.stderr b/tests/ui/borrowck/move-error-in-promoted-2.stderr index 1e9b1d5209cb..f2bc6bd4760a 100644 --- a/tests/ui/borrowck/move-error-in-promoted-2.stderr +++ b/tests/ui/borrowck/move-error-in-promoted-2.stderr @@ -7,7 +7,7 @@ LL | &([S][0],); | cannot move out of here | move occurs because value has type `S`, which does not implement the `Copy` trait | -note: if `S` implemented `Clone`, you could clone the value +help: if `S` implemented `Clone`, you could clone the value --> $DIR/move-error-in-promoted-2.rs:3:1 | LL | struct S; diff --git a/tests/ui/borrowck/move-error-snippets.stderr b/tests/ui/borrowck/move-error-snippets.stderr index 97d140515184..3796b7e05fb4 100644 --- a/tests/ui/borrowck/move-error-snippets.stderr +++ b/tests/ui/borrowck/move-error-snippets.stderr @@ -9,7 +9,7 @@ LL | let a = $c; LL | sss!(); | ------ in this macro invocation | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-error-snippets.rs:9:1 | LL | struct A; diff --git a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr index 009e85a8031e..af5cbdcf150f 100644 --- a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr +++ b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | static Y: usize = get(*&X); | ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-in-static-initializer-issue-38520.rs:5:1 | LL | struct Foo(usize); @@ -19,7 +19,7 @@ error[E0507]: cannot move out of a shared reference LL | const Z: usize = get(*&X); | ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-in-static-initializer-issue-38520.rs:5:1 | LL | struct Foo(usize); diff --git a/tests/ui/box/leak-alloc.stderr b/tests/ui/box/leak-alloc.stderr index bdaa9449f913..f0d6dd3d4692 100644 --- a/tests/ui/box/leak-alloc.stderr +++ b/tests/ui/box/leak-alloc.stderr @@ -12,7 +12,7 @@ LL | LL | use_value(*theref) | ------- borrow later used here | -note: if `Alloc` implemented `Clone`, you could clone the value +help: if `Alloc` implemented `Clone`, you could clone the value --> $DIR/leak-alloc.rs:8:1 | LL | struct Alloc {} diff --git a/tests/ui/closures/closure-move-use-after-move-diagnostic.rs b/tests/ui/closures/closure-move-use-after-move-diagnostic.rs index 3326af7486c5..b55c8c16f611 100644 --- a/tests/ui/closures/closure-move-use-after-move-diagnostic.rs +++ b/tests/ui/closures/closure-move-use-after-move-diagnostic.rs @@ -1,5 +1,5 @@ //! regression test for -struct NoCopy; //~ NOTE if `NoCopy` implemented `Clone`, you could clone the value +struct NoCopy; //~ HELP if `NoCopy` implemented `Clone`, you could clone the value //~^ NOTE consider implementing `Clone` for this type fn main() { let x = NoCopy; diff --git a/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr b/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr index 94f80da1b10a..bde39ca6ca71 100644 --- a/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr +++ b/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr @@ -13,7 +13,7 @@ LL | let y = x; LL | let z = x; | ^ value used here after move | -note: if `NoCopy` implemented `Clone`, you could clone the value +help: if `NoCopy` implemented `Clone`, you could clone the value --> $DIR/closure-move-use-after-move-diagnostic.rs:2:1 | LL | struct NoCopy; diff --git a/tests/ui/coroutine/moved-twice.stderr b/tests/ui/coroutine/moved-twice.stderr index 2b21f6c59f0b..561b3b331d9f 100644 --- a/tests/ui/coroutine/moved-twice.stderr +++ b/tests/ui/coroutine/moved-twice.stderr @@ -10,7 +10,7 @@ LL | yield; LL | let second = first; | ^^^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/moved-twice.rs:9:1 | LL | struct Foo([u8; FOO_SIZE]); diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr index 9cfc4abdc0cb..7c716fb9dd4c 100644 --- a/tests/ui/derives/deriving-with-repr-packed.stderr +++ b/tests/ui/derives/deriving-with-repr-packed.stderr @@ -7,7 +7,7 @@ LL | #[repr(packed)] LL | struct X(Y); | ^ move occurs because value has type `Y`, which does not implement the `Copy` trait | -note: if `Y` implemented `Clone`, you could clone the value +help: if `Y` implemented `Clone`, you could clone the value --> $DIR/deriving-with-repr-packed.rs:16:1 | LL | struct Y(usize); diff --git a/tests/ui/error-codes/E0504.stderr b/tests/ui/error-codes/E0504.stderr index c4cbc834ad98..528f311765df 100644 --- a/tests/ui/error-codes/E0504.stderr +++ b/tests/ui/error-codes/E0504.stderr @@ -14,7 +14,7 @@ LL | println!("child function: {}", fancy_num.num); LL | println!("main function: {}", fancy_ref.num); | ------------- borrow later used here | -note: if `FancyNum` implemented `Clone`, you could clone the value +help: if `FancyNum` implemented `Clone`, you could clone the value --> $DIR/E0504.rs:2:1 | LL | struct FancyNum { diff --git a/tests/ui/error-codes/E0505.stderr b/tests/ui/error-codes/E0505.stderr index 3f2913e9fe3c..ac0f390bc54b 100644 --- a/tests/ui/error-codes/E0505.stderr +++ b/tests/ui/error-codes/E0505.stderr @@ -11,7 +11,7 @@ LL | eat(x); LL | _ref_to_val.use_ref(); | ----------- borrow later used here | -note: if `Value` implemented `Clone`, you could clone the value +help: if `Value` implemented `Clone`, you could clone the value --> $DIR/E0505.rs:1:1 | LL | struct Value {} diff --git a/tests/ui/error-codes/E0507.stderr b/tests/ui/error-codes/E0507.stderr index 70d99ea2cce5..ac03e5ea9cd5 100644 --- a/tests/ui/error-codes/E0507.stderr +++ b/tests/ui/error-codes/E0507.stderr @@ -11,7 +11,7 @@ note: `TheDarkKnight::nothing_is_true` takes ownership of the receiver `self`, w | LL | fn nothing_is_true(self) {} | ^^^^ -note: if `TheDarkKnight` implemented `Clone`, you could clone the value +help: if `TheDarkKnight` implemented `Clone`, you could clone the value --> $DIR/E0507.rs:3:1 | LL | struct TheDarkKnight; diff --git a/tests/ui/error-codes/E0508-fail.stderr b/tests/ui/error-codes/E0508-fail.stderr index fcfac399e0df..48ede17dc26a 100644 --- a/tests/ui/error-codes/E0508-fail.stderr +++ b/tests/ui/error-codes/E0508-fail.stderr @@ -7,7 +7,7 @@ LL | let _value = array[0]; | cannot move out of here | move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/E0508-fail.rs:1:1 | LL | struct NonCopy; diff --git a/tests/ui/error-codes/E0508.stderr b/tests/ui/error-codes/E0508.stderr index b9fa0f4d17a5..c001b9461ebf 100644 --- a/tests/ui/error-codes/E0508.stderr +++ b/tests/ui/error-codes/E0508.stderr @@ -7,7 +7,7 @@ LL | let _value = array[0]; | cannot move out of here | move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/E0508.rs:1:1 | LL | struct NonCopy; diff --git a/tests/ui/error-codes/E0509.stderr b/tests/ui/error-codes/E0509.stderr index 628a253e0859..89c3a5848423 100644 --- a/tests/ui/error-codes/E0509.stderr +++ b/tests/ui/error-codes/E0509.stderr @@ -7,7 +7,7 @@ LL | let fancy_field = drop_struct.fancy; | cannot move out of here | move occurs because `drop_struct.fancy` has type `FancyNum`, which does not implement the `Copy` trait | -note: if `FancyNum` implemented `Clone`, you could clone the value +help: if `FancyNum` implemented `Clone`, you could clone the value --> $DIR/E0509.rs:1:1 | LL | struct FancyNum { diff --git a/tests/ui/mir/issue-102389.stderr b/tests/ui/mir/issue-102389.stderr index 162d7ac031a6..7aafe081deaf 100644 --- a/tests/ui/mir/issue-102389.stderr +++ b/tests/ui/mir/issue-102389.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of `*inbounds` which is behind a shared reference LL | array[*inbounds as usize] | ^^^^^^^^^ move occurs because `*inbounds` has type `Enum`, which does not implement the `Copy` trait | -note: if `Enum` implemented `Clone`, you could clone the value +help: if `Enum` implemented `Clone`, you could clone the value --> $DIR/issue-102389.rs:1:1 | LL | enum Enum { A, B, C } diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.rs b/tests/ui/moves/issue-72649-uninit-in-loop.rs index 8f2e01bdf1ab..965a4206253e 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.rs +++ b/tests/ui/moves/issue-72649-uninit-in-loop.rs @@ -3,10 +3,10 @@ // 'value moved in previous iteration of loop' message struct NonCopy; -//~^ NOTE if `NonCopy` implemented `Clone` -//~| NOTE if `NonCopy` implemented `Clone` -//~| NOTE if `NonCopy` implemented `Clone` -//~| NOTE if `NonCopy` implemented `Clone` +//~^ HELP if `NonCopy` implemented `Clone` +//~| HELP if `NonCopy` implemented `Clone` +//~| HELP if `NonCopy` implemented `Clone` +//~| HELP if `NonCopy` implemented `Clone` //~| NOTE consider implementing `Clone` for this type //~| NOTE consider implementing `Clone` for this type //~| NOTE consider implementing `Clone` for this type @@ -70,6 +70,7 @@ fn moved_loop_2() { fn uninit_1() { loop { let value: NonCopy; //~ NOTE declared here + //~^ HELP consider assigning a value let _used = value; //~ ERROR binding `value` isn't initialized //~^ NOTE `value` used here but it isn't initialized } @@ -77,6 +78,7 @@ fn uninit_1() { fn uninit_2() { let mut value: NonCopy; //~ NOTE declared here + //~^ HELP consider assigning a value loop { let _used = value; //~ ERROR binding `value` isn't initialized //~^ NOTE `value` used here but it isn't initialized diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.stderr b/tests/ui/moves/issue-72649-uninit-in-loop.stderr index 3a93769ac454..1c54d3997ed6 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.stderr +++ b/tests/ui/moves/issue-72649-uninit-in-loop.stderr @@ -10,7 +10,7 @@ LL | let _used = value; LL | let _used2 = value; | ^^^^^ value used here after move | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -33,7 +33,7 @@ LL | let _used = value; LL | let _used2 = value; | ^^^^^ value used here after move | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -53,7 +53,7 @@ LL | loop { LL | let _used = value; | ^^^^^ value moved here, in previous iteration of loop | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -73,7 +73,7 @@ LL | loop { LL | let _used2 = value; | ^^^^^ value moved here, in previous iteration of loop | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -83,10 +83,11 @@ LL | let _used2 = value; | ----- you could clone this value error[E0381]: used binding `value` isn't initialized - --> $DIR/issue-72649-uninit-in-loop.rs:73:21 + --> $DIR/issue-72649-uninit-in-loop.rs:74:21 | LL | let value: NonCopy; | ----- binding declared here but left uninitialized +LL | LL | let _used = value; | ^^^^^ `value` used here but it isn't initialized | @@ -96,11 +97,11 @@ LL | let value: NonCopy = /* value */; | +++++++++++++ error[E0381]: used binding `value` isn't initialized - --> $DIR/issue-72649-uninit-in-loop.rs:81:21 + --> $DIR/issue-72649-uninit-in-loop.rs:83:21 | LL | let mut value: NonCopy; | --------- binding declared here but left uninitialized -LL | loop { +... LL | let _used = value; | ^^^^^ `value` used here but it isn't initialized | diff --git a/tests/ui/moves/issue-75904-move-closure-loop.stderr b/tests/ui/moves/issue-75904-move-closure-loop.stderr index 815e91b0f4df..3fc50c48315d 100644 --- a/tests/ui/moves/issue-75904-move-closure-loop.stderr +++ b/tests/ui/moves/issue-75904-move-closure-loop.stderr @@ -11,7 +11,7 @@ LL | &mut a; LL | a; | - use occurs due to use in closure | -note: if `NotCopy` implemented `Clone`, you could clone the value +help: if `NotCopy` implemented `Clone`, you could clone the value --> $DIR/issue-75904-move-closure-loop.rs:5:1 | LL | struct NotCopy; diff --git a/tests/ui/moves/matching-partially-moved-value-17385.stderr b/tests/ui/moves/matching-partially-moved-value-17385.stderr index 906f7868bccb..83f4f4320485 100644 --- a/tests/ui/moves/matching-partially-moved-value-17385.stderr +++ b/tests/ui/moves/matching-partially-moved-value-17385.stderr @@ -8,7 +8,7 @@ LL | drop(foo); LL | match foo { | ^^^^^^^^^ value used here after move | -note: if `X` implemented `Clone`, you could clone the value +help: if `X` implemented `Clone`, you could clone the value --> $DIR/matching-partially-moved-value-17385.rs:2:1 | LL | struct X(isize); @@ -27,7 +27,7 @@ LL | drop(e); LL | match e { | ^ value used here after move | -note: if `Enum` implemented `Clone`, you could clone the value +help: if `Enum` implemented `Clone`, you could clone the value --> $DIR/matching-partially-moved-value-17385.rs:4:1 | LL | enum Enum { diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr index de19a99d388c..b3a1215fa2f7 100644 --- a/tests/ui/moves/move-fn-self-receiver.stderr +++ b/tests/ui/moves/move-fn-self-receiver.stderr @@ -132,7 +132,7 @@ LL | foo_add + Foo; LL | foo_add; | ^^^^^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-fn-self-receiver.rs:5:1 | LL | struct Foo; diff --git a/tests/ui/moves/move-out-of-array-1.stderr b/tests/ui/moves/move-out-of-array-1.stderr index 8a030f021920..7ef859200b21 100644 --- a/tests/ui/moves/move-out-of-array-1.stderr +++ b/tests/ui/moves/move-out-of-array-1.stderr @@ -7,7 +7,7 @@ LL | a[i] | cannot move out of here | move occurs because `a[_]` has type `D`, which does not implement the `Copy` trait | -note: if `D` implemented `Clone`, you could clone the value +help: if `D` implemented `Clone`, you could clone the value --> $DIR/move-out-of-array-1.rs:5:1 | LL | struct D { _x: u8 } diff --git a/tests/ui/moves/moved-value-on-as-ref-arg.stderr b/tests/ui/moves/moved-value-on-as-ref-arg.stderr index a99bdb4fe9d4..b553938c6fed 100644 --- a/tests/ui/moves/moved-value-on-as-ref-arg.stderr +++ b/tests/ui/moves/moved-value-on-as-ref-arg.stderr @@ -23,7 +23,7 @@ LL | qux(bar); LL | let _baa = bar; | ^^^ value used here after move | -note: if `Bar` implemented `Clone`, you could clone the value +help: if `Bar` implemented `Clone`, you could clone the value --> $DIR/moved-value-on-as-ref-arg.rs:5:1 | LL | struct Bar; @@ -61,7 +61,7 @@ LL | baz(bar); LL | let _baa = bar; | ^^^ value used here after move | -note: if `Bar` implemented `Clone`, you could clone the value +help: if `Bar` implemented `Clone`, you could clone the value --> $DIR/moved-value-on-as-ref-arg.rs:5:1 | LL | struct Bar; diff --git a/tests/ui/nll/issue-21232-partial-init-and-use.stderr b/tests/ui/nll/issue-21232-partial-init-and-use.stderr index 496a298a36ce..84c543921687 100644 --- a/tests/ui/nll/issue-21232-partial-init-and-use.stderr +++ b/tests/ui/nll/issue-21232-partial-init-and-use.stderr @@ -28,7 +28,7 @@ LL | let mut s: S = S::new(); drop(s); LL | s.x = 10; s.y = Box::new(20); | ^^^^^^^^ value partially assigned here after move | -note: if `S>` implemented `Clone`, you could clone the value +help: if `S>` implemented `Clone`, you could clone the value --> $DIR/issue-21232-partial-init-and-use.rs:15:1 | LL | struct S { @@ -82,7 +82,7 @@ LL | let mut s: S = S::new(); drop(s); LL | s.x = 10; | ^^^^^^^^ value partially assigned here after move | -note: if `S>` implemented `Clone`, you could clone the value +help: if `S>` implemented `Clone`, you could clone the value --> $DIR/issue-21232-partial-init-and-use.rs:15:1 | LL | struct S { diff --git a/tests/ui/nll/move-errors.stderr b/tests/ui/nll/move-errors.stderr index bcb2ab84a239..e84f75455217 100644 --- a/tests/ui/nll/move-errors.stderr +++ b/tests/ui/nll/move-errors.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference LL | let b = *a; | ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -27,7 +27,7 @@ LL | let b = a[0]; | cannot move out of here | move occurs because `a[_]` has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -46,7 +46,7 @@ error[E0507]: cannot move out of `**r` which is behind a shared reference LL | let s = **r; | ^^^ move occurs because `**r` has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -66,7 +66,7 @@ error[E0507]: cannot move out of an `Rc` LL | let s = *r; | ^^ move occurs because value has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -89,7 +89,7 @@ LL | let a = [A("".to_string())][0]; | cannot move out of here | move occurs because value has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -137,7 +137,7 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference LL | b = *a; | ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait | -note: if `A` implemented `Clone`, you could clone the value +help: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); diff --git a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr index cc438461a5d1..f9bef8d83f96 100644 --- a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr +++ b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr @@ -8,7 +8,7 @@ LL | foo_pin_mut(&pin mut foo); LL | foo_move(foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -27,7 +27,7 @@ LL | let x = &pin mut foo; LL | foo_move(foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -46,7 +46,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_move(foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -65,7 +65,7 @@ LL | let x = &pin mut foo; // ok LL | foo_move(foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -87,7 +87,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -106,7 +106,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_ref(&foo); | ^^^^ value borrowed here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -125,7 +125,7 @@ LL | let x = &pin mut foo; // ok LL | foo_ref(&foo); | ^^^^ value borrowed here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -144,7 +144,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_pin_mut(&pin mut foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -163,7 +163,7 @@ LL | let x = &pin mut foo; // ok LL | foo_pin_mut(&pin mut foo); | ^^^ value used here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -185,7 +185,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -204,7 +204,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_pin_ref(&pin const foo); | ^^^^^^^^^^^^^^ value borrowed here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -223,7 +223,7 @@ LL | let x = &pin mut foo; // ok LL | foo_pin_ref(&pin const foo); | ^^^^^^^^^^^^^^ value borrowed here after move | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); diff --git a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr index bf9921343ee7..523191655813 100644 --- a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr +++ b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr @@ -33,7 +33,7 @@ LL | LL | foo_pin_mut(x); // | - borrow later used here | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; @@ -55,7 +55,7 @@ LL | LL | foo_pin_mut(x); // | - borrow later used here | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; @@ -77,7 +77,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -note: if `Foo` implemented `Clone`, you could clone the value +help: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; diff --git a/tests/ui/pin-macro/pin_move.stderr b/tests/ui/pin-macro/pin_move.stderr index 3f4660209885..cf7d50091ba4 100644 --- a/tests/ui/pin-macro/pin_move.stderr +++ b/tests/ui/pin-macro/pin_move.stderr @@ -8,7 +8,7 @@ LL | pin!(pointee); LL | let _moved = pointee; | ^^^^^^^ value used here after move | -note: if `a::NotCopy` implemented `Clone`, you could clone the value +help: if `a::NotCopy` implemented `Clone`, you could clone the value --> $DIR/pin_move.rs:7:5 | LL | struct NotCopy(T); @@ -23,7 +23,7 @@ error[E0507]: cannot move out of a mutable reference LL | pin!(*&mut pointee); | ^^^^^^^^^^^^^ move occurs because value has type `b::NotCopy`, which does not implement the `Copy` trait | -note: if `b::NotCopy` implemented `Clone`, you could clone the value +help: if `b::NotCopy` implemented `Clone`, you could clone the value --> $DIR/pin_move.rs:16:5 | LL | struct NotCopy(T); diff --git a/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr index 62f24324fcc1..5e447a57bfee 100644 --- a/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr +++ b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr @@ -7,7 +7,7 @@ LL | (b,) = *tuple; | data moved here | move occurs because the place has type `NonCopy`, which does not implement the `Copy` trait | -note: if `NonCopy` implemented `Clone`, you could clone the value +help: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/non_copy_move_out_of_tuple.rs:3:1 | LL | struct NonCopy; diff --git a/tests/ui/suggestions/option-content-move3.stderr b/tests/ui/suggestions/option-content-move3.stderr index f78d3cf67862..cd13592d652e 100644 --- a/tests/ui/suggestions/option-content-move3.stderr +++ b/tests/ui/suggestions/option-content-move3.stderr @@ -10,7 +10,7 @@ LL | let x = var; | ^^^ move occurs because `var` has type `NotCopyable`, which does not implement the `Copy` trait | = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once -note: if `NotCopyable` implemented `Clone`, you could clone the value +help: if `NotCopyable` implemented `Clone`, you could clone the value --> $DIR/option-content-move3.rs:2:1 | LL | struct NotCopyable; @@ -43,7 +43,7 @@ help: `Fn` and `FnMut` closures require captured values to be able to be consume | LL | fn func H, H: FnMut()>(_: F) {} | ^^^^^^^^^^^^ -note: if `NotCopyable` implemented `Clone`, you could clone the value +help: if `NotCopyable` implemented `Clone`, you could clone the value --> $DIR/option-content-move3.rs:2:1 | LL | struct NotCopyable; diff --git a/tests/ui/union/union-borrow-move-parent-sibling.stderr b/tests/ui/union/union-borrow-move-parent-sibling.stderr index 461ee407e2dd..5974441dd807 100644 --- a/tests/ui/union/union-borrow-move-parent-sibling.stderr +++ b/tests/ui/union/union-borrow-move-parent-sibling.stderr @@ -59,7 +59,7 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec, Moc LL | let a = (u.x.0).0; | ^^^^^^^^^ move occurs because value has type `MockVec`, which does not implement the `Copy` trait | -note: if `MockVec` implemented `Clone`, you could clone the value +help: if `MockVec` implemented `Clone`, you could clone the value --> $DIR/union-borrow-move-parent-sibling.rs:25:1 | LL | struct MockVec { diff --git a/tests/ui/union/union-move.stderr b/tests/ui/union/union-move.stderr index d520fb00ea9d..6266bb4770e0 100644 --- a/tests/ui/union/union-move.stderr +++ b/tests/ui/union/union-move.stderr @@ -16,7 +16,7 @@ LL | fn move_out(x: T) {} | -------- ^ this parameter takes ownership of the value | | | in this function -note: if `U1` implemented `Clone`, you could clone the value +help: if `U1` implemented `Clone`, you could clone the value --> $DIR/union-move.rs:9:1 | LL | union U1 { @@ -43,7 +43,7 @@ LL | fn move_out(x: T) {} | -------- ^ this parameter takes ownership of the value | | | in this function -note: if `U1` implemented `Clone`, you could clone the value +help: if `U1` implemented `Clone`, you could clone the value --> $DIR/union-move.rs:9:1 | LL | union U1 { diff --git a/tests/ui/variance/variance-issue-20533.stderr b/tests/ui/variance/variance-issue-20533.stderr index 21d8de6ae881..2a33a88bdd56 100644 --- a/tests/ui/variance/variance-issue-20533.stderr +++ b/tests/ui/variance/variance-issue-20533.stderr @@ -10,7 +10,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -note: if `AffineU32` implemented `Clone`, you could clone the value +help: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -31,7 +31,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -note: if `AffineU32` implemented `Clone`, you could clone the value +help: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -52,7 +52,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -note: if `AffineU32` implemented `Clone`, you could clone the value +help: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -73,7 +73,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -note: if `AffineU32` implemented `Clone`, you could clone the value +help: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); From 8543404e8d8668d9834dc48a687d5096d4949f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 19 Jan 2026 21:33:39 +0000 Subject: [PATCH 377/978] Tweak span in E0599 --- .../rustc_hir_typeck/src/method/suggest.rs | 50 ++++++++++++------- .../derives/derive-assoc-type-not-impl.stderr | 6 ++- .../deriving-with-repr-packed-2.stderr | 7 ++- tests/ui/union/union-derive-clone.stderr | 6 ++- 4 files changed, 45 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index f5ef5adff6bd..517d73f51783 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1752,16 +1752,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (p, parent_p, cause) in unsatisfied_predicates { // Extract the predicate span and parent def id of the cause, // if we have one. - let (item_def_id, cause_span) = match cause.as_ref().map(|cause| cause.code()) { - Some(ObligationCauseCode::ImplDerived(data)) => { - (data.impl_or_alias_def_id, data.span) - } - Some( - ObligationCauseCode::WhereClauseInExpr(def_id, span, _, _) - | ObligationCauseCode::WhereClause(def_id, span), - ) if !span.is_dummy() => (*def_id, *span), - _ => continue, - }; + let (item_def_id, cause_span, cause_msg) = + match cause.as_ref().map(|cause| cause.code()) { + Some(ObligationCauseCode::ImplDerived(data)) => { + let msg = if let DefKind::Impl { of_trait: true } = + self.tcx.def_kind(data.impl_or_alias_def_id) + { + format!( + "type parameter would need to implement `{}`", + self.tcx + .item_name(self.tcx.impl_trait_id(data.impl_or_alias_def_id)) + ) + } else { + format!("unsatisfied bound `{p}` introduced here") + }; + (data.impl_or_alias_def_id, data.span, msg) + } + Some( + ObligationCauseCode::WhereClauseInExpr(def_id, span, _, _) + | ObligationCauseCode::WhereClause(def_id, span), + ) if !span.is_dummy() => { + (*def_id, *span, format!("unsatisfied bound `{p}` introduced here")) + } + _ => continue, + }; // Don't point out the span of `WellFormed` predicates. if !matches!( @@ -1792,10 +1806,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let entry = entry.or_insert_with(|| { (FxIndexSet::default(), FxIndexSet::default(), Vec::new()) }); - entry.0.insert(span); + entry.0.insert(cause_span); entry.1.insert(( - span, - "unsatisfied trait bound introduced in this `derive` macro", + cause_span, + cause_msg, )); entry.2.push(p); skip_list.insert(p); @@ -1844,7 +1858,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.2.push(p); if cause_span != *item_span { entry.0.insert(cause_span); - entry.1.insert((cause_span, "unsatisfied trait bound introduced here")); + entry.1.insert((cause_span, "unsatisfied trait bound introduced here".to_string())); } else { if let Some(of_trait) = of_trait { entry.0.insert(of_trait.trait_ref.path.span); @@ -1852,9 +1866,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.0.insert(self_ty.span); }; if let Some(of_trait) = of_trait { - entry.1.insert((of_trait.trait_ref.path.span, "")); + entry.1.insert((of_trait.trait_ref.path.span, String::new())); } - entry.1.insert((self_ty.span, "")); + entry.1.insert((self_ty.span, String::new())); } Some(Node::Item(hir::Item { kind: hir::ItemKind::Trait(_, rustc_ast::ast::IsAuto::Yes, ..), @@ -1883,8 +1897,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (FxIndexSet::default(), FxIndexSet::default(), Vec::new()) }); entry.0.insert(cause_span); - entry.1.insert((ident.span, "")); - entry.1.insert((cause_span, "unsatisfied trait bound introduced here")); + entry.1.insert((ident.span, String::new())); + entry.1.insert((cause_span, "unsatisfied trait bound introduced here".to_string())); entry.2.push(p); } _ => { diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr index e239ad4ef209..ca968910fde4 100644 --- a/tests/ui/derives/derive-assoc-type-not-impl.stderr +++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr @@ -11,10 +11,12 @@ LL | Bar:: { x: 1 }.clone(); | ^^^^^ method cannot be called on `Bar` due to unsatisfied trait bounds | note: trait bound `NotClone: Clone` was not satisfied - --> $DIR/derive-assoc-type-not-impl.rs:6:10 + --> $DIR/derive-assoc-type-not-impl.rs:7:12 | LL | #[derive(Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ----- in this derive macro expansion +LL | struct Bar { + | ^ type parameter would need to implement `Clone` = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `NotClone` with `#[derive(Clone)]` | diff --git a/tests/ui/derives/deriving-with-repr-packed-2.stderr b/tests/ui/derives/deriving-with-repr-packed-2.stderr index fff6269472bd..6bd3fff39790 100644 --- a/tests/ui/derives/deriving-with-repr-packed-2.stderr +++ b/tests/ui/derives/deriving-with-repr-packed-2.stderr @@ -21,10 +21,13 @@ LL | let x: Foo = Foo(NonCopy, NonCopy, NonCopy); note: the following trait bounds were not satisfied: `NonCopy: Clone` `NonCopy: Copy` - --> $DIR/deriving-with-repr-packed-2.rs:5:16 + --> $DIR/deriving-with-repr-packed-2.rs:7:16 | LL | #[derive(Copy, Clone, Default, PartialEq, Eq)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ----- in this derive macro expansion +LL | #[repr(packed)] +LL | pub struct Foo(T, T, T); + | ^ type parameter would need to implement `Clone` = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `NonCopy` with `#[derive(Clone, Copy)]` | diff --git a/tests/ui/union/union-derive-clone.stderr b/tests/ui/union/union-derive-clone.stderr index 65488629b629..62ef35b76192 100644 --- a/tests/ui/union/union-derive-clone.stderr +++ b/tests/ui/union/union-derive-clone.stderr @@ -25,10 +25,12 @@ LL | let w = u.clone(); | ^^^^^ method cannot be called on `U5` due to unsatisfied trait bounds | note: trait bound `CloneNoCopy: Copy` was not satisfied - --> $DIR/union-derive-clone.rs:25:10 + --> $DIR/union-derive-clone.rs:26:10 | LL | #[derive(Clone, Copy)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ----- in this derive macro expansion +LL | union U5 { + | ^ type parameter would need to implement `Clone` = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]` | From dffec20dee76131f74736f05f01abf44161d3264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 19 Jan 2026 21:54:43 +0000 Subject: [PATCH 378/978] Tweak help to unify formatting and wording --- .../src/diagnostics/conflict_errors.rs | 27 +++++++++++-------- tests/ui/associated-types/issue-25700.stderr | 2 +- .../closure-shim-borrowck-error.stderr | 2 +- .../async-closures/move-out-of-ref.stderr | 2 +- .../borrowck-move-out-of-static-item.stderr | 2 +- .../borrowck-move-subcomponent.stderr | 2 +- .../borrowck/borrowck-overloaded-call.stderr | 2 +- tests/ui/borrowck/clone-on-ref.stderr | 2 +- .../borrowck/derive-clone-implicit-bound.rs | 26 +++++++++--------- .../derive-clone-implicit-bound.stderr | 12 ++++----- tests/ui/borrowck/issue-103624.stderr | 2 +- .../issue-119915-bad-clone-suggestion.stderr | 2 +- .../borrowck/issue-17718-static-move.stderr | 2 +- tests/ui/borrowck/issue-20801.stderr | 8 +++--- .../borrowck/move-error-in-promoted-2.stderr | 2 +- tests/ui/borrowck/move-error-snippets.stderr | 2 +- ...e-in-static-initializer-issue-38520.stderr | 4 +-- tests/ui/box/leak-alloc.stderr | 2 +- .../closure-move-use-after-move-diagnostic.rs | 16 +++++------ ...sure-move-use-after-move-diagnostic.stderr | 2 +- tests/ui/coroutine/moved-twice.stderr | 2 +- .../derives/deriving-with-repr-packed.stderr | 2 +- tests/ui/error-codes/E0504.stderr | 2 +- tests/ui/error-codes/E0505.stderr | 2 +- tests/ui/error-codes/E0507.stderr | 2 +- tests/ui/error-codes/E0508-fail.stderr | 2 +- tests/ui/error-codes/E0508.stderr | 2 +- tests/ui/error-codes/E0509.stderr | 2 +- tests/ui/mir/issue-102389.stderr | 2 +- tests/ui/moves/issue-72649-uninit-in-loop.rs | 8 +++--- .../moves/issue-72649-uninit-in-loop.stderr | 8 +++--- .../issue-75904-move-closure-loop.stderr | 2 +- ...atching-partially-moved-value-17385.stderr | 4 +-- tests/ui/moves/move-fn-self-receiver.stderr | 2 +- tests/ui/moves/move-out-of-array-1.stderr | 2 +- .../ui/moves/moved-value-on-as-ref-arg.stderr | 4 +-- .../issue-21232-partial-init-and-use.stderr | 4 +-- tests/ui/nll/move-errors.stderr | 12 ++++----- .../pin-ergonomics/borrow-unpin.pinned.stderr | 24 ++++++++--------- .../pin-ergonomics/borrow-unpin.unpin.stderr | 6 ++--- tests/ui/pin-macro/pin_move.stderr | 4 +-- .../non_copy_move_out_of_tuple.stderr | 2 +- .../suggestions/option-content-move3.stderr | 4 +-- .../union-borrow-move-parent-sibling.stderr | 2 +- tests/ui/union/union-move.stderr | 4 +-- tests/ui/variance/variance-issue-20533.stderr | 8 +++--- 46 files changed, 122 insertions(+), 117 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 72a35de73f32..a39300f7030f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1293,18 +1293,23 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } }, ); - span.push_span_label( - ty_span, - format!( - "consider {}implementing `Clone` for this type", - if derive_clone { "manually " } else { "" } - ), - ); + let msg = if !derive_clone { + span.push_span_label( + ty_span, + format!( + "consider {}implementing `Clone` for this type", + if derive_clone { "manually " } else { "" } + ), + ); + format!("if `{ty}` implemented `Clone`, you could clone the value") + } else { + format!("if all bounds were met, you could clone the value") + }; span.push_span_label(expr.span, "you could clone this value"); - err.span_help( - span, - format!("if `{ty}` implemented `Clone`, you could clone the value"), - ); + err.span_note(span, msg); + if derive_clone { + err.help("consider manually implementing `Clone` to avoid undesired bounds"); + } } else if let ty::Param(param) = ty.kind() && let Some(_clone_trait_def) = self.infcx.tcx.lang_items().clone_trait() && let generics = self.infcx.tcx.generics_of(self.mir_def_id()) diff --git a/tests/ui/associated-types/issue-25700.stderr b/tests/ui/associated-types/issue-25700.stderr index 595aefc9a215..8d40e6905e07 100644 --- a/tests/ui/associated-types/issue-25700.stderr +++ b/tests/ui/associated-types/issue-25700.stderr @@ -8,7 +8,7 @@ LL | drop(t); LL | drop(t); | ^ value used here after move | -help: if `S<()>` implemented `Clone`, you could clone the value +note: if `S<()>` implemented `Clone`, you could clone the value --> $DIR/issue-25700.rs:1:1 | LL | struct S(#[allow(dead_code)] Option<&'static T>); diff --git a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr index a4d239090830..3fe1431fda71 100644 --- a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr +++ b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr @@ -9,7 +9,7 @@ LL | LL | x.hello(); | - variable moved due to use in coroutine | -help: if `Ty` implemented `Clone`, you could clone the value +note: if `Ty` implemented `Clone`, you could clone the value --> $DIR/closure-shim-borrowck-error.rs:17:1 | LL | x.hello(); diff --git a/tests/ui/async-await/async-closures/move-out-of-ref.stderr b/tests/ui/async-await/async-closures/move-out-of-ref.stderr index c516597c81f9..d443dc9d4831 100644 --- a/tests/ui/async-await/async-closures/move-out-of-ref.stderr +++ b/tests/ui/async-await/async-closures/move-out-of-ref.stderr @@ -7,7 +7,7 @@ LL | let c = async || { LL | *x; | ^^ `*x` is moved here | -help: if `Ty` implemented `Clone`, you could clone the value +note: if `Ty` implemented `Clone`, you could clone the value --> $DIR/move-out-of-ref.rs:5:1 | LL | struct Ty; diff --git a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr index 9eb90e169fd3..b4b60d40d914 100644 --- a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr +++ b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of static item `BAR` LL | test(BAR); | ^^^ move occurs because `BAR` has type `Foo`, which does not implement the `Copy` trait | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrowck-move-out-of-static-item.rs:3:1 | LL | struct Foo { diff --git a/tests/ui/borrowck/borrowck-move-subcomponent.stderr b/tests/ui/borrowck/borrowck-move-subcomponent.stderr index 8dcb81273f89..b5dc01f180b2 100644 --- a/tests/ui/borrowck/borrowck-move-subcomponent.stderr +++ b/tests/ui/borrowck/borrowck-move-subcomponent.stderr @@ -10,7 +10,7 @@ LL | let S { x: ax } = a; LL | f(pb); | -- borrow later used here | -help: if `S` implemented `Clone`, you could clone the value +note: if `S` implemented `Clone`, you could clone the value --> $DIR/borrowck-move-subcomponent.rs:6:1 | LL | struct S { diff --git a/tests/ui/borrowck/borrowck-overloaded-call.stderr b/tests/ui/borrowck/borrowck-overloaded-call.stderr index c838c6512bc4..c3b7b0b6080c 100644 --- a/tests/ui/borrowck/borrowck-overloaded-call.stderr +++ b/tests/ui/borrowck/borrowck-overloaded-call.stderr @@ -30,7 +30,7 @@ LL | s(" world".to_string()); LL | s(" world".to_string()); | ^ value used here after move | -help: if `SFnOnce` implemented `Clone`, you could clone the value +note: if `SFnOnce` implemented `Clone`, you could clone the value --> $DIR/borrowck-overloaded-call.rs:41:1 | LL | struct SFnOnce { diff --git a/tests/ui/borrowck/clone-on-ref.stderr b/tests/ui/borrowck/clone-on-ref.stderr index 535550409dd8..72580e7464b7 100644 --- a/tests/ui/borrowck/clone-on-ref.stderr +++ b/tests/ui/borrowck/clone-on-ref.stderr @@ -59,7 +59,7 @@ LL | LL | println!("{b:?}"); | - borrow later used here | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/clone-on-ref.rs:19:1 | LL | struct A; diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.rs b/tests/ui/borrowck/derive-clone-implicit-bound.rs index 12fd2129331b..cd92ac1e9e59 100644 --- a/tests/ui/borrowck/derive-clone-implicit-bound.rs +++ b/tests/ui/borrowck/derive-clone-implicit-bound.rs @@ -2,11 +2,10 @@ use std::marker::PhantomData; -#[derive(Clone, Copy)] //~ NOTE derived `Clone` adds implicit bounds on type parameters +#[derive(Clone, Copy)] //~ NOTE: derived `Clone` adds implicit bounds on type parameters pub struct TypedAddress{ -//~^ HELP if `TypedAddress` implemented `Clone`, you could clone the value -//~| NOTE consider manually implementing `Clone` for this type -//~| NOTE introduces an implicit `T: Clone` bound +//~^ NOTE: if all bounds were met, you could clone the value +//~| NOTE: introduces an implicit `T: Clone` bound inner: u64, phantom: PhantomData, } @@ -14,18 +13,19 @@ pub struct TypedAddress{ pub trait Memory { fn write_value(&self, offset: TypedAddress, value: &T); fn return_value(&self, offset: TypedAddress) -> T; - //~^ NOTE consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary - //~| NOTE in this method - //~| NOTE this parameter takes ownership of the value + //~^ NOTE: consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary + //~| NOTE: in this method + //~| NOTE: this parameter takes ownership of the value fn update_value(&self, offset: TypedAddress, update: F) - //~^ NOTE move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait - where F: FnOnce(T) -> T //~ HELP consider further restricting type parameter `T` + //~^ NOTE: move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait + where F: FnOnce(T) -> T //~ HELP: consider further restricting type parameter `T` { - let old = self.return_value(offset); //~ NOTE value moved here - //~^ NOTE you could clone this value + let old = self.return_value(offset); //~ NOTE: value moved here + //~^ NOTE: you could clone this value let new = update(old); - self.write_value(offset, &new); //~ ERROR use of moved value: `offset` - //~^ NOTE value used here after move + self.write_value(offset, &new); //~ ERROR: use of moved value: `offset` + //~^ NOTE: value used here after move + //~| HELP: consider manually implementing `Clone` to avoid undesired bounds } } diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.stderr b/tests/ui/borrowck/derive-clone-implicit-bound.stderr index 31a55b448eb6..246fd1eaf075 100644 --- a/tests/ui/borrowck/derive-clone-implicit-bound.stderr +++ b/tests/ui/borrowck/derive-clone-implicit-bound.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `offset` - --> $DIR/derive-clone-implicit-bound.rs:27:26 + --> $DIR/derive-clone-implicit-bound.rs:26:26 | LL | fn update_value(&self, offset: TypedAddress, update: F) | ------ move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait @@ -11,23 +11,23 @@ LL | self.write_value(offset, &new); | ^^^^^^ value used here after move | note: consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary - --> $DIR/derive-clone-implicit-bound.rs:16:39 + --> $DIR/derive-clone-implicit-bound.rs:15:39 | LL | fn return_value(&self, offset: TypedAddress) -> T; | ------------ in this method ^^^^^^^^^^^^^^^ this parameter takes ownership of the value -help: if `TypedAddress` implemented `Clone`, you could clone the value +note: if all bounds were met, you could clone the value --> $DIR/derive-clone-implicit-bound.rs:6:1 | LL | #[derive(Clone, Copy)] | ----- derived `Clone` adds implicit bounds on type parameters LL | pub struct TypedAddress{ | ^^^^^^^^^^^^^^^^^^^^^^^^-^ - | | | - | | introduces an implicit `T: Clone` bound - | consider manually implementing `Clone` for this type + | | + | introduces an implicit `T: Clone` bound ... LL | let old = self.return_value(offset); | ------ you could clone this value + = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `T` with trait `Copy` | LL | where F: FnOnce(T) -> T, T: Copy diff --git a/tests/ui/borrowck/issue-103624.stderr b/tests/ui/borrowck/issue-103624.stderr index 85769e187691..bd6c1c44bfb3 100644 --- a/tests/ui/borrowck/issue-103624.stderr +++ b/tests/ui/borrowck/issue-103624.stderr @@ -18,7 +18,7 @@ help: `Fn` and `FnMut` closures require captured values to be able to be consume | LL | async fn spawn_blocking(f: impl (Fn() -> T) + Send + Sync + 'static) -> T { | ^^^^^^^^^^^ -help: if `StructB` implemented `Clone`, you could clone the value +note: if `StructB` implemented `Clone`, you could clone the value --> $DIR/issue-103624.rs:23:1 | LL | self.b; diff --git a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr index a5a218a0641d..dde17d1f6523 100644 --- a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr +++ b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr @@ -11,7 +11,7 @@ note: `Example::::change` takes ownership of the receiver `self`, | LL | unsafe fn change(self) -> Example { | ^^^^ -help: if `Example` implemented `Clone`, you could clone the value +note: if `Example` implemented `Clone`, you could clone the value --> $DIR/issue-119915-bad-clone-suggestion.rs:3:1 | LL | struct Example(PhantomData<(fn(E), fn(FakeParam))>); diff --git a/tests/ui/borrowck/issue-17718-static-move.stderr b/tests/ui/borrowck/issue-17718-static-move.stderr index 959b1d1a3b84..057ac6d7e3df 100644 --- a/tests/ui/borrowck/issue-17718-static-move.stderr +++ b/tests/ui/borrowck/issue-17718-static-move.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of static item `FOO` LL | let _a = FOO; | ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/issue-17718-static-move.rs:1:1 | LL | struct Foo; diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr index 5336352e0dbd..5fda92634d8f 100644 --- a/tests/ui/borrowck/issue-20801.stderr +++ b/tests/ui/borrowck/issue-20801.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of a mutable reference LL | let a = unsafe { *mut_ref() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -help: if `T` implemented `Clone`, you could clone the value +note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -24,7 +24,7 @@ error[E0507]: cannot move out of a shared reference LL | let b = unsafe { *imm_ref() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -help: if `T` implemented `Clone`, you could clone the value +note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -44,7 +44,7 @@ error[E0507]: cannot move out of a raw pointer LL | let c = unsafe { *mut_ptr() }; | ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -help: if `T` implemented `Clone`, you could clone the value +note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); @@ -59,7 +59,7 @@ error[E0507]: cannot move out of a raw pointer LL | let d = unsafe { *const_ptr() }; | ^^^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait | -help: if `T` implemented `Clone`, you could clone the value +note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); diff --git a/tests/ui/borrowck/move-error-in-promoted-2.stderr b/tests/ui/borrowck/move-error-in-promoted-2.stderr index f2bc6bd4760a..1e9b1d5209cb 100644 --- a/tests/ui/borrowck/move-error-in-promoted-2.stderr +++ b/tests/ui/borrowck/move-error-in-promoted-2.stderr @@ -7,7 +7,7 @@ LL | &([S][0],); | cannot move out of here | move occurs because value has type `S`, which does not implement the `Copy` trait | -help: if `S` implemented `Clone`, you could clone the value +note: if `S` implemented `Clone`, you could clone the value --> $DIR/move-error-in-promoted-2.rs:3:1 | LL | struct S; diff --git a/tests/ui/borrowck/move-error-snippets.stderr b/tests/ui/borrowck/move-error-snippets.stderr index 3796b7e05fb4..97d140515184 100644 --- a/tests/ui/borrowck/move-error-snippets.stderr +++ b/tests/ui/borrowck/move-error-snippets.stderr @@ -9,7 +9,7 @@ LL | let a = $c; LL | sss!(); | ------ in this macro invocation | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-error-snippets.rs:9:1 | LL | struct A; diff --git a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr index af5cbdcf150f..009e85a8031e 100644 --- a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr +++ b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | static Y: usize = get(*&X); | ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-in-static-initializer-issue-38520.rs:5:1 | LL | struct Foo(usize); @@ -19,7 +19,7 @@ error[E0507]: cannot move out of a shared reference LL | const Z: usize = get(*&X); | ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-in-static-initializer-issue-38520.rs:5:1 | LL | struct Foo(usize); diff --git a/tests/ui/box/leak-alloc.stderr b/tests/ui/box/leak-alloc.stderr index f0d6dd3d4692..bdaa9449f913 100644 --- a/tests/ui/box/leak-alloc.stderr +++ b/tests/ui/box/leak-alloc.stderr @@ -12,7 +12,7 @@ LL | LL | use_value(*theref) | ------- borrow later used here | -help: if `Alloc` implemented `Clone`, you could clone the value +note: if `Alloc` implemented `Clone`, you could clone the value --> $DIR/leak-alloc.rs:8:1 | LL | struct Alloc {} diff --git a/tests/ui/closures/closure-move-use-after-move-diagnostic.rs b/tests/ui/closures/closure-move-use-after-move-diagnostic.rs index b55c8c16f611..863bcedd01e6 100644 --- a/tests/ui/closures/closure-move-use-after-move-diagnostic.rs +++ b/tests/ui/closures/closure-move-use-after-move-diagnostic.rs @@ -1,16 +1,16 @@ //! regression test for -struct NoCopy; //~ HELP if `NoCopy` implemented `Clone`, you could clone the value -//~^ NOTE consider implementing `Clone` for this type +struct NoCopy; //~ NOTE: if `NoCopy` implemented `Clone`, you could clone the value +//~^ NOTE: consider implementing `Clone` for this type fn main() { let x = NoCopy; - //~^ NOTE move occurs because `x` has type `NoCopy` + //~^ NOTE: move occurs because `x` has type `NoCopy` let f = move || { - //~^ NOTE value moved into closure here + //~^ NOTE: value moved into closure here let y = x; - //~^ NOTE variable moved due to use in closure - //~| NOTE you could clone this value + //~^ NOTE: variable moved due to use in closure + //~| NOTE: you could clone this value }; let z = x; - //~^ ERROR use of moved value: `x` - //~| NOTE value used here after move + //~^ ERROR: use of moved value: `x` + //~| NOTE: value used here after move } diff --git a/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr b/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr index bde39ca6ca71..94f80da1b10a 100644 --- a/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr +++ b/tests/ui/closures/closure-move-use-after-move-diagnostic.stderr @@ -13,7 +13,7 @@ LL | let y = x; LL | let z = x; | ^ value used here after move | -help: if `NoCopy` implemented `Clone`, you could clone the value +note: if `NoCopy` implemented `Clone`, you could clone the value --> $DIR/closure-move-use-after-move-diagnostic.rs:2:1 | LL | struct NoCopy; diff --git a/tests/ui/coroutine/moved-twice.stderr b/tests/ui/coroutine/moved-twice.stderr index 561b3b331d9f..2b21f6c59f0b 100644 --- a/tests/ui/coroutine/moved-twice.stderr +++ b/tests/ui/coroutine/moved-twice.stderr @@ -10,7 +10,7 @@ LL | yield; LL | let second = first; | ^^^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/moved-twice.rs:9:1 | LL | struct Foo([u8; FOO_SIZE]); diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr index 7c716fb9dd4c..9cfc4abdc0cb 100644 --- a/tests/ui/derives/deriving-with-repr-packed.stderr +++ b/tests/ui/derives/deriving-with-repr-packed.stderr @@ -7,7 +7,7 @@ LL | #[repr(packed)] LL | struct X(Y); | ^ move occurs because value has type `Y`, which does not implement the `Copy` trait | -help: if `Y` implemented `Clone`, you could clone the value +note: if `Y` implemented `Clone`, you could clone the value --> $DIR/deriving-with-repr-packed.rs:16:1 | LL | struct Y(usize); diff --git a/tests/ui/error-codes/E0504.stderr b/tests/ui/error-codes/E0504.stderr index 528f311765df..c4cbc834ad98 100644 --- a/tests/ui/error-codes/E0504.stderr +++ b/tests/ui/error-codes/E0504.stderr @@ -14,7 +14,7 @@ LL | println!("child function: {}", fancy_num.num); LL | println!("main function: {}", fancy_ref.num); | ------------- borrow later used here | -help: if `FancyNum` implemented `Clone`, you could clone the value +note: if `FancyNum` implemented `Clone`, you could clone the value --> $DIR/E0504.rs:2:1 | LL | struct FancyNum { diff --git a/tests/ui/error-codes/E0505.stderr b/tests/ui/error-codes/E0505.stderr index ac0f390bc54b..3f2913e9fe3c 100644 --- a/tests/ui/error-codes/E0505.stderr +++ b/tests/ui/error-codes/E0505.stderr @@ -11,7 +11,7 @@ LL | eat(x); LL | _ref_to_val.use_ref(); | ----------- borrow later used here | -help: if `Value` implemented `Clone`, you could clone the value +note: if `Value` implemented `Clone`, you could clone the value --> $DIR/E0505.rs:1:1 | LL | struct Value {} diff --git a/tests/ui/error-codes/E0507.stderr b/tests/ui/error-codes/E0507.stderr index ac03e5ea9cd5..70d99ea2cce5 100644 --- a/tests/ui/error-codes/E0507.stderr +++ b/tests/ui/error-codes/E0507.stderr @@ -11,7 +11,7 @@ note: `TheDarkKnight::nothing_is_true` takes ownership of the receiver `self`, w | LL | fn nothing_is_true(self) {} | ^^^^ -help: if `TheDarkKnight` implemented `Clone`, you could clone the value +note: if `TheDarkKnight` implemented `Clone`, you could clone the value --> $DIR/E0507.rs:3:1 | LL | struct TheDarkKnight; diff --git a/tests/ui/error-codes/E0508-fail.stderr b/tests/ui/error-codes/E0508-fail.stderr index 48ede17dc26a..fcfac399e0df 100644 --- a/tests/ui/error-codes/E0508-fail.stderr +++ b/tests/ui/error-codes/E0508-fail.stderr @@ -7,7 +7,7 @@ LL | let _value = array[0]; | cannot move out of here | move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/E0508-fail.rs:1:1 | LL | struct NonCopy; diff --git a/tests/ui/error-codes/E0508.stderr b/tests/ui/error-codes/E0508.stderr index c001b9461ebf..b9fa0f4d17a5 100644 --- a/tests/ui/error-codes/E0508.stderr +++ b/tests/ui/error-codes/E0508.stderr @@ -7,7 +7,7 @@ LL | let _value = array[0]; | cannot move out of here | move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/E0508.rs:1:1 | LL | struct NonCopy; diff --git a/tests/ui/error-codes/E0509.stderr b/tests/ui/error-codes/E0509.stderr index 89c3a5848423..628a253e0859 100644 --- a/tests/ui/error-codes/E0509.stderr +++ b/tests/ui/error-codes/E0509.stderr @@ -7,7 +7,7 @@ LL | let fancy_field = drop_struct.fancy; | cannot move out of here | move occurs because `drop_struct.fancy` has type `FancyNum`, which does not implement the `Copy` trait | -help: if `FancyNum` implemented `Clone`, you could clone the value +note: if `FancyNum` implemented `Clone`, you could clone the value --> $DIR/E0509.rs:1:1 | LL | struct FancyNum { diff --git a/tests/ui/mir/issue-102389.stderr b/tests/ui/mir/issue-102389.stderr index 7aafe081deaf..162d7ac031a6 100644 --- a/tests/ui/mir/issue-102389.stderr +++ b/tests/ui/mir/issue-102389.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of `*inbounds` which is behind a shared reference LL | array[*inbounds as usize] | ^^^^^^^^^ move occurs because `*inbounds` has type `Enum`, which does not implement the `Copy` trait | -help: if `Enum` implemented `Clone`, you could clone the value +note: if `Enum` implemented `Clone`, you could clone the value --> $DIR/issue-102389.rs:1:1 | LL | enum Enum { A, B, C } diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.rs b/tests/ui/moves/issue-72649-uninit-in-loop.rs index 965a4206253e..f115656d7c0d 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.rs +++ b/tests/ui/moves/issue-72649-uninit-in-loop.rs @@ -3,10 +3,10 @@ // 'value moved in previous iteration of loop' message struct NonCopy; -//~^ HELP if `NonCopy` implemented `Clone` -//~| HELP if `NonCopy` implemented `Clone` -//~| HELP if `NonCopy` implemented `Clone` -//~| HELP if `NonCopy` implemented `Clone` +//~^ NOTE if `NonCopy` implemented `Clone` +//~| NOTE if `NonCopy` implemented `Clone` +//~| NOTE if `NonCopy` implemented `Clone` +//~| NOTE if `NonCopy` implemented `Clone` //~| NOTE consider implementing `Clone` for this type //~| NOTE consider implementing `Clone` for this type //~| NOTE consider implementing `Clone` for this type diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.stderr b/tests/ui/moves/issue-72649-uninit-in-loop.stderr index 1c54d3997ed6..8bde3b5c042d 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.stderr +++ b/tests/ui/moves/issue-72649-uninit-in-loop.stderr @@ -10,7 +10,7 @@ LL | let _used = value; LL | let _used2 = value; | ^^^^^ value used here after move | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -33,7 +33,7 @@ LL | let _used = value; LL | let _used2 = value; | ^^^^^ value used here after move | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -53,7 +53,7 @@ LL | loop { LL | let _used = value; | ^^^^^ value moved here, in previous iteration of loop | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; @@ -73,7 +73,7 @@ LL | loop { LL | let _used2 = value; | ^^^^^ value moved here, in previous iteration of loop | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; diff --git a/tests/ui/moves/issue-75904-move-closure-loop.stderr b/tests/ui/moves/issue-75904-move-closure-loop.stderr index 3fc50c48315d..815e91b0f4df 100644 --- a/tests/ui/moves/issue-75904-move-closure-loop.stderr +++ b/tests/ui/moves/issue-75904-move-closure-loop.stderr @@ -11,7 +11,7 @@ LL | &mut a; LL | a; | - use occurs due to use in closure | -help: if `NotCopy` implemented `Clone`, you could clone the value +note: if `NotCopy` implemented `Clone`, you could clone the value --> $DIR/issue-75904-move-closure-loop.rs:5:1 | LL | struct NotCopy; diff --git a/tests/ui/moves/matching-partially-moved-value-17385.stderr b/tests/ui/moves/matching-partially-moved-value-17385.stderr index 83f4f4320485..906f7868bccb 100644 --- a/tests/ui/moves/matching-partially-moved-value-17385.stderr +++ b/tests/ui/moves/matching-partially-moved-value-17385.stderr @@ -8,7 +8,7 @@ LL | drop(foo); LL | match foo { | ^^^^^^^^^ value used here after move | -help: if `X` implemented `Clone`, you could clone the value +note: if `X` implemented `Clone`, you could clone the value --> $DIR/matching-partially-moved-value-17385.rs:2:1 | LL | struct X(isize); @@ -27,7 +27,7 @@ LL | drop(e); LL | match e { | ^ value used here after move | -help: if `Enum` implemented `Clone`, you could clone the value +note: if `Enum` implemented `Clone`, you could clone the value --> $DIR/matching-partially-moved-value-17385.rs:4:1 | LL | enum Enum { diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr index b3a1215fa2f7..de19a99d388c 100644 --- a/tests/ui/moves/move-fn-self-receiver.stderr +++ b/tests/ui/moves/move-fn-self-receiver.stderr @@ -132,7 +132,7 @@ LL | foo_add + Foo; LL | foo_add; | ^^^^^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-fn-self-receiver.rs:5:1 | LL | struct Foo; diff --git a/tests/ui/moves/move-out-of-array-1.stderr b/tests/ui/moves/move-out-of-array-1.stderr index 7ef859200b21..8a030f021920 100644 --- a/tests/ui/moves/move-out-of-array-1.stderr +++ b/tests/ui/moves/move-out-of-array-1.stderr @@ -7,7 +7,7 @@ LL | a[i] | cannot move out of here | move occurs because `a[_]` has type `D`, which does not implement the `Copy` trait | -help: if `D` implemented `Clone`, you could clone the value +note: if `D` implemented `Clone`, you could clone the value --> $DIR/move-out-of-array-1.rs:5:1 | LL | struct D { _x: u8 } diff --git a/tests/ui/moves/moved-value-on-as-ref-arg.stderr b/tests/ui/moves/moved-value-on-as-ref-arg.stderr index b553938c6fed..a99bdb4fe9d4 100644 --- a/tests/ui/moves/moved-value-on-as-ref-arg.stderr +++ b/tests/ui/moves/moved-value-on-as-ref-arg.stderr @@ -23,7 +23,7 @@ LL | qux(bar); LL | let _baa = bar; | ^^^ value used here after move | -help: if `Bar` implemented `Clone`, you could clone the value +note: if `Bar` implemented `Clone`, you could clone the value --> $DIR/moved-value-on-as-ref-arg.rs:5:1 | LL | struct Bar; @@ -61,7 +61,7 @@ LL | baz(bar); LL | let _baa = bar; | ^^^ value used here after move | -help: if `Bar` implemented `Clone`, you could clone the value +note: if `Bar` implemented `Clone`, you could clone the value --> $DIR/moved-value-on-as-ref-arg.rs:5:1 | LL | struct Bar; diff --git a/tests/ui/nll/issue-21232-partial-init-and-use.stderr b/tests/ui/nll/issue-21232-partial-init-and-use.stderr index 84c543921687..496a298a36ce 100644 --- a/tests/ui/nll/issue-21232-partial-init-and-use.stderr +++ b/tests/ui/nll/issue-21232-partial-init-and-use.stderr @@ -28,7 +28,7 @@ LL | let mut s: S = S::new(); drop(s); LL | s.x = 10; s.y = Box::new(20); | ^^^^^^^^ value partially assigned here after move | -help: if `S>` implemented `Clone`, you could clone the value +note: if `S>` implemented `Clone`, you could clone the value --> $DIR/issue-21232-partial-init-and-use.rs:15:1 | LL | struct S { @@ -82,7 +82,7 @@ LL | let mut s: S = S::new(); drop(s); LL | s.x = 10; | ^^^^^^^^ value partially assigned here after move | -help: if `S>` implemented `Clone`, you could clone the value +note: if `S>` implemented `Clone`, you could clone the value --> $DIR/issue-21232-partial-init-and-use.rs:15:1 | LL | struct S { diff --git a/tests/ui/nll/move-errors.stderr b/tests/ui/nll/move-errors.stderr index e84f75455217..bcb2ab84a239 100644 --- a/tests/ui/nll/move-errors.stderr +++ b/tests/ui/nll/move-errors.stderr @@ -4,7 +4,7 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference LL | let b = *a; | ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -27,7 +27,7 @@ LL | let b = a[0]; | cannot move out of here | move occurs because `a[_]` has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -46,7 +46,7 @@ error[E0507]: cannot move out of `**r` which is behind a shared reference LL | let s = **r; | ^^^ move occurs because `**r` has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -66,7 +66,7 @@ error[E0507]: cannot move out of an `Rc` LL | let s = *r; | ^^ move occurs because value has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -89,7 +89,7 @@ LL | let a = [A("".to_string())][0]; | cannot move out of here | move occurs because value has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); @@ -137,7 +137,7 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference LL | b = *a; | ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait | -help: if `A` implemented `Clone`, you could clone the value +note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); diff --git a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr index f9bef8d83f96..cc438461a5d1 100644 --- a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr +++ b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr @@ -8,7 +8,7 @@ LL | foo_pin_mut(&pin mut foo); LL | foo_move(foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -27,7 +27,7 @@ LL | let x = &pin mut foo; LL | foo_move(foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -46,7 +46,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_move(foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -65,7 +65,7 @@ LL | let x = &pin mut foo; // ok LL | foo_move(foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -87,7 +87,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -106,7 +106,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_ref(&foo); | ^^^^ value borrowed here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -125,7 +125,7 @@ LL | let x = &pin mut foo; // ok LL | foo_ref(&foo); | ^^^^ value borrowed here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -144,7 +144,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_pin_mut(&pin mut foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -163,7 +163,7 @@ LL | let x = &pin mut foo; // ok LL | foo_pin_mut(&pin mut foo); | ^^^ value used here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -185,7 +185,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -204,7 +204,7 @@ LL | foo_pin_mut(&pin mut foo); // ok LL | foo_pin_ref(&pin const foo); | ^^^^^^^^^^^^^^ value borrowed here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); @@ -223,7 +223,7 @@ LL | let x = &pin mut foo; // ok LL | foo_pin_ref(&pin const foo); | ^^^^^^^^^^^^^^ value borrowed here after move | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:16:1 | LL | struct Foo(PhantomPinned); diff --git a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr index 523191655813..bf9921343ee7 100644 --- a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr +++ b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr @@ -33,7 +33,7 @@ LL | LL | foo_pin_mut(x); // | - borrow later used here | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; @@ -55,7 +55,7 @@ LL | LL | foo_pin_mut(x); // | - borrow later used here | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; @@ -77,7 +77,7 @@ LL | LL | foo_pin_ref(x); | - borrow later used here | -help: if `Foo` implemented `Clone`, you could clone the value +note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrow-unpin.rs:20:1 | LL | struct Foo; diff --git a/tests/ui/pin-macro/pin_move.stderr b/tests/ui/pin-macro/pin_move.stderr index cf7d50091ba4..3f4660209885 100644 --- a/tests/ui/pin-macro/pin_move.stderr +++ b/tests/ui/pin-macro/pin_move.stderr @@ -8,7 +8,7 @@ LL | pin!(pointee); LL | let _moved = pointee; | ^^^^^^^ value used here after move | -help: if `a::NotCopy` implemented `Clone`, you could clone the value +note: if `a::NotCopy` implemented `Clone`, you could clone the value --> $DIR/pin_move.rs:7:5 | LL | struct NotCopy(T); @@ -23,7 +23,7 @@ error[E0507]: cannot move out of a mutable reference LL | pin!(*&mut pointee); | ^^^^^^^^^^^^^ move occurs because value has type `b::NotCopy`, which does not implement the `Copy` trait | -help: if `b::NotCopy` implemented `Clone`, you could clone the value +note: if `b::NotCopy` implemented `Clone`, you could clone the value --> $DIR/pin_move.rs:16:5 | LL | struct NotCopy(T); diff --git a/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr index 5e447a57bfee..62f24324fcc1 100644 --- a/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr +++ b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr @@ -7,7 +7,7 @@ LL | (b,) = *tuple; | data moved here | move occurs because the place has type `NonCopy`, which does not implement the `Copy` trait | -help: if `NonCopy` implemented `Clone`, you could clone the value +note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/non_copy_move_out_of_tuple.rs:3:1 | LL | struct NonCopy; diff --git a/tests/ui/suggestions/option-content-move3.stderr b/tests/ui/suggestions/option-content-move3.stderr index cd13592d652e..f78d3cf67862 100644 --- a/tests/ui/suggestions/option-content-move3.stderr +++ b/tests/ui/suggestions/option-content-move3.stderr @@ -10,7 +10,7 @@ LL | let x = var; | ^^^ move occurs because `var` has type `NotCopyable`, which does not implement the `Copy` trait | = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once -help: if `NotCopyable` implemented `Clone`, you could clone the value +note: if `NotCopyable` implemented `Clone`, you could clone the value --> $DIR/option-content-move3.rs:2:1 | LL | struct NotCopyable; @@ -43,7 +43,7 @@ help: `Fn` and `FnMut` closures require captured values to be able to be consume | LL | fn func H, H: FnMut()>(_: F) {} | ^^^^^^^^^^^^ -help: if `NotCopyable` implemented `Clone`, you could clone the value +note: if `NotCopyable` implemented `Clone`, you could clone the value --> $DIR/option-content-move3.rs:2:1 | LL | struct NotCopyable; diff --git a/tests/ui/union/union-borrow-move-parent-sibling.stderr b/tests/ui/union/union-borrow-move-parent-sibling.stderr index 5974441dd807..461ee407e2dd 100644 --- a/tests/ui/union/union-borrow-move-parent-sibling.stderr +++ b/tests/ui/union/union-borrow-move-parent-sibling.stderr @@ -59,7 +59,7 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec, Moc LL | let a = (u.x.0).0; | ^^^^^^^^^ move occurs because value has type `MockVec`, which does not implement the `Copy` trait | -help: if `MockVec` implemented `Clone`, you could clone the value +note: if `MockVec` implemented `Clone`, you could clone the value --> $DIR/union-borrow-move-parent-sibling.rs:25:1 | LL | struct MockVec { diff --git a/tests/ui/union/union-move.stderr b/tests/ui/union/union-move.stderr index 6266bb4770e0..d520fb00ea9d 100644 --- a/tests/ui/union/union-move.stderr +++ b/tests/ui/union/union-move.stderr @@ -16,7 +16,7 @@ LL | fn move_out(x: T) {} | -------- ^ this parameter takes ownership of the value | | | in this function -help: if `U1` implemented `Clone`, you could clone the value +note: if `U1` implemented `Clone`, you could clone the value --> $DIR/union-move.rs:9:1 | LL | union U1 { @@ -43,7 +43,7 @@ LL | fn move_out(x: T) {} | -------- ^ this parameter takes ownership of the value | | | in this function -help: if `U1` implemented `Clone`, you could clone the value +note: if `U1` implemented `Clone`, you could clone the value --> $DIR/union-move.rs:9:1 | LL | union U1 { diff --git a/tests/ui/variance/variance-issue-20533.stderr b/tests/ui/variance/variance-issue-20533.stderr index 2a33a88bdd56..21d8de6ae881 100644 --- a/tests/ui/variance/variance-issue-20533.stderr +++ b/tests/ui/variance/variance-issue-20533.stderr @@ -10,7 +10,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -help: if `AffineU32` implemented `Clone`, you could clone the value +note: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -31,7 +31,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -help: if `AffineU32` implemented `Clone`, you could clone the value +note: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -52,7 +52,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -help: if `AffineU32` implemented `Clone`, you could clone the value +note: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); @@ -73,7 +73,7 @@ LL | drop(a); LL | drop(x); | - borrow later used here | -help: if `AffineU32` implemented `Clone`, you could clone the value +note: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); From c95210f013cd0e607b4932cc841f90096037f191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 1 Feb 2026 18:30:08 +0000 Subject: [PATCH 379/978] Do not suggest manual `impl Copy` --- .../src/error_reporting/traits/suggestions.rs | 2 +- tests/ui/associated-types/issue-38821.stderr | 1 - tests/ui/consts/const-blocks/trait-error.stderr | 1 - tests/ui/derives/deriving-copyclone.stderr | 2 -- tests/ui/generic-associated-types/impl_bounds.stderr | 2 -- 5 files changed, 1 insertion(+), 7 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 1880465eff54..764790a75bb4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3629,7 +3629,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } err.span_note(spans, msg); - if derived { + if derived && trait_name != "Copy" { err.help(format!( "consider manually implementing `{trait_name}` to avoid undesired \ bounds", diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index fae388c98d36..07b146f8bfca 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -159,7 +159,6 @@ LL | pub enum ColumnInsertValue where ... LL | Expr: Expression::Nullable>, | ------------------------------------------------ unsatisfied trait bound - = help: consider manually implementing `Copy` to avoid undesired bounds help: consider further restricting the associated type | LL | Expr: Expression::Nullable>, ::SqlType: NotNull, diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 853e10e0b35a..308d71f0f4bd 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -11,7 +11,6 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Foo(T); | ^^^ - type parameter would need to implement `Copy` - = help: consider manually implementing `Copy` to avoid undesired bounds = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block | diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index 40f96919121f..20a73ffdcfbf 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -13,7 +13,6 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct B { | ^ - type parameter would need to implement `Copy` - = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 | @@ -65,7 +64,6 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct B { | ^ - type parameter would need to implement `Copy` - = help: consider manually implementing `Copy` to avoid undesired bounds note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 | diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index 63c4ba900829..65e1dff479e5 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -35,7 +35,6 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Fooy(T); | ^^^^ - type parameter would need to implement `Copy` - = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 | @@ -62,7 +61,6 @@ LL | #[derive(Copy, Clone)] | ---- in this derive macro expansion LL | struct Fooy(T); | ^^^^ - type parameter would need to implement `Copy` - = help: consider manually implementing `Copy` to avoid undesired bounds note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 | From 675656188786ebb1444b5ea7baece40d8afa51ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 1 Feb 2026 18:31:21 +0000 Subject: [PATCH 380/978] fix test after rebase --- .../derive-clone-already-present-issue-146515.rs | 5 ++--- .../derive-clone-already-present-issue-146515.stderr | 11 ++++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs b/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs index 083d73711a51..78b4c017251e 100644 --- a/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs +++ b/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs @@ -2,8 +2,8 @@ use std::rc::Rc; -#[derive(Clone)] -struct ContainsRc { +#[derive(Clone)] //~ NOTE in this expansion +struct ContainsRc { //~ NOTE derive introduces an implicit `T: Clone` bound value: Rc, } @@ -14,7 +14,6 @@ fn clone_me(x: &ContainsRc) -> ContainsRc { //~| NOTE expected `ContainsRc`, found `&ContainsRc` //~| NOTE expected struct `ContainsRc<_>` //~| NOTE `ContainsRc` does not implement `Clone`, so `&ContainsRc` was cloned instead - //~| NOTE the trait `Clone` must be implemented } fn main() {} diff --git a/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr b/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr index 516ef38f668d..6ecf4e7ca943 100644 --- a/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr +++ b/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr @@ -14,9 +14,14 @@ note: `ContainsRc` does not implement `Clone`, so `&ContainsRc` was cloned | LL | x.clone() | ^ - = help: `Clone` is not implemented because the trait bound `T: Clone` is not satisfied -note: the trait `Clone` must be implemented - --> $SRC_DIR/core/src/clone.rs:LL:COL +help: `Clone` is not implemented because a trait bound is not satisfied + --> $DIR/derive-clone-already-present-issue-146515.rs:6:19 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct ContainsRc { + | ^ derive introduces an implicit `T: Clone` bound + = help: consider manually implementing `Clone` to avoid the implicit type parameter bounds error: aborting due to 1 previous error From f490f6420bbc7055e212e96c1745b44436a017e3 Mon Sep 17 00:00:00 2001 From: Maarten Craeynest Date: Sun, 1 Feb 2026 21:51:27 +0100 Subject: [PATCH 381/978] Add regression test for issue-136514: Negative literal in unsigned range --- .../range-negative-literal-unsigned-type.rs | 21 +++ ...ange-negative-literal-unsigned-type.stderr | 122 ++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 tests/ui/range/range-negative-literal-unsigned-type.rs create mode 100644 tests/ui/range/range-negative-literal-unsigned-type.stderr diff --git a/tests/ui/range/range-negative-literal-unsigned-type.rs b/tests/ui/range/range-negative-literal-unsigned-type.rs new file mode 100644 index 000000000000..b6152abb340e --- /dev/null +++ b/tests/ui/range/range-negative-literal-unsigned-type.rs @@ -0,0 +1,21 @@ +// Regression tests for: https://github.com/rust-lang/rust/issues/136514 + +#![allow(unreachable_patterns)] +fn main() { + match 0u8 { + -1..=2 => {} + //~^ ERROR the trait bound `u8: Neg` is not satisfied + -0..=0 => {} + //~^ ERROR the trait bound `u8: Neg` is not satisfied + -256..=2 => {} + //~^ ERROR the trait bound `u8: Neg` is not satisfied + -255..=2 => {} + //~^ ERROR the trait bound `u8: Neg` is not satisfied + 0..=-1 => {} + //~^ ERROR the trait bound `u8: Neg` is not satisfied + -2..=-1 => {} + //~^ ERROR the trait bound `u8: Neg` is not satisfied + //~| ERROR the trait bound `u8: Neg` is not satisfied + _ => {} + } +} diff --git a/tests/ui/range/range-negative-literal-unsigned-type.stderr b/tests/ui/range/range-negative-literal-unsigned-type.stderr new file mode 100644 index 000000000000..7ca14c3d7790 --- /dev/null +++ b/tests/ui/range/range-negative-literal-unsigned-type.stderr @@ -0,0 +1,122 @@ +error[E0277]: the trait bound `u8: Neg` is not satisfied + --> $DIR/range-negative-literal-unsigned-type.rs:6:9 + | +LL | -1..=2 => {} + | ^^ the trait `Neg` is not implemented for `u8` + | + = help: the following other types implement trait `Neg`: + &f128 + &f16 + &f32 + &f64 + &i128 + &i16 + &i32 + &i64 + and 12 others + +error[E0277]: the trait bound `u8: Neg` is not satisfied + --> $DIR/range-negative-literal-unsigned-type.rs:8:9 + | +LL | -0..=0 => {} + | ^^ the trait `Neg` is not implemented for `u8` + | + = help: the following other types implement trait `Neg`: + &f128 + &f16 + &f32 + &f64 + &i128 + &i16 + &i32 + &i64 + and 12 others + +error[E0277]: the trait bound `u8: Neg` is not satisfied + --> $DIR/range-negative-literal-unsigned-type.rs:10:9 + | +LL | -256..=2 => {} + | ^^^^ the trait `Neg` is not implemented for `u8` + | + = help: the following other types implement trait `Neg`: + &f128 + &f16 + &f32 + &f64 + &i128 + &i16 + &i32 + &i64 + and 12 others + +error[E0277]: the trait bound `u8: Neg` is not satisfied + --> $DIR/range-negative-literal-unsigned-type.rs:12:9 + | +LL | -255..=2 => {} + | ^^^^ the trait `Neg` is not implemented for `u8` + | + = help: the following other types implement trait `Neg`: + &f128 + &f16 + &f32 + &f64 + &i128 + &i16 + &i32 + &i64 + and 12 others + +error[E0277]: the trait bound `u8: Neg` is not satisfied + --> $DIR/range-negative-literal-unsigned-type.rs:14:13 + | +LL | 0..=-1 => {} + | ^^ the trait `Neg` is not implemented for `u8` + | + = help: the following other types implement trait `Neg`: + &f128 + &f16 + &f32 + &f64 + &i128 + &i16 + &i32 + &i64 + and 12 others + +error[E0277]: the trait bound `u8: Neg` is not satisfied + --> $DIR/range-negative-literal-unsigned-type.rs:16:9 + | +LL | -2..=-1 => {} + | ^^ the trait `Neg` is not implemented for `u8` + | + = help: the following other types implement trait `Neg`: + &f128 + &f16 + &f32 + &f64 + &i128 + &i16 + &i32 + &i64 + and 12 others + +error[E0277]: the trait bound `u8: Neg` is not satisfied + --> $DIR/range-negative-literal-unsigned-type.rs:16:14 + | +LL | -2..=-1 => {} + | ^^ the trait `Neg` is not implemented for `u8` + | + = help: the following other types implement trait `Neg`: + &f128 + &f16 + &f32 + &f64 + &i128 + &i16 + &i32 + &i64 + and 12 others + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0277`. From cd1c7736614dcde9fe19961c83d935adedf98662 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Jan 2026 14:45:35 +1100 Subject: [PATCH 382/978] Remove `lift_query_info`. It doesn't use `self`, which means it doesn't need to be part of the `QueryContext` trait; we can just call `extract` directly where necessary. --- compiler/rustc_query_impl/src/plumbing.rs | 12 +----------- compiler/rustc_query_system/src/query/job.rs | 9 +++------ compiler/rustc_query_system/src/query/mod.rs | 6 ++---- compiler/rustc_query_system/src/query/plumbing.rs | 10 +++++----- 4 files changed, 11 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 2d4e10a0380c..da11623d77b7 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -104,13 +104,6 @@ impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> { if complete { Ok(jobs) } else { Err(jobs) } } - fn lift_query_info( - self, - info: &QueryStackDeferred<'tcx>, - ) -> rustc_query_system::query::QueryStackFrameExtra { - info.extract() - } - // Interactions with on_disk_cache fn load_side_effect( self, @@ -174,10 +167,7 @@ impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> { self.tcx.sess.dcx().emit_fatal(QueryOverflow { span: info.job.span, - note: QueryOverflowNote { - desc: self.lift_query_info(&info.query.info).description, - depth, - }, + note: QueryOverflowNote { desc: info.query.info.extract().description, depth }, suggested_limit, crate_name: self.tcx.crate_name(LOCAL_CRATE), }); diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 177bcd63cbc6..3affb23d3022 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -27,11 +27,8 @@ pub struct QueryInfo { } impl<'tcx> QueryInfo> { - pub(crate) fn lift>( - &self, - qcx: Qcx, - ) -> QueryInfo { - QueryInfo { span: self.span, query: self.query.lift(qcx) } + pub(crate) fn lift(&self) -> QueryInfo { + QueryInfo { span: self.span, query: self.query.lift() } } } @@ -628,7 +625,7 @@ pub fn print_query_stack<'tcx, Qcx: QueryContext<'tcx>>( let Some(query_info) = query_map.get(&query) else { break; }; - let query_extra = qcx.lift_query_info(&query_info.query.info); + let query_extra = query_info.query.info.extract(); if Some(count_printed) < limit_frames || limit_frames.is_none() { // Only print to stderr as many stack frames as `num_frames` when present. dcx.struct_failure_note(format!( diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 63202429679d..e40dcf2daf35 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -70,9 +70,9 @@ impl<'tcx> QueryStackFrame> { Self { info, def_id, dep_kind, hash, def_id_for_ty_in_cycle } } - fn lift>(&self, qcx: Qcx) -> QueryStackFrame { + fn lift(&self) -> QueryStackFrame { QueryStackFrame { - info: qcx.lift_query_info(&self.info), + info: self.info.extract(), dep_kind: self.dep_kind, hash: self.hash, def_id: self.def_id, @@ -168,8 +168,6 @@ pub trait QueryContext<'tcx>: HasDepContext { fn collect_active_jobs(self, require_complete: bool) -> Result, QueryMap<'tcx>>; - fn lift_query_info(self, info: &QueryStackDeferred<'tcx>) -> QueryStackFrameExtra; - /// Load a side effect associated to the node in the previous session. fn load_side_effect( self, diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 98bbd3ebc4a0..04b62daa86b4 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -253,10 +253,10 @@ pub struct CycleError { } impl<'tcx> CycleError> { - fn lift>(&self, qcx: Qcx) -> CycleError { + fn lift(&self) -> CycleError { CycleError { - usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift(qcx))), - cycle: self.cycle.iter().map(|info| info.lift(qcx)).collect(), + usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift())), + cycle: self.cycle.iter().map(|info| info.lift()).collect(), } } } @@ -297,7 +297,7 @@ where let query_map = qcx.collect_active_jobs(false).ok().expect("failed to collect active queries"); let error = try_execute.find_cycle_in_stack(query_map, &qcx.current_query_job(), span); - (mk_cycle(query, qcx, error.lift(qcx)), None) + (mk_cycle(query, qcx, error.lift()), None) } #[inline(always)] @@ -345,7 +345,7 @@ where (v, Some(index)) } - Err(cycle) => (mk_cycle(query, qcx, cycle.lift(qcx)), None), + Err(cycle) => (mk_cycle(query, qcx, cycle.lift()), None), } } From 4ff360e997eaf57005454eaa8dc6eff2b820d425 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Jan 2026 14:50:45 +1100 Subject: [PATCH 383/978] Rename some query-related things. Various `QueryStackFrame` variables are called `query`; `frame` is a better name. And various `QueryInfo` variables are called `frame`; `info` is a better name. This eliminates some confusing `query.query()` occurrences, which is a good sign, and some `frame.query` occurrences become `info.frame`. --- compiler/rustc_middle/src/values.rs | 34 +++++++------- compiler/rustc_query_impl/src/plumbing.rs | 6 +-- compiler/rustc_query_system/src/query/job.rs | 44 +++++++++---------- .../rustc_query_system/src/query/plumbing.rs | 10 ++--- 4 files changed, 47 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index bc73d36216ef..fd08b5a972c6 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -50,9 +50,9 @@ impl<'tcx> Value> for ty::Binder<'_, ty::FnSig<'_>> { ) -> Self { let err = Ty::new_error(tcx, guar); - let arity = if let Some(frame) = cycle_error.cycle.get(0) - && frame.query.dep_kind == dep_kinds::fn_sig - && let Some(def_id) = frame.query.def_id + let arity = if let Some(info) = cycle_error.cycle.get(0) + && info.frame.dep_kind == dep_kinds::fn_sig + && let Some(def_id) = info.frame.def_id && let Some(node) = tcx.hir_get_if_local(def_id) && let Some(sig) = node.fn_sig() { @@ -85,10 +85,10 @@ impl<'tcx> Value> for Representability { let mut item_and_field_ids = Vec::new(); let mut representable_ids = FxHashSet::default(); for info in &cycle_error.cycle { - if info.query.dep_kind == dep_kinds::representability - && let Some(field_id) = info.query.def_id + if info.frame.dep_kind == dep_kinds::representability + && let Some(field_id) = info.frame.def_id && let Some(field_id) = field_id.as_local() - && let Some(DefKind::Field) = info.query.info.def_kind + && let Some(DefKind::Field) = info.frame.info.def_kind { let parent_id = tcx.parent(field_id.to_def_id()); let item_id = match tcx.def_kind(parent_id) { @@ -99,8 +99,8 @@ impl<'tcx> Value> for Representability { } } for info in &cycle_error.cycle { - if info.query.dep_kind == dep_kinds::representability_adt_ty - && let Some(def_id) = info.query.def_id_for_ty_in_cycle + if info.frame.dep_kind == dep_kinds::representability_adt_ty + && let Some(def_id) = info.frame.def_id_for_ty_in_cycle && let Some(def_id) = def_id.as_local() && !item_and_field_ids.iter().any(|&(id, _)| id == def_id) { @@ -141,9 +141,9 @@ impl<'tcx> Value> for &[ty::Variance] { search_for_cycle_permutation( &cycle_error.cycle, |cycle| { - if let Some(frame) = cycle.get(0) - && frame.query.dep_kind == dep_kinds::variances_of - && let Some(def_id) = frame.query.def_id + if let Some(info) = cycle.get(0) + && info.frame.dep_kind == dep_kinds::variances_of + && let Some(def_id) = info.frame.def_id { let n = tcx.generics_of(def_id).own_params.len(); ControlFlow::Break(vec![ty::Bivariant; n].leak()) @@ -189,8 +189,8 @@ impl<'tcx, T> Value> for Result> let diag = search_for_cycle_permutation( &cycle_error.cycle, |cycle| { - if cycle[0].query.dep_kind == dep_kinds::layout_of - && let Some(def_id) = cycle[0].query.def_id_for_ty_in_cycle + if cycle[0].frame.dep_kind == dep_kinds::layout_of + && let Some(def_id) = cycle[0].frame.def_id_for_ty_in_cycle && let Some(def_id) = def_id.as_local() && let def_kind = tcx.def_kind(def_id) && matches!(def_kind, DefKind::Closure) @@ -213,18 +213,18 @@ impl<'tcx, T> Value> for Result> tcx.def_kind_descr_article(def_kind, def_id.to_def_id()), tcx.def_kind_descr(def_kind, def_id.to_def_id()), ); - for (i, frame) in cycle.iter().enumerate() { - if frame.query.dep_kind != dep_kinds::layout_of { + for (i, info) in cycle.iter().enumerate() { + if info.frame.dep_kind != dep_kinds::layout_of { continue; } - let Some(frame_def_id) = frame.query.def_id_for_ty_in_cycle else { + let Some(frame_def_id) = info.frame.def_id_for_ty_in_cycle else { continue; }; let Some(frame_coroutine_kind) = tcx.coroutine_kind(frame_def_id) else { continue; }; let frame_span = - frame.query.info.default_span(cycle[(i + 1) % cycle.len()].span); + info.frame.info.default_span(cycle[(i + 1) % cycle.len()].span); if frame_span.is_dummy() { continue; } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index da11623d77b7..b7ce8587695b 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -167,7 +167,7 @@ impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> { self.tcx.sess.dcx().emit_fatal(QueryOverflow { span: info.job.span, - note: QueryOverflowNote { desc: info.query.info.extract().description, depth }, + note: QueryOverflowNote { desc: info.frame.info.extract().description, depth }, suggested_limit, crate_name: self.tcx.crate_name(LOCAL_CRATE), }); @@ -728,14 +728,14 @@ macro_rules! define_queries { qmap: &mut QueryMap<'tcx>, require_complete: bool, ) -> Option<()> { - let make_query = |tcx, key| { + let make_frame = |tcx, key| { let kind = rustc_middle::dep_graph::dep_kinds::$name; let name = stringify!($name); $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name) }; let res = tcx.query_system.states.$name.collect_active_jobs( tcx, - make_query, + make_frame, qmap, require_complete, ); diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 3affb23d3022..82b23b022c37 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -23,12 +23,12 @@ use crate::query::{QueryContext, QueryStackFrame}; pub struct QueryInfo { /// The span corresponding to the reason for which this query was required. pub span: Span, - pub query: QueryStackFrame, + pub frame: QueryStackFrame, } impl<'tcx> QueryInfo> { pub(crate) fn lift(&self) -> QueryInfo { - QueryInfo { span: self.span, query: self.query.lift() } + QueryInfo { span: self.span, frame: self.frame.lift() } } } @@ -39,8 +39,8 @@ pub type QueryMap<'tcx> = FxHashMap>; pub struct QueryJobId(pub NonZero); impl QueryJobId { - fn query<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> QueryStackFrame> { - map.get(&self).unwrap().query.clone() + fn frame<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> QueryStackFrame> { + map.get(&self).unwrap().frame.clone() } fn span<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> Span { @@ -58,7 +58,7 @@ impl QueryJobId { #[derive(Clone, Debug)] pub struct QueryJobInfo<'tcx> { - pub query: QueryStackFrame>, + pub frame: QueryStackFrame>, pub job: QueryJob<'tcx>, } @@ -122,7 +122,7 @@ impl QueryJobId { while let Some(job) = current_job { let info = query_map.get(&job).unwrap(); - cycle.push(QueryInfo { span: info.job.span, query: info.query.clone() }); + cycle.push(QueryInfo { span: info.job.span, frame: info.frame.clone() }); if job == *self { cycle.reverse(); @@ -137,7 +137,7 @@ impl QueryJobId { .job .parent .as_ref() - .map(|parent| (info.job.span, parent.query(&query_map))); + .map(|parent| (info.job.span, parent.frame(&query_map))); return CycleError { usage, cycle }; } @@ -155,13 +155,13 @@ impl QueryJobId { ) -> (QueryJobInfo<'tcx>, usize) { let mut depth = 1; let info = query_map.get(&self).unwrap(); - let dep_kind = info.query.dep_kind; + let dep_kind = info.frame.dep_kind; let mut current_id = info.job.parent; let mut last_layout = (info.clone(), depth); while let Some(id) = current_id { let info = query_map.get(&id).unwrap(); - if info.query.dep_kind == dep_kind { + if info.frame.dep_kind == dep_kind { depth += 1; last_layout = (info.clone(), depth); } @@ -386,7 +386,7 @@ where .iter() .min_by_key(|v| { let (span, query) = f(v); - let hash = query.query(query_map).hash; + let hash = query.frame(query_map).hash; // Prefer entry points which have valid spans for nicer error messages // We add an integer to the tuple ensuring that entry points // with valid spans are picked first @@ -470,14 +470,14 @@ fn remove_cycle<'tcx>( stack.rotate_left(pos); } - let usage = usage.as_ref().map(|(span, query)| (*span, query.query(query_map))); + let usage = usage.as_ref().map(|(span, query)| (*span, query.frame(query_map))); // Create the cycle error let error = CycleError { usage, cycle: stack .iter() - .map(|&(s, ref q)| QueryInfo { span: s, query: q.query(query_map) }) + .map(|&(s, ref q)| QueryInfo { span: s, frame: q.frame(query_map) }) .collect(), }; @@ -556,7 +556,7 @@ pub fn report_cycle<'a>( ) -> Diag<'a> { assert!(!stack.is_empty()); - let span = stack[0].query.info.default_span(stack[1 % stack.len()].span); + let span = stack[0].frame.info.default_span(stack[1 % stack.len()].span); let mut cycle_stack = Vec::new(); @@ -564,9 +564,9 @@ pub fn report_cycle<'a>( let stack_count = if stack.len() == 1 { StackCount::Single } else { StackCount::Multiple }; for i in 1..stack.len() { - let query = &stack[i].query; - let span = query.info.default_span(stack[(i + 1) % stack.len()].span); - cycle_stack.push(CycleStack { span, desc: query.info.description.to_owned() }); + let frame = &stack[i].frame; + let span = frame.info.default_span(stack[(i + 1) % stack.len()].span); + cycle_stack.push(CycleStack { span, desc: frame.info.description.to_owned() }); } let mut cycle_usage = None; @@ -578,9 +578,9 @@ pub fn report_cycle<'a>( } let alias = - if stack.iter().all(|entry| matches!(entry.query.info.def_kind, Some(DefKind::TyAlias))) { + if stack.iter().all(|entry| matches!(entry.frame.info.def_kind, Some(DefKind::TyAlias))) { Some(crate::error::Alias::Ty) - } else if stack.iter().all(|entry| entry.query.info.def_kind == Some(DefKind::TraitAlias)) { + } else if stack.iter().all(|entry| entry.frame.info.def_kind == Some(DefKind::TraitAlias)) { Some(crate::error::Alias::Trait) } else { None @@ -589,7 +589,7 @@ pub fn report_cycle<'a>( let cycle_diag = crate::error::Cycle { span, cycle_stack, - stack_bottom: stack[0].query.info.description.to_owned(), + stack_bottom: stack[0].frame.info.description.to_owned(), alias, cycle_usage, stack_count, @@ -625,12 +625,12 @@ pub fn print_query_stack<'tcx, Qcx: QueryContext<'tcx>>( let Some(query_info) = query_map.get(&query) else { break; }; - let query_extra = query_info.query.info.extract(); + let query_extra = query_info.frame.info.extract(); if Some(count_printed) < limit_frames || limit_frames.is_none() { // Only print to stderr as many stack frames as `num_frames` when present. dcx.struct_failure_note(format!( "#{} [{:?}] {}", - count_printed, query_info.query.dep_kind, query_extra.description + count_printed, query_info.frame.dep_kind, query_extra.description )) .with_span(query_info.job.span) .emit(); @@ -642,7 +642,7 @@ pub fn print_query_stack<'tcx, Qcx: QueryContext<'tcx>>( file, "#{} [{}] {}", count_total, - qcx.dep_context().dep_kind_vtable(query_info.query.dep_kind).name, + qcx.dep_context().dep_kind_vtable(query_info.frame.dep_kind).name, query_extra.description ); } diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 04b62daa86b4..25f96315cd13 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -82,7 +82,7 @@ where pub fn collect_active_jobs( &self, qcx: Qcx, - make_query: fn(Qcx, K) -> QueryStackFrame>, + make_frame: fn(Qcx, K) -> QueryStackFrame>, jobs: &mut QueryMap<'tcx>, require_complete: bool, ) -> Option<()> { @@ -108,11 +108,11 @@ where } } - // Call `make_query` while we're not holding a `self.active` lock as `make_query` may call + // Call `make_frame` while we're not holding a `self.active` lock as `make_frame` may call // queries leading to a deadlock. for (key, job) in active { - let query = make_query(qcx, key); - jobs.insert(job.id, QueryJobInfo { query, job }); + let frame = make_frame(qcx, key); + jobs.insert(job.id, QueryJobInfo { frame, job }); } Some(()) @@ -170,7 +170,7 @@ where } CycleErrorHandling::Stash => { let guar = if let Some(root) = cycle_error.cycle.first() - && let Some(span) = root.query.info.span + && let Some(span) = root.frame.info.span { error.stash(span, StashKey::Cycle).unwrap() } else { From 8e2c9c69c6279c0a63833163d622e4a55df07b3f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Jan 2026 15:14:41 +1100 Subject: [PATCH 384/978] Eliminate some `'a` lifetimes. Putting `+ 'tcx` on the `QueryDispatcher` trait lets a few other places be simplified. --- compiler/rustc_query_impl/src/lib.rs | 11 ++++------- compiler/rustc_query_system/src/query/dispatcher.rs | 6 +++--- compiler/rustc_query_system/src/query/plumbing.rs | 10 +++++----- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 4e79d0842da2..6e119bf92e2d 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -86,10 +86,7 @@ where } #[inline(always)] - fn query_state<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a QueryState<'tcx, Self::Key> - where - QueryCtxt<'tcx>: 'a, - { + fn query_state(self, qcx: QueryCtxt<'tcx>) -> &'tcx QueryState<'tcx, Self::Key> { // Safety: // This is just manually doing the subfield referencing through pointer math. unsafe { @@ -100,7 +97,7 @@ where } #[inline(always)] - fn query_cache<'a>(self, qcx: QueryCtxt<'tcx>) -> &'a Self::Cache { + fn query_cache(self, qcx: QueryCtxt<'tcx>) -> &'tcx Self::Cache { // Safety: // This is just manually doing the subfield referencing through pointer math. unsafe { @@ -216,12 +213,12 @@ trait QueryDispatcherUnerased<'tcx> { ) -> Self::UnerasedValue; } -pub fn query_system<'a>( +pub fn query_system<'tcx>( local_providers: Providers, extern_providers: ExternProviders, on_disk_cache: Option, incremental: bool, -) -> QuerySystem<'a> { +) -> QuerySystem<'tcx> { QuerySystem { states: Default::default(), arenas: Default::default(), diff --git a/compiler/rustc_query_system/src/query/dispatcher.rs b/compiler/rustc_query_system/src/query/dispatcher.rs index ac6c38dd7db5..bcd3d0322d07 100644 --- a/compiler/rustc_query_system/src/query/dispatcher.rs +++ b/compiler/rustc_query_system/src/query/dispatcher.rs @@ -25,7 +25,7 @@ type DepContextOf<'tcx, This: QueryDispatcher<'tcx>> = /// Those types are not visible from this `rustc_query_system` crate. /// /// "Dispatcher" should be understood as a near-synonym of "vtable". -pub trait QueryDispatcher<'tcx>: Copy { +pub trait QueryDispatcher<'tcx>: Copy + 'tcx { fn name(self) -> &'static str; /// Query context used by this dispatcher, i.e. `rustc_query_impl::QueryCtxt`. @@ -41,10 +41,10 @@ pub trait QueryDispatcher<'tcx>: Copy { fn format_value(self) -> fn(&Self::Value) -> String; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_state<'a>(self, tcx: Self::Qcx) -> &'a QueryState<'tcx, Self::Key>; + fn query_state(self, tcx: Self::Qcx) -> &'tcx QueryState<'tcx, Self::Key>; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_cache<'a>(self, tcx: Self::Qcx) -> &'a Self::Cache; + fn query_cache(self, tcx: Self::Qcx) -> &'tcx Self::Cache; fn will_cache_on_disk_for_key(self, tcx: DepContextOf<'tcx, Self>, key: &Self::Key) -> bool; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 25f96315cd13..472839116107 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -127,11 +127,11 @@ impl<'tcx, K> Default for QueryState<'tcx, K> { /// A type representing the responsibility to execute the job in the `job` field. /// This will poison the relevant query if dropped. -struct JobOwner<'a, 'tcx, K> +struct JobOwner<'tcx, K> where K: Eq + Hash + Copy, { - state: &'a QueryState<'tcx, K>, + state: &'tcx QueryState<'tcx, K>, key: K, } @@ -181,7 +181,7 @@ where } } -impl<'a, 'tcx, K> JobOwner<'a, 'tcx, K> +impl<'tcx, K> JobOwner<'tcx, K> where K: Eq + Hash + Copy, { @@ -218,7 +218,7 @@ where } } -impl<'a, 'tcx, K> Drop for JobOwner<'a, 'tcx, K> +impl<'tcx, K> Drop for JobOwner<'tcx, K> where K: Eq + Hash + Copy, { @@ -422,7 +422,7 @@ where fn execute_job<'tcx, Q, const INCR: bool>( query: Q, qcx: Q::Qcx, - state: &QueryState<'tcx, Q::Key>, + state: &'tcx QueryState<'tcx, Q::Key>, key: Q::Key, key_hash: u64, id: QueryJobId, From c6afd45ac16e0a665ed6feb2d45cf2a4e2769643 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 2 Feb 2026 10:41:03 +1100 Subject: [PATCH 385/978] Move `depth_limit_error` out of `QueryContext` trait. It's defined and used in `rustc_query_impl`; `rustc_query_system` doesn't need it. So it can just be an inherent method on `QueryCtxt`. --- compiler/rustc_query_impl/src/plumbing.rs | 34 ++++++++++---------- compiler/rustc_query_system/src/query/mod.rs | 2 -- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index b7ce8587695b..0002e5950a33 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -48,6 +48,23 @@ impl<'tcx> QueryCtxt<'tcx> { pub fn new(tcx: TyCtxt<'tcx>) -> Self { QueryCtxt { tcx } } + + fn depth_limit_error(self, job: QueryJobId) { + let query_map = self.collect_active_jobs(true).expect("failed to collect active queries"); + let (info, depth) = job.find_dep_kind_root(query_map); + + let suggested_limit = match self.tcx.recursion_limit() { + Limit(0) => Limit(2), + limit => limit * 2, + }; + + self.tcx.sess.dcx().emit_fatal(QueryOverflow { + span: info.job.span, + note: QueryOverflowNote { desc: info.frame.info.extract().description, depth }, + suggested_limit, + crate_name: self.tcx.crate_name(LOCAL_CRATE), + }); + } } impl<'tcx> HasDepContext for QueryCtxt<'tcx> { @@ -155,23 +172,6 @@ impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> { tls::enter_context(&new_icx, compute) }) } - - fn depth_limit_error(self, job: QueryJobId) { - let query_map = self.collect_active_jobs(true).expect("failed to collect active queries"); - let (info, depth) = job.find_dep_kind_root(query_map); - - let suggested_limit = match self.tcx.recursion_limit() { - Limit(0) => Limit(2), - limit => limit * 2, - }; - - self.tcx.sess.dcx().emit_fatal(QueryOverflow { - span: info.job.span, - note: QueryOverflowNote { desc: info.frame.info.extract().description, depth }, - suggested_limit, - crate_name: self.tcx.crate_name(LOCAL_CRATE), - }); - } } pub(super) fn try_mark_green<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool { diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index e40dcf2daf35..54e5fa4d7229 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -181,6 +181,4 @@ pub trait QueryContext<'tcx>: HasDepContext { /// new query job while it executes. fn start_query(self, token: QueryJobId, depth_limit: bool, compute: impl FnOnce() -> R) -> R; - - fn depth_limit_error(self, job: QueryJobId); } From f3b7a1a9d8e0beb8998f5b621b26d4942c423123 Mon Sep 17 00:00:00 2001 From: Carl Lundin Date: Sun, 1 Feb 2026 17:14:41 -0800 Subject: [PATCH 386/978] Update documentation for `Result::ok()` The term of "discard" is misleading. An error is not discarded but converted to an `Option::None`. --- library/core/src/result.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 52f3d43dfd6d..5f438d72ac13 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -690,7 +690,7 @@ impl Result { /// Converts from `Result` to [`Option`]. /// /// Converts `self` into an [`Option`], consuming `self`, - /// and discarding the error, if any. + /// and converting the error to `None`, if any. /// /// # Examples /// From c64f9a0fc46fecb8ccb15d1ab1fcfd83ce94b5e5 Mon Sep 17 00:00:00 2001 From: ritik chahar Date: Mon, 2 Feb 2026 07:38:14 +0530 Subject: [PATCH 387/978] Add backlink to issue --- tests/codegen-llvm/slp-vectorization-mul3.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/codegen-llvm/slp-vectorization-mul3.rs b/tests/codegen-llvm/slp-vectorization-mul3.rs index bb4965c46bc0..b6edc212c82d 100644 --- a/tests/codegen-llvm/slp-vectorization-mul3.rs +++ b/tests/codegen-llvm/slp-vectorization-mul3.rs @@ -1,3 +1,4 @@ +//! Regression test for #142519 //@ only-x86_64 //@ compile-flags: -O From 0cbbe56d84ef44715e4e12496d904848c0863968 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 2 Feb 2026 13:03:10 +1100 Subject: [PATCH 388/978] Work around rustfmt giving up on a large expression --- compiler/rustc_interface/src/util.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index b3889849430a..249368fd1194 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -231,7 +231,12 @@ pub(crate) fn run_in_thread_pool_with_globals< .name("rustc query cycle handler".to_string()) .spawn(move || { let on_panic = defer(|| { - eprintln!("internal compiler error: query cycle handler thread panicked, aborting process"); + // Split this long string so that it doesn't cause rustfmt to + // give up on the entire builder expression. + // + const MESSAGE: &str = "\ +internal compiler error: query cycle handler thread panicked, aborting process"; + eprintln!("{MESSAGE}"); // We need to abort here as we failed to resolve the deadlock, // otherwise the compiler could just hang, process::abort(); @@ -244,11 +249,16 @@ pub(crate) fn run_in_thread_pool_with_globals< tls::with(|tcx| { // Accessing session globals is sound as they outlive `GlobalCtxt`. // They are needed to hash query keys containing spans or symbols. - let query_map = rustc_span::set_session_globals_then(unsafe { &*(session_globals as *const SessionGlobals) }, || { - // Ensure there was no errors collecting all active jobs. - // We need the complete map to ensure we find a cycle to break. - QueryCtxt::new(tcx).collect_active_jobs(false).expect("failed to collect active queries in deadlock handler") - }); + let query_map = rustc_span::set_session_globals_then( + unsafe { &*(session_globals as *const SessionGlobals) }, + || { + // Ensure there were no errors collecting all active jobs. + // We need the complete map to ensure we find a cycle to break. + QueryCtxt::new(tcx).collect_active_jobs(false).expect( + "failed to collect active queries in deadlock handler", + ) + }, + ); break_query_cycles(query_map, ®istry); }) }) From 59868c13947753220a6727e50c2c596d2f513b29 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 23 Jan 2026 13:43:20 -0500 Subject: [PATCH 389/978] Fix uninitialized UEFI globals in tests Export globals via a `doc(hidden)` module. In test code, use the globals from `realstd` so that they are properly initialized. --- library/std/src/lib.rs | 1 + library/std/src/os/uefi/env.rs | 24 ++++++++++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index b213fa749177..dcde208fac77 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -260,6 +260,7 @@ all(target_vendor = "fortanix", target_env = "sgx"), feature(slice_index_methods, coerce_unsized, sgx_platform) )] +#![cfg_attr(all(test, target_os = "uefi"), feature(uefi_std))] #![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))] #![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))] // diff --git a/library/std/src/os/uefi/env.rs b/library/std/src/os/uefi/env.rs index ab5406e605c6..82e3fc9775cb 100644 --- a/library/std/src/os/uefi/env.rs +++ b/library/std/src/os/uefi/env.rs @@ -4,13 +4,25 @@ use crate::ffi::c_void; use crate::ptr::NonNull; -use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, Ordering}; +use crate::sync::atomic::Ordering; -static SYSTEM_TABLE: Atomic<*mut c_void> = AtomicPtr::new(crate::ptr::null_mut()); -static IMAGE_HANDLE: Atomic<*mut c_void> = AtomicPtr::new(crate::ptr::null_mut()); -// Flag to check if BootServices are still valid. -// Start with assuming that they are not available -static BOOT_SERVICES_FLAG: Atomic = AtomicBool::new(false); +#[doc(hidden)] +#[cfg(not(test))] +pub mod globals { + use crate::ffi::c_void; + use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr}; + + pub static SYSTEM_TABLE: Atomic<*mut c_void> = AtomicPtr::new(crate::ptr::null_mut()); + pub static IMAGE_HANDLE: Atomic<*mut c_void> = AtomicPtr::new(crate::ptr::null_mut()); + // Flag to check if BootServices are still valid. + // Start with assuming that they are not available + pub static BOOT_SERVICES_FLAG: Atomic = AtomicBool::new(false); +} + +#[cfg(not(test))] +use globals::*; +#[cfg(test)] +use realstd::os::uefi::env::globals::*; /// Initializes the global System Table and Image Handle pointers. /// From 09de0fd848251aed26149bd5938b1e05ef35dc82 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 30 Jan 2026 12:41:04 +1100 Subject: [PATCH 390/978] Use `#![feature(adt_const_params)]` for static query flags --- compiler/rustc_query_impl/src/lib.rs | 40 ++++++++++++++--------- compiler/rustc_query_impl/src/plumbing.rs | 10 ++++-- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 4e79d0842da2..8dd220e1ae0f 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -2,10 +2,13 @@ // tidy-alphabetical-start #![allow(internal_features)] +#![feature(adt_const_params)] #![feature(min_specialization)] #![feature(rustc_attrs)] // tidy-alphabetical-end +use std::marker::ConstParamTy; + use rustc_data_structures::stable_hasher::HashStable; use rustc_data_structures::sync::AtomicU64; use rustc_middle::arena::Arena; @@ -35,29 +38,34 @@ pub use crate::plumbing::{QueryCtxt, query_key_hash_verify_all}; mod profiling_support; pub use self::profiling_support::alloc_self_profile_query_strings; +#[derive(ConstParamTy)] // Allow this struct to be used for const-generic values. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +struct QueryFlags { + /// True if this query has the `anon` modifier. + is_anon: bool, + /// True if this query has the `depth_limit` modifier. + is_depth_limit: bool, + /// True if this query has the `feedable` modifier. + is_feedable: bool, +} + /// Combines a [`QueryVTable`] with some additional compile-time booleans /// to implement [`QueryDispatcher`], for use by code in [`rustc_query_system`]. /// /// Baking these boolean flags into the type gives a modest but measurable /// improvement to compiler perf and compiler code size; see /// . -struct SemiDynamicQueryDispatcher< - 'tcx, - C: QueryCache, - const ANON: bool, - const DEPTH_LIMIT: bool, - const FEEDABLE: bool, -> { +struct SemiDynamicQueryDispatcher<'tcx, C: QueryCache, const FLAGS: QueryFlags> { vtable: &'tcx QueryVTable<'tcx, C>, } // Manually implement Copy/Clone, because deriving would put trait bounds on the cache type. -impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Copy - for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE> +impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> Copy + for SemiDynamicQueryDispatcher<'tcx, C, FLAGS> { } -impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> Clone - for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE> +impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> Clone + for SemiDynamicQueryDispatcher<'tcx, C, FLAGS> { fn clone(&self) -> Self { *self @@ -65,8 +73,8 @@ impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDA } // This is `impl QueryDispatcher for SemiDynamicQueryDispatcher`. -impl<'tcx, C: QueryCache, const ANON: bool, const DEPTH_LIMIT: bool, const FEEDABLE: bool> - QueryDispatcher<'tcx> for SemiDynamicQueryDispatcher<'tcx, C, ANON, DEPTH_LIMIT, FEEDABLE> +impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> QueryDispatcher<'tcx> + for SemiDynamicQueryDispatcher<'tcx, C, FLAGS> where for<'a> C::Key: HashStable>, { @@ -158,7 +166,7 @@ where #[inline(always)] fn anon(self) -> bool { - ANON + FLAGS.is_anon } #[inline(always)] @@ -168,12 +176,12 @@ where #[inline(always)] fn depth_limit(self) -> bool { - DEPTH_LIMIT + FLAGS.is_depth_limit } #[inline(always)] fn feedable(self) -> bool { - FEEDABLE + FLAGS.is_feedable } #[inline(always)] diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 2d4e10a0380c..48aed0bad4b8 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -708,14 +708,18 @@ macro_rules! define_queries { data: PhantomData<&'tcx ()> } + const FLAGS: QueryFlags = QueryFlags { + is_anon: is_anon!([$($modifiers)*]), + is_depth_limit: depth_limit!([$($modifiers)*]), + is_feedable: feedable!([$($modifiers)*]), + }; + impl<'tcx> QueryDispatcherUnerased<'tcx> for QueryType<'tcx> { type UnerasedValue = queries::$name::Value<'tcx>; type Dispatcher = SemiDynamicQueryDispatcher< 'tcx, queries::$name::Storage<'tcx>, - { is_anon!([$($modifiers)*]) }, - { depth_limit!([$($modifiers)*]) }, - { feedable!([$($modifiers)*]) }, + FLAGS, >; const NAME: &'static &'static str = &stringify!($name); From b5d9b7f6837e50d8984275f11704d8c7f8493923 Mon Sep 17 00:00:00 2001 From: usamoi Date: Sun, 1 Feb 2026 22:34:46 +0800 Subject: [PATCH 391/978] escape symbol names in global asm --- compiler/rustc_codegen_llvm/src/asm.rs | 45 ++++++++++++++++++++++-- tests/ui/asm/x86_64/global_asm_escape.rs | 17 +++++++++ tests/ui/asm/x86_64/naked_asm_escape.rs | 32 +++++++++++++++++ 3 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 tests/ui/asm/x86_64/global_asm_escape.rs create mode 100644 tests/ui/asm/x86_64/naked_asm_escape.rs diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 7f02518d6c0d..fd25fba2daac 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -399,7 +399,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { for piece in template { match *piece { InlineAsmTemplatePiece::String(ref s) => template_str.push_str(s), - InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => { + InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => { match operands[operand_idx] { GlobalAsmOperandRef::Const { ref string } => { // Const operands get injected directly into the @@ -414,7 +414,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { llvm::LLVMRustGetMangledName(llval, s); }) .expect("symbol is not valid UTF-8"); - template_str.push_str(&symbol); + template_str.push_str(&escape_symbol_name(self, symbol, span)); } GlobalAsmOperandRef::SymStatic { def_id } => { let llval = self @@ -428,7 +428,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { llvm::LLVMRustGetMangledName(llval, s); }) .expect("symbol is not valid UTF-8"); - template_str.push_str(&symbol); + template_str.push_str(&escape_symbol_name(self, symbol, span)); } } } @@ -1390,3 +1390,42 @@ fn llvm_fixup_output_type<'ll, 'tcx>( _ => layout.llvm_type(cx), } } + +fn escape_symbol_name<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, symbol: String, span: Span) -> String { + use rustc_target::spec::{Arch, BinaryFormat}; + if !symbol.is_empty() + && symbol.chars().all(|c| matches!(c, '0'..='9' | 'A'..='Z' | 'a'..='z' | '_' | '$' | '.')) + { + return symbol; + } + if cx.tcx.sess.target.binary_format == BinaryFormat::Xcoff { + cx.tcx.sess.dcx().span_fatal( + span, + format!( + "symbol escaping is not supported for the binary format {}", + cx.tcx.sess.target.binary_format + ), + ); + } + if cx.tcx.sess.target.arch == Arch::Nvptx64 { + cx.tcx.sess.dcx().span_fatal( + span, + format!( + "symbol escaping is not supported for the architecture {}", + cx.tcx.sess.target.arch + ), + ); + } + let mut escaped_symbol = String::new(); + escaped_symbol.push('\"'); + for c in symbol.chars() { + match c { + '\n' => escaped_symbol.push_str("\\\n"), + '"' => escaped_symbol.push_str("\\\""), + '\\' => escaped_symbol.push_str("\\\\"), + c => escaped_symbol.push(c), + } + } + escaped_symbol.push('\"'); + escaped_symbol +} diff --git a/tests/ui/asm/x86_64/global_asm_escape.rs b/tests/ui/asm/x86_64/global_asm_escape.rs new file mode 100644 index 000000000000..59214e958a85 --- /dev/null +++ b/tests/ui/asm/x86_64/global_asm_escape.rs @@ -0,0 +1,17 @@ +//@ run-pass +//@ only-x86_64-unknown-linux-gnu +//@ ignore-backends: gcc + +// https://github.com/rust-lang/rust/issues/151950 + +unsafe extern "C" { + #[link_name = "exit@GLIBC_2.2.5"] + safe fn exit(status: i32) -> !; + safe fn my_exit(status: i32) -> !; +} + +core::arch::global_asm!(".global my_exit", "my_exit:", "jmp {}", sym exit); + +fn main() { + my_exit(0); +} diff --git a/tests/ui/asm/x86_64/naked_asm_escape.rs b/tests/ui/asm/x86_64/naked_asm_escape.rs new file mode 100644 index 000000000000..57962993ef91 --- /dev/null +++ b/tests/ui/asm/x86_64/naked_asm_escape.rs @@ -0,0 +1,32 @@ +//@ build-fail +//@ only-x86_64-unknown-linux-gnu +//@ dont-check-compiler-stderr +//@ dont-check-compiler-stdout +//@ ignore-backends: gcc + +// https://github.com/rust-lang/rust/issues/151950 + +unsafe extern "C" { + #[link_name = "memset]; mov eax, 1; #"] + unsafe fn inject(); +} + +#[unsafe(export_name = "memset]; mov eax, 1; #")] +extern "C" fn inject_() {} + +#[unsafe(naked)] +extern "C" fn print_0() -> usize { + core::arch::naked_asm!("lea rax, [{}]", "ret", sym inject) +} + +#[unsafe(naked)] +extern "C" fn print_1() -> usize { + core::arch::naked_asm!("lea rax, [{}]", "ret", sym inject_) +} + +fn main() { + dbg!(print_0()); + dbg!(print_1()); +} + +//~? ERROR linking From 992a6f6c891aeb39b38e99f9e8de4e0cbd867f4a Mon Sep 17 00:00:00 2001 From: vishnupoddar12 Date: Mon, 2 Feb 2026 12:46:57 +0530 Subject: [PATCH 392/978] fix: allow_attributes false negative on attributes with whitespace --- clippy_utils/src/check_proc_macro.rs | 23 +++++++++++------------ tests/ui/allow_attributes.fixed | 5 +++++ tests/ui/allow_attributes.rs | 5 +++++ tests/ui/allow_attributes.stderr | 8 +++++++- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 7fb8616072a5..def5d968b063 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -45,6 +45,8 @@ pub enum Pat { Sym(Symbol), /// Any decimal or hexadecimal digit depending on the location. Num, + /// An attribute. + Attr(Symbol), } /// Checks if the start and the end of the span's text matches the patterns. This will return false @@ -65,12 +67,20 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) -> Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)), Pat::Sym(sym) => start_str.starts_with(sym.as_str()), Pat::Num => start_str.as_bytes().first().is_some_and(u8::is_ascii_digit), + Pat::Attr(sym) => { + let start_str = start_str + .strip_prefix("#[") + .or_else(|| start_str.strip_prefix("#![")) + .unwrap_or(start_str); + start_str.trim_start().starts_with(sym.as_str()) + }, } && match end_pat { Pat::Str(text) => end_str.ends_with(text), Pat::MultiStr(texts) => texts.iter().any(|s| end_str.ends_with(s)), Pat::OwnedMultiStr(texts) => texts.iter().any(|s| end_str.ends_with(s)), Pat::Sym(sym) => end_str.ends_with(sym.as_str()), Pat::Num => end_str.as_bytes().last().is_some_and(u8::is_ascii_hexdigit), + Pat::Attr(_) => false, }) }) } @@ -350,18 +360,7 @@ fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) { AttrKind::Normal(..) => { if let Some(name) = attr.name() { // NOTE: This will likely have false positives, like `allow = 1` - let ident_string = name.to_string(); - if attr.style == AttrStyle::Outer { - ( - Pat::OwnedMultiStr(vec!["#[".to_owned() + &ident_string, ident_string]), - Pat::Str(""), - ) - } else { - ( - Pat::OwnedMultiStr(vec!["#![".to_owned() + &ident_string, ident_string]), - Pat::Str(""), - ) - } + (Pat::Attr(name), Pat::Str("")) } else { (Pat::Str("#"), Pat::Str("]")) } diff --git a/tests/ui/allow_attributes.fixed b/tests/ui/allow_attributes.fixed index 56a98cca3404..ecc9f08c1968 100644 --- a/tests/ui/allow_attributes.fixed +++ b/tests/ui/allow_attributes.fixed @@ -63,6 +63,11 @@ fn msrv_1_80() { let x = 1; } +#[rustfmt::skip] +#[ expect ( dead_code ) ] +//~^ allow_attributes +struct Spaced; + #[deny(clippy::allow_attributes)] fn deny_allow_attributes() -> Option { let allow = None; diff --git a/tests/ui/allow_attributes.rs b/tests/ui/allow_attributes.rs index 65a0a6b5a108..3ab328b25aff 100644 --- a/tests/ui/allow_attributes.rs +++ b/tests/ui/allow_attributes.rs @@ -63,6 +63,11 @@ fn msrv_1_80() { let x = 1; } +#[rustfmt::skip] +#[ allow ( dead_code ) ] +//~^ allow_attributes +struct Spaced; + #[deny(clippy::allow_attributes)] fn deny_allow_attributes() -> Option { let allow = None; diff --git a/tests/ui/allow_attributes.stderr b/tests/ui/allow_attributes.stderr index dd5fb21ffeaf..67a70aac8a86 100644 --- a/tests/ui/allow_attributes.stderr +++ b/tests/ui/allow_attributes.stderr @@ -19,5 +19,11 @@ error: #[allow] attribute found LL | #[allow(unused)] | ^^^^^ help: replace it with: `expect` -error: aborting due to 3 previous errors +error: #[allow] attribute found + --> tests/ui/allow_attributes.rs:67:4 + | +LL | #[ allow ( dead_code ) ] + | ^^^^^ help: replace it with: `expect` + +error: aborting due to 4 previous errors From 821f139a2903af53734b8359145edb426bc3f4a9 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 2 Feb 2026 10:51:20 +0100 Subject: [PATCH 393/978] Revert "Revert "Use LLVM intrinsics for `madd` intrinsics"" --- .../stdarch/crates/core_arch/src/x86/avx2.rs | 36 +++++------ .../crates/core_arch/src/x86/avx512bw.rs | 64 +++++++++---------- .../stdarch/crates/core_arch/src/x86/sse2.rs | 26 +++++--- 3 files changed, 63 insertions(+), 63 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index e9463d433180..83aef753c9d9 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -1841,14 +1841,20 @@ pub const fn _mm256_inserti128_si256(a: __m256i, b: __m128i) -> #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpmaddwd))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_madd_epi16(a: __m256i, b: __m256i) -> __m256i { - unsafe { - let r: i32x16 = simd_mul(simd_cast(a.as_i16x16()), simd_cast(b.as_i16x16())); - let even: i32x8 = simd_shuffle!(r, r, [0, 2, 4, 6, 8, 10, 12, 14]); - let odd: i32x8 = simd_shuffle!(r, r, [1, 3, 5, 7, 9, 11, 13, 15]); - simd_add(even, odd).as_m256i() - } +pub fn _mm256_madd_epi16(a: __m256i, b: __m256i) -> __m256i { + // It's a trick used in the Adler-32 algorithm to perform a widening addition. + // + // ```rust + // #[target_feature(enable = "avx2")] + // unsafe fn widening_add(mad: __m256i) -> __m256i { + // _mm256_madd_epi16(mad, _mm256_set1_epi16(1)) + // } + // ``` + // + // If we implement this using generic vector intrinsics, the optimizer + // will eliminate this pattern, and `vpmaddwd` will no longer be emitted. + // For this reason, we use x86 intrinsics. + unsafe { transmute(pmaddwd(a.as_i16x16(), b.as_i16x16())) } } /// Vertically multiplies each unsigned 8-bit integer from `a` with the @@ -3813,6 +3819,8 @@ pub const fn _mm256_extract_epi16(a: __m256i) -> i32 { #[allow(improper_ctypes)] unsafe extern "C" { + #[link_name = "llvm.x86.avx2.pmadd.wd"] + fn pmaddwd(a: i16x16, b: i16x16) -> i32x8; #[link_name = "llvm.x86.avx2.pmadd.ub.sw"] fn pmaddubsw(a: u8x32, b: i8x32) -> i16x16; #[link_name = "llvm.x86.avx2.mpsadbw"] @@ -4661,7 +4669,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm256_madd_epi16() { + fn test_mm256_madd_epi16() { let a = _mm256_set1_epi16(2); let b = _mm256_set1_epi16(4); let r = _mm256_madd_epi16(a, b); @@ -4669,16 +4677,6 @@ mod tests { assert_eq_m256i(r, e); } - #[target_feature(enable = "avx2")] - #[cfg_attr(test, assert_instr(vpmaddwd))] - unsafe fn test_mm256_madd_epi16_mul_one(mad: __m256i) -> __m256i { - // This is a trick used in the adler32 algorithm to get a widening addition. The - // multiplication by 1 is trivial, but must not be optimized out because then the vpmaddwd - // instruction is no longer selected. The assert_instr verifies that this is the case. - let one_v = _mm256_set1_epi16(1); - _mm256_madd_epi16(mad, one_v) - } - #[simd_test(enable = "avx2")] const fn test_mm256_inserti128_si256() { let a = _mm256_setr_epi64x(1, 2, 3, 4); diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs index e2d12cd97264..8e074fdcfa48 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs @@ -6321,22 +6321,20 @@ pub const unsafe fn _mm_mask_storeu_epi8(mem_addr: *mut i8, mask: __mmask16, a: #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_madd_epi16(a: __m512i, b: __m512i) -> __m512i { - unsafe { - let r: i32x32 = simd_mul(simd_cast(a.as_i16x32()), simd_cast(b.as_i16x32())); - let even: i32x16 = simd_shuffle!( - r, - r, - [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30] - ); - let odd: i32x16 = simd_shuffle!( - r, - r, - [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31] - ); - simd_add(even, odd).as_m512i() - } +pub fn _mm512_madd_epi16(a: __m512i, b: __m512i) -> __m512i { + // It's a trick used in the Adler-32 algorithm to perform a widening addition. + // + // ```rust + // #[target_feature(enable = "avx512bw")] + // unsafe fn widening_add(mad: __m512i) -> __m512i { + // _mm512_madd_epi16(mad, _mm512_set1_epi16(1)) + // } + // ``` + // + // If we implement this using generic vector intrinsics, the optimizer + // will eliminate this pattern, and `vpmaddwd` will no longer be emitted. + // For this reason, we use x86 intrinsics. + unsafe { transmute(vpmaddwd(a.as_i16x32(), b.as_i16x32())) } } /// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -6346,8 +6344,7 @@ pub const fn _mm512_madd_epi16(a: __m512i, b: __m512i) -> __m512i { #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_mask_madd_epi16(src: __m512i, k: __mmask16, a: __m512i, b: __m512i) -> __m512i { +pub fn _mm512_mask_madd_epi16(src: __m512i, k: __mmask16, a: __m512i, b: __m512i) -> __m512i { unsafe { let madd = _mm512_madd_epi16(a, b).as_i32x16(); transmute(simd_select_bitmask(k, madd, src.as_i32x16())) @@ -6361,8 +6358,7 @@ pub const fn _mm512_mask_madd_epi16(src: __m512i, k: __mmask16, a: __m512i, b: _ #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_maskz_madd_epi16(k: __mmask16, a: __m512i, b: __m512i) -> __m512i { +pub fn _mm512_maskz_madd_epi16(k: __mmask16, a: __m512i, b: __m512i) -> __m512i { unsafe { let madd = _mm512_madd_epi16(a, b).as_i32x16(); transmute(simd_select_bitmask(k, madd, i32x16::ZERO)) @@ -6376,8 +6372,7 @@ pub const fn _mm512_maskz_madd_epi16(k: __mmask16, a: __m512i, b: __m512i) -> __ #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_mask_madd_epi16(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { +pub fn _mm256_mask_madd_epi16(src: __m256i, k: __mmask8, a: __m256i, b: __m256i) -> __m256i { unsafe { let madd = _mm256_madd_epi16(a, b).as_i32x8(); transmute(simd_select_bitmask(k, madd, src.as_i32x8())) @@ -6391,8 +6386,7 @@ pub const fn _mm256_mask_madd_epi16(src: __m256i, k: __mmask8, a: __m256i, b: __ #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_maskz_madd_epi16(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { +pub fn _mm256_maskz_madd_epi16(k: __mmask8, a: __m256i, b: __m256i) -> __m256i { unsafe { let madd = _mm256_madd_epi16(a, b).as_i32x8(); transmute(simd_select_bitmask(k, madd, i32x8::ZERO)) @@ -6406,8 +6400,7 @@ pub const fn _mm256_maskz_madd_epi16(k: __mmask8, a: __m256i, b: __m256i) -> __m #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_mask_madd_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_mask_madd_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m128i) -> __m128i { unsafe { let madd = _mm_madd_epi16(a, b).as_i32x4(); transmute(simd_select_bitmask(k, madd, src.as_i32x4())) @@ -6421,8 +6414,7 @@ pub const fn _mm_mask_madd_epi16(src: __m128i, k: __mmask8, a: __m128i, b: __m12 #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmaddwd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_maskz_madd_epi16(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { +pub fn _mm_maskz_madd_epi16(k: __mmask8, a: __m128i, b: __m128i) -> __m128i { unsafe { let madd = _mm_madd_epi16(a, b).as_i32x4(); transmute(simd_select_bitmask(k, madd, i32x4::ZERO)) @@ -12582,6 +12574,8 @@ unsafe extern "C" { #[link_name = "llvm.x86.avx512.pmul.hr.sw.512"] fn vpmulhrsw(a: i16x32, b: i16x32) -> i16x32; + #[link_name = "llvm.x86.avx512.pmaddw.d.512"] + fn vpmaddwd(a: i16x32, b: i16x32) -> i32x16; #[link_name = "llvm.x86.avx512.pmaddubs.w.512"] fn vpmaddubsw(a: u8x64, b: i8x64) -> i16x32; @@ -17506,7 +17500,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_madd_epi16() { + fn test_mm512_madd_epi16() { let a = _mm512_set1_epi16(1); let b = _mm512_set1_epi16(1); let r = _mm512_madd_epi16(a, b); @@ -17515,7 +17509,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_mask_madd_epi16() { + fn test_mm512_mask_madd_epi16() { let a = _mm512_set1_epi16(1); let b = _mm512_set1_epi16(1); let r = _mm512_mask_madd_epi16(a, 0, a, b); @@ -17543,7 +17537,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_maskz_madd_epi16() { + fn test_mm512_maskz_madd_epi16() { let a = _mm512_set1_epi16(1); let b = _mm512_set1_epi16(1); let r = _mm512_maskz_madd_epi16(0, a, b); @@ -17554,7 +17548,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_mask_madd_epi16() { + fn test_mm256_mask_madd_epi16() { let a = _mm256_set1_epi16(1); let b = _mm256_set1_epi16(1); let r = _mm256_mask_madd_epi16(a, 0, a, b); @@ -17574,7 +17568,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_maskz_madd_epi16() { + fn test_mm256_maskz_madd_epi16() { let a = _mm256_set1_epi16(1); let b = _mm256_set1_epi16(1); let r = _mm256_maskz_madd_epi16(0, a, b); @@ -17585,7 +17579,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_mask_madd_epi16() { + fn test_mm_mask_madd_epi16() { let a = _mm_set1_epi16(1); let b = _mm_set1_epi16(1); let r = _mm_mask_madd_epi16(a, 0, a, b); @@ -17596,7 +17590,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_maskz_madd_epi16() { + fn test_mm_maskz_madd_epi16() { let a = _mm_set1_epi16(1); let b = _mm_set1_epi16(1); let r = _mm_maskz_madd_epi16(0, a, b); diff --git a/library/stdarch/crates/core_arch/src/x86/sse2.rs b/library/stdarch/crates/core_arch/src/x86/sse2.rs index ecd478511b06..f339a003df4d 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse2.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse2.rs @@ -210,14 +210,20 @@ pub const fn _mm_avg_epu16(a: __m128i, b: __m128i) -> __m128i { #[target_feature(enable = "sse2")] #[cfg_attr(test, assert_instr(pmaddwd))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_madd_epi16(a: __m128i, b: __m128i) -> __m128i { - unsafe { - let r: i32x8 = simd_mul(simd_cast(a.as_i16x8()), simd_cast(b.as_i16x8())); - let even: i32x4 = simd_shuffle!(r, r, [0, 2, 4, 6]); - let odd: i32x4 = simd_shuffle!(r, r, [1, 3, 5, 7]); - simd_add(even, odd).as_m128i() - } +pub fn _mm_madd_epi16(a: __m128i, b: __m128i) -> __m128i { + // It's a trick used in the Adler-32 algorithm to perform a widening addition. + // + // ```rust + // #[target_feature(enable = "sse2")] + // unsafe fn widening_add(mad: __m128i) -> __m128i { + // _mm_madd_epi16(mad, _mm_set1_epi16(1)) + // } + // ``` + // + // If we implement this using generic vector intrinsics, the optimizer + // will eliminate this pattern, and `pmaddwd` will no longer be emitted. + // For this reason, we use x86 intrinsics. + unsafe { transmute(pmaddwd(a.as_i16x8(), b.as_i16x8())) } } /// Compares packed 16-bit integers in `a` and `b`, and returns the packed @@ -3187,6 +3193,8 @@ unsafe extern "C" { fn lfence(); #[link_name = "llvm.x86.sse2.mfence"] fn mfence(); + #[link_name = "llvm.x86.sse2.pmadd.wd"] + fn pmaddwd(a: i16x8, b: i16x8) -> i32x4; #[link_name = "llvm.x86.sse2.psad.bw"] fn psadbw(a: u8x16, b: u8x16) -> u64x2; #[link_name = "llvm.x86.sse2.psll.w"] @@ -3465,7 +3473,7 @@ mod tests { } #[simd_test(enable = "sse2")] - const fn test_mm_madd_epi16() { + fn test_mm_madd_epi16() { let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8); let b = _mm_setr_epi16(9, 10, 11, 12, 13, 14, 15, 16); let r = _mm_madd_epi16(a, b); From 95ac5673cedf8b0ba543aac2ccb67b47f60662e1 Mon Sep 17 00:00:00 2001 From: ritik chahar Date: Mon, 2 Feb 2026 15:38:26 +0530 Subject: [PATCH 394/978] Fix SLP vectorization test CHECK patterns --- tests/codegen-llvm/slp-vectorization-mul3.rs | 29 ++++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/tests/codegen-llvm/slp-vectorization-mul3.rs b/tests/codegen-llvm/slp-vectorization-mul3.rs index b6edc212c82d..1c40c6b28f3f 100644 --- a/tests/codegen-llvm/slp-vectorization-mul3.rs +++ b/tests/codegen-llvm/slp-vectorization-mul3.rs @@ -4,23 +4,22 @@ #![crate_type = "lib"] -// CHECK-LABEL: mul3 -// CHECK: %[[C_BPP:.*]] = phi <4 x i8> -// CHECK: %[[V:.*]] = load <4 x i8>, ptr -// CHECK: %[[ADD:.*]] = add <4 x i8> %[[V]], %[[C_BPP]] -// CHECK: store {{<4 x i8>|i32}} {{.*}}, ptr +// CHECK-LABEL: @mul3 +// CHECK: phi <4 x i8> +// CHECK: load <4 x i8> +// CHECK: add <4 x i8> +// CHECK: store <4 x i8> -pub fn mul3(previous: &[u8], current: &mut [u8]) { +#[no_mangle] +pub fn mul3(previous: &[[u8; 4]], current: &mut [[u8; 4]]) { let mut c_bpp = [0u8; 4]; - for (chunk, b_bpp) in current.chunks_exact_mut(4).zip(previous.chunks_exact(4)) { - let new_chunk = [ - chunk[0].wrapping_add(c_bpp[0]), - chunk[1].wrapping_add(c_bpp[1]), - chunk[2].wrapping_add(c_bpp[2]), - chunk[3].wrapping_add(c_bpp[3]), - ]; - chunk.copy_from_slice(&new_chunk); - c_bpp.copy_from_slice(b_bpp); + for i in 0..previous.len() { + current[i][0] = current[i][0].wrapping_add(c_bpp[0]); + current[i][1] = current[i][1].wrapping_add(c_bpp[1]); + current[i][2] = current[i][2].wrapping_add(c_bpp[2]); + current[i][3] = current[i][3].wrapping_add(c_bpp[3]); + + c_bpp = previous[i]; } } From 0830a5a9286e351a009e8eaa1fa86691e3a3b62e Mon Sep 17 00:00:00 2001 From: ritik chahar Date: Mon, 2 Feb 2026 15:44:50 +0530 Subject: [PATCH 395/978] fix: add min-llvm-version --- tests/codegen-llvm/slp-vectorization-mul3.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/codegen-llvm/slp-vectorization-mul3.rs b/tests/codegen-llvm/slp-vectorization-mul3.rs index 1c40c6b28f3f..2987493e0371 100644 --- a/tests/codegen-llvm/slp-vectorization-mul3.rs +++ b/tests/codegen-llvm/slp-vectorization-mul3.rs @@ -1,6 +1,8 @@ //! Regression test for #142519 //@ only-x86_64 //@ compile-flags: -O +//@ min-llvm-version: 18.0 + #![crate_type = "lib"] From c725637dc24fbe47704e92b7e8a8875f60ccd2be Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Feb 2026 11:22:33 +0100 Subject: [PATCH 396/978] explain why we dont skip some of this work when there are field projections --- compiler/rustc_middle/src/mir/statement.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 393e9c59c355..973ceccc67f9 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -441,6 +441,8 @@ impl<'tcx> Place<'tcx> { where D: ?Sized + HasLocalDecls<'tcx>, { + // If there's a field projection element in `projection`, we *could* skip everything + // before that, but on 2026-01-31 a perf experiment showed no benefit from doing so. PlaceTy::from_ty(local_decls.local_decls()[local].ty).multi_projection_ty(tcx, projection) } From 4956604c7db5fb272214331c9db82608fbbbe185 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 31 Jan 2026 21:34:36 +0200 Subject: [PATCH 397/978] external-rustc-drivers.md: some improvements --- .../rustc-driver/external-rustc-drivers.md | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/external-rustc-drivers.md b/src/doc/rustc-dev-guide/src/rustc-driver/external-rustc-drivers.md index 1049d7a82ddd..2d409ad201b1 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver/external-rustc-drivers.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver/external-rustc-drivers.md @@ -42,29 +42,28 @@ For custom-built toolchains or environments not using rustup, additional configu #### Troubleshooting Steps -1. **Check LLVM installation**: Verify LLVM is installed and accessible -2. **Configure library paths**: You may need to set environment variables: - ```text +1. Verify LLVM is installed and accessible +2. Ensure that library paths are set: + ```sh export LD_LIBRARY_PATH=/path/to/llvm/lib:$LD_LIBRARY_PATH ``` -3. **Check version compatibility**: Ensure your LLVM version is compatible with your Rust toolchain +3. Ensure your LLVM version is compatible with your Rust toolchain -### Configuring `rust-analyzer` for Out-of-Tree Projects +### Configuring `rust-analyzer` for out-of-tree projects When developing out-of-tree projects that use `rustc_private` crates, you can configure `rust-analyzer` to recognize these crates. #### Configuration Steps -1. **Set rust-analyzer configuration** - Configure `rust-analyzer.rustc.source` to `"discover"` in your editor settings. +1. Configure `rust-analyzer.rustc.source` to `"discover"` in your editor settings. For VS Code, add to `rust_analyzer_settings.json`: ```json { "rust-analyzer.rustc.source": "discover" } ``` -2. **Add metadata to Cargo.toml** - Add the following to the `Cargo.toml` of every crate that uses `rustc_private`: + +2. Add the following to the `Cargo.toml` of every crate that uses `rustc_private`: ```toml [package.metadata.rust-analyzer] rustc_private = true @@ -74,4 +73,6 @@ This configuration allows `rust-analyzer` to properly recognize and provide IDE ### Additional Resources -- [GitHub Issue #137421](https://github.com/rust-lang/rust/issues/137421): Explains that `rustc_private` linker failures often occur because `llvm-tools` is not installed +- [GitHub Issue #137421] explains that `rustc_private` linker failures often occur because `llvm-tools` is not installed + +[GitHub Issue #137421]: https://github.com/rust-lang/rust/issues/137421 From 61769452234deaf0e035789009ab807dd1ca93d4 Mon Sep 17 00:00:00 2001 From: ritik chahar Date: Mon, 2 Feb 2026 16:05:08 +0530 Subject: [PATCH 398/978] fix: remove space for tidy and only for x86_64 --- tests/codegen-llvm/slp-vectorization-mul3.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/codegen-llvm/slp-vectorization-mul3.rs b/tests/codegen-llvm/slp-vectorization-mul3.rs index 2987493e0371..d7c44c8db71a 100644 --- a/tests/codegen-llvm/slp-vectorization-mul3.rs +++ b/tests/codegen-llvm/slp-vectorization-mul3.rs @@ -3,7 +3,6 @@ //@ compile-flags: -O //@ min-llvm-version: 18.0 - #![crate_type = "lib"] // CHECK-LABEL: @mul3 From 5aba6b1635935237a146d759e67bc7d3e8bdc73b Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Mon, 2 Feb 2026 09:38:07 +0000 Subject: [PATCH 399/978] Fix missing unused_variables lint when using a match guard Within a binding pattern match guard, only real reads of a bound local impact its liveness analysis - not the fake read that is injected. --- compiler/rustc_mir_transform/src/liveness.rs | 9 ++++++--- .../clippy/clippy_lints/src/time_subtraction.rs | 2 +- tests/ui/lint/unused/match_with_guard.rs | 10 ++++++++++ tests/ui/lint/unused/match_with_guard.stderr | 15 +++++++++++++++ 4 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 tests/ui/lint/unused/match_with_guard.rs create mode 100644 tests/ui/lint/unused/match_with_guard.stderr diff --git a/compiler/rustc_mir_transform/src/liveness.rs b/compiler/rustc_mir_transform/src/liveness.rs index cf977be4c3df..9bafee9f31c3 100644 --- a/compiler/rustc_mir_transform/src/liveness.rs +++ b/compiler/rustc_mir_transform/src/liveness.rs @@ -1243,9 +1243,12 @@ struct TransferFunction<'a, 'tcx> { impl<'tcx> Visitor<'tcx> for TransferFunction<'_, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match statement.kind { - // `ForLet(None)` fake read erroneously marks the just-assigned local as live. - // This defeats the purpose of the analysis for `let` bindings. - StatementKind::FakeRead(box (FakeReadCause::ForLet(None), _)) => return, + // `ForLet(None)` and `ForGuardBinding` fake reads erroneously mark the just-assigned + // locals as live. This defeats the purpose of the analysis for such bindings. + StatementKind::FakeRead(box ( + FakeReadCause::ForLet(None) | FakeReadCause::ForGuardBinding, + _, + )) => return, // Handle self-assignment by restricting the read/write they do. StatementKind::Assign(box (ref dest, ref rvalue)) if self.self_assignment.contains(&location) => diff --git a/src/tools/clippy/clippy_lints/src/time_subtraction.rs b/src/tools/clippy/clippy_lints/src/time_subtraction.rs index 3ba59aefea06..ca8378ba7c6a 100644 --- a/src/tools/clippy/clippy_lints/src/time_subtraction.rs +++ b/src/tools/clippy/clippy_lints/src/time_subtraction.rs @@ -85,7 +85,7 @@ impl LateLintPass<'_> for UncheckedTimeSubtraction { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { let (lhs, rhs) = match expr.kind { ExprKind::Binary(op, lhs, rhs) if matches!(op.node, BinOpKind::Sub,) => (lhs, rhs), - ExprKind::MethodCall(fn_name, lhs, [rhs], _) if cx.ty_based_def(expr).is_diag_item(cx, sym::sub) => { + ExprKind::MethodCall(_, lhs, [rhs], _) if cx.ty_based_def(expr).is_diag_item(cx, sym::sub) => { (lhs, rhs) }, _ => return, diff --git a/tests/ui/lint/unused/match_with_guard.rs b/tests/ui/lint/unused/match_with_guard.rs new file mode 100644 index 000000000000..61e4321f6735 --- /dev/null +++ b/tests/ui/lint/unused/match_with_guard.rs @@ -0,0 +1,10 @@ +//! The mere presence of a match guard should not deem bound variables "used". +//! Regression test for https://github.com/rust-lang/rust/issues/151983 +//@ check-pass +#![warn(unused)] +fn main() { + match Some(42) { + Some(unused) if true => (), //~WARN unused variable: `unused` + _ => (), + } +} diff --git a/tests/ui/lint/unused/match_with_guard.stderr b/tests/ui/lint/unused/match_with_guard.stderr new file mode 100644 index 000000000000..6a509e568b68 --- /dev/null +++ b/tests/ui/lint/unused/match_with_guard.stderr @@ -0,0 +1,15 @@ +warning: unused variable: `unused` + --> $DIR/match_with_guard.rs:7:14 + | +LL | Some(unused) if true => (), + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + | +note: the lint level is defined here + --> $DIR/match_with_guard.rs:4:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: 1 warning emitted + From 267f40dbb42e7bb6a18e83091d95297f277a5782 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Mon, 2 Feb 2026 09:38:07 +0000 Subject: [PATCH 400/978] Fix missing unused_variables lint when using a match guard Within a binding pattern match guard, only real reads of a bound local impact its liveness analysis - not the fake read that is injected. --- clippy_lints/src/time_subtraction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/time_subtraction.rs b/clippy_lints/src/time_subtraction.rs index 3ba59aefea06..ca8378ba7c6a 100644 --- a/clippy_lints/src/time_subtraction.rs +++ b/clippy_lints/src/time_subtraction.rs @@ -85,7 +85,7 @@ impl LateLintPass<'_> for UncheckedTimeSubtraction { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { let (lhs, rhs) = match expr.kind { ExprKind::Binary(op, lhs, rhs) if matches!(op.node, BinOpKind::Sub,) => (lhs, rhs), - ExprKind::MethodCall(fn_name, lhs, [rhs], _) if cx.ty_based_def(expr).is_diag_item(cx, sym::sub) => { + ExprKind::MethodCall(_, lhs, [rhs], _) if cx.ty_based_def(expr).is_diag_item(cx, sym::sub) => { (lhs, rhs) }, _ => return, From 8476e893e72e1e3617fb50a06a01548d6177d192 Mon Sep 17 00:00:00 2001 From: Ritik Chahar <126174435+chahar-ritik@users.noreply.github.com> Date: Mon, 2 Feb 2026 16:47:09 +0530 Subject: [PATCH 401/978] Update min-llvm-version: 22 Co-authored-by: Nikita Popov --- tests/codegen-llvm/slp-vectorization-mul3.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codegen-llvm/slp-vectorization-mul3.rs b/tests/codegen-llvm/slp-vectorization-mul3.rs index d7c44c8db71a..38c0949b8271 100644 --- a/tests/codegen-llvm/slp-vectorization-mul3.rs +++ b/tests/codegen-llvm/slp-vectorization-mul3.rs @@ -1,7 +1,7 @@ //! Regression test for #142519 //@ only-x86_64 //@ compile-flags: -O -//@ min-llvm-version: 18.0 +//@ min-llvm-version: 22 #![crate_type = "lib"] From c0393cf8dbfc91f4719e6be9895b5c8a983ef8ec Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 24 Oct 2025 15:29:33 +0300 Subject: [PATCH 402/978] resolve: Report more early resolution ambiguities for imports The new ambiguities are reported when the import's visibility is ambiguous and may depend on the resolution/expansion order. --- compiler/rustc_lint_defs/src/builtin.rs | 50 +++++++++++++++++++ compiler/rustc_middle/src/ty/mod.rs | 6 +++ compiler/rustc_resolve/src/diagnostics.rs | 17 +++++-- compiler/rustc_resolve/src/errors.rs | 9 +++- compiler/rustc_resolve/src/ident.rs | 34 ++++++++++--- compiler/rustc_resolve/src/imports.rs | 6 ++- compiler/rustc_resolve/src/lib.rs | 4 ++ .../ambiguous-import-visibility-macro.rs | 19 +++++++ .../ambiguous-import-visibility-macro.stderr | 29 +++++++++++ .../ambiguous-import-visibility-module.rs | 24 +++++++++ .../ambiguous-import-visibility-module.stderr | 29 +++++++++++ .../ui/imports/ambiguous-import-visibility.rs | 14 ++++++ .../ambiguous-import-visibility.stderr | 25 ++++++++++ 13 files changed, 254 insertions(+), 12 deletions(-) create mode 100644 tests/ui/imports/ambiguous-import-visibility-macro.rs create mode 100644 tests/ui/imports/ambiguous-import-visibility-macro.stderr create mode 100644 tests/ui/imports/ambiguous-import-visibility-module.rs create mode 100644 tests/ui/imports/ambiguous-import-visibility-module.stderr create mode 100644 tests/ui/imports/ambiguous-import-visibility.rs create mode 100644 tests/ui/imports/ambiguous-import-visibility.stderr diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index ff108031badc..d1d5d0a56ead 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -20,6 +20,7 @@ declare_lint_pass! { AMBIGUOUS_GLOB_IMPORTED_TRAITS, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_GLOB_REEXPORTS, + AMBIGUOUS_IMPORT_VISIBILITIES, AMBIGUOUS_PANIC_IMPORTS, ARITHMETIC_OVERFLOW, ASM_SUB_REGISTER, @@ -4564,6 +4565,55 @@ declare_lint! { }; } +declare_lint! { + /// The `ambiguous_import_visibilities` lint detects imports that should report ambiguity + /// errors, but previously didn't do that due to rustc bugs. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(unknown_lints)] + /// #![deny(ambiguous_import_visibilities)] + /// mod reexport { + /// mod m { + /// pub struct S {} + /// } + /// + /// macro_rules! mac { + /// () => { use m::S; } + /// } + /// + /// pub use m::*; + /// mac!(); + /// + /// pub use S as Z; // ambiguous visibility + /// } + /// + /// fn main() { + /// reexport::Z {}; + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Previous versions of Rust compile it successfully because it + /// fetched the glob import's visibility for `pub use S as Z` import, and ignored the private + /// `use m::S` import that appeared later. + /// + /// This is a [future-incompatible] lint to transition this to a + /// hard error in the future. + /// + /// [future-incompatible]: ../index.md#future-incompatible-lints + pub AMBIGUOUS_IMPORT_VISIBILITIES, + Warn, + "detects certain glob imports that require reporting an ambiguity error", + @future_incompatible = FutureIncompatibleInfo { + reason: fcw!(FutureReleaseError #149145), + }; +} + declare_lint! { /// The `refining_impl_trait_reachable` lint detects `impl Trait` return /// types in method signatures that are refined by a publically reachable diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 4e33b8ebb6de..0220531b09fa 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -408,6 +408,12 @@ impl> Visibility { } } +impl + Copy> Visibility { + pub fn min(self, vis: Visibility, tcx: TyCtxt<'_>) -> Visibility { + if self.is_at_least(vis, tcx) { vis } else { self } + } +} + impl Visibility { pub fn expect_local(self) -> Visibility { self.map_id(|id| id.expect_local()) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 6884ed1891a3..f09b98715799 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -24,8 +24,8 @@ use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ - ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_PANIC_IMPORTS, - MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, + ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_IMPORT_VISIBILITIES, + AMBIGUOUS_PANIC_IMPORTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, }; use rustc_session::utils::was_invoked_from_cargo; use rustc_span::edit_distance::find_best_match_for_name; @@ -145,6 +145,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; let lint = match ambiguity_warning { + _ if ambiguity_error.ambig_vis.is_some() => AMBIGUOUS_IMPORT_VISIBILITIES, AmbiguityWarning::GlobImport => AMBIGUOUS_GLOB_IMPORTS, AmbiguityWarning::PanicImport => AMBIGUOUS_PANIC_IMPORTS, }; @@ -1995,7 +1996,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn ambiguity_diagnostic(&self, ambiguity_error: &AmbiguityError<'ra>) -> errors::Ambiguity { - let AmbiguityError { kind, ident, b1, b2, scope1, scope2, .. } = *ambiguity_error; + let AmbiguityError { kind, ambig_vis, ident, b1, b2, scope1, scope2, .. } = + *ambiguity_error; let extern_prelude_ambiguity = || { // Note: b1 may come from a module scope, as an extern crate item in module. matches!(scope2, Scope::ExternPreludeFlags) @@ -2074,9 +2076,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None }; + let ambig_vis = ambig_vis.map(|(vis1, vis2)| { + format!( + "{} or {}", + vis1.to_string(CRATE_DEF_ID, self.tcx), + vis2.to_string(CRATE_DEF_ID, self.tcx) + ) + }); + errors::Ambiguity { ident, help, + ambig_vis, kind: kind.descr(), b1_note, b1_help_msgs, diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 205f2c6aa539..3e5446403052 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1463,6 +1463,7 @@ pub(crate) struct UnknownDiagnosticAttributeTypoSugg { // FIXME: Make this properly translatable. pub(crate) struct Ambiguity { pub ident: Ident, + pub ambig_vis: Option, pub kind: &'static str, pub help: Option<&'static [&'static str]>, pub b1_note: Spanned, @@ -1473,8 +1474,12 @@ pub(crate) struct Ambiguity { impl Ambiguity { fn decorate<'a>(self, diag: &mut Diag<'a, impl EmissionGuarantee>) { - diag.primary_message(format!("`{}` is ambiguous", self.ident)); - diag.span_label(self.ident.span, "ambiguous name"); + if let Some(ambig_vis) = self.ambig_vis { + diag.primary_message(format!("ambiguous import visibility: {ambig_vis}")); + } else { + diag.primary_message(format!("`{}` is ambiguous", self.ident)); + diag.span_label(self.ident.span, "ambiguous name"); + } diag.note(format!("ambiguous because of {}", self.kind)); diag.span_note(self.b1_note.span, self.b1_note.node); if let Some(help) = self.help { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 0e73c349c8cd..d4d373d82064 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -5,6 +5,7 @@ use Namespace::*; use rustc_ast::{self as ast, NodeId}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRes, PerNS}; +use rustc_middle::ty::Visibility; use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK; use rustc_session::parse::feature_err; @@ -485,9 +486,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // We do not need to report them if we are either in speculative resolution, // or in late resolution when everything is already imported and expanded // and no ambiguities exist. - if matches!(finalize, None | Some(Finalize { stage: Stage::Late, .. })) { - return ControlFlow::Break(Ok(decl)); - } + let import_vis = match finalize { + None | Some(Finalize { stage: Stage::Late, .. }) => { + return ControlFlow::Break(Ok(decl)); + } + Some(Finalize { import_vis, .. }) => import_vis, + }; if let Some(&(innermost_decl, _)) = innermost_results.first() { // Found another solution, if the first one was "weak", report an error. @@ -500,6 +504,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { decl, scope, &innermost_results, + import_vis, ) { // No need to search for more potential ambiguities, one is enough. return ControlFlow::Break(Ok(innermost_decl)); @@ -779,12 +784,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { decl: Decl<'ra>, scope: Scope<'ra>, innermost_results: &[(Decl<'ra>, Scope<'ra>)], + import_vis: Option, ) -> bool { let (innermost_decl, innermost_scope) = innermost_results[0]; let (res, innermost_res) = (decl.res(), innermost_decl.res()); - if res == innermost_res { + let ambig_vis = if res != innermost_res { + None + } else if let Some(import_vis) = import_vis + && let min = + (|d: Decl<'_>| d.vis().min(import_vis.to_def_id(), self.tcx).expect_local()) + && let (min1, min2) = (min(decl), min(innermost_decl)) + && min1 != min2 + { + Some((min1, min2)) + } else { return false; - } + }; // FIXME: Use `scope` instead of `res` to detect built-in attrs and derive helpers, // it will exclude imports, make slightly more code legal, and will require lang approval. @@ -871,10 +886,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { || (self.is_specific_builtin_macro(res, sym::core_panic) && self.is_specific_builtin_macro(innermost_res, sym::std_panic))); - let warning = is_issue_147319_hack.then_some(AmbiguityWarning::PanicImport); + let warning = if ambig_vis.is_some() { + Some(AmbiguityWarning::GlobImport) + } else if is_issue_147319_hack { + Some(AmbiguityWarning::PanicImport) + } else { + None + }; self.ambiguity_errors.push(AmbiguityError { kind, + ambig_vis, ident: ident.orig(orig_ident_span), b1: innermost_decl, b2: decl, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 057340028085..78ad139cff79 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1189,7 +1189,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ident, ns, &import.parent_scope, - Some(Finalize { report_private: false, ..finalize }), + Some(Finalize { + report_private: false, + import_vis: Some(import.vis), + ..finalize + }), bindings[ns].get().decl(), Some(import), ); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 75bd2c62f9b4..3a65598584ae 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -969,6 +969,7 @@ enum AmbiguityWarning { struct AmbiguityError<'ra> { kind: AmbiguityKind, + ambig_vis: Option<(Visibility, Visibility)>, ident: Ident, b1: Decl<'ra>, b2: Decl<'ra>, @@ -2087,6 +2088,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if let Some(b2) = used_decl.ambiguity.get() { let ambiguity_error = AmbiguityError { kind: AmbiguityKind::GlobVsGlob, + ambig_vis: None, ident, b1: used_decl, b2, @@ -2556,6 +2558,8 @@ struct Finalize { used: Used = Used::Other, /// Finalizing early or late resolution. stage: Stage = Stage::Early, + /// Nominal visibility of the import item, in case we are resolving an import's final segment. + import_vis: Option = None, } impl Finalize { diff --git a/tests/ui/imports/ambiguous-import-visibility-macro.rs b/tests/ui/imports/ambiguous-import-visibility-macro.rs new file mode 100644 index 000000000000..e1861cc5d4e0 --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility-macro.rs @@ -0,0 +1,19 @@ +//@ check-pass +//@ edition:2018 +//@ proc-macro: same-res-ambigious-extern-macro.rs + +macro_rules! globbing{ + () => { + pub use same_res_ambigious_extern_macro::*; + } +} + +#[macro_use] // this imports the `RustEmbed` macro with `pub(crate)` visibility +extern crate same_res_ambigious_extern_macro; +globbing! {} // this imports the same `RustEmbed` macro with `pub` visibility + +pub trait RustEmbed {} + +pub use RustEmbed as Embed; //~ WARN ambiguous import visibility + //~| WARN this was previously accepted +fn main() {} diff --git a/tests/ui/imports/ambiguous-import-visibility-macro.stderr b/tests/ui/imports/ambiguous-import-visibility-macro.stderr new file mode 100644 index 000000000000..ed6eb6f893af --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility-macro.stderr @@ -0,0 +1,29 @@ +warning: ambiguous import visibility: pub(crate) or pub + --> $DIR/ambiguous-import-visibility-macro.rs:17:9 + | +LL | pub use RustEmbed as Embed; + | ^^^^^^^^^ + | + = 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 #149145 + = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution +note: `RustEmbed` could refer to the derive macro imported here + --> $DIR/ambiguous-import-visibility-macro.rs:7:17 + | +LL | pub use same_res_ambigious_extern_macro::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | globbing! {} // this imports the same `RustEmbed` macro with `pub` visibility + | ------------ in this macro invocation + = help: consider adding an explicit import of `RustEmbed` to disambiguate + = help: or use `crate::RustEmbed` to refer to this derive macro unambiguously +note: `RustEmbed` could also refer to the derive macro imported here + --> $DIR/ambiguous-import-visibility-macro.rs:11:1 + | +LL | #[macro_use] // this imports the `RustEmbed` macro with `pub(crate)` visibility + | ^^^^^^^^^^^^ + = note: `#[warn(ambiguous_import_visibilities)]` (part of `#[warn(future_incompatible)]`) on by default + = note: this warning originates in the macro `globbing` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 1 warning emitted + diff --git a/tests/ui/imports/ambiguous-import-visibility-module.rs b/tests/ui/imports/ambiguous-import-visibility-module.rs new file mode 100644 index 000000000000..35c6da8b21a4 --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility-module.rs @@ -0,0 +1,24 @@ +//@ check-pass +//@ edition:2018.. + +mod reexport { + mod m { + pub struct S {} + } + + macro_rules! mac { + () => { + use m::S; + }; + } + + pub use m::*; + mac!(); + + pub use S as Z; //~ WARN ambiguous import visibility + //~| WARN this was previously accepted +} + +fn main() { + reexport::Z {}; +} diff --git a/tests/ui/imports/ambiguous-import-visibility-module.stderr b/tests/ui/imports/ambiguous-import-visibility-module.stderr new file mode 100644 index 000000000000..a97070c20a62 --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility-module.stderr @@ -0,0 +1,29 @@ +warning: ambiguous import visibility: pub or pub(in crate::reexport) + --> $DIR/ambiguous-import-visibility-module.rs:18:13 + | +LL | pub use S as Z; + | ^ + | + = 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 #149145 + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `S` could refer to the struct imported here + --> $DIR/ambiguous-import-visibility-module.rs:11:17 + | +LL | use m::S; + | ^^^^ +... +LL | mac!(); + | ------ in this macro invocation + = help: use `self::S` to refer to this struct unambiguously +note: `S` could also refer to the struct imported here + --> $DIR/ambiguous-import-visibility-module.rs:15:13 + | +LL | pub use m::*; + | ^^^^ + = help: use `self::S` to refer to this struct unambiguously + = note: `#[warn(ambiguous_import_visibilities)]` (part of `#[warn(future_incompatible)]`) on by default + = note: this warning originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 1 warning emitted + diff --git a/tests/ui/imports/ambiguous-import-visibility.rs b/tests/ui/imports/ambiguous-import-visibility.rs new file mode 100644 index 000000000000..4cb8b763fbc9 --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility.rs @@ -0,0 +1,14 @@ +//@ check-pass +//@ edition:2018 +//@ proc-macro: same-res-ambigious-extern-macro.rs + +#[macro_use] // this imports the `RustEmbed` macro with `pub(crate)` visibility +extern crate same_res_ambigious_extern_macro; +// this imports the same `RustEmbed` macro with `pub` visibility +pub use same_res_ambigious_extern_macro::*; + +pub trait RustEmbed {} + +pub use RustEmbed as Embed; //~ WARN ambiguous import visibility + //~| WARN this was previously accepted +fn main() {} diff --git a/tests/ui/imports/ambiguous-import-visibility.stderr b/tests/ui/imports/ambiguous-import-visibility.stderr new file mode 100644 index 000000000000..30cddca4697d --- /dev/null +++ b/tests/ui/imports/ambiguous-import-visibility.stderr @@ -0,0 +1,25 @@ +warning: ambiguous import visibility: pub(crate) or pub + --> $DIR/ambiguous-import-visibility.rs:12:9 + | +LL | pub use RustEmbed as Embed; + | ^^^^^^^^^ + | + = 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 #149145 + = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution +note: `RustEmbed` could refer to the derive macro imported here + --> $DIR/ambiguous-import-visibility.rs:8:9 + | +LL | pub use same_res_ambigious_extern_macro::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: consider adding an explicit import of `RustEmbed` to disambiguate + = help: or use `crate::RustEmbed` to refer to this derive macro unambiguously +note: `RustEmbed` could also refer to the derive macro imported here + --> $DIR/ambiguous-import-visibility.rs:5:1 + | +LL | #[macro_use] // this imports the `RustEmbed` macro with `pub(crate)` visibility + | ^^^^^^^^^^^^ + = note: `#[warn(ambiguous_import_visibilities)]` (part of `#[warn(future_incompatible)]`) on by default + +warning: 1 warning emitted + From 629ff9b4aa1f0216b26b44958d114332a793cf19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Mon, 2 Feb 2026 12:48:42 +0100 Subject: [PATCH 403/978] Update tests/ui/traits/next-solver/generalize/relate-alias-in-lub.rs Co-authored-by: lcnr --- tests/ui/traits/next-solver/generalize/relate-alias-in-lub.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/traits/next-solver/generalize/relate-alias-in-lub.rs b/tests/ui/traits/next-solver/generalize/relate-alias-in-lub.rs index 0a948989f981..a81e18559a39 100644 --- a/tests/ui/traits/next-solver/generalize/relate-alias-in-lub.rs +++ b/tests/ui/traits/next-solver/generalize/relate-alias-in-lub.rs @@ -7,7 +7,7 @@ // The change we tried to make there caused relating a type variable with an alias inside lub, // In 5bd20bbd0ba6c0285664e55a1ffc677d7487c98b, we moved around code // that adds an alias-relate predicate to be earlier, from one shared codepath into several -// distinct code paths. However, we forgot one codepath, through lub, causing an ICE in serde. +// distinct code paths. However, we forgot the codepath in `LatticeOp`, causing an ICE in serde. // In the end we dropped said commit, but the reproducer is still a useful as test. use std::marker::PhantomData; From 82a530c61c56df0fb89e1d3d70565ec3b69fbf32 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 2 Feb 2026 11:53:30 +0000 Subject: [PATCH 404/978] Port --- .../src/attributes/rustc_internal.rs | 8 ++++++++ compiler/rustc_attr_parsing/src/context.rs | 16 +++++++++------- compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_hir_analysis/src/collect/dump.rs | 3 +-- compiler/rustc_passes/src/check_attr.rs | 2 +- 6 files changed, 23 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 38f728fa9f55..250bceecbd65 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -307,6 +307,14 @@ impl NoArgsAttributeParser for RustcHasIncoherentInherentImplsParse const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcHasIncoherentInherentImpls; } +pub(crate) struct RustcHiddenTypeOfOpaquesParser; + +impl NoArgsAttributeParser for RustcHiddenTypeOfOpaquesParser { + const PATH: &[Symbol] = &[sym::rustc_hidden_type_of_opaques]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcHiddenTypeOfOpaques; +} pub(crate) struct RustcNounwindParser; impl NoArgsAttributeParser for RustcNounwindParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 0cabc0895053..51da6def086c 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -75,13 +75,14 @@ use crate::attributes::rustc_dump::{ RustcDumpVtable, }; use crate::attributes::rustc_internal::{ - RustcHasIncoherentInherentImplsParser, RustcLayoutParser, RustcLayoutScalarValidRangeEndParser, - RustcLayoutScalarValidRangeStartParser, RustcLegacyConstGenericsParser, - RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, RustcLintQueryInstabilityParser, - RustcLintUntrackedQueryInformationParser, RustcMainParser, RustcMustImplementOneOfParser, - RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser, - RustcNonConstTraitMethodParser, RustcNounwindParser, RustcObjectLifetimeDefaultParser, - RustcOffloadKernelParser, RustcScalableVectorParser, RustcSimdMonomorphizeLaneLimitParser, + RustcHasIncoherentInherentImplsParser, RustcHiddenTypeOfOpaquesParser, RustcLayoutParser, + RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, + RustcLegacyConstGenericsParser, RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, + RustcLintQueryInstabilityParser, RustcLintUntrackedQueryInformationParser, RustcMainParser, + RustcMustImplementOneOfParser, RustcNeverReturnsNullPointerParser, + RustcNoImplicitAutorefsParser, RustcNonConstTraitMethodParser, RustcNounwindParser, + RustcObjectLifetimeDefaultParser, RustcOffloadKernelParser, RustcScalableVectorParser, + RustcSimdMonomorphizeLaneLimitParser, }; use crate::attributes::semantics::MayDangleParser; use crate::attributes::stability::{ @@ -299,6 +300,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 92dda79b0920..3104a08d7547 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1057,6 +1057,9 @@ pub enum AttributeKind { /// Represents `#[rustc_has_incoherent_inherent_impls]` RustcHasIncoherentInherentImpls, + /// Represents `#[rustc_hidden_type_of_opaques]` + RustcHiddenTypeOfOpaques, + /// Represents `#[rustc_layout]` RustcLayout(ThinVec), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 816ed07c1dc4..f03f55f85b39 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -111,6 +111,7 @@ impl AttributeKind { RustcDumpVtable(..) => No, RustcDynIncompatibleTrait(..) => No, RustcHasIncoherentInherentImpls => Yes, + RustcHiddenTypeOfOpaques => No, RustcLayout(..) => No, RustcLayoutScalarValidRangeEnd(..) => Yes, RustcLayoutScalarValidRangeStart(..) => Yes, diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs index 2dfd4ab6111f..bbf912cd4bde 100644 --- a/compiler/rustc_hir_analysis/src/collect/dump.rs +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs @@ -7,10 +7,9 @@ use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_span::sym; pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) { - if !tcx.has_attr(CRATE_DEF_ID, sym::rustc_hidden_type_of_opaques) { + if !find_attr!(tcx.get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcHiddenTypeOfOpaques) { return; } - for id in tcx.hir_crate_items(()).opaques() { if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. } | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } = diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 8cf68b280850..e413780d6c4f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -299,6 +299,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcDumpVtable(..) | AttributeKind::RustcDynIncompatibleTrait(..) | AttributeKind::RustcHasIncoherentInherentImpls + | AttributeKind::RustcHiddenTypeOfOpaques | AttributeKind::RustcLayout(..) | AttributeKind::RustcLayoutScalarValidRangeEnd(..) | AttributeKind::RustcLayoutScalarValidRangeStart(..) @@ -390,7 +391,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_capture_analysis | sym::rustc_regions | sym::rustc_strict_coherence - | sym::rustc_hidden_type_of_opaques | sym::rustc_mir | sym::rustc_effective_visibility | sym::rustc_outlives From fd023cb122ffacff4bd14f27d9751ffce1bd7878 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 2 Feb 2026 12:57:35 +0100 Subject: [PATCH 405/978] Add uv to the list of possible python runners I'm one of the rare cases that does have uv, but doesn't have python installed globally --- x | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/x b/x index 4fce0be219e7..a8acbd4d5ac6 100755 --- a/x +++ b/x @@ -29,16 +29,19 @@ xpy=$(dirname "$(realpath "$0")")/x.py # On MacOS, `py` tries to install "Developer command line tools". Try `python3` first. # NOTE: running `bash -c ./x` from Windows doesn't set OSTYPE. case ${OSTYPE:-} in - cygwin*|msys*) SEARCH="py python3 python python2";; - *) SEARCH="python3 python py python2";; + cygwin*|msys*) SEARCH="py python3 python python2 uv";; + *) SEARCH="python3 python py python2 uv";; esac for SEARCH_PYTHON in $SEARCH; do if python=$(command -v $SEARCH_PYTHON) && [ -x "$python" ]; then - if [ $SEARCH_PYTHON = py ]; then - extra_arg="-3" - else - extra_arg="" - fi + case $SEARCH_PYTHON in + py) + extra_arg="-3";; + uv) + extra_arg="run";; + *) + extra_arg="";; + esac exec "$python" $extra_arg "$xpy" "$@" fi done From 73d06be9f3eaf94960ac95f8d5986b5eddfe1008 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 22 Jan 2026 09:18:09 +0100 Subject: [PATCH 406/978] Set hidden visibility on naked functions in compiler-builtins 88b46460fa1483b3283b7f1e37c7abd033610a68 made builtin functions hidden, but it doesn't apply to naked functions, which are generated through a different code path. --- .../rustc_codegen_ssa/src/mir/naked_asm.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 4bbb7470debe..f12410c65d98 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -1,5 +1,6 @@ use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind}; use rustc_hir::attrs::{InstructionSetAttr, Linkage}; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::mir::mono::{MonoItemData, Visibility}; use rustc_middle::mir::{InlineAsmOperand, START_BLOCK}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; @@ -128,6 +129,15 @@ fn prefix_and_suffix<'tcx>( let is_arm = tcx.sess.target.arch == Arch::Arm; let is_thumb = tcx.sess.unstable_target_features.contains(&sym::thumb_mode); + // If we're compiling the compiler-builtins crate, e.g., the equivalent of + // compiler-rt, then we want to implicitly compile everything with hidden + // visibility as we're going to link this object all over the place but + // don't want the symbols to get exported. For naked asm we set the visibility here. + let mut visibility = item_data.visibility; + if item_data.linkage != Linkage::Internal && tcx.is_compiler_builtins(LOCAL_CRATE) { + visibility = Visibility::Hidden; + } + let attrs = tcx.codegen_instance_attrs(instance.def); let link_section = attrs.link_section.map(|symbol| symbol.as_str().to_string()); @@ -217,7 +227,7 @@ fn prefix_and_suffix<'tcx>( writeln!(begin, ".pushsection {section},\"ax\", {progbits}").unwrap(); writeln!(begin, ".balign {align_bytes}").unwrap(); write_linkage(&mut begin).unwrap(); - match item_data.visibility { + match visibility { Visibility::Default => {} Visibility::Protected => writeln!(begin, ".protected {asm_name}").unwrap(), Visibility::Hidden => writeln!(begin, ".hidden {asm_name}").unwrap(), @@ -243,7 +253,7 @@ fn prefix_and_suffix<'tcx>( writeln!(begin, ".pushsection {},regular,pure_instructions", section).unwrap(); writeln!(begin, ".balign {align_bytes}").unwrap(); write_linkage(&mut begin).unwrap(); - match item_data.visibility { + match visibility { Visibility::Default | Visibility::Protected => {} Visibility::Hidden => writeln!(begin, ".private_extern {asm_name}").unwrap(), } @@ -280,7 +290,7 @@ fn prefix_and_suffix<'tcx>( writeln!(begin, ".section {section},\"\",@").unwrap(); // wasm functions cannot be aligned, so skip write_linkage(&mut begin).unwrap(); - if let Visibility::Hidden = item_data.visibility { + if let Visibility::Hidden = visibility { writeln!(begin, ".hidden {asm_name}").unwrap(); } writeln!(begin, ".type {asm_name}, @function").unwrap(); @@ -313,7 +323,7 @@ fn prefix_and_suffix<'tcx>( writeln!(begin, ".align {}", align_bytes).unwrap(); write_linkage(&mut begin).unwrap(); - if let Visibility::Hidden = item_data.visibility { + if let Visibility::Hidden = visibility { // FIXME apparently `.globl {asm_name}, hidden` is valid // but due to limitations with `.weak` (see above) we can't really use that in general yet } From 30ae46fab148f8f924d445feddc68b9103204423 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Mon, 2 Feb 2026 14:43:33 +0100 Subject: [PATCH 407/978] Use rustc_parse's Recovery instead of a boolean --- compiler/rustc_attr_parsing/src/attributes/cfg.rs | 10 ++++++---- .../src/attributes/cfg_select.rs | 12 +++++++----- compiler/rustc_attr_parsing/src/context.rs | 11 ++++++----- compiler/rustc_attr_parsing/src/parser.rs | 14 ++++++++++---- compiler/rustc_builtin_macros/src/cfg.rs | 5 +++-- compiler/rustc_expand/src/config.rs | 5 ++++- compiler/rustc_expand/src/expand.rs | 6 +++--- 7 files changed, 39 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 3a540d80998d..157a91c249d4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -10,7 +10,7 @@ use rustc_feature::{ use rustc_hir::attrs::CfgEntry; use rustc_hir::lints::AttributeLintKind; use rustc_hir::{AttrPath, RustcVersion, Target}; -use rustc_parse::parser::{ForceCollect, Parser}; +use rustc_parse::parser::{ForceCollect, Parser, Recovery}; use rustc_parse::{exp, parse_in}; use rustc_session::Session; use rustc_session::config::ExpectedValues; @@ -360,8 +360,10 @@ fn parse_cfg_attr_internal<'a>( ) -> PResult<'a, (CfgEntry, Vec<(ast::AttrItem, Span)>)> { // Parse cfg predicate let pred_start = parser.token.span; - let meta = - MetaItemOrLitParser::parse_single(parser, ShouldEmit::ErrorsAndLints { recover: true })?; + let meta = MetaItemOrLitParser::parse_single( + parser, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, + )?; let pred_span = pred_start.with_hi(parser.token.span.hi()); let cfg_predicate = AttributeParser::parse_single_args( @@ -376,7 +378,7 @@ fn parse_cfg_attr_internal<'a>( CRATE_NODE_ID, Target::Crate, features, - ShouldEmit::ErrorsAndLints { recover: true }, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, &meta, parse_cfg_entry, &CFG_ATTR_TEMPLATE, diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs index ca844758daaa..4005ad2cba11 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -5,7 +5,7 @@ use rustc_feature::{AttributeTemplate, Features}; use rustc_hir::attrs::CfgEntry; use rustc_hir::{AttrPath, Target}; use rustc_parse::exp; -use rustc_parse::parser::Parser; +use rustc_parse::parser::{Parser, Recovery}; use rustc_session::Session; use rustc_span::{ErrorGuaranteed, Span, sym}; @@ -78,9 +78,11 @@ pub fn parse_cfg_select( } } } else { - let meta = - MetaItemOrLitParser::parse_single(p, ShouldEmit::ErrorsAndLints { recover: true }) - .map_err(|diag| diag.emit())?; + let meta = MetaItemOrLitParser::parse_single( + p, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, + ) + .map_err(|diag| diag.emit())?; let cfg_span = meta.span(); let cfg = AttributeParser::parse_single_args( sess, @@ -95,7 +97,7 @@ pub fn parse_cfg_select( // Doesn't matter what the target actually is here. Target::Crate, features, - ShouldEmit::ErrorsAndLints { recover: true }, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, &meta, parse_cfg_entry, &AttributeTemplate::default(), diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 0cabc0895053..fa6c9513c59c 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -10,6 +10,7 @@ use rustc_feature::{AttrSuggestionStyle, AttributeTemplate}; use rustc_hir::attrs::AttributeKind; use rustc_hir::lints::AttributeLintKind; use rustc_hir::{AttrPath, HirId}; +use rustc_parse::parser::Recovery; use rustc_session::Session; use rustc_session::lint::{Lint, LintId}; use rustc_span::{ErrorGuaranteed, Span, Symbol}; @@ -383,7 +384,7 @@ impl Stage for Late { } fn should_emit(&self) -> ShouldEmit { - ShouldEmit::ErrorsAndLints { recover: true } + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed } } } @@ -770,10 +771,10 @@ pub enum ShouldEmit { ErrorsAndLints { /// Whether [`ArgParser`] will attempt to recover from errors. /// - /// If true, it will attempt to recover from bad input (like an invalid literal). Setting - /// this to false will instead return early, and not raise errors except at the top level - /// (in [`ArgParser::from_attr_args`]). - recover: bool, + /// Whether it is allowed to recover from bad input (like an invalid literal). Setting + /// this to `Forbidden` will instead return early, and not raise errors except at the top + /// level (in [`ArgParser::from_attr_args`]). + recovery: Recovery, }, /// The operation will *not* emit errors and lints. /// diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 7f3c6d28005f..80dab0b85edd 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -15,7 +15,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::{Diag, PResult}; use rustc_hir::{self as hir, AttrPath}; use rustc_parse::exp; -use rustc_parse::parser::{ForceCollect, Parser, PathStyle, token_descr}; +use rustc_parse::parser::{ForceCollect, Parser, PathStyle, Recovery, token_descr}; use rustc_session::errors::create_lit_error; use rustc_session::parse::ParseSess; use rustc_span::{Ident, Span, Symbol, sym}; @@ -121,7 +121,7 @@ impl ArgParser { &args.tokens, args.dspan.entire(), psess, - ShouldEmit::ErrorsAndLints { recover: false }, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden }, ) { Ok(p) => return Some(ArgParser::List(p)), Err(e) => { @@ -373,7 +373,10 @@ fn expr_to_lit<'sess>( } Err(err) => { let err = create_lit_error(psess, err, token_lit, expr.span); - if matches!(should_emit, ShouldEmit::ErrorsAndLints { recover: false }) { + if matches!( + should_emit, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden } + ) { Err(err) } else { let lit = MetaItemLit { @@ -431,7 +434,10 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { if !lit.kind.is_unsuffixed() { // Emit error and continue, we can still parse the attribute as if the suffix isn't there let err = self.parser.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }); - if matches!(self.should_emit, ShouldEmit::ErrorsAndLints { recover: false }) { + if matches!( + self.should_emit, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden } + ) { return Err(err); } else { self.should_emit.emit_err(err) diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 8e925cfe09a2..3ebde949b99b 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -13,6 +13,7 @@ use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpa use rustc_hir::attrs::CfgEntry; use rustc_hir::{AttrPath, Target}; use rustc_parse::exp; +use rustc_parse::parser::Recovery; use rustc_span::{ErrorGuaranteed, Span, sym}; use crate::errors; @@ -42,7 +43,7 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result, span: Span, tts: TokenStream) -> Result StripUnconfigured<'a> { fn in_cfg(&self, attrs: &[Attribute]) -> bool { attrs.iter().all(|attr| { !is_cfg(attr) - || self.cfg_true(attr, ShouldEmit::ErrorsAndLints { recover: true }).as_bool() + || self + .cfg_true(attr, ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }) + .as_bool() }) } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index cfa7725c7400..48e2ee8e9abd 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -26,7 +26,7 @@ use rustc_hir::def::MacroKinds; use rustc_hir::limit::Limit; use rustc_parse::parser::{ AllowConstBlockItems, AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, - RecoverColon, RecoverComma, token_descr, + RecoverColon, RecoverComma, Recovery, token_descr, }; use rustc_session::Session; use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS}; @@ -2170,7 +2170,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { call.span(), self.cx.current_expansion.lint_node_id, Some(self.cx.ecfg.features), - ShouldEmit::ErrorsAndLints { recover: true }, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, ); let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span }; @@ -2220,7 +2220,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { // Target doesn't matter for `cfg` parsing. Target::Crate, self.cfg().features, - ShouldEmit::ErrorsAndLints { recover: true }, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, parse_cfg, &CFG_TEMPLATE, ) else { From aef821794367e03e654acbb2fa8f098102b9ef64 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Mon, 2 Feb 2026 14:55:21 +0100 Subject: [PATCH 408/978] Pass `Recovery` down to rustc_parse's Parser --- compiler/rustc_attr_parsing/src/parser.rs | 4 ++++ .../do_not_recommend/does_not_acccept_args.current.stderr | 4 ++-- .../do_not_recommend/does_not_acccept_args.next.stderr | 4 ++-- .../do_not_recommend/does_not_acccept_args.rs | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 80dab0b85edd..973635f432e8 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -575,6 +575,10 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { should_emit: ShouldEmit, ) -> PResult<'sess, MetaItemListParser> { let mut parser = Parser::new(psess, tokens, None); + if let ShouldEmit::ErrorsAndLints { recovery } = should_emit { + parser = parser.recovery(recovery); + } + let mut this = MetaItemListParserContext { parser: &mut parser, should_emit }; // Presumably, the majority of the time there will only be one attr. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr index 43205bd395fc..075e4bf0384d 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr @@ -1,8 +1,8 @@ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments --> $DIR/does_not_acccept_args.rs:12:1 | -LL | #[diagnostic::do_not_recommend(not_accepted)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[diagnostic::do_not_recommend(if, crate, do yeet, false, dyn, abstract, gen, not_accepted)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr index 43205bd395fc..075e4bf0384d 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr @@ -1,8 +1,8 @@ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments --> $DIR/does_not_acccept_args.rs:12:1 | -LL | #[diagnostic::do_not_recommend(not_accepted)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[diagnostic::do_not_recommend(if, crate, do yeet, false, dyn, abstract, gen, not_accepted)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs index 918bf5a0113e..943b5a37f938 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs @@ -9,7 +9,7 @@ trait Bar {} trait Baz {} trait Boo {} -#[diagnostic::do_not_recommend(not_accepted)] +#[diagnostic::do_not_recommend(if, crate, do yeet, false, dyn, abstract, gen, not_accepted)] //~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments impl Foo for T where T: Send {} From bdd19d0db39266bd5c22348d15b8215e3a804e59 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 2 Feb 2026 15:13:38 +0100 Subject: [PATCH 409/978] clarity that the neon extension is present --- tests/ui/asm/cortex-r82.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/ui/asm/cortex-r82.rs b/tests/ui/asm/cortex-r82.rs index a64349b37af7..74313e5cb48c 100644 --- a/tests/ui/asm/cortex-r82.rs +++ b/tests/ui/asm/cortex-r82.rs @@ -22,6 +22,10 @@ use minicore::*; * A `/* */` comment indicates that the extension is being tested in the ISA level codegen test * (`tests/ui/asm/aarch64v8r.rs`) * + * Note that as we use the hard-float `aarch64v8r-unknown-none` target as the base, the neon + * extension is present (`NEON_FPm=1`). This affects which R82-specific extensions are enabled + * (see "when `NEON_FPm == 1`" note in Cortex-R82 Processor Technical Reference Manual) + * * ## References: * * - Arm Cortex-R82 Processor Technical Reference Manual Revision r3p1 (102670_0301_06_en Issue 6) @@ -55,7 +59,7 @@ pub fn mandatory_extensions() { // FEAT_nTLBPA /* FEAT_CRC32 */ /* FEAT_LSE */ - feat_rdm(); + feat_rdm(); // mandatory given that NEON_FPm=1 /* FEAT_HPDS */ /* FEAT_PAN */ // FEAT_HAFDBS @@ -68,10 +72,10 @@ pub fn mandatory_extensions() { /* FEAT_Debugv8p2 */ /* FEAT_ASMv8p2 */ // FEAT_IESB - feat_fp16(); + feat_fp16(); // mandatory given that NEON_FPm=1 // FEAT_PCSRv8p2 - feat_dotprod(); - feat_fhm(); + feat_dotprod(); // mandatory given that NEON_FPm=1 + feat_fhm(); // mandatory given that NEON_FPm=1 feat_dpb2(); /* FEAT_PAuth */ // FEAT_PACQARMA3 @@ -79,9 +83,9 @@ pub fn mandatory_extensions() { // FEAT_FPAC // FEAT_FPACCOMBINE // FEAT_CONSTPACFIELD - feat_jscvt(); + feat_jscvt(); // mandatory given that NEON_FPm=1 /* FEAT_LRCPC */ - feat_fcma(); + feat_fcma(); // mandatory given that NEON_FPm=1 // FEAT_DoPD // FEAT_SEL2 /* FEAT_S2FWB */ From 81c0218ae8d0b9d3895974d2945ac836113f2371 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 27 Jan 2026 19:06:53 +0100 Subject: [PATCH 410/978] aarch64: use `read_unaligned` for `vld1_*` --- .../src/arm_shared/neon/generated.rs | 734 ++++++------------ .../spec/neon/arm_shared.spec.yml | 92 +-- 2 files changed, 266 insertions(+), 560 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs index 2f52e3b52b07..c2e90d41eff0 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs @@ -15808,21 +15808,13 @@ pub unsafe fn vld1q_f16(ptr: *const f16) -> float16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[unstable(feature = "stdarch_neon_f16", issue = "136306")] #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1_f16_x2(a: *const f16) -> float16x4x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v4f16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v4f16.p0")] - fn _vld1_f16_x2(a: *const f16) -> float16x4x2_t; - } - _vld1_f16_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_f16_x3)"] @@ -15834,21 +15826,13 @@ pub unsafe fn vld1_f16_x2(a: *const f16) -> float16x4x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[unstable(feature = "stdarch_neon_f16", issue = "136306")] #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1_f16_x3(a: *const f16) -> float16x4x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v4f16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v4f16.p0")] - fn _vld1_f16_x3(a: *const f16) -> float16x4x3_t; - } - _vld1_f16_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_f16_x4)"] @@ -15860,21 +15844,13 @@ pub unsafe fn vld1_f16_x3(a: *const f16) -> float16x4x3_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[unstable(feature = "stdarch_neon_f16", issue = "136306")] #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1_f16_x4(a: *const f16) -> float16x4x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v4f16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v4f16.p0")] - fn _vld1_f16_x4(a: *const f16) -> float16x4x4_t; - } - _vld1_f16_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_f16_x2)"] @@ -15886,21 +15862,13 @@ pub unsafe fn vld1_f16_x4(a: *const f16) -> float16x4x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[unstable(feature = "stdarch_neon_f16", issue = "136306")] #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1q_f16_x2(a: *const f16) -> float16x8x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v8f16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v8f16.p0")] - fn _vld1q_f16_x2(a: *const f16) -> float16x8x2_t; - } - _vld1q_f16_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_f16_x3)"] @@ -15912,21 +15880,13 @@ pub unsafe fn vld1q_f16_x2(a: *const f16) -> float16x8x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[unstable(feature = "stdarch_neon_f16", issue = "136306")] #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1q_f16_x3(a: *const f16) -> float16x8x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v8f16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v8f16.p0")] - fn _vld1q_f16_x3(a: *const f16) -> float16x8x3_t; - } - _vld1q_f16_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_f16_x4)"] @@ -15938,21 +15898,13 @@ pub unsafe fn vld1q_f16_x3(a: *const f16) -> float16x8x3_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[unstable(feature = "stdarch_neon_f16", issue = "136306")] #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1q_f16_x4(a: *const f16) -> float16x8x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v8f16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v8f16.p0")] - fn _vld1q_f16_x4(a: *const f16) -> float16x8x4_t; - } - _vld1q_f16_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_f32)"] @@ -16156,10 +16108,10 @@ pub unsafe fn vld1q_p64(ptr: *const p64) -> poly64x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -16170,15 +16122,7 @@ pub unsafe fn vld1q_p64(ptr: *const p64) -> poly64x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_f32_x2(a: *const f32) -> float32x2x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v2f32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v2f32.p0")] - fn _vld1_f32_x2(a: *const f32) -> float32x2x2_t; - } - _vld1_f32_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_f32_x3)"] @@ -16187,10 +16131,10 @@ pub unsafe fn vld1_f32_x2(a: *const f32) -> float32x2x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -16201,15 +16145,7 @@ pub unsafe fn vld1_f32_x2(a: *const f32) -> float32x2x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_f32_x3(a: *const f32) -> float32x2x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v2f32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v2f32.p0")] - fn _vld1_f32_x3(a: *const f32) -> float32x2x3_t; - } - _vld1_f32_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_f32_x4)"] @@ -16218,10 +16154,10 @@ pub unsafe fn vld1_f32_x3(a: *const f32) -> float32x2x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -16232,15 +16168,7 @@ pub unsafe fn vld1_f32_x3(a: *const f32) -> float32x2x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_f32_x4(a: *const f32) -> float32x2x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v2f32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v2f32.p0")] - fn _vld1_f32_x4(a: *const f32) -> float32x2x4_t; - } - _vld1_f32_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_f32_x2)"] @@ -16249,10 +16177,10 @@ pub unsafe fn vld1_f32_x4(a: *const f32) -> float32x2x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -16263,15 +16191,7 @@ pub unsafe fn vld1_f32_x4(a: *const f32) -> float32x2x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_f32_x2(a: *const f32) -> float32x4x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v4f32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v4f32.p0")] - fn _vld1q_f32_x2(a: *const f32) -> float32x4x2_t; - } - _vld1q_f32_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_f32_x3)"] @@ -16280,10 +16200,10 @@ pub unsafe fn vld1q_f32_x2(a: *const f32) -> float32x4x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -16294,15 +16214,7 @@ pub unsafe fn vld1q_f32_x2(a: *const f32) -> float32x4x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_f32_x3(a: *const f32) -> float32x4x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v4f32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v4f32.p0")] - fn _vld1q_f32_x3(a: *const f32) -> float32x4x3_t; - } - _vld1q_f32_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_f32_x4)"] @@ -16311,10 +16223,10 @@ pub unsafe fn vld1q_f32_x3(a: *const f32) -> float32x4x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -16325,15 +16237,7 @@ pub unsafe fn vld1q_f32_x3(a: *const f32) -> float32x4x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_f32_x4(a: *const f32) -> float32x4x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v4f32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v4f32.p0")] - fn _vld1q_f32_x4(a: *const f32) -> float32x4x4_t; - } - _vld1q_f32_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load one single-element structure to one lane of one register"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_f16)"] @@ -17000,10 +16904,10 @@ pub unsafe fn vld1_p64(ptr: *const p64) -> poly64x1_t { #[inline(always)] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17014,7 +16918,7 @@ pub unsafe fn vld1_p64(ptr: *const p64) -> poly64x1_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p64_x2(a: *const p64) -> poly64x1x2_t { - transmute(vld1_s64_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p64_x3)"] @@ -17026,7 +16930,7 @@ pub unsafe fn vld1_p64_x2(a: *const p64) -> poly64x1x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17037,7 +16941,7 @@ pub unsafe fn vld1_p64_x2(a: *const p64) -> poly64x1x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p64_x3(a: *const p64) -> poly64x1x3_t { - transmute(vld1_s64_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p64_x4)"] @@ -17049,7 +16953,7 @@ pub unsafe fn vld1_p64_x3(a: *const p64) -> poly64x1x3_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17060,7 +16964,7 @@ pub unsafe fn vld1_p64_x3(a: *const p64) -> poly64x1x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p64_x4(a: *const p64) -> poly64x1x4_t { - transmute(vld1_s64_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x2)"] @@ -17072,7 +16976,7 @@ pub unsafe fn vld1_p64_x4(a: *const p64) -> poly64x1x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17083,7 +16987,7 @@ pub unsafe fn vld1_p64_x4(a: *const p64) -> poly64x1x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t { - transmute(vld1q_s64_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x3)"] @@ -17095,7 +16999,7 @@ pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17106,7 +17010,7 @@ pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { - transmute(vld1q_s64_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p64_x4)"] @@ -17118,7 +17022,7 @@ pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17129,7 +17033,7 @@ pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p64_x4(a: *const p64) -> poly64x2x4_t { - transmute(vld1q_s64_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s8)"] @@ -17242,10 +17146,10 @@ pub unsafe fn vld1q_s64(ptr: *const i64) -> int64x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17256,15 +17160,7 @@ pub unsafe fn vld1q_s64(ptr: *const i64) -> int64x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s8_x2(a: *const i8) -> int8x8x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v8i8.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v8i8.p0")] - fn _vld1_s8_x2(a: *const i8) -> int8x8x2_t; - } - _vld1_s8_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s8_x3)"] @@ -17273,10 +17169,10 @@ pub unsafe fn vld1_s8_x2(a: *const i8) -> int8x8x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17287,15 +17183,7 @@ pub unsafe fn vld1_s8_x2(a: *const i8) -> int8x8x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s8_x3(a: *const i8) -> int8x8x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v8i8.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v8i8.p0")] - fn _vld1_s8_x3(a: *const i8) -> int8x8x3_t; - } - _vld1_s8_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s8_x4)"] @@ -17304,10 +17192,10 @@ pub unsafe fn vld1_s8_x3(a: *const i8) -> int8x8x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17318,15 +17206,7 @@ pub unsafe fn vld1_s8_x3(a: *const i8) -> int8x8x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s8_x4(a: *const i8) -> int8x8x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v8i8.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v8i8.p0")] - fn _vld1_s8_x4(a: *const i8) -> int8x8x4_t; - } - _vld1_s8_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s8_x2)"] @@ -17335,10 +17215,10 @@ pub unsafe fn vld1_s8_x4(a: *const i8) -> int8x8x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17349,15 +17229,7 @@ pub unsafe fn vld1_s8_x4(a: *const i8) -> int8x8x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s8_x2(a: *const i8) -> int8x16x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v16i8.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v16i8.p0")] - fn _vld1q_s8_x2(a: *const i8) -> int8x16x2_t; - } - _vld1q_s8_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s8_x3)"] @@ -17366,10 +17238,10 @@ pub unsafe fn vld1q_s8_x2(a: *const i8) -> int8x16x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17380,15 +17252,7 @@ pub unsafe fn vld1q_s8_x2(a: *const i8) -> int8x16x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s8_x3(a: *const i8) -> int8x16x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v16i8.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v16i8.p0")] - fn _vld1q_s8_x3(a: *const i8) -> int8x16x3_t; - } - _vld1q_s8_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s8_x4)"] @@ -17397,10 +17261,10 @@ pub unsafe fn vld1q_s8_x3(a: *const i8) -> int8x16x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17411,15 +17275,7 @@ pub unsafe fn vld1q_s8_x3(a: *const i8) -> int8x16x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s8_x4(a: *const i8) -> int8x16x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v16i8.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v16i8.p0")] - fn _vld1q_s8_x4(a: *const i8) -> int8x16x4_t; - } - _vld1q_s8_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s16_x2)"] @@ -17428,10 +17284,10 @@ pub unsafe fn vld1q_s8_x4(a: *const i8) -> int8x16x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17442,15 +17298,7 @@ pub unsafe fn vld1q_s8_x4(a: *const i8) -> int8x16x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s16_x2(a: *const i16) -> int16x4x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v4i16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v4i16.p0")] - fn _vld1_s16_x2(a: *const i16) -> int16x4x2_t; - } - _vld1_s16_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s16_x3)"] @@ -17459,10 +17307,10 @@ pub unsafe fn vld1_s16_x2(a: *const i16) -> int16x4x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17473,15 +17321,7 @@ pub unsafe fn vld1_s16_x2(a: *const i16) -> int16x4x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s16_x3(a: *const i16) -> int16x4x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v4i16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v4i16.p0")] - fn _vld1_s16_x3(a: *const i16) -> int16x4x3_t; - } - _vld1_s16_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s16_x4)"] @@ -17490,10 +17330,10 @@ pub unsafe fn vld1_s16_x3(a: *const i16) -> int16x4x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17504,15 +17344,7 @@ pub unsafe fn vld1_s16_x3(a: *const i16) -> int16x4x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s16_x4(a: *const i16) -> int16x4x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v4i16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v4i16.p0")] - fn _vld1_s16_x4(a: *const i16) -> int16x4x4_t; - } - _vld1_s16_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s16_x2)"] @@ -17521,10 +17353,10 @@ pub unsafe fn vld1_s16_x4(a: *const i16) -> int16x4x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17535,15 +17367,7 @@ pub unsafe fn vld1_s16_x4(a: *const i16) -> int16x4x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s16_x2(a: *const i16) -> int16x8x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v8i16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v8i16.p0")] - fn _vld1q_s16_x2(a: *const i16) -> int16x8x2_t; - } - _vld1q_s16_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s16_x3)"] @@ -17552,10 +17376,10 @@ pub unsafe fn vld1q_s16_x2(a: *const i16) -> int16x8x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17566,15 +17390,7 @@ pub unsafe fn vld1q_s16_x2(a: *const i16) -> int16x8x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s16_x3(a: *const i16) -> int16x8x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v8i16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v8i16.p0")] - fn _vld1q_s16_x3(a: *const i16) -> int16x8x3_t; - } - _vld1q_s16_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s16_x4)"] @@ -17583,10 +17399,10 @@ pub unsafe fn vld1q_s16_x3(a: *const i16) -> int16x8x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17597,15 +17413,7 @@ pub unsafe fn vld1q_s16_x3(a: *const i16) -> int16x8x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s16_x4(a: *const i16) -> int16x8x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v8i16.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v8i16.p0")] - fn _vld1q_s16_x4(a: *const i16) -> int16x8x4_t; - } - _vld1q_s16_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s32_x2)"] @@ -17614,10 +17422,10 @@ pub unsafe fn vld1q_s16_x4(a: *const i16) -> int16x8x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17628,15 +17436,7 @@ pub unsafe fn vld1q_s16_x4(a: *const i16) -> int16x8x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s32_x2(a: *const i32) -> int32x2x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v2i32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v2i32.p0")] - fn _vld1_s32_x2(a: *const i32) -> int32x2x2_t; - } - _vld1_s32_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s32_x3)"] @@ -17645,10 +17445,10 @@ pub unsafe fn vld1_s32_x2(a: *const i32) -> int32x2x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17659,15 +17459,7 @@ pub unsafe fn vld1_s32_x2(a: *const i32) -> int32x2x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s32_x3(a: *const i32) -> int32x2x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v2i32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v2i32.p0")] - fn _vld1_s32_x3(a: *const i32) -> int32x2x3_t; - } - _vld1_s32_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s32_x4)"] @@ -17676,10 +17468,10 @@ pub unsafe fn vld1_s32_x3(a: *const i32) -> int32x2x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17690,15 +17482,7 @@ pub unsafe fn vld1_s32_x3(a: *const i32) -> int32x2x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s32_x4(a: *const i32) -> int32x2x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v2i32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v2i32.p0")] - fn _vld1_s32_x4(a: *const i32) -> int32x2x4_t; - } - _vld1_s32_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s32_x2)"] @@ -17707,10 +17491,10 @@ pub unsafe fn vld1_s32_x4(a: *const i32) -> int32x2x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17721,15 +17505,7 @@ pub unsafe fn vld1_s32_x4(a: *const i32) -> int32x2x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s32_x2(a: *const i32) -> int32x4x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v4i32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v4i32.p0")] - fn _vld1q_s32_x2(a: *const i32) -> int32x4x2_t; - } - _vld1q_s32_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s32_x3)"] @@ -17738,10 +17514,10 @@ pub unsafe fn vld1q_s32_x2(a: *const i32) -> int32x4x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17752,15 +17528,7 @@ pub unsafe fn vld1q_s32_x2(a: *const i32) -> int32x4x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s32_x3(a: *const i32) -> int32x4x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v4i32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v4i32.p0")] - fn _vld1q_s32_x3(a: *const i32) -> int32x4x3_t; - } - _vld1q_s32_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s32_x4)"] @@ -17769,10 +17537,10 @@ pub unsafe fn vld1q_s32_x3(a: *const i32) -> int32x4x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17783,15 +17551,7 @@ pub unsafe fn vld1q_s32_x3(a: *const i32) -> int32x4x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s32_x4(a: *const i32) -> int32x4x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v4i32.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v4i32.p0")] - fn _vld1q_s32_x4(a: *const i32) -> int32x4x4_t; - } - _vld1q_s32_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s64_x2)"] @@ -17800,10 +17560,10 @@ pub unsafe fn vld1q_s32_x4(a: *const i32) -> int32x4x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17814,15 +17574,7 @@ pub unsafe fn vld1q_s32_x4(a: *const i32) -> int32x4x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s64_x2(a: *const i64) -> int64x1x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v1i64.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v1i64.p0")] - fn _vld1_s64_x2(a: *const i64) -> int64x1x2_t; - } - _vld1_s64_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s64_x3)"] @@ -17831,10 +17583,10 @@ pub unsafe fn vld1_s64_x2(a: *const i64) -> int64x1x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17845,15 +17597,7 @@ pub unsafe fn vld1_s64_x2(a: *const i64) -> int64x1x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s64_x3(a: *const i64) -> int64x1x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v1i64.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v1i64.p0")] - fn _vld1_s64_x3(a: *const i64) -> int64x1x3_t; - } - _vld1_s64_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_s64_x4)"] @@ -17862,10 +17606,10 @@ pub unsafe fn vld1_s64_x3(a: *const i64) -> int64x1x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17876,15 +17620,7 @@ pub unsafe fn vld1_s64_x3(a: *const i64) -> int64x1x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_s64_x4(a: *const i64) -> int64x1x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v1i64.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v1i64.p0")] - fn _vld1_s64_x4(a: *const i64) -> int64x1x4_t; - } - _vld1_s64_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s64_x2)"] @@ -17893,10 +17629,10 @@ pub unsafe fn vld1_s64_x4(a: *const i64) -> int64x1x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17907,15 +17643,7 @@ pub unsafe fn vld1_s64_x4(a: *const i64) -> int64x1x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s64_x2(a: *const i64) -> int64x2x2_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x2.v2i64.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x2.v2i64.p0")] - fn _vld1q_s64_x2(a: *const i64) -> int64x2x2_t; - } - _vld1q_s64_x2(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s64_x3)"] @@ -17924,10 +17652,10 @@ pub unsafe fn vld1q_s64_x2(a: *const i64) -> int64x2x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17938,15 +17666,7 @@ pub unsafe fn vld1q_s64_x2(a: *const i64) -> int64x2x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s64_x3(a: *const i64) -> int64x2x3_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x3.v2i64.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x3.v2i64.p0")] - fn _vld1q_s64_x3(a: *const i64) -> int64x2x3_t; - } - _vld1q_s64_x3(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_s64_x4)"] @@ -17955,10 +17675,10 @@ pub unsafe fn vld1q_s64_x3(a: *const i64) -> int64x2x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -17969,15 +17689,7 @@ pub unsafe fn vld1q_s64_x3(a: *const i64) -> int64x2x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_s64_x4(a: *const i64) -> int64x2x4_t { - unsafe extern "unadjusted" { - #[cfg_attr( - any(target_arch = "aarch64", target_arch = "arm64ec"), - link_name = "llvm.aarch64.neon.ld1x4.v2i64.p0" - )] - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v2i64.p0")] - fn _vld1q_s64_x4(a: *const i64) -> int64x2x4_t; - } - _vld1q_s64_x4(a) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x2)"] @@ -17986,10 +17698,10 @@ pub unsafe fn vld1q_s64_x4(a: *const i64) -> int64x2x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18000,7 +17712,7 @@ pub unsafe fn vld1q_s64_x4(a: *const i64) -> int64x2x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t { - transmute(vld1_s8_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x3)"] @@ -18009,10 +17721,10 @@ pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18023,7 +17735,7 @@ pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { - transmute(vld1_s8_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u8_x4)"] @@ -18032,10 +17744,10 @@ pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18046,7 +17758,7 @@ pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { - transmute(vld1_s8_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x2)"] @@ -18055,10 +17767,10 @@ pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18069,7 +17781,7 @@ pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { - transmute(vld1q_s8_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x3)"] @@ -18078,10 +17790,10 @@ pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18092,7 +17804,7 @@ pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { - transmute(vld1q_s8_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u8_x4)"] @@ -18101,10 +17813,10 @@ pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18115,7 +17827,7 @@ pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { - transmute(vld1q_s8_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x2)"] @@ -18124,10 +17836,10 @@ pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18138,7 +17850,7 @@ pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { - transmute(vld1_s16_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x3)"] @@ -18147,10 +17859,10 @@ pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18161,7 +17873,7 @@ pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t { - transmute(vld1_s16_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u16_x4)"] @@ -18170,10 +17882,10 @@ pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18184,7 +17896,7 @@ pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t { - transmute(vld1_s16_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x2)"] @@ -18193,10 +17905,10 @@ pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18207,7 +17919,7 @@ pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t { - transmute(vld1q_s16_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x3)"] @@ -18216,10 +17928,10 @@ pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18230,7 +17942,7 @@ pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t { - transmute(vld1q_s16_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u16_x4)"] @@ -18239,10 +17951,10 @@ pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18253,7 +17965,7 @@ pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t { - transmute(vld1q_s16_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x2)"] @@ -18262,10 +17974,10 @@ pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18276,7 +17988,7 @@ pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t { - transmute(vld1_s32_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x3)"] @@ -18285,10 +17997,10 @@ pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18299,7 +18011,7 @@ pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t { - transmute(vld1_s32_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u32_x4)"] @@ -18308,10 +18020,10 @@ pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18322,7 +18034,7 @@ pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t { - transmute(vld1_s32_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x2)"] @@ -18331,10 +18043,10 @@ pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18345,7 +18057,7 @@ pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t { - transmute(vld1q_s32_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x3)"] @@ -18354,10 +18066,10 @@ pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18368,7 +18080,7 @@ pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t { - transmute(vld1q_s32_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u32_x4)"] @@ -18377,10 +18089,10 @@ pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18391,7 +18103,7 @@ pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t { - transmute(vld1q_s32_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u64_x2)"] @@ -18400,10 +18112,10 @@ pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18414,7 +18126,7 @@ pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u64_x2(a: *const u64) -> uint64x1x2_t { - transmute(vld1_s64_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u64_x3)"] @@ -18423,10 +18135,10 @@ pub unsafe fn vld1_u64_x2(a: *const u64) -> uint64x1x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18437,7 +18149,7 @@ pub unsafe fn vld1_u64_x2(a: *const u64) -> uint64x1x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u64_x3(a: *const u64) -> uint64x1x3_t { - transmute(vld1_s64_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_u64_x4)"] @@ -18446,10 +18158,10 @@ pub unsafe fn vld1_u64_x3(a: *const u64) -> uint64x1x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18460,7 +18172,7 @@ pub unsafe fn vld1_u64_x3(a: *const u64) -> uint64x1x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_u64_x4(a: *const u64) -> uint64x1x4_t { - transmute(vld1_s64_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x2)"] @@ -18469,10 +18181,10 @@ pub unsafe fn vld1_u64_x4(a: *const u64) -> uint64x1x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18483,7 +18195,7 @@ pub unsafe fn vld1_u64_x4(a: *const u64) -> uint64x1x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t { - transmute(vld1q_s64_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x3)"] @@ -18492,10 +18204,10 @@ pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18506,7 +18218,7 @@ pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t { - transmute(vld1q_s64_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_u64_x4)"] @@ -18515,10 +18227,10 @@ pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18529,7 +18241,7 @@ pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t { - transmute(vld1q_s64_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x2)"] @@ -18538,10 +18250,10 @@ pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18552,7 +18264,7 @@ pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t { - transmute(vld1_s8_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x3)"] @@ -18561,10 +18273,10 @@ pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18575,7 +18287,7 @@ pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { - transmute(vld1_s8_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p8_x4)"] @@ -18584,10 +18296,10 @@ pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18598,7 +18310,7 @@ pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { - transmute(vld1_s8_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x2)"] @@ -18607,10 +18319,10 @@ pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18621,7 +18333,7 @@ pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { - transmute(vld1q_s8_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x3)"] @@ -18630,10 +18342,10 @@ pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18644,7 +18356,7 @@ pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { - transmute(vld1q_s8_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p8_x4)"] @@ -18653,10 +18365,10 @@ pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18667,7 +18379,7 @@ pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { - transmute(vld1q_s8_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x2)"] @@ -18676,10 +18388,10 @@ pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18690,7 +18402,7 @@ pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { - transmute(vld1_s16_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x3)"] @@ -18699,10 +18411,10 @@ pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18713,7 +18425,7 @@ pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { - transmute(vld1_s16_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p16_x4)"] @@ -18722,10 +18434,10 @@ pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18736,7 +18448,7 @@ pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { - transmute(vld1_s16_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x2)"] @@ -18745,10 +18457,10 @@ pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18759,7 +18471,7 @@ pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { - transmute(vld1q_s16_x2(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x3)"] @@ -18768,10 +18480,10 @@ pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18782,7 +18494,7 @@ pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { - transmute(vld1q_s16_x3(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[doc = "Load multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_p16_x4)"] @@ -18791,10 +18503,10 @@ pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), - assert_instr(ld1) + assert_instr(ld) )] #[cfg_attr( not(target_arch = "arm"), @@ -18805,7 +18517,7 @@ pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_p16_x4(a: *const p16) -> poly16x8x4_t { - transmute(vld1q_s16_x4(transmute(a))) + crate::ptr::read_unaligned(a.cast()) } #[inline(always)] #[rustc_legacy_const_generics(1)] diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml index 3ec7ba8814e5..c726d1a028a5 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml @@ -2603,8 +2603,8 @@ intrinsics: return_type: "{neon_type[1]}" attr: - *neon-v7 - - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld1]]}]] - - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] + - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld]]}]] + - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld]]}]] - *neon-not-arm-stable - *neon-cfg-arm-unstable safety: @@ -2617,13 +2617,12 @@ intrinsics: - ["*const f32", float32x2x4_t] - ["*const f32", float32x4x4_t] compose: - - LLVMLink: - name: "vld1x{neon_type[1].tuple}.{neon_type[1]}" - links: - - link: "llvm.aarch64.neon.ld1x{neon_type[1].tuple}.v{neon_type[1].lane}f{neon_type[1].base}.p0" - arch: aarch64,arm64ec - - link: "llvm.arm.neon.vld1x{neon_type[1].tuple}.v{neon_type[1].lane}f{neon_type[1].base}.p0" - arch: arm + - FnCall: + - 'crate::ptr::read_unaligned' + - - MethodCall: + - a + - cast + - [] - name: "vld1{neon_type[1].no}" doc: "Load multiple single-element structures to one, two, three, or four registers" @@ -2631,8 +2630,8 @@ intrinsics: return_type: "{neon_type[1]}" attr: - *neon-v7 - - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld1]]}]] - - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] + - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld]]}]] + - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld]]}]] - *neon-not-arm-stable - *neon-cfg-arm-unstable safety: @@ -2663,13 +2662,12 @@ intrinsics: - ["*const i64", int64x2x3_t] - ["*const i64", int64x2x4_t] compose: - - LLVMLink: - name: "ld1x{neon_type[1].tuple}.{neon_type[1]}" - links: - - link: "llvm.aarch64.neon.ld1x{neon_type[1].tuple}.v{neon_type[1].lane}i{neon_type[1].base}.p0" - arch: aarch64,arm64ec - - link: "llvm.arm.neon.vld1x{neon_type[1].tuple}.v{neon_type[1].lane}i{neon_type[1].base}.p0" - arch: arm + - FnCall: + - 'crate::ptr::read_unaligned' + - - MethodCall: + - a + - cast + - [] - name: "vld1{neon_type[1].no}" doc: "Load multiple single-element structures to one, two, three, or four registers" @@ -2677,8 +2675,8 @@ intrinsics: return_type: "{neon_type[1]}" attr: - *neon-v7 - - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld1]]}]] - - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] + - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld]]}]] + - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld]]}]] - *neon-not-arm-stable - *neon-cfg-arm-unstable big_endian_inverse: false @@ -2723,12 +2721,11 @@ intrinsics: - ["*const p16", poly16x8x4_t, int16x8x4_t] compose: - FnCall: - - transmute - - - FnCall: - - "vld1{neon_type[2].no}" - - - FnCall: - - transmute - - - a + - 'crate::ptr::read_unaligned' + - - MethodCall: + - a + - cast + - [] - name: "vld1{neon_type[1].no}" doc: "Load multiple single-element structures to one, two, three, or four registers" @@ -2738,7 +2735,7 @@ intrinsics: - *neon-aes - *neon-v8 - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [nop]]}]] - - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] + - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld]]}]] - *neon-not-arm-stable - *neon-cfg-arm-unstable big_endian_inverse: false @@ -2752,12 +2749,11 @@ intrinsics: - ["*const p64", poly64x2x4_t, int64x2x4_t] compose: - FnCall: - - transmute - - - FnCall: - - "vld1{neon_type[2].no}" - - - FnCall: - - transmute - - - a + - 'crate::ptr::read_unaligned' + - - MethodCall: + - a + - cast + - [] - name: "vld1{neon_type[1].no}" doc: "Load multiple single-element structures to one, two, three, or four registers" @@ -2766,8 +2762,8 @@ intrinsics: attr: - *neon-aes - *neon-v8 - - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld1]]}]] - - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] + - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld]]}]] + - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld]]}]] - *neon-not-arm-stable - *neon-cfg-arm-unstable safety: @@ -2776,12 +2772,11 @@ intrinsics: - ["*const p64", poly64x1x2_t, int64x1x2_t] compose: - FnCall: - - transmute - - - FnCall: - - "vld1{neon_type[2].no}" - - - FnCall: - - transmute - - - a + - 'crate::ptr::read_unaligned' + - - MethodCall: + - a + - cast + - [] - name: "vld1{neon_type[1].no}" doc: "Load multiple single-element structures to one, two, three, or four registers" @@ -2790,7 +2785,7 @@ intrinsics: attr: - *neon-v7 - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vld1]]}]] - - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld1]]}]] + - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [ld]]}]] - *arm-fp16 - *neon-unstable-f16 - *target-not-arm64ec @@ -2804,13 +2799,12 @@ intrinsics: - ["*const f16", float16x4x4_t] - ["*const f16", float16x8x4_t] compose: - - LLVMLink: - name: "vld1x{neon_type[1].tuple}.{neon_type[1]}" - links: - - link: "llvm.aarch64.neon.ld1x{neon_type[1].tuple}.v{neon_type[1].lane}f{neon_type[1].base}.p0" - arch: aarch64,arm64ec - - link: "llvm.arm.neon.vld1x{neon_type[1].tuple}.v{neon_type[1].lane}f{neon_type[1].base}.p0" - arch: arm + - FnCall: + - 'crate::ptr::read_unaligned' + - - MethodCall: + - a + - cast + - [] - name: "vld1{type[2]}_{neon_type[1]}" doc: "Load one single-element structure to one lane of one register" From 54641efc6839b75405d19dbe20150985df0fbb8d Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 2 Feb 2026 17:01:10 +0100 Subject: [PATCH 411/978] add `vpmaddwd` tests back in --- .../stdarch/crates/core_arch/src/x86/avx2.rs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index 83aef753c9d9..04a88e461f75 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -4677,6 +4677,26 @@ mod tests { assert_eq_m256i(r, e); } + #[target_feature(enable = "avx2")] + #[cfg_attr(test, assert_instr(vpmaddwd))] + unsafe fn test_mm256_madd_epi16_mul_one(v: __m256i) -> __m256i { + // This is a trick used in the adler32 algorithm to get a widening addition. The + // multiplication by 1 is trivial, but must not be optimized out because then the vpmaddwd + // instruction is no longer selected. The assert_instr verifies that this is the case. + let one_v = _mm256_set1_epi16(1); + _mm256_madd_epi16(v, one_v) + } + + #[target_feature(enable = "avx2")] + #[cfg_attr(test, assert_instr(vpmaddwd))] + unsafe fn test_mm256_madd_epi16_shl(v: __m256i) -> __m256i { + // This is a trick used in the base64 algorithm to get a widening addition. Instead of a + // multiplication, a vector shl is used. In LLVM 22 that breaks the pattern recognition + // for the automatic optimization to vpmaddwd. + let shift_value = _mm256_set1_epi32(12i32); + _mm256_madd_epi16(v, shift_value) + } + #[simd_test(enable = "avx2")] const fn test_mm256_inserti128_si256() { let a = _mm256_setr_epi64x(1, 2, 3, 4); From 6490e0ecb5e78932f2e7f5bf5c11726f972eec8c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Feb 2026 13:57:40 +0100 Subject: [PATCH 412/978] stabilize ptr_as_ref_unchecked --- compiler/rustc_resolve/src/lib.rs | 2 +- library/core/src/ptr/const_ptr.rs | 8 +++--- library/core/src/ptr/docs/as_ref.md | 8 +++--- library/core/src/ptr/mut_ptr.rs | 26 +++++++++---------- .../data_race/mixed_size_read_write_read.rs | 1 - 5 files changed, 22 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 5fe1be039a88..cc3c7bc49446 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -8,6 +8,7 @@ // tidy-alphabetical-start #![allow(internal_features)] +#![cfg_attr(bootstrap, feature(ptr_as_ref_unchecked))] #![feature(arbitrary_self_types)] #![feature(assert_matches)] #![feature(box_patterns)] @@ -18,7 +19,6 @@ #![feature(default_field_values)] #![feature(if_let_guard)] #![feature(iter_intersperse)] -#![feature(ptr_as_ref_unchecked)] #![feature(rustc_attrs)] #![feature(trim_prefix_suffix)] #![recursion_limit = "256"] diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 2566d1471ab7..75777144dfb8 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -239,7 +239,7 @@ impl *const T { /// let ptr: *const u8 = &10u8 as *const u8; /// /// unsafe { - /// let val_back = &*ptr; + /// let val_back = ptr.as_ref_unchecked(); /// assert_eq!(val_back, &10); /// } /// ``` @@ -259,6 +259,7 @@ impl *const T { /// /// [`is_null`]: #method.is_null /// [`as_uninit_ref`]: #method.as_uninit_ref + /// [`as_ref_unchecked`]: #method.as_ref_unchecked #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] #[inline] @@ -283,15 +284,14 @@ impl *const T { /// # Examples /// /// ``` - /// #![feature(ptr_as_ref_unchecked)] /// let ptr: *const u8 = &10u8 as *const u8; /// /// unsafe { /// assert_eq!(ptr.as_ref_unchecked(), &10); /// } /// ``` - // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. - #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] #[inline] #[must_use] pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { diff --git a/library/core/src/ptr/docs/as_ref.md b/library/core/src/ptr/docs/as_ref.md index 0c0d2768c748..2c7d6e149b76 100644 --- a/library/core/src/ptr/docs/as_ref.md +++ b/library/core/src/ptr/docs/as_ref.md @@ -1,6 +1,7 @@ Returns `None` if the pointer is null, or else returns a shared reference to the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_ref`] -must be used instead. +must be used instead. If the value is known to be non-null, [`as_ref_unchecked`] +can be used instead. # Safety @@ -14,6 +15,5 @@ determined to be null or not. See [`is_null`] for more information. # Null-unchecked version -If you are sure the pointer can never be null and are looking for some kind of -`as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can -dereference the pointer directly. +If you are sure the pointer can never be null, you can use `as_ref_unchecked` which returns +`&mut T` instead of `Option<&mut T>`. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 20e71bc2a1a5..02e12d56fa65 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -230,7 +230,7 @@ impl *mut T { /// let ptr: *mut u8 = &mut 10u8 as *mut u8; /// /// unsafe { - /// let val_back = &*ptr; + /// let val_back = ptr.as_ref_unchecked(); /// println!("We got back the value: {val_back}!"); /// } /// ``` @@ -252,7 +252,8 @@ impl *mut T { /// For the mutable counterpart see [`as_mut`]. /// /// [`is_null`]: #method.is_null-1 - /// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1 + /// [`as_uninit_ref`]: #method.as_uninit_ref-1 + /// [`as_ref_unchecked`]: #method.as_ref_unchecked-1 /// [`as_mut`]: #method.as_mut #[stable(feature = "ptr_as_ref", since = "1.9.0")] @@ -281,15 +282,14 @@ impl *mut T { /// # Examples /// /// ``` - /// #![feature(ptr_as_ref_unchecked)] /// let ptr: *mut u8 = &mut 10u8 as *mut u8; /// /// unsafe { /// println!("We got back the value: {}!", ptr.as_ref_unchecked()); /// } /// ``` - // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. - #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] #[inline] #[must_use] pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { @@ -531,11 +531,13 @@ impl *mut T { /// Returns `None` if the pointer is null, or else returns a unique reference to /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_mut`] - /// must be used instead. + /// must be used instead. If the value is known to be non-null, [`as_mut_unchecked`] + /// can be used instead. /// /// For the shared counterpart see [`as_ref`]. /// /// [`as_uninit_mut`]: #method.as_uninit_mut + /// [`as_mut_unchecked`]: #method.as_mut_unchecked /// [`as_ref`]: pointer#method.as_ref-1 /// /// # Safety @@ -564,14 +566,13 @@ impl *mut T { /// /// # Null-unchecked version /// - /// If you are sure the pointer can never be null and are looking for some kind of - /// `as_mut_unchecked` that returns the `&mut T` instead of `Option<&mut T>`, know that - /// you can dereference the pointer directly. + /// If you are sure the pointer can never be null, you can use `as_mut_unchecked` which returns + /// `&mut T` instead of `Option<&mut T>`. /// /// ``` /// let mut s = [1, 2, 3]; /// let ptr: *mut u32 = s.as_mut_ptr(); - /// let first_value = unsafe { &mut *ptr }; + /// let first_value = unsafe { ptr.as_mut_unchecked() }; /// *first_value = 4; /// # assert_eq!(s, [4, 2, 3]); /// println!("{s:?}"); // It'll print: "[4, 2, 3]". @@ -603,7 +604,6 @@ impl *mut T { /// # Examples /// /// ``` - /// #![feature(ptr_as_ref_unchecked)] /// let mut s = [1, 2, 3]; /// let ptr: *mut u32 = s.as_mut_ptr(); /// let first_value = unsafe { ptr.as_mut_unchecked() }; @@ -611,8 +611,8 @@ impl *mut T { /// # assert_eq!(s, [4, 2, 3]); /// println!("{s:?}"); // It'll print: "[4, 2, 3]". /// ``` - // FIXME: mention it in the docs for `as_mut` and `as_uninit_mut` once stabilized. - #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] #[inline] #[must_use] pub const unsafe fn as_mut_unchecked<'a>(self) -> &'a mut T { diff --git a/src/tools/miri/tests/fail/data_race/mixed_size_read_write_read.rs b/src/tools/miri/tests/fail/data_race/mixed_size_read_write_read.rs index c84895799b69..2d3d36c0e64a 100644 --- a/src/tools/miri/tests/fail/data_race/mixed_size_read_write_read.rs +++ b/src/tools/miri/tests/fail/data_race/mixed_size_read_write_read.rs @@ -1,6 +1,5 @@ //@compile-flags: -Zmiri-deterministic-concurrency // A case that is not covered by `mixed_size_read_write`. -#![feature(ptr_as_ref_unchecked)] use std::sync::atomic::*; use std::thread; From 8fa27e03c0e3a080e3b030459fdb69c2ecf4bb4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 2 Feb 2026 21:12:44 +0200 Subject: [PATCH 413/978] Also exclude proc-macro-srv-cli from stage 0 tests --- src/bootstrap/src/core/build_steps/test.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 844251f2c64d..217fa344699e 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -513,6 +513,7 @@ impl Step for RustAnalyzer { // This builds a proc macro against the bootstrap libproc_macro, which is not ABI // compatible with the ABI proc-macro-srv expects to load. cargo.arg("--exclude=proc-macro-srv"); + cargo.arg("--exclude=proc-macro-srv-cli"); } let mut skip_tests = vec![]; From c7c3266b8a073ad51e6cc1bc65ff344ad33860a6 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Mon, 2 Feb 2026 20:48:14 +0100 Subject: [PATCH 414/978] error on unsized AnonConsts --- compiler/rustc_hir_typeck/src/lib.rs | 8 +++ tests/crashes/137582.rs | 16 ----- .../unsized-anon-const-err-1.rs | 22 +++++++ .../unsized-anon-const-err-1.stderr | 44 +++++++++++++ .../unsized-anon-const-err-2.rs | 21 ++++++ .../unsized-anon-const-err-2.stderr | 66 +++++++++++++++++++ .../unsized-anon-const-func-err.rs | 16 +++++ .../unsized-anon-const-func-err.stderr | 38 +++++++++++ .../unsized-anon-const-struct-err.rs | 16 +++++ .../unsized-anon-const-struct-err.stderr | 38 +++++++++++ 10 files changed, 269 insertions(+), 16 deletions(-) delete mode 100644 tests/crashes/137582.rs create mode 100644 tests/ui/const-generics/adt_const_params/unsized-anon-const-err-1.rs create mode 100644 tests/ui/const-generics/adt_const_params/unsized-anon-const-err-1.stderr create mode 100644 tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.rs create mode 100644 tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.stderr create mode 100644 tests/ui/const-generics/adt_const_params/unsized-anon-const-func-err.rs create mode 100644 tests/ui/const-generics/adt_const_params/unsized-anon-const-func-err.stderr create mode 100644 tests/ui/const-generics/adt_const_params/unsized-anon-const-struct-err.rs create mode 100644 tests/ui/const-generics/adt_const_params/unsized-anon-const-struct-err.stderr diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 39c28c4f4e99..6e126b3013c9 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -200,6 +200,14 @@ fn typeck_with_inspect<'tcx>( let wf_code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(def_id))); fcx.register_wf_obligation(expected_type.into(), body.value.span, wf_code); + if let hir::Node::AnonConst(_) = node { + fcx.require_type_is_sized( + expected_type, + body.value.span, + ObligationCauseCode::SizedConstOrStatic, + ); + } + fcx.check_expr_coercible_to_type(body.value, expected_type, None); fcx.write_ty(id, expected_type); diff --git a/tests/crashes/137582.rs b/tests/crashes/137582.rs deleted file mode 100644 index e21b6c9578b7..000000000000 --- a/tests/crashes/137582.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: #137582 -#![feature(adt_const_params)] - -mod lib { - pub type Matrix = [&'static u32]; - - const EMPTY_MATRIX: Matrix = [[0; 4]; 4]; - - pub struct Walk { - _p: (), - } - - impl Walk {} -} - -fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-1.rs b/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-1.rs new file mode 100644 index 000000000000..17910d52d3d7 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-1.rs @@ -0,0 +1,22 @@ +// regression test for issue #137582, where constant evaluating an unsized AnonConst would ICE + +#![feature(adt_const_params)] + +mod lib { + pub type Matrix = [&'static u32]; + + const EMPTY_MATRIX: Matrix = [[0; 4]; 4]; + //~^ ERROR the size for values of type `[&'static u32]` cannot be known at compilation time + //~| ERROR mismatched types + //~| ERROR mismatched types + + pub struct Walk { + //~^ ERROR use of unstable library feature `unsized_const_params` + _p: (), + } + + impl Walk {} + //~^ ERROR the size for values of type `[&'static u32]` cannot be known at compilation time +} + +fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-1.stderr b/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-1.stderr new file mode 100644 index 000000000000..daea55efbbc7 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-1.stderr @@ -0,0 +1,44 @@ +error[E0277]: the size for values of type `[&'static u32]` cannot be known at compilation time + --> $DIR/unsized-anon-const-err-1.rs:8:25 + | +LL | const EMPTY_MATRIX: Matrix = [[0; 4]; 4]; + | ^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[&'static u32]` + = note: statics and constants must have a statically known size + +error[E0658]: use of unstable library feature `unsized_const_params` + --> $DIR/unsized-anon-const-err-1.rs:13:43 + | +LL | pub struct Walk { + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unsized_const_params)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: required for `[&'static u32]` to implement `ConstParamTy_` + +error[E0277]: the size for values of type `[&'static u32]` cannot be known at compilation time + --> $DIR/unsized-anon-const-err-1.rs:18:46 + | +LL | impl Walk {} + | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[&'static u32]` + = note: statics and constants must have a statically known size + +error[E0308]: mismatched types + --> $DIR/unsized-anon-const-err-1.rs:8:35 + | +LL | const EMPTY_MATRIX: Matrix = [[0; 4]; 4]; + | ^^^^^^ expected `&u32`, found `[{integer}; 4]` + +error[E0308]: mismatched types + --> $DIR/unsized-anon-const-err-1.rs:8:34 + | +LL | const EMPTY_MATRIX: Matrix = [[0; 4]; 4]; + | ^^^^^^^^^^^ expected `[&u32]`, found `[&u32; 4]` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0277, E0308, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.rs b/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.rs new file mode 100644 index 000000000000..81b1ec6a7719 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.rs @@ -0,0 +1,21 @@ +// regression test for issue #151591, where constant evaluating an unsized AnonConst would ICE + +#![feature(adt_const_params)] +#![feature(unsized_const_params)] +//~^ WARN the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + +#[derive(Clone)] +struct S; + +const A: [u8]; +//~^ ERROR free constant item without body +//~| ERROR the size for values of type `[u8]` cannot be known at compilation time + +impl Copy for S {} +//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time +//~| ERROR the const parameter `N` is not constrained by the impl trait, self type, or predicates +impl Copy for S {} +//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time +//~| ERROR the const parameter `M` is not constrained by the impl trait, self type, or predicates + +fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.stderr b/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.stderr new file mode 100644 index 000000000000..d538bb0af09a --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/unsized-anon-const-err-2.stderr @@ -0,0 +1,66 @@ +error: free constant item without body + --> $DIR/unsized-anon-const-err-2.rs:10:1 + | +LL | const A: [u8]; + | ^^^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + +warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/unsized-anon-const-err-2.rs:4:12 + | +LL | #![feature(unsized_const_params)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #95174 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-anon-const-err-2.rs:10:10 + | +LL | const A: [u8]; + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: statics and constants must have a statically known size + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-anon-const-err-2.rs:14:31 + | +LL | impl Copy for S {} + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: statics and constants must have a statically known size + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/unsized-anon-const-err-2.rs:17:33 + | +LL | impl Copy for S {} + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: statics and constants must have a statically known size + +error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates + --> $DIR/unsized-anon-const-err-2.rs:14:6 + | +LL | impl Copy for S {} + | ^^^^^^^^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error[E0207]: the const parameter `M` is not constrained by the impl trait, self type, or predicates + --> $DIR/unsized-anon-const-err-2.rs:17:6 + | +LL | impl Copy for S {} + | ^^^^^^^^^^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error: aborting due to 6 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0207, E0277. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/const-generics/adt_const_params/unsized-anon-const-func-err.rs b/tests/ui/const-generics/adt_const_params/unsized-anon-const-func-err.rs new file mode 100644 index 000000000000..a299cc29fcc5 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/unsized-anon-const-func-err.rs @@ -0,0 +1,16 @@ +// manually reduced reproduction of issue #137582, where constant evaluating an unsized AnonConst +// would ICE + +#![feature(adt_const_params)] + +fn func() {} +//~^ ERROR use of unstable library feature `unsized_const_params` + +const VALUE: [u32] = [0; 4]; +//~^ ERROR mismatched types +//~| ERROR the size for values of type `[u32]` cannot be known at compilation time + +fn main() { + func::(); + //~^ ERROR the size for values of type `[u32]` cannot be known at compilation time +} diff --git a/tests/ui/const-generics/adt_const_params/unsized-anon-const-func-err.stderr b/tests/ui/const-generics/adt_const_params/unsized-anon-const-func-err.stderr new file mode 100644 index 000000000000..14a41e87e4aa --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/unsized-anon-const-func-err.stderr @@ -0,0 +1,38 @@ +error[E0658]: use of unstable library feature `unsized_const_params` + --> $DIR/unsized-anon-const-func-err.rs:6:9 + | +LL | fn func() {} + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(unsized_const_params)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: required for `[u32]` to implement `ConstParamTy_` + +error[E0277]: the size for values of type `[u32]` cannot be known at compilation time + --> $DIR/unsized-anon-const-func-err.rs:9:14 + | +LL | const VALUE: [u32] = [0; 4]; + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u32]` + = note: statics and constants must have a statically known size + +error[E0308]: mismatched types + --> $DIR/unsized-anon-const-func-err.rs:9:22 + | +LL | const VALUE: [u32] = [0; 4]; + | ^^^^^^ expected `[u32]`, found `[u32; 4]` + +error[E0277]: the size for values of type `[u32]` cannot be known at compilation time + --> $DIR/unsized-anon-const-func-err.rs:14:12 + | +LL | func::(); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u32]` + = note: statics and constants must have a statically known size + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/adt_const_params/unsized-anon-const-struct-err.rs b/tests/ui/const-generics/adt_const_params/unsized-anon-const-struct-err.rs new file mode 100644 index 000000000000..35407d02f6ef --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/unsized-anon-const-struct-err.rs @@ -0,0 +1,16 @@ +// manually reduced reproduction of issue #137582, where constant evaluating an unsized AnonConst +// would ICE + +#![feature(adt_const_params)] + +const VALUE: [u32] = [0; 4]; +//~^ ERROR the size for values of type `[u32]` cannot be known at compilation time +//~| ERROR mismatched types + +struct SomeStruct {} +//~^ ERROR use of unstable library feature `unsized_const_params` + +impl SomeStruct {} +//~^ ERROR the size for values of type `[u32]` cannot be known at compilation time + +fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/unsized-anon-const-struct-err.stderr b/tests/ui/const-generics/adt_const_params/unsized-anon-const-struct-err.stderr new file mode 100644 index 000000000000..d9a13976d68a --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/unsized-anon-const-struct-err.stderr @@ -0,0 +1,38 @@ +error[E0277]: the size for values of type `[u32]` cannot be known at compilation time + --> $DIR/unsized-anon-const-struct-err.rs:6:14 + | +LL | const VALUE: [u32] = [0; 4]; + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u32]` + = note: statics and constants must have a statically known size + +error[E0658]: use of unstable library feature `unsized_const_params` + --> $DIR/unsized-anon-const-struct-err.rs:10:19 + | +LL | struct SomeStruct {} + | ^^^^^^^^^^^^^^ + | + = help: add `#![feature(unsized_const_params)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: required for `[u32]` to implement `ConstParamTy_` + +error[E0277]: the size for values of type `[u32]` cannot be known at compilation time + --> $DIR/unsized-anon-const-struct-err.rs:13:17 + | +LL | impl SomeStruct {} + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u32]` + = note: statics and constants must have a statically known size + +error[E0308]: mismatched types + --> $DIR/unsized-anon-const-struct-err.rs:6:22 + | +LL | const VALUE: [u32] = [0; 4]; + | ^^^^^^ expected `[u32]`, found `[u32; 4]` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308, E0658. +For more information about an error, try `rustc --explain E0277`. From 06fe81964e924a2cd0f94fbe3859615a5cf66329 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 2 Feb 2026 22:26:46 +0200 Subject: [PATCH 415/978] use sentence case for titles This makes things consistent --- src/doc/rustc-dev-guide/src/external-repos.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/external-repos.md b/src/doc/rustc-dev-guide/src/external-repos.md index 2e32fcfe78c1..7ae1c881be8f 100644 --- a/src/doc/rustc-dev-guide/src/external-repos.md +++ b/src/doc/rustc-dev-guide/src/external-repos.md @@ -1,4 +1,4 @@ -# Using External Repositories +# Using external repositories The `rust-lang/rust` git repository depends on several other repos in the `rust-lang` organization. There are three main ways we use dependencies: @@ -12,7 +12,7 @@ As a general rule: changes - Use submodules for tools that are independent of the compiler -## External Dependencies (subtrees) +## External dependencies (subtrees) The following external projects are managed using some form of a `subtree`: @@ -153,7 +153,7 @@ Now you're done, the `src/tools/clippy` directory behaves as if Clippy were part of the rustc monorepo, so no one but you (or others that synchronize subtrees) actually needs to use `git subtree`. -## External Dependencies (submodules) +## External dependencies (submodules) Building Rust will also use external git repositories tracked using [git submodules]. The complete list may be found in the [`.gitmodules`] file. From 6b1d4059cbd650617c298079b6c488cb6b68086f Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Mon, 2 Feb 2026 21:14:30 +0000 Subject: [PATCH 416/978] Port rustc_preserve_ub_checks to attr parser. --- .../rustc_attr_parsing/src/attributes/crate_level.rs | 9 +++++++++ compiler/rustc_attr_parsing/src/context.rs | 4 +++- compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ compiler/rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_mir_transform/src/instsimplify.rs | 6 +++--- compiler/rustc_passes/src/check_attr.rs | 4 ++-- 6 files changed, 21 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index a367e699fcb9..557dfe09853b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -274,3 +274,12 @@ impl NoArgsAttributeParser for NoBuiltinsParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoBuiltins; } + +pub(crate) struct RustcPreserveUbChecksParser; + +impl NoArgsAttributeParser for RustcPreserveUbChecksParser { + const PATH: &[Symbol] = &[sym::rustc_preserve_ub_checks]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 0cabc0895053..736eb704b737 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -31,7 +31,8 @@ use crate::attributes::crate_level::{ CrateNameParser, CrateTypeParser, MoveSizeLimitParser, NeedsPanicRuntimeParser, NoBuiltinsParser, NoCoreParser, NoMainParser, NoStdParser, PanicRuntimeParser, PatternComplexityLimitParser, ProfilerRuntimeParser, RecursionLimitParser, - RustcCoherenceIsCoreParser, TypeLengthLimitParser, WindowsSubsystemParser, + RustcCoherenceIsCoreParser, RustcPreserveUbChecksParser, TypeLengthLimitParser, + WindowsSubsystemParser, }; use crate::attributes::debugger::DebuggerViualizerParser; use crate::attributes::deprecation::DeprecationParser; @@ -309,6 +310,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 92dda79b0920..13e36a0ed8e6 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1123,6 +1123,9 @@ pub enum AttributeKind { /// Represents `#[rustc_pass_indirectly_in_non_rustic_abis]` RustcPassIndirectlyInNonRusticAbis(Span), + /// Represents `#[rustc_preserve_ub_checks]` + RustcPreserveUbChecks, + /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint). RustcPubTransparent(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 816ed07c1dc4..4ffabf82dceb 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -133,6 +133,7 @@ impl AttributeKind { RustcParenSugar(..) => No, RustcPassByValue(..) => Yes, RustcPassIndirectlyInNonRusticAbis(..) => No, + RustcPreserveUbChecks => No, RustcPubTransparent(..) => Yes, RustcReallocator => No, RustcScalableVector { .. } => Yes, diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index fa9ceb018dd5..84d642ea4ebc 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -1,8 +1,8 @@ //! Performs various peephole optimizations. use rustc_abi::ExternAbi; -use rustc_ast::attr; -use rustc_hir::LangItem; +use rustc_hir::attrs::AttributeKind; +use rustc_hir::{LangItem, find_attr}; use rustc_middle::bug; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; @@ -31,7 +31,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let preserve_ub_checks = - attr::contains_name(tcx.hir_krate_attrs(), sym::rustc_preserve_ub_checks); + find_attr!(tcx.hir_krate_attrs(), AttributeKind::RustcPreserveUbChecks); if !preserve_ub_checks { SimplifyUbCheck { tcx }.visit_body(body); } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 8cf68b280850..f93d420fb06d 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -318,6 +318,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcParenSugar(..) | AttributeKind::RustcPassByValue (..) | AttributeKind::RustcPassIndirectlyInNonRusticAbis(..) + | AttributeKind::RustcPreserveUbChecks | AttributeKind::RustcReallocator | AttributeKind::RustcScalableVector { .. } | AttributeKind::RustcShouldNotBeCalledOnConstItems(..) @@ -406,8 +407,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::register_tool | sym::rustc_no_implicit_bounds | sym::test_runner - | sym::reexport_test_harness_main - | sym::rustc_preserve_ub_checks, + | sym::reexport_test_harness_main, .. ] => {} [name, rest@..] => { From adb3861f98f5991703160e7d8a5e67de3bcef903 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 2 Feb 2026 23:18:00 +0200 Subject: [PATCH 417/978] sembr src/profiling/wpa-profiling.md --- .../src/profiling/wpa-profiling.md | 57 +++++++++++-------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md b/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md index 2267f9b490f7..eb829242e02f 100644 --- a/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md @@ -3,13 +3,13 @@ ## Introducing WPR and WPA High-level performance analysis (including memory usage) can be performed with the Windows -Performance Recorder (WPR) and Windows Performance Analyzer (WPA). As the names suggest, WPR is for -recording system statistics (in the form of event trace log a.k.a. ETL files), while WPA is for -analyzing these ETL files. +Performance Recorder (WPR) and Windows Performance Analyzer (WPA). +As the names suggest, WPR is for recording system statistics (in the form of event trace log a.k.a. +ETL files), while WPA is for analyzing these ETL files. WPR collects system wide statistics, so it won't just record things relevant to rustc but also -everything else that's running on the machine. During analysis, we can filter to just the things we -find interesting. +everything else that's running on the machine. +During analysis, we can filter to just the things we find interesting. These tools are quite powerful but also require a bit of learning before we can successfully profile the Rust compiler. @@ -21,36 +21,42 @@ specifically designed to make analyzing rustc easier. ### Installing WPR and WPA You can install WPR and WPA as part of the Windows Performance Toolkit which itself is an option as -part of downloading the Windows Assessment and Deployment Kit (ADK). You can download the ADK -installer [here](https://learn.microsoft.com/en-us/windows-hardware/get-started/adk-install). Make -sure to select the Windows Performance Toolkit (you don't need to select anything else). +part of downloading the Windows Assessment and Deployment Kit (ADK). +You can download the ADK +installer [here](https://learn.microsoft.com/en-us/windows-hardware/get-started/adk-install). +Make sure to select the Windows Performance Toolkit (you don't need to select anything else). ## Recording -In order to perform system analysis, you'll first need to record your system with WPR. Open WPR and -at the bottom of the window select the "profiles" of the things you want to record. For looking +In order to perform system analysis, you'll first need to record your system with WPR. +Open WPR and at the bottom of the window select the "profiles" of the things you want to record. +For looking into memory usage of the rustc bootstrap process, we'll want to select the following items: * CPU usage * VirtualAlloc usage You might be tempted to record "Heap usage" as well, but this records every single heap allocation -and can be very, very expensive. For high-level analysis, it might be best to leave that turned -off. +and can be very, very expensive. +For high-level analysis, it might be best to leave that turned off. -Now we need to get our setup ready to record. For memory usage analysis, it is best to record the -stage 2 compiler build with a stage 1 compiler build with debug symbols. Having symbols in the +Now we need to get our setup ready to record. +For memory usage analysis, it is best to record the +stage 2 compiler build with a stage 1 compiler build with debug symbols. +Having symbols in the compiler we're using to build rustc will aid our analysis greatly by allowing WPA to resolve Rust -symbols correctly. Unfortunately, the stage 0 compiler does not have symbols turned on which is why +symbols correctly. +Unfortunately, the stage 0 compiler does not have symbols turned on which is why we'll need to build a stage 1 compiler and then a stage 2 compiler ourselves. -To do this, make sure you have set `debuginfo-level = 1` in your `bootstrap.toml` file. This tells -rustc to generate debug information which includes stack frames when bootstrapping. +To do this, make sure you have set `debuginfo-level = 1` in your `bootstrap.toml` file. +This tells rustc to generate debug information which includes stack frames when bootstrapping. Now you can build the stage 1 compiler: `x build --stage 1 -i library` or however else you want to build the stage 1 compiler. -Now that the stage 1 compiler is built, we can record the stage 2 build. Go back to WPR, click the +Now that the stage 1 compiler is built, we can record the stage 2 build. +Go back to WPR, click the "start" button and build the stage 2 compiler (e.g., `x build --stage=2 -i library`). When this process finishes, stop the recording. @@ -61,8 +67,10 @@ appears. ## Analysis -Now that our ETL file is open in WPA, we can analyze the results. First, we'll want to apply the -pre-made "profile" which will put WPA into a state conducive to analyzing rustc bootstrap. Download +Now that our ETL file is open in WPA, we can analyze the results. +First, we'll want to apply the +pre-made "profile" which will put WPA into a state conducive to analyzing rustc bootstrap. +Download the profile [here](https://github.com/wesleywiser/rustc-bootstrap-wpa-analysis/releases/download/1/rustc.generic.wpaProfile). Select the "Profiles" menu at the top, then "apply" and then choose the downloaded profile. @@ -71,8 +79,9 @@ You should see something resembling the following: ![WPA with profile applied](../img/wpa-initial-memory.png) Next, we will need to tell WPA to load and process debug symbols so that it can properly demangle -the Rust stack traces. To do this, click "Trace" and then choose "Load Symbols". This step can take -a while. +the Rust stack traces. +To do this, click "Trace" and then choose "Load Symbols". +This step can take a while. Once WPA has loaded symbols for rustc, we can expand the rustc.exe node and begin drilling down into the stack with the largest allocations. @@ -81,8 +90,8 @@ To do that, we'll expand the `[Root]` node in the "Commit Stack" column and cont until we find interesting stack frames. > Tip: After selecting the node you want to expand, press the right arrow key. This will expand the -node and put the selection on the next largest node in the expanded set. You can continue pressing -the right arrow key until you reach an interesting frame. +node and put the selection on the next largest node in the expanded set. +You can continue pressing the right arrow key until you reach an interesting frame. ![WPA with expanded stack](../img/wpa-stack.png) From f59931384687c4a9bf14fca54f5af4f0e5083150 Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Mon, 2 Feb 2026 21:19:50 +0000 Subject: [PATCH 418/978] Make parser naming consistent for dump parsers. --- .../src/attributes/rustc_dump.rs | 20 +++++++++---------- compiler/rustc_attr_parsing/src/context.rs | 14 ++++++------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs index 53120dece916..71a8fb0dd47d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs @@ -7,36 +7,36 @@ use crate::attributes::{NoArgsAttributeParser, OnDuplicate}; use crate::context::Stage; use crate::target_checking::AllowedTargets; -pub(crate) struct RustcDumpUserArgs; +pub(crate) struct RustcDumpUserArgsParser; -impl NoArgsAttributeParser for RustcDumpUserArgs { +impl NoArgsAttributeParser for RustcDumpUserArgsParser { const PATH: &[Symbol] = &[sym::rustc_dump_user_args]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpUserArgs; } -pub(crate) struct RustcDumpDefParents; +pub(crate) struct RustcDumpDefParentsParser; -impl NoArgsAttributeParser for RustcDumpDefParents { +impl NoArgsAttributeParser for RustcDumpDefParentsParser { const PATH: &[Symbol] = &[sym::rustc_dump_def_parents]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpDefParents; } -pub(crate) struct RustcDumpItemBounds; +pub(crate) struct RustcDumpItemBoundsParser; -impl NoArgsAttributeParser for RustcDumpItemBounds { +impl NoArgsAttributeParser for RustcDumpItemBoundsParser { const PATH: &[Symbol] = &[sym::rustc_dump_item_bounds]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::AssocTy)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpItemBounds; } -pub(crate) struct RustcDumpPredicates; +pub(crate) struct RustcDumpPredicatesParser; -impl NoArgsAttributeParser for RustcDumpPredicates { +impl NoArgsAttributeParser for RustcDumpPredicatesParser { const PATH: &[Symbol] = &[sym::rustc_dump_predicates]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ @@ -49,9 +49,9 @@ impl NoArgsAttributeParser for RustcDumpPredicates { const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpPredicates; } -pub(crate) struct RustcDumpVtable; +pub(crate) struct RustcDumpVtableParser; -impl NoArgsAttributeParser for RustcDumpVtable { +impl NoArgsAttributeParser for RustcDumpVtableParser { const PATH: &[Symbol] = &[sym::rustc_dump_vtable]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 736eb704b737..451638725c52 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -72,8 +72,8 @@ use crate::attributes::rustc_allocator::{ RustcDeallocatorParser, RustcReallocatorParser, }; use crate::attributes::rustc_dump::{ - RustcDumpDefParents, RustcDumpItemBounds, RustcDumpPredicates, RustcDumpUserArgs, - RustcDumpVtable, + RustcDumpDefParentsParser, RustcDumpItemBoundsParser, RustcDumpPredicatesParser, + RustcDumpUserArgsParser, RustcDumpVtableParser, }; use crate::attributes::rustc_internal::{ RustcHasIncoherentInherentImplsParser, RustcLayoutParser, RustcLayoutScalarValidRangeEndParser, @@ -294,11 +294,11 @@ attribute_parsers!( Single>, Single>, Single>, - Single>, - Single>, - Single>, - Single>, - Single>, + Single>, + Single>, + Single>, + Single>, + Single>, Single>, Single>, Single>, From 957f28c9b8c8fc1513c61657be836ceafc2eafe7 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 2 Feb 2026 23:25:33 +0200 Subject: [PATCH 419/978] add some pauses --- src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md b/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md index eb829242e02f..6d885d303629 100644 --- a/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md @@ -46,8 +46,9 @@ stage 2 compiler build with a stage 1 compiler build with debug symbols. Having symbols in the compiler we're using to build rustc will aid our analysis greatly by allowing WPA to resolve Rust symbols correctly. -Unfortunately, the stage 0 compiler does not have symbols turned on which is why -we'll need to build a stage 1 compiler and then a stage 2 compiler ourselves. +Unfortunately, the stage 0 compiler does not have symbols turned on, +which is why we'll need to build a stage 1 compiler, +and then a stage 2 compiler ourselves. To do this, make sure you have set `debuginfo-level = 1` in your `bootstrap.toml` file. This tells rustc to generate debug information which includes stack frames when bootstrapping. From f285d5d0601d0e08db06b6beda18925337829ada Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 2 Feb 2026 23:27:22 +0200 Subject: [PATCH 420/978] provide the full path --- src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md b/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md index 6d885d303629..a0a5bee63e9e 100644 --- a/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md @@ -50,7 +50,7 @@ Unfortunately, the stage 0 compiler does not have symbols turned on, which is why we'll need to build a stage 1 compiler, and then a stage 2 compiler ourselves. -To do this, make sure you have set `debuginfo-level = 1` in your `bootstrap.toml` file. +To do this, make sure you have set `rust.debuginfo-level = 1` in your `bootstrap.toml` file. This tells rustc to generate debug information which includes stack frames when bootstrapping. Now you can build the stage 1 compiler: `x build --stage 1 -i library` or however From 6169f2e4849f35165793ab3f810b1f9fdea6a33e Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 2 Feb 2026 23:27:41 +0200 Subject: [PATCH 421/978] sembr src/effects.md --- src/doc/rustc-dev-guide/src/effects.md | 78 +++++++++++++------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/effects.md b/src/doc/rustc-dev-guide/src/effects.md index 732ba7153116..a78428cf09eb 100644 --- a/src/doc/rustc-dev-guide/src/effects.md +++ b/src/doc/rustc-dev-guide/src/effects.md @@ -2,16 +2,17 @@ ## The `HostEffect` predicate -[`HostEffectPredicate`]s are a kind of predicate from `~const Tr` or `const Tr` -bounds. It has a trait reference, and a `constness` which could be `Maybe` or -`Const` depending on the bound. Because `~const Tr`, or rather `Maybe` bounds +[`HostEffectPredicate`]s are a kind of predicate from `~const Tr` or `const Tr` bounds. +It has a trait reference, and a `constness` which could be `Maybe` or +`Const` depending on the bound. +Because `~const Tr`, or rather `Maybe` bounds apply differently based on whichever contexts they are in, they have different -behavior than normal bounds. Where normal trait bounds on a function such as +behavior than normal bounds. +Where normal trait bounds on a function such as `T: Tr` are collected within the [`predicates_of`] query to be proven when a function is called and to be assumed within the function, bounds such as `T: ~const Tr` will behave as a normal trait bound and add `T: Tr` to the result -from `predicates_of`, but also adds a `HostEffectPredicate` to the -[`const_conditions`] query. +from `predicates_of`, but also adds a `HostEffectPredicate` to the [`const_conditions`] query. On the other hand, `T: const Tr` bounds do not change meaning across contexts, therefore they will result in `HostEffect(T: Tr, const)` being added to @@ -23,17 +24,17 @@ therefore they will result in `HostEffect(T: Tr, const)` being added to ## The `const_conditions` query -`predicates_of` represents a set of predicates that need to be proven to use an -item. For example, to use `foo` in the example below: +`predicates_of` represents a set of predicates that need to be proven to use an item. +For example, to use `foo` in the example below: ```rust fn foo() where T: Default {} ``` -We must be able to prove that `T` implements `Default`. In a similar vein, +We must be able to prove that `T` implements `Default`. +In a similar vein, `const_conditions` represents a set of predicates that need to be proven to use -an item *in const contexts*. If we adjust the example above to use `const` trait -bounds: +an item *in const contexts*. If we adjust the example above to use `const` trait bounds: ```rust const fn foo() where T: ~const Default {} @@ -45,13 +46,13 @@ prove that `T` has a const implementation of `Default`. ## Enforcement of `const_conditions` -`const_conditions` are currently checked in various places. +`const_conditions` are currently checked in various places. Every call in HIR from a const context (which includes `const fn` and `const` items) will check that `const_conditions` of the function we are calling hold. -This is done in [`FnCtxt::enforce_context_effects`]. Note that we don't check -if the function is only referred to but not called, as the following code needs -to compile: +This is done in [`FnCtxt::enforce_context_effects`]. +Note that we don't check +if the function is only referred to but not called, as the following code needs to compile: ```rust const fn hi() -> T { @@ -61,8 +62,8 @@ const X: fn() -> u32 = hi::; ``` For a trait `impl` to be well-formed, we must be able to prove the -`const_conditions` of the trait from the `impl`'s environment. This is checked -in [`wfcheck::check_impl`]. +`const_conditions` of the trait from the `impl`'s environment. +This is checked in [`wfcheck::check_impl`]. Here's an example: @@ -77,10 +78,11 @@ impl const Foo for () {} ``` Methods of trait impls must not have stricter bounds than the method of the -trait that they are implementing. To check that the methods are compatible, a +trait that they are implementing. +To check that the methods are compatible, a hybrid environment is constructed with the predicates of the `impl` plus the -predicates of the trait method, and we attempt to prove the predicates of the -impl method. We do the same for `const_conditions`: +predicates of the trait method, and we attempt to prove the predicates of the impl method. +We do the same for `const_conditions`: ```rust const trait Foo { @@ -95,10 +97,10 @@ impl Foo for Vec { } ``` -These checks are done in [`compare_method_predicate_entailment`]. A similar -function that does the same check for associated types is called -[`compare_type_predicate_entailment`]. Both of these need to consider -`const_conditions` when in const contexts. +These checks are done in [`compare_method_predicate_entailment`]. +A similar function that does the same check for associated types is called +[`compare_type_predicate_entailment`]. +Both of these need to consider `const_conditions` when in const contexts. In MIR, as part of const checking, `const_conditions` of items that are called are revalidated again in [`Checker::revalidate_conditional_constness`]. @@ -122,11 +124,12 @@ fn foo() -> impl ~const PartialEq { } ``` -Have their bounds represented differently. Unlike `const_conditions` which need +Have their bounds represented differently. +Unlike `const_conditions` which need to be proved for callers, and can be assumed inside the definition (e.g. trait bounds on functions), these bounds need to be proved at definition (at the impl, -or when returning the opaque) but can be assumed for callers. The non-const -equivalent of these bounds are called [`explicit_item_bounds`]. +or when returning the opaque) but can be assumed for callers. +The non-const equivalent of these bounds are called [`explicit_item_bounds`]. These bounds are checked in [`compare_impl_item::check_type_bounds`] for HIR typeck, [`evaluate_host_effect_from_item_bounds`] in the old solver and @@ -139,16 +142,14 @@ typeck, [`evaluate_host_effect_from_item_bounds`] in the old solver and ## Proving `HostEffectPredicate`s -`HostEffectPredicate`s are implemented both in the [old solver] and the [new -trait solver]. In general, we can prove a `HostEffect` predicate when either of -these conditions are met: +`HostEffectPredicate`s are implemented both in the [old solver] and the [new trait solver]. +In general, we can prove a `HostEffect` predicate when either of these conditions are met: * The predicate can be assumed from caller bounds; * The type has a `const` `impl` for the trait, *and* that const conditions on -the impl holds, *and* that the `explicit_implied_const_bounds` on the trait -holds; or -* The type has a built-in implementation for the trait in const contexts. For -example, `Fn` may be implemented by function items if their const conditions +the impl holds, *and* that the `explicit_implied_const_bounds` on the trait holds; or +* The type has a built-in implementation for the trait in const contexts. + For example, `Fn` may be implemented by function items if their const conditions are satisfied, or `Destruct` is implemented in const contexts if the type can be dropped at compile time. @@ -161,10 +162,11 @@ To be expanded later. ### The `#[rustc_non_const_trait_method]` attribute -This is intended for internal (standard library) usage only. With this attribute -applied to a trait method, the compiler will not check the default body of this -method for ability to run in compile time. Users of the trait will also not be -allowed to use this trait method in const contexts. This attribute is primarily +This is intended for internal (standard library) usage only. +With this attribute applied to a trait method, the compiler will not check the default body of this +method for ability to run in compile time. +Users of the trait will also not be allowed to use this trait method in const contexts. +This attribute is primarily used for constifying large traits such as `Iterator` without having to make all its methods `const` at the same time. From 5143080050451dc45f30668b788078bdba2f8fdc Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 2 Feb 2026 23:38:03 +0200 Subject: [PATCH 422/978] some improvements --- src/doc/rustc-dev-guide/src/effects.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/effects.md b/src/doc/rustc-dev-guide/src/effects.md index a78428cf09eb..26530a30d066 100644 --- a/src/doc/rustc-dev-guide/src/effects.md +++ b/src/doc/rustc-dev-guide/src/effects.md @@ -113,7 +113,9 @@ are revalidated again in [`Checker::revalidate_conditional_constness`]. ## `explicit_implied_const_bounds` on associated types and traits -Bounds on associated types, opaque types, and supertraits such as +Bounds on associated types, opaque types, and supertraits such as the following +have their bounds represented differently: + ```rust trait Foo: ~const PartialEq { type X: ~const PartialEq; @@ -124,9 +126,8 @@ fn foo() -> impl ~const PartialEq { } ``` -Have their bounds represented differently. -Unlike `const_conditions` which need -to be proved for callers, and can be assumed inside the definition (e.g. trait +Unlike `const_conditions`, which need to be proved for callers, +and can be assumed inside the definition (e.g. trait bounds on functions), these bounds need to be proved at definition (at the impl, or when returning the opaque) but can be assumed for callers. The non-const equivalent of these bounds are called [`explicit_item_bounds`]. @@ -147,11 +148,11 @@ In general, we can prove a `HostEffect` predicate when either of these condition * The predicate can be assumed from caller bounds; * The type has a `const` `impl` for the trait, *and* that const conditions on -the impl holds, *and* that the `explicit_implied_const_bounds` on the trait holds; or + the impl holds, *and* that the `explicit_implied_const_bounds` on the trait holds; or * The type has a built-in implementation for the trait in const contexts. For example, `Fn` may be implemented by function items if their const conditions -are satisfied, or `Destruct` is implemented in const contexts if the type can -be dropped at compile time. + are satisfied, or `Destruct` is implemented in const contexts if the type can + be dropped at compile time. [old solver]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_trait_selection/traits/effects.rs.html [new trait solver]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_next_trait_solver/solve/effect_goals.rs.html From a802e7c161a351fea0a35eca5c145361c9974234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 2 Feb 2026 22:50:29 +0100 Subject: [PATCH 423/978] Remove `with_no_trimmed_paths` use in query macro --- compiler/rustc_macros/src/query.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 0cac699e5b62..0e2b16d72eb1 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -303,9 +303,7 @@ fn add_query_desc_cached_impl( #[allow(unused_variables)] pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::query::queries::#name::Key<'tcx>) -> String { let (#tcx, #key) = (tcx, key); - ::rustc_middle::ty::print::with_no_trimmed_paths!( - format!(#desc) - ) + format!(#desc) } }; From 06d17c0d3bd16286090f1db445e757875c7821c5 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:10:22 +0200 Subject: [PATCH 424/978] use convenient notation, as seen in bootstrap.example.toml --- .../rustc-dev-guide/src/backend/debugging.md | 7 +++---- .../src/backend/updating-llvm.md | 3 +-- .../src/building/compiler-documenting.md | 3 +-- .../src/building/how-to-build-and-run.md | 13 ++++++------ .../src/building/new-target.md | 12 +++-------- .../src/building/optimized-build.md | 21 +++++++------------ .../rustc-dev-guide/src/building/suggested.md | 2 +- .../rustc-dev-guide/src/compiler-debugging.md | 14 ++++++------- .../src/llvm-coverage-instrumentation.md | 6 ++---- src/doc/rustc-dev-guide/src/profiling.md | 11 +++++----- src/doc/rustc-dev-guide/src/sanitizers.md | 5 ++--- .../rustc-dev-guide/src/tests/compiletest.md | 4 +--- .../rustc-dev-guide/src/tests/directives.md | 2 +- src/doc/rustc-dev-guide/src/tests/docker.md | 2 +- src/doc/rustc-dev-guide/src/tracing.md | 2 +- 15 files changed, 42 insertions(+), 65 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/backend/debugging.md b/src/doc/rustc-dev-guide/src/backend/debugging.md index 84efa72f4c46..319154f023cf 100644 --- a/src/doc/rustc-dev-guide/src/backend/debugging.md +++ b/src/doc/rustc-dev-guide/src/backend/debugging.md @@ -38,7 +38,7 @@ which means that LLVM assertion failures can show up as compiler crashes (not ICEs but "real" crashes) and other sorts of weird behavior. If you are encountering these, it is a good idea to try using a compiler with LLVM assertions enabled - either an "alt" nightly or a compiler you build yourself -by setting `[llvm] assertions=true` in your bootstrap.toml - and see whether +by setting `llvm.assertions = true` in your bootstrap.toml - and see whether anything turns up. The rustc build process builds the LLVM tools into @@ -162,12 +162,11 @@ aware of its [internal debug infrastructure][llvm-debug]. This is provided in LLVM Debug builds, which you enable for rustc LLVM builds by changing this setting in the bootstrap.toml: ``` -[llvm] # Indicates whether the LLVM assertions are enabled or not -assertions = true +llvm.assertions = true # Indicates whether the LLVM build is a Release or Debug build -optimize = false +llvm.optimize = false ``` The quick summary is: * Setting `assertions=true` enables coarse-grain debug messaging. diff --git a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md index 70deeebf8bec..5962791f64b1 100644 --- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md +++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md @@ -145,8 +145,7 @@ so let's go through each in detail. This is done by having the following setting in `bootstrap.toml`: ```toml - [llvm] - download-ci-llvm = false + llvm.download-ci-llvm = false ``` 1. Test for regressions across other platforms. LLVM often has at least one bug diff --git a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md index b031462ea15f..026a42907493 100644 --- a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md +++ b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md @@ -39,8 +39,7 @@ like the standard library (std) or the compiler (rustc). To create it by default with `x doc`, modify `bootstrap.toml`: ```toml - [build] - compiler-docs = true + build.compiler-docs = true ``` Note that when enabled, diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index d0a38b12c550..3e44a75ad732 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -10,7 +10,7 @@ case, `./x {check,build} library/std` should still work. In the short-term, you may need to disable `download-rustc` for `./x test library/std`. This can be done either by: 1. `./x test library/std --set rust.download-rustc=false` -2. Or set `rust.download-rustc=false` in `bootstrap.toml`. +2. Or set `rust.download-rustc = false` in `bootstrap.toml`. Unfortunately that will require building the stage 1 compiler. The bootstrap team is working on this, but implementing a maintainable fix is taking some time. @@ -278,9 +278,9 @@ Once you have successfully built `rustc`, you will have created a bunch of files in your `build` directory. In order to actually run the resulting `rustc`, we recommend creating rustup toolchains. The first command listed below creates the stage1 toolchain, which was built in the -steps above, with the name `stage1`. The second command creates the stage2 -toolchain using the stage1 compiler. This will be needed in the future -if running the entire test suite, but will not be built in this page. +steps above, with the name `stage1`. The second command creates the stage2 +toolchain using the stage1 compiler. This will be needed in the future +if running the entire test suite, but will not be built in this page. Building stage2 is done with the same `./x build` command as for stage1, specifying that the stage is 2 instead. @@ -289,7 +289,7 @@ rustup toolchain link stage1 build/host/stage1 rustup toolchain link stage2 build/host/stage2 ``` -Now you can run the `rustc` you built with via the toolchain. If you run with +Now you can run the `rustc` you built with via the toolchain. If you run with `-vV`, you should see a version number ending in `-dev`, indicating a build from your local environment: @@ -342,8 +342,7 @@ If you want to always build for other targets without needing to pass flags to ` you can configure this in the `[build]` section of your `bootstrap.toml` like so: ```toml -[build] -target = ["x86_64-unknown-linux-gnu", "wasm32-wasip1"] +build.target = ["x86_64-unknown-linux-gnu", "wasm32-wasip1"] ``` Note that building for some targets requires having external dependencies installed diff --git a/src/doc/rustc-dev-guide/src/building/new-target.md b/src/doc/rustc-dev-guide/src/building/new-target.md index d0ed787f520a..1be83e4a5a58 100644 --- a/src/doc/rustc-dev-guide/src/building/new-target.md +++ b/src/doc/rustc-dev-guide/src/building/new-target.md @@ -52,7 +52,7 @@ own preinstalled LLVM, you will need to provide `FileCheck` in some other way. On Debian-based systems, you can install the `llvm-N-tools` package (where `N` is the LLVM version number, e.g. `llvm-8-tools`). Alternately, you can specify the path to `FileCheck` with the `llvm-filecheck` config item in `bootstrap.toml` -or you can disable codegen test with the `codegen-tests` item in `bootstrap.toml`. +or you can disable codegen test with the `rust.codegen-tests` item in `bootstrap.toml`. ## Creating a target specification @@ -118,16 +118,10 @@ After this, run `cargo update -p libc` to update the lockfiles. Beware that if you patch to a local `path` dependency, this will enable warnings for that dependency. Some dependencies are not warning-free, and due -to the `deny-warnings` setting in `bootstrap.toml`, the build may suddenly start to fail. +to the `rust.deny-warnings` setting in `bootstrap.toml`, the build may suddenly start to fail. To work around warnings, you may want to: - Modify the dependency to remove the warnings -- Or for local development purposes, suppress the warnings by setting deny-warnings = false in bootstrap.toml. - -```toml -# bootstrap.toml -[rust] -deny-warnings = false -``` +- Or for local development purposes, suppress the warnings by setting `rust.deny-warnings = false` in bootstrap.toml. [`libc`]: https://crates.io/crates/libc [`cc`]: https://crates.io/crates/cc diff --git a/src/doc/rustc-dev-guide/src/building/optimized-build.md b/src/doc/rustc-dev-guide/src/building/optimized-build.md index 46def66d1782..d11bfaa4ba00 100644 --- a/src/doc/rustc-dev-guide/src/building/optimized-build.md +++ b/src/doc/rustc-dev-guide/src/building/optimized-build.md @@ -14,8 +14,7 @@ enable (Thin-)LTO when building `rustc`, set the `rust.lto` config option to `"t in `bootstrap.toml`: ```toml -[rust] -lto = "thin" +rust.lto = "thin" ``` > Note that LTO for `rustc` is currently supported and tested only for @@ -35,8 +34,7 @@ want to enable the `jemalloc` allocator, you can set the `rust.jemalloc` option in `bootstrap.toml`: ```toml -[rust] -jemalloc = true +rust.jemalloc = true ``` > Note that this option is currently only supported for Linux and macOS targets. @@ -48,9 +46,8 @@ You can modify the number of codegen units for `rustc` and `libstd` in `bootstra following options: ```toml -[rust] -codegen-units = 1 -codegen-units-std = 1 +rust.codegen-units = 1 +rust.codegen-units-std = 1 ``` ## Instruction set @@ -68,9 +65,8 @@ If you also want to compile LLVM for a specific instruction set, you can set `ll in `bootstrap.toml`: ```toml -[llvm] -cxxflags = "-march=x86-64-v3" -cflags = "-march=x86-64-v3" +llvm.cxxflags = "-march=x86-64-v3" +llvm.cflags = "-march=x86-64-v3" ``` ## Profile-guided optimization @@ -108,9 +104,8 @@ like Python or LLVM. Here is an example of how can `opt-dist` be used locally (outside of CI): 1. Enable metrics in your `bootstrap.toml` file, because `opt-dist` expects it to be enabled: - ```toml - [build] - metrics = true + ```toml + build.metrics = true ``` 2. Build the tool with the following command: ```bash diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index 5eb214fac904..af4dc0ab699c 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -441,7 +441,7 @@ ln -s ./src/tools/nix-dev-shell/envrc-shell ./.envrc # Use nix-shell ### Note Note that when using nix on a not-NixOS distribution, it may be necessary to set -**`patch-binaries-for-nix = true` in `bootstrap.toml`**. Bootstrap tries to detect +**`build.patch-binaries-for-nix = true` in `bootstrap.toml`**. Bootstrap tries to detect whether it's running in nix and enable patching automatically, but this detection can have false negatives. diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md index 1944bf53378d..7b67c262c456 100644 --- a/src/doc/rustc-dev-guide/src/compiler-debugging.md +++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md @@ -9,18 +9,17 @@ chapter](./backend/debugging.md)). ## Configuring the compiler By default, rustc is built without most debug information. To enable debug info, -set `debug = true` in your bootstrap.toml. +set `rust.debug = true` in your bootstrap.toml. -Setting `debug = true` turns on many different debug options (e.g., `debug-assertions`, +Setting `rust.debug = true` turns on many different debug options (e.g., `debug-assertions`, `debug-logging`, etc.) which can be individually tweaked if you want to, but many people -simply set `debug = true`. +simply set `rust.debug = true`. If you want to use GDB to debug rustc, please set `bootstrap.toml` with options: ```toml -[rust] -debug = true -debuginfo-level = 2 +rust.debug = true +rust.debuginfo-level = 2 ``` > NOTE: @@ -36,8 +35,7 @@ This requires at least GDB v10.2, otherwise you need to disable new symbol-mangling-version in `bootstrap.toml`. ```toml -[rust] -new-symbol-mangling = false +rust.new-symbol-mangling = false ``` > See the comments in `bootstrap.example.toml` for more info. diff --git a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md index d71e51d5f61b..fbfcc4198de6 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -47,15 +47,13 @@ mandatory. # These assertions can detect malformed coverage mappings in some cases. profile = "codegen" -[build] # IMPORTANT: This tells the build system to build the LLVM profiler runtime. # Without it, the compiler can't produce coverage-instrumented binaries, # and many of the coverage tests will be skipped. -profiler = true +build.profiler = true -[rust] # Enable debug assertions in the compiler. -debug-assertions = true +rust.debug-assertions = true ``` ## Rust symbol mangling diff --git a/src/doc/rustc-dev-guide/src/profiling.md b/src/doc/rustc-dev-guide/src/profiling.md index 519d9b5488cb..06ebb8998342 100644 --- a/src/doc/rustc-dev-guide/src/profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling.md @@ -89,22 +89,21 @@ Since this doesn't seem to work with incremental compilation or `./x check`, you will be compiling rustc _a lot_. I recommend changing a few settings in `bootstrap.toml` to make it bearable: ``` -[rust] # A debug build takes _a third_ as long on my machine, # but compiling more than stage0 rustc becomes unbearably slow. -optimize = false +rust.optimize = false # We can't use incremental anyway, so we disable it for a little speed boost. -incremental = false +rust.incremental = false # We won't be running it, so no point in compiling debug checks. -debug = false +rust.debug = false # Using a single codegen unit gives less output, but is slower to compile. -codegen-units = 0 # num_cpus +rust.codegen-units = 0 # num_cpus ``` The llvm-lines output is affected by several options. -`optimize = false` increases it from 2.1GB to 3.5GB and `codegen-units = 0` to 4.1GB. +`rust.optimize = false` increases it from 2.1GB to 3.5GB and `codegen-units = 0` to 4.1GB. MIR optimizations have little impact. Compared to the default `RUSTFLAGS="-Z mir-opt-level=1"`, level 0 adds 0.3GB and level 2 removes 0.2GB. diff --git a/src/doc/rustc-dev-guide/src/sanitizers.md b/src/doc/rustc-dev-guide/src/sanitizers.md index 673d650e6050..65e1c0c70505 100644 --- a/src/doc/rustc-dev-guide/src/sanitizers.md +++ b/src/doc/rustc-dev-guide/src/sanitizers.md @@ -36,8 +36,7 @@ Highlight of the most important aspects of the implementation: when enabled in `bootstrap.toml`: ```toml - [build] - sanitizers = true + build.sanitizers = true ``` The runtimes are [placed into target libdir][sanitizer-copy]. @@ -84,7 +83,7 @@ Sanitizers are validated by code generation tests in [`tests/ui/sanitizer/`][test-ui] directory. Testing sanitizer functionality requires the sanitizer runtimes (built when -`sanitizer = true` in `bootstrap.toml`) and target providing support for particular a sanitizer. +`build.sanitizer = true` in `bootstrap.toml`) and target providing support for particular a sanitizer. When a sanitizer is unsupported on a given target, sanitizer tests will be ignored. This behaviour is controlled by compiletest `needs-sanitizer-*` directives. diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 5c4dfb6e0dd1..d7372de11ff8 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -570,9 +570,7 @@ Instrumented binaries need to be linked against the LLVM profiler runtime, so is enabled in `bootstrap.toml`: ```toml -# bootstrap.toml -[build] -profiler = true +build.profiler = true ``` This also means that they typically don't run in PR CI jobs, though they do run diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 08371a779e11..7034420e9be0 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -166,7 +166,7 @@ The following directives will check rustc build settings and target settings: - `needs-profiler-runtime` — ignores the test if the profiler runtime was not enabled for the target (`build.profiler = true` in rustc's `bootstrap.toml`) - `needs-sanitizer-support` — ignores if the sanitizer support was not enabled - for the target (`sanitizers = true` in rustc's `bootstrap.toml`) + for the target (`build.sanitizers = true` in rustc's `bootstrap.toml`) - `needs-sanitizer-{address,hwaddress,leak,memory,thread}` — ignores if the corresponding sanitizer is not enabled for the target (AddressSanitizer, hardware-assisted AddressSanitizer, LeakSanitizer, MemorySanitizer or diff --git a/src/doc/rustc-dev-guide/src/tests/docker.md b/src/doc/rustc-dev-guide/src/tests/docker.md index af8e0c36d050..436aa13545eb 100644 --- a/src/doc/rustc-dev-guide/src/tests/docker.md +++ b/src/doc/rustc-dev-guide/src/tests/docker.md @@ -21,7 +21,7 @@ The [`src/ci/docker/run.sh`] script is used to build a specific Docker image, ru build Rust within the image, and either run tests or prepare a set of archives designed for distribution. The script will mount your local Rust source tree in read-only mode, and an `obj` directory in read-write mode. All the compiler artifacts will be stored in the `obj` directory. The shell will start out in the `obj`directory. From there, it will execute `../src/ci/run.sh` which starts the build as defined by the Docker image. You can run `src/ci/docker/run.sh ` directly. A few important notes regarding the `run.sh` script: -- When executed on CI, the script expects that all submodules are checked out. If some submodule that is accessed by the job is not available, the build will result in an error. You should thus make sure that you have all required submodules checked out locally. You can either do that manually through git, or set `submodules = true` in your `bootstrap.toml` and run a command such as `x build` to let bootstrap download the most important submodules (this might not be enough for the given CI job that you are trying to execute though). +- When executed on CI, the script expects that all submodules are checked out. If some submodule that is accessed by the job is not available, the build will result in an error. You should thus make sure that you have all required submodules checked out locally. You can either do that manually through git, or set `build.submodules = true` in your `bootstrap.toml` and run a command such as `x build` to let bootstrap download the most important submodules (this might not be enough for the given CI job that you are trying to execute though). - `` corresponds to a single directory located in one of the `src/ci/docker/host-*` directories. Note that image name does not necessarily correspond to a job name, as some jobs execute the same image, but with different environment variables or Docker build arguments (this is a part of the complexity that makes it difficult to run CI jobs locally). - If you are executing a "dist" job (job beginning with `dist-`), you should set the `DEPLOY=1` environment variable. - If you are executing an "alternative dist" job (job beginning with `dist-` and ending with `-alt`), you should set the `DEPLOY_ALT=1` environment variable. diff --git a/src/doc/rustc-dev-guide/src/tracing.md b/src/doc/rustc-dev-guide/src/tracing.md index 28c0bcc737ca..323f81dcee04 100644 --- a/src/doc/rustc-dev-guide/src/tracing.md +++ b/src/doc/rustc-dev-guide/src/tracing.md @@ -194,7 +194,7 @@ calls to `debug!` and `trace!` are only included in the program if `rust.debug-logging=true` is turned on in bootstrap.toml (it is turned off by default), so if you don't see `DEBUG` logs, especially if you run the compiler with `RUSTC_LOG=rustc rustc some.rs` and only see -`INFO` logs, make sure that `debug-logging=true` is turned on in your bootstrap.toml. +`INFO` logs, make sure that `rust.debug-logging=true` is turned on in your bootstrap.toml. ## Logging etiquette and conventions From ed50cc909ad5e8dc1a8cdf0b16aa805028286ebf Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:10:50 +0200 Subject: [PATCH 425/978] I do not expect there will be any confusion --- src/doc/rustc-dev-guide/src/tests/directives.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 7034420e9be0..ac76a2e15d9a 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -164,9 +164,9 @@ The following directives will check rustc build settings and target settings: via `--target`, use `needs-llvm-components` instead to ensure the appropriate backend is available. - `needs-profiler-runtime` — ignores the test if the profiler runtime was not - enabled for the target (`build.profiler = true` in rustc's `bootstrap.toml`) + enabled for the target (`build.profiler = true` in `bootstrap.toml`) - `needs-sanitizer-support` — ignores if the sanitizer support was not enabled - for the target (`build.sanitizers = true` in rustc's `bootstrap.toml`) + for the target (`build.sanitizers = true` in `bootstrap.toml`) - `needs-sanitizer-{address,hwaddress,leak,memory,thread}` — ignores if the corresponding sanitizer is not enabled for the target (AddressSanitizer, hardware-assisted AddressSanitizer, LeakSanitizer, MemorySanitizer or From ca24637a66fd274087d2393176cf30bd1c1c4943 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:12:31 +0200 Subject: [PATCH 426/978] sembr src/backend/debugging.md --- .../rustc-dev-guide/src/backend/debugging.md | 93 ++++++++++--------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/backend/debugging.md b/src/doc/rustc-dev-guide/src/backend/debugging.md index 319154f023cf..2f26181abfca 100644 --- a/src/doc/rustc-dev-guide/src/backend/debugging.md +++ b/src/doc/rustc-dev-guide/src/backend/debugging.md @@ -6,16 +6,16 @@ [codegen]: ./codegen.md This section is about debugging compiler bugs in code generation (e.g. why the -compiler generated some piece of code or crashed in LLVM). LLVM is a big -project on its own that probably needs to have its own debugging document (not -that I could find one). But here are some tips that are important in a rustc -context: +compiler generated some piece of code or crashed in LLVM). + LLVM is a big project on its own that probably needs to have its own debugging document (not +that I could find one). +But here are some tips that are important in a rustc context: ### Minimize the example As a general rule, compilers generate lots of information from analyzing code. -Thus, a useful first step is usually to find a minimal example. One way to do -this is to +Thus, a useful first step is usually to find a minimal example. +One way to do this is to 1. create a new crate that reproduces the issue (e.g. adding whatever crate is at fault as a dependency, and using it from there) @@ -35,14 +35,13 @@ For more discussion on methodology for steps 2 and 3 above, there is an The official compilers (including nightlies) have LLVM assertions disabled, which means that LLVM assertion failures can show up as compiler crashes (not -ICEs but "real" crashes) and other sorts of weird behavior. If you are -encountering these, it is a good idea to try using a compiler with LLVM +ICEs but "real" crashes) and other sorts of weird behavior. +If you are encountering these, it is a good idea to try using a compiler with LLVM assertions enabled - either an "alt" nightly or a compiler you build yourself -by setting `llvm.assertions = true` in your bootstrap.toml - and see whether -anything turns up. +by setting `llvm.assertions = true` in your bootstrap.toml - and see whether anything turns up. -The rustc build process builds the LLVM tools into -`./build//llvm/bin`. They can be called directly. +The rustc build process builds the LLVM tools into `./build//llvm/bin`. +They can be called directly. These tools include: * [`llc`], which compiles bitcode (`.bc` files) to executable code; this can be used to replicate LLVM backend bugs. @@ -55,7 +54,8 @@ These tools include: [`bugpoint`]: https://llvm.org/docs/Bugpoint.html By default, the Rust build system does not check for changes to the LLVM source code or -its build configuration settings. So, if you need to rebuild the LLVM that is linked +its build configuration settings. +So, if you need to rebuild the LLVM that is linked into `rustc`, first delete the file `.llvm-stamp`, which should be located in `build//llvm/`. @@ -66,26 +66,28 @@ disappear), passing `-C codegen-units=1` to rustc will make debugging easier. ### Get your hands on raw LLVM input -For rustc to generate LLVM IR, you need to pass the `--emit=llvm-ir` flag. If +For rustc to generate LLVM IR, you need to pass the `--emit=llvm-ir` flag. +If you are building via cargo, use the `RUSTFLAGS` environment variable (e.g. -`RUSTFLAGS='--emit=llvm-ir'`). This causes rustc to spit out LLVM IR into the -target directory. +`RUSTFLAGS='--emit=llvm-ir'`). +This causes rustc to spit out LLVM IR into the target directory. -`cargo llvm-ir [options] path` spits out the LLVM IR for a particular function -at `path`. (`cargo install cargo-asm` installs `cargo asm` and `cargo -llvm-ir`). `--build-type=debug` emits code for debug builds. There are also -other useful options. Also, debug info in LLVM IR can clutter the output a lot: +`cargo llvm-ir [options] path` spits out the LLVM IR for a particular function at `path`. +(`cargo install cargo-asm` installs `cargo asm` and `cargo llvm-ir`). +`--build-type=debug` emits code for debug builds. +There are also other useful options. +Also, debug info in LLVM IR can clutter the output a lot: `RUSTFLAGS="-C debuginfo=0"` is really useful. `RUSTFLAGS="-C save-temps"` outputs LLVM bitcode at -different stages during compilation, which is sometimes useful. The output LLVM -bitcode will be in `.bc` files in the compiler's output directory, set via the +different stages during compilation, which is sometimes useful. +The output LLVM bitcode will be in `.bc` files in the compiler's output directory, set via the `--out-dir DIR` argument to `rustc`. * If you are hitting an assertion failure or segmentation fault from the LLVM backend when invoking `rustc` itself, it is a good idea to try passing each - of these `.bc` files to the `llc` command, and see if you get the same - failure. (LLVM developers often prefer a bug reduced to a `.bc` file over one + of these `.bc` files to the `llc` command, and see if you get the same failure. + (LLVM developers often prefer a bug reduced to a `.bc` file over one that uses a Rust crate for its minimized reproduction.) * To get human readable versions of the LLVM bitcode, one just needs to convert @@ -112,8 +114,8 @@ llvm-args='-filter-print-funcs=EXACT_FUNCTION_NAME` (e.g. `-C llvm-args='-filter-print-funcs=_ZN11collections3str21_$LT$impl$u20$str$GT$\ 7replace17hbe10ea2e7c809b0bE'`). -That produces a lot of output into standard error, so you'll want to pipe that -to some file. Also, if you are using neither `-filter-print-funcs` nor `-C +That produces a lot of output into standard error, so you'll want to pipe that to some file. +Also, if you are using neither `-filter-print-funcs` nor `-C codegen-units=1`, then, because the multiple codegen units run in parallel, the printouts will mix together and you won't be able to read anything. @@ -125,8 +127,8 @@ printouts will mix together and you won't be able to read anything. * Within LLVM itself, calling `F.getParent()->dump()` at the beginning of `SafeStackLegacyPass::runOnFunction` will dump the whole module, which - may provide better basis for reproduction. (However, you - should be able to get that same dump from the `.bc` files dumped by + may provide better basis for reproduction. + (However, you should be able to get that same dump from the `.bc` files dumped by `-C save-temps`.) If you want just the IR for a specific function (say, you want to see why it @@ -145,10 +147,11 @@ $ ./build/$TRIPLE/llvm/bin/llvm-extract \ If you are seeing incorrect behavior due to an optimization pass, a very handy LLVM option is `-opt-bisect-limit`, which takes an integer denoting the index -value of the highest pass to run. Index values for taken passes are stable +value of the highest pass to run. + Index values for taken passes are stable from run to run; by coupling this with software that automates bisecting the -search space based on the resulting program, an errant pass can be quickly -determined. When an `-opt-bisect-limit` is specified, all runs are displayed +search space based on the resulting program, an errant pass can be quickly determined. + When an `-opt-bisect-limit` is specified, all runs are displayed to standard error, along with their index and output indicating if the pass was run or skipped. Setting the limit to an index of -1 (e.g., `RUSTFLAGS="-C llvm-args=-opt-bisect-limit=-1"`) will show all passes and @@ -189,8 +192,8 @@ specifically the `#t-compiler/wg-llvm` channel. ### Compiler options to know and love The `-C help` and `-Z help` compiler switches will list out a variety -of interesting options you may find useful. Here are a few of the most -common that pertain to LLVM development (some of them are employed in the +of interesting options you may find useful. +Here are a few of the most common that pertain to LLVM development (some of them are employed in the tutorial above): - The `--emit llvm-ir` option emits a `.ll` file with LLVM IR in textual format @@ -200,7 +203,8 @@ tutorial above): e.g. `-C llvm-args=-print-before-all` to print IR before every LLVM pass. - The `-C no-prepopulate-passes` will avoid pre-populate the LLVM pass - manager with a list of passes. This will allow you to view the LLVM + manager with a list of passes. + This will allow you to view the LLVM IR that rustc generates, not the LLVM IR after optimizations. - The `-C passes=val` option allows you to supply a space separated list of extra LLVM passes to run - The `-C save-temps` option saves all temporary output files during compilation @@ -210,18 +214,17 @@ tutorial above): - The `-Z no-parallel-backend` will disable parallel compilation of distinct compilation units - The `-Z llvm-time-trace` option will output a Chrome profiler compatible JSON file which contains details and timings for LLVM passes. -- The `-C llvm-args=-opt-bisect-limit=` option allows for bisecting LLVM - optimizations. +- The `-C llvm-args=-opt-bisect-limit=` option allows for bisecting LLVM optimizations. ### Filing LLVM bug reports When filing an LLVM bug report, you will probably want some sort of minimal -working example that demonstrates the problem. The Godbolt compiler explorer is -really helpful for this. +working example that demonstrates the problem. +The Godbolt compiler explorer is really helpful for this. 1. Once you have some LLVM IR for the problematic code (see above), you can -create a minimal working example with Godbolt. Go to -[llvm.godbolt.org](https://llvm.godbolt.org). +create a minimal working example with Godbolt. +Go to [llvm.godbolt.org](https://llvm.godbolt.org). 2. Choose `LLVM-IR` as programming language. @@ -229,8 +232,7 @@ create a minimal working example with Godbolt. Go to - There are some useful flags: `-mattr` enables target features, `-march=` selects the target, `-mcpu=` selects the CPU, etc. - Commands like `llc -march=help` output all architectures available, which - is useful because sometimes the Rust arch names and the LLVM names do not - match. + is useful because sometimes the Rust arch names and the LLVM names do not match. - If you have compiled rustc yourself somewhere, in the target directory you have binaries for `llc`, `opt`, etc. @@ -238,7 +240,8 @@ create a minimal working example with Godbolt. Go to optimizations transform it. 5. Once you have a godbolt link demonstrating the issue, it is pretty easy to - fill in an LLVM bug. Just visit their [github issues page][llvm-issues]. + fill in an LLVM bug. + Just visit their [github issues page][llvm-issues]. [llvm-issues]: https://github.com/llvm/llvm-project/issues @@ -250,8 +253,8 @@ gotten the fix yet (or perhaps you are familiar enough with LLVM to fix it yours In that case, we can sometimes opt to port the fix for the bug directly to our own LLVM fork, so that rustc can use it more easily. -Our fork of LLVM is maintained in [rust-lang/llvm-project]. Once -you've landed the fix there, you'll also need to land a PR modifying +Our fork of LLVM is maintained in [rust-lang/llvm-project]. +Once you've landed the fix there, you'll also need to land a PR modifying our submodule commits -- ask around on Zulip for help. [rust-lang/llvm-project]: https://github.com/rust-lang/llvm-project/ From 4c958e731b9ee0aa3c21c3e0eca745fb04788d31 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:18:37 +0200 Subject: [PATCH 427/978] this is text with multiple authors --- src/doc/rustc-dev-guide/src/backend/debugging.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/backend/debugging.md b/src/doc/rustc-dev-guide/src/backend/debugging.md index 2f26181abfca..f18154662e69 100644 --- a/src/doc/rustc-dev-guide/src/backend/debugging.md +++ b/src/doc/rustc-dev-guide/src/backend/debugging.md @@ -7,9 +7,8 @@ This section is about debugging compiler bugs in code generation (e.g. why the compiler generated some piece of code or crashed in LLVM). - LLVM is a big project on its own that probably needs to have its own debugging document (not -that I could find one). -But here are some tips that are important in a rustc context: +LLVM is a big project that probably needs to have its own debugging document, +but following are some tips that are important in a rustc context. ### Minimize the example From b658d1521f4fcc4ead01a85c94f23aa9054cee61 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:20:22 +0200 Subject: [PATCH 428/978] a symlink is now helpfully provided --- src/doc/rustc-dev-guide/src/backend/debugging.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/backend/debugging.md b/src/doc/rustc-dev-guide/src/backend/debugging.md index f18154662e69..8f0d35f0c9da 100644 --- a/src/doc/rustc-dev-guide/src/backend/debugging.md +++ b/src/doc/rustc-dev-guide/src/backend/debugging.md @@ -39,7 +39,7 @@ If you are encountering these, it is a good idea to try using a compiler with LL assertions enabled - either an "alt" nightly or a compiler you build yourself by setting `llvm.assertions = true` in your bootstrap.toml - and see whether anything turns up. -The rustc build process builds the LLVM tools into `./build//llvm/bin`. +The rustc build process builds the LLVM tools into `./build/host/llvm/bin`. They can be called directly. These tools include: * [`llc`], which compiles bitcode (`.bc` files) to executable code; this can be used to @@ -56,7 +56,7 @@ By default, the Rust build system does not check for changes to the LLVM source its build configuration settings. So, if you need to rebuild the LLVM that is linked into `rustc`, first delete the file `.llvm-stamp`, which should be located -in `build//llvm/`. +in `build/host/llvm/`. The default rustc compilation pipeline has multiple codegen units, which is hard to replicate manually and means that LLVM is called multiple times in @@ -157,7 +157,7 @@ pass was run or skipped. Setting the limit to an index of -1 (e.g., their corresponding index values. If you want to play with the optimization pipeline, you can use the [`opt`] tool -from `./build//llvm/bin/` with the LLVM IR emitted by rustc. +from `./build/host/llvm/bin/` with the LLVM IR emitted by rustc. When investigating the implementation of LLVM itself, you should be aware of its [internal debug infrastructure][llvm-debug]. From c305590083a85118afca0c136eefb39b875daeb8 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:21:02 +0200 Subject: [PATCH 429/978] more clean --- src/doc/rustc-dev-guide/src/backend/debugging.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/backend/debugging.md b/src/doc/rustc-dev-guide/src/backend/debugging.md index 8f0d35f0c9da..c9d47181bde8 100644 --- a/src/doc/rustc-dev-guide/src/backend/debugging.md +++ b/src/doc/rustc-dev-guide/src/backend/debugging.md @@ -39,7 +39,7 @@ If you are encountering these, it is a good idea to try using a compiler with LL assertions enabled - either an "alt" nightly or a compiler you build yourself by setting `llvm.assertions = true` in your bootstrap.toml - and see whether anything turns up. -The rustc build process builds the LLVM tools into `./build/host/llvm/bin`. +The rustc build process builds the LLVM tools into `build/host/llvm/bin`. They can be called directly. These tools include: * [`llc`], which compiles bitcode (`.bc` files) to executable code; this can be used to @@ -101,7 +101,7 @@ you should: ```bash $ rustc +local my-file.rs --emit=llvm-ir -O -C no-prepopulate-passes \ -C codegen-units=1 -$ OPT=./build/$TRIPLE/llvm/bin/opt +$ OPT=build/$TRIPLE/llvm/bin/opt $ $OPT -S -O2 < my-file.ll > my ``` From b55c621216f62f7e0fb8183d0f19fa2f8ccadd31 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:22:44 +0200 Subject: [PATCH 430/978] reflow --- src/doc/rustc-dev-guide/src/backend/debugging.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/backend/debugging.md b/src/doc/rustc-dev-guide/src/backend/debugging.md index c9d47181bde8..d3e59993a86d 100644 --- a/src/doc/rustc-dev-guide/src/backend/debugging.md +++ b/src/doc/rustc-dev-guide/src/backend/debugging.md @@ -66,9 +66,8 @@ disappear), passing `-C codegen-units=1` to rustc will make debugging easier. ### Get your hands on raw LLVM input For rustc to generate LLVM IR, you need to pass the `--emit=llvm-ir` flag. -If -you are building via cargo, use the `RUSTFLAGS` environment variable (e.g. -`RUSTFLAGS='--emit=llvm-ir'`). +If you are building via cargo, +use the `RUSTFLAGS` environment variable (e.g. `RUSTFLAGS='--emit=llvm-ir'`). This causes rustc to spit out LLVM IR into the target directory. `cargo llvm-ir [options] path` spits out the LLVM IR for a particular function at `path`. From 616954b0bd1fbd5368b323317f1218f9ba62c6bd Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:25:41 +0200 Subject: [PATCH 431/978] whitespace --- src/doc/rustc-dev-guide/src/backend/debugging.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/backend/debugging.md b/src/doc/rustc-dev-guide/src/backend/debugging.md index d3e59993a86d..eaa9e399a052 100644 --- a/src/doc/rustc-dev-guide/src/backend/debugging.md +++ b/src/doc/rustc-dev-guide/src/backend/debugging.md @@ -146,10 +146,10 @@ $ ./build/$TRIPLE/llvm/bin/llvm-extract \ If you are seeing incorrect behavior due to an optimization pass, a very handy LLVM option is `-opt-bisect-limit`, which takes an integer denoting the index value of the highest pass to run. - Index values for taken passes are stable +Index values for taken passes are stable from run to run; by coupling this with software that automates bisecting the search space based on the resulting program, an errant pass can be quickly determined. - When an `-opt-bisect-limit` is specified, all runs are displayed +When an `-opt-bisect-limit` is specified, all runs are displayed to standard error, along with their index and output indicating if the pass was run or skipped. Setting the limit to an index of -1 (e.g., `RUSTFLAGS="-C llvm-args=-opt-bisect-limit=-1"`) will show all passes and @@ -202,7 +202,7 @@ tutorial above): pass. - The `-C no-prepopulate-passes` will avoid pre-populate the LLVM pass manager with a list of passes. - This will allow you to view the LLVM + This will allow you to view the LLVM IR that rustc generates, not the LLVM IR after optimizations. - The `-C passes=val` option allows you to supply a space separated list of extra LLVM passes to run - The `-C save-temps` option saves all temporary output files during compilation From 9bafb7744aa82f0298a961fa8fb26aed75dde88f Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:27:12 +0200 Subject: [PATCH 432/978] sembr src/backend/updating-llvm.md --- .../src/backend/updating-llvm.md | 77 +++++++++---------- 1 file changed, 35 insertions(+), 42 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md index 5962791f64b1..3d0e130b6aaa 100644 --- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md +++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md @@ -3,16 +3,16 @@ Rust supports building against multiple LLVM versions: -* Tip-of-tree for the current LLVM development branch is usually supported - within a few days. PRs for such fixes are tagged with `llvm-main`. +* Tip-of-tree for the current LLVM development branch is usually supported within a few days. + PRs for such fixes are tagged with `llvm-main`. * The latest released major version is always supported. * The one or two preceding major versions are usually supported. By default, Rust uses its own fork in the [rust-lang/llvm-project repository]. This fork is based on a `release/$N.x` branch of the upstream project, where `$N` is either the latest released major version, or the current major version -in release candidate phase. The fork is never based on the `main` development -branch. +in release candidate phase. +The fork is never based on the `main` development branch. Our LLVM fork only accepts: @@ -32,16 +32,15 @@ There are three types of LLVM updates, with different procedures: ## Backports (upstream supported) While the current major LLVM version is supported upstream, fixes should be -backported upstream first, and the release branch then merged back into the -Rust fork. +backported upstream first, and the release branch then merged back into the Rust fork. 1. Make sure the bugfix is in upstream LLVM. -2. If this hasn't happened already, request a backport to the upstream release - branch. If you have LLVM commit access, follow the [backport process]. - Otherwise, open an issue requesting the backport. Continue once the - backport has been approved and merged. -3. Identify the branch that rustc is currently using. The `src/llvm-project` - submodule is always pinned to a branch of the +2. If this hasn't happened already, request a backport to the upstream release branch. + If you have LLVM commit access, follow the [backport process]. + Otherwise, open an issue requesting the backport. + Continue once the backport has been approved and merged. +3. Identify the branch that rustc is currently using. + The `src/llvm-project` submodule is always pinned to a branch of the [rust-lang/llvm-project repository]. 4. Fork the rust-lang/llvm-project repository. 5. Check out the appropriate branch (typically named `rustc/a.b-yyyy-mm-dd`). @@ -51,26 +50,23 @@ Rust fork. 7. Merge the `upstream/release/$N.x` branch. 8. Push this branch to your fork. 9. Send a Pull Request to rust-lang/llvm-project to the same branch as before. - Be sure to reference the Rust and/or LLVM issue that you're fixing in the PR - description. + Be sure to reference the Rust and/or LLVM issue that you're fixing in the PR description. 10. Wait for the PR to be merged. -11. Send a PR to rust-lang/rust updating the `src/llvm-project` submodule with - your bugfix. This can be done locally with `git submodule update --remote - src/llvm-project` typically. +11. Send a PR to rust-lang/rust updating the `src/llvm-project` submodule with your bugfix. + This can be done locally with `git submodule update --remote src/llvm-project` typically. 12. Wait for PR to be merged. -An example PR: -[#59089](https://github.com/rust-lang/rust/pull/59089) +An example PR: [#59089](https://github.com/rust-lang/rust/pull/59089) ## Backports (upstream not supported) -Upstream LLVM releases are only supported for two to three months after the -GA release. Once upstream backports are no longer accepted, changes should be +Upstream LLVM releases are only supported for two to three months after the GA release. +Once upstream backports are no longer accepted, changes should be cherry-picked directly to our fork. 1. Make sure the bugfix is in upstream LLVM. -2. Identify the branch that rustc is currently using. The `src/llvm-project` - submodule is always pinned to a branch of the +2. Identify the branch that rustc is currently using. + The `src/llvm-project` submodule is always pinned to a branch of the [rust-lang/llvm-project repository]. 3. Fork the rust-lang/llvm-project repository. 4. Check out the appropriate branch (typically named `rustc/a.b-yyyy-mm-dd`). @@ -80,16 +76,13 @@ cherry-picked directly to our fork. 6. Cherry-pick the relevant commit(s) using `git cherry-pick -x`. 7. Push this branch to your fork. 8. Send a Pull Request to rust-lang/llvm-project to the same branch as before. - Be sure to reference the Rust and/or LLVM issue that you're fixing in the PR - description. + Be sure to reference the Rust and/or LLVM issue that you're fixing in the PR description. 9. Wait for the PR to be merged. -10. Send a PR to rust-lang/rust updating the `src/llvm-project` submodule with - your bugfix. This can be done locally with `git submodule update --remote - src/llvm-project` typically. +10. Send a PR to rust-lang/rust updating the `src/llvm-project` submodule with your bugfix. + This can be done locally with `git submodule update --remote src/llvm-project` typically. 11. Wait for PR to be merged. -An example PR: -[#59089](https://github.com/rust-lang/rust/pull/59089) +An example PR: [#59089](https://github.com/rust-lang/rust/pull/59089) ## New LLVM Release Updates @@ -110,14 +103,12 @@ so let's go through each in detail. 1. Create a new branch in the [rust-lang/llvm-project repository] from this `release/$N.x` branch, and name it `rustc/a.b-yyyy-mm-dd`, - where `a.b` is the current version number of LLVM in-tree - at the time of the branch, + where `a.b` is the current version number of LLVM in-tree at the time of the branch, and the remaining part is the current date. 1. Apply Rust-specific patches to the llvm-project repository. All features and bugfixes are upstream, - but there's often some weird build-related patches - that don't make sense to upstream. + but there's often some weird build-related patches that don't make sense to upstream. These patches are typically the latest patches in the rust-lang/llvm-project branch that rustc is currently using. @@ -148,9 +139,11 @@ so let's go through each in detail. llvm.download-ci-llvm = false ``` -1. Test for regressions across other platforms. LLVM often has at least one bug +1. Test for regressions across other platforms. + LLVM often has at least one bug for non-tier-1 architectures, so it's good to do some more testing before - sending this to bors! If you're low on resources you can send the PR as-is + sending this to bors! + If you're low on resources you can send the PR as-is now to bors, though, and it'll get tested anyway. Ideally, build LLVM and test it on a few platforms: @@ -167,9 +160,11 @@ so let's go through each in detail. * `./src/ci/docker/run.sh dist-various-2` * `./src/ci/docker/run.sh armhf-gnu` -1. Prepare a PR to `rust-lang/rust`. Work with maintainers of +1. Prepare a PR to `rust-lang/rust`. + Work with maintainers of `rust-lang/llvm-project` to get your commit in a branch of that repository, - and then you can send a PR to `rust-lang/rust`. You'll change at least + and then you can send a PR to `rust-lang/rust`. + You'll change at least `src/llvm-project` and will likely also change [`llvm-wrapper`] as well. @@ -191,14 +186,12 @@ so let's go through each in detail. We will often want to have those bug fixes as well. The merge process for that is to use `git merge` itself to merge LLVM's `release/a.b` branch with the branch created in step 2. - This is typically - done multiple times when necessary while LLVM's release branch is baking. + This is typically done multiple times when necessary while LLVM's release branch is baking. 1. LLVM then announces the release of version `a.b`. 1. After LLVM's official release, - we follow the process of creating a new branch on the - rust-lang/llvm-project repository again, + we follow the process of creating a new branch on the rust-lang/llvm-project repository again, this time with a new date. It is only then that the PR to update Rust to use that version is merged. From 299b429e966c4e8de65be80bb6b003c80a61348e Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:36:10 +0200 Subject: [PATCH 433/978] sembr src/building/how-to-build-and-run.md --- .../src/building/how-to-build-and-run.md | 139 ++++++++++-------- 1 file changed, 76 insertions(+), 63 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index 3e44a75ad732..2c127245b810 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -4,22 +4,25 @@ For `profile = "library"` users, or users who use `download-rustc = true | "if-unchanged"`, please be advised that the `./x test library/std` flow where `download-rustc` is active (i.e. no compiler changes) is currently broken. -This is tracked in . Only the `./x test` flow is affected in this +This is tracked in . +Only the `./x test` flow is affected in this case, `./x {check,build} library/std` should still work. -In the short-term, you may need to disable `download-rustc` for `./x test library/std`. This can be done either by: +In the short-term, you may need to disable `download-rustc` for `./x test library/std`. +This can be done either by: 1. `./x test library/std --set rust.download-rustc=false` 2. Or set `rust.download-rustc = false` in `bootstrap.toml`. -Unfortunately that will require building the stage 1 compiler. The bootstrap team is working on this, but +Unfortunately that will require building the stage 1 compiler. +The bootstrap team is working on this, but implementing a maintainable fix is taking some time. -The compiler is built using a tool called `x.py`. You will need to -have Python installed to run it. +The compiler is built using a tool called `x.py`. +You will need to have Python installed to run it. ## Quick Start @@ -28,7 +31,8 @@ For a less in-depth quick-start of getting the compiler running, see [quickstart ## Get the source code -The main repository is [`rust-lang/rust`][repo]. This contains the compiler, +The main repository is [`rust-lang/rust`][repo]. +This contains the compiler, the standard library (including `core`, `alloc`, `test`, `proc_macro`, etc), and a bunch of tools (e.g. `rustdoc`, the bootstrapping infrastructure, etc). @@ -86,8 +90,8 @@ cd rust ## What is `x.py`? -`x.py` is the build tool for the `rust` repository. It can build docs, run tests, and compile the -compiler and standard library. +`x.py` is the build tool for the `rust` repository. +It can build docs, run tests, and compile the compiler and standard library. This chapter focuses on the basics to be productive, but if you want to learn more about `x.py`, [read this chapter][bootstrap]. @@ -103,11 +107,13 @@ Also, using `x` rather than `x.py` is recommended as: (You can find the platform related scripts around the `x.py`, like `x.ps1`) -Notice that this is not absolute. For instance, using Nushell in VSCode on Win10, -typing `x` or `./x` still opens `x.py` in an editor rather than invoking the program. :) +Notice that this is not absolute. +For instance, using Nushell in VSCode on Win10, +typing `x` or `./x` still opens `x.py` in an editor rather than invoking the program. +:) -In the rest of this guide, we use `x` rather than `x.py` directly. The following -command: +In the rest of this guide, we use `x` rather than `x.py` directly. +The following command: ```bash ./x check @@ -164,9 +170,10 @@ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser #### Running `x.py` slightly more conveniently -There is a binary that wraps `x.py` called `x` in `src/tools/x`. All it does is -run `x.py`, but it can be installed system-wide and run from any subdirectory -of a checkout. It also looks up the appropriate version of `python` to use. +There is a binary that wraps `x.py` called `x` in `src/tools/x`. +All it does is run `x.py`, but it can be installed system-wide and run from any subdirectory +of a checkout. +It also looks up the appropriate version of `python` to use. You can install it with `cargo install --path src/tools/x`. @@ -177,18 +184,20 @@ shell to run the platform related scripts. ## Create a `bootstrap.toml` -To start, run `./x setup` and select the `compiler` defaults. This will do some initialization -and create a `bootstrap.toml` for you with reasonable defaults. If you use a different default (which +To start, run `./x setup` and select the `compiler` defaults. +This will do some initialization and create a `bootstrap.toml` for you with reasonable defaults. +If you use a different default (which you'll likely want to do if you want to contribute to an area of rust other than the compiler, such as rustdoc), make sure to read information about that default (located in `src/bootstrap/defaults`) as the build process may be different for other defaults. -Alternatively, you can write `bootstrap.toml` by hand. See `bootstrap.example.toml` for all the available -settings and explanations of them. See `src/bootstrap/defaults` for common settings to change. +Alternatively, you can write `bootstrap.toml` by hand. +See `bootstrap.example.toml` for all the available settings and explanations of them. +See `src/bootstrap/defaults` for common settings to change. If you have already built `rustc` and you change settings related to LLVM, then you may have to -execute `./x clean --all` for subsequent configuration changes to take effect. Note that `./x -clean` will not cause a rebuild of LLVM. +execute `./x clean --all` for subsequent configuration changes to take effect. +Note that `./x clean` will not cause a rebuild of LLVM. ## Common `x` commands @@ -202,28 +211,28 @@ working on `rustc`, `std`, `rustdoc`, and other tools. | `./x test` | Runs all tests | | `./x fmt` | Formats all code | -As written, these commands are reasonable starting points. However, there are -additional options and arguments for each of them that are worth learning for -serious development work. In particular, `./x build` and `./x test` -provide many ways to compile or test a subset of the code, which can save a lot -of time. +As written, these commands are reasonable starting points. +However, there are additional options and arguments for each of them that are worth learning for +serious development work. +In particular, `./x build` and `./x test` +provide many ways to compile or test a subset of the code, which can save a lot of time. Also, note that `x` supports all kinds of path suffixes for `compiler`, `library`, -and `src/tools` directories. So, you can simply run `x test tidy` instead of -`x test src/tools/tidy`. Or, `x build std` instead of `x build library/std`. +and `src/tools` directories. +So, you can simply run `x test tidy` instead of `x test src/tools/tidy`. +Or, `x build std` instead of `x build library/std`. [rust-analyzer]: suggested.html#configuring-rust-analyzer-for-rustc -See the chapters on -[testing](../tests/running.md) and [rustdoc](../rustdoc.md) for more details. +See the chapters on [testing](../tests/running.md) and [rustdoc](../rustdoc.md) for more details. ### Building the compiler Note that building will require a relatively large amount of storage space. You may want to have upwards of 10 or 15 gigabytes available to build the compiler. -Once you've created a `bootstrap.toml`, you are now ready to run -`x`. There are a lot of options here, but let's start with what is +Once you've created a `bootstrap.toml`, you are now ready to run `x`. +There are a lot of options here, but let's start with what is probably the best "go to" command for building a local compiler: ```console @@ -236,8 +245,7 @@ What this command does is: - Assemble a working stage1 sysroot, containing the stage1 compiler and stage1 standard libraries. This final product (stage1 compiler + libs built using that compiler) -is what you need to build other Rust programs (unless you use `#![no_std]` or -`#![no_core]`). +is what you need to build other Rust programs (unless you use `#![no_std]` or `#![no_core]`). You will probably find that building the stage1 `std` is a bottleneck for you, but fear not, there is a (hacky) workaround... @@ -245,12 +253,12 @@ see [the section on avoiding rebuilds for std][keep-stage]. [keep-stage]: ./suggested.md#faster-rebuilds-with---keep-stage-std -Sometimes you don't need a full build. When doing some kind of -"type-based refactoring", like renaming a method, or changing the +Sometimes you don't need a full build. +When doing some kind of "type-based refactoring", like renaming a method, or changing the signature of some function, you can use `./x check` instead for a much faster build. -Note that this whole command just gives you a subset of the full `rustc` -build. The **full** `rustc` build (what you get with `./x build +Note that this whole command just gives you a subset of the full `rustc` build. +The **full** `rustc` build (what you get with `./x build --stage 2 rustc`) has quite a few more steps: - Build `rustc` with the stage1 compiler. @@ -262,8 +270,8 @@ You almost never need to do this. ### Build specific components If you are working on the standard library, you probably don't need to build -every other default component. Instead, you can build a specific component by -providing its name, like this: +every other default component. +Instead, you can build a specific component by providing its name, like this: ```bash ./x build --stage 1 library @@ -275,11 +283,12 @@ default). ## Creating a rustup toolchain Once you have successfully built `rustc`, you will have created a bunch -of files in your `build` directory. In order to actually run the -resulting `rustc`, we recommend creating rustup toolchains. The first -command listed below creates the stage1 toolchain, which was built in the -steps above, with the name `stage1`. The second command creates the stage2 -toolchain using the stage1 compiler. This will be needed in the future +of files in your `build` directory. +In order to actually run the resulting `rustc`, we recommend creating rustup toolchains. +The first command listed below creates the stage1 toolchain, which was built in the +steps above, with the name `stage1`. +The second command creates the stage2 toolchain using the stage1 compiler. +This will be needed in the future if running the entire test suite, but will not be built in this page. Building stage2 is done with the same `./x build` command as for stage1, specifying that the stage is 2 instead. @@ -289,8 +298,8 @@ rustup toolchain link stage1 build/host/stage1 rustup toolchain link stage2 build/host/stage2 ``` -Now you can run the `rustc` you built with via the toolchain. If you run with -`-vV`, you should see a version number ending in `-dev`, indicating a build from +Now you can run the `rustc` you built with via the toolchain. +If you run with `-vV`, you should see a version number ending in `-dev`, indicating a build from your local environment: ```bash @@ -308,14 +317,18 @@ The rustup toolchain points to the specified toolchain compiled in your `build` so the rustup toolchain will be updated whenever `x build` or `x test` are run for that toolchain/stage. -**Note:** the toolchain we've built does not include `cargo`. In this case, `rustup` will +**Note:** the toolchain we've built does not include `cargo`. + In this case, `rustup` will fall back to using `cargo` from the installed `nightly`, `beta`, or `stable` toolchain -(in that order). If you need to use unstable `cargo` flags, be sure to run -`rustup install nightly` if you haven't already. See the +(in that order). + If you need to use unstable `cargo` flags, be sure to run +`rustup install nightly` if you haven't already. + See the [rustup documentation on custom toolchains](https://rust-lang.github.io/rustup/concepts/toolchains.html#custom-toolchains). **Note:** rust-analyzer and IntelliJ Rust plugin use a component called -`rust-analyzer-proc-macro-srv` to work with proc macros. If you intend to use a +`rust-analyzer-proc-macro-srv` to work with proc macros. +If you intend to use a custom toolchain for a project (e.g. via `rustup override set stage1`) you may want to build this component: @@ -368,16 +381,14 @@ cargo +stage1 build --target wasm32-wasip1 ## Other `x` commands -Here are a few other useful `x` commands. We'll cover some of them in detail -in other sections: +Here are a few other useful `x` commands. +We'll cover some of them in detail in other sections: - Building things: - `./x build` – builds everything using the stage 1 compiler, not just up to `std` - - `./x build --stage 2` – builds everything with the stage 2 compiler including - `rustdoc` -- Running tests (see the [section on running tests](../tests/running.html) for - more details): + - `./x build --stage 2` – builds everything with the stage 2 compiler including `rustdoc` +- Running tests (see the [section on running tests](../tests/running.html) for more details): - `./x test library/std` – runs the unit tests and integration tests from `std` - `./x test tests/ui` – runs the `ui` test suite - `./x test tests/ui/const-generics` - runs all the tests in @@ -389,8 +400,8 @@ in other sections: Sometimes you need to start fresh, but this is normally not the case. If you need to run this then bootstrap is most likely not acting right and -you should file a bug as to what is going wrong. If you do need to clean -everything up then you only need to run one command! +you should file a bug as to what is going wrong. +If you do need to clean everything up then you only need to run one command! ```bash ./x clean @@ -402,15 +413,17 @@ a long time even on fast computers. ## Remarks on disk space Building the compiler (especially if beyond stage 1) can require significant amounts of free disk -space, possibly around 100GB. This is compounded if you have a separate build directory for +space, possibly around 100GB. +This is compounded if you have a separate build directory for rust-analyzer (e.g. `build-rust-analyzer`). This is easy to hit with dev-desktops which have a [set disk quota](https://github.com/rust-lang/simpleinfra/blob/8a59e4faeb75a09b072671c74a7cb70160ebef50/ansible/roles/dev-desktop/defaults/main.yml#L7) -for each user, but this also applies to local development as well. Occasionally, you may need to: +for each user, but this also applies to local development as well. +Occasionally, you may need to: - Remove `build/` directory. - Remove `build-rust-analyzer/` directory (if you have a separate rust-analyzer build directory). -- Uninstall unnecessary toolchains if you use `cargo-bisect-rustc`. You can check which toolchains - are installed with `rustup toolchain list`. +- Uninstall unnecessary toolchains if you use `cargo-bisect-rustc`. + You can check which toolchains are installed with `rustup toolchain list`. [^1]: issue[#1707](https://github.com/rust-lang/rustc-dev-guide/issues/1707) From d4ff9c82273c3322c3cc49fb97731d5d3df5c020 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:44:47 +0200 Subject: [PATCH 434/978] less awkward --- src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index 2c127245b810..11c4cac024b0 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -91,7 +91,7 @@ cd rust ## What is `x.py`? `x.py` is the build tool for the `rust` repository. -It can build docs, run tests, and compile the compiler and standard library. +It can build docs, run tests, and build the compiler and standard library. This chapter focuses on the basics to be productive, but if you want to learn more about `x.py`, [read this chapter][bootstrap]. @@ -192,7 +192,7 @@ as rustdoc), make sure to read information about that default (located in `src/b as the build process may be different for other defaults. Alternatively, you can write `bootstrap.toml` by hand. -See `bootstrap.example.toml` for all the available settings and explanations of them. +See `bootstrap.example.toml` for all the available settings and what they do. See `src/bootstrap/defaults` for common settings to change. If you have already built `rustc` and you change settings related to LLVM, then you may have to From e83ee8a2be96f6182703c3d994579ded413d141f Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:45:01 +0200 Subject: [PATCH 435/978] missing pause --- src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index 11c4cac024b0..fc8fe402bfa9 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -329,7 +329,7 @@ fall back to using `cargo` from the installed `nightly`, `beta`, or `stable` too **Note:** rust-analyzer and IntelliJ Rust plugin use a component called `rust-analyzer-proc-macro-srv` to work with proc macros. If you intend to use a -custom toolchain for a project (e.g. via `rustup override set stage1`) you may +custom toolchain for a project (e.g. via `rustup override set stage1`), you may want to build this component: ```bash From 222e5216a0cf4c7b1cdaeb82e72947275fcff8d0 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:46:00 +0200 Subject: [PATCH 436/978] sembr src/building/optimized-build.md --- .../src/building/optimized-build.md | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/optimized-build.md b/src/doc/rustc-dev-guide/src/building/optimized-build.md index d11bfaa4ba00..4953e2004a4c 100644 --- a/src/doc/rustc-dev-guide/src/building/optimized-build.md +++ b/src/doc/rustc-dev-guide/src/building/optimized-build.md @@ -2,15 +2,16 @@ There are multiple additional build configuration options and techniques that can be used to compile a build of `rustc` that is as optimized as possible (for example when building `rustc` for a Linux -distribution). The status of these configuration options for various Rust targets is tracked [here]. +distribution). +The status of these configuration options for various Rust targets is tracked [here]. This page describes how you can use these approaches when building `rustc` yourself. [here]: https://github.com/rust-lang/rust/issues/103595 ## Link-time optimization -Link-time optimization is a powerful compiler technique that can increase program performance. To -enable (Thin-)LTO when building `rustc`, set the `rust.lto` config option to `"thin"` +Link-time optimization is a powerful compiler technique that can increase program performance. +To enable (Thin-)LTO when building `rustc`, set the `rust.lto` config option to `"thin"` in `bootstrap.toml`: ```toml @@ -29,8 +30,8 @@ Enabling LTO on Linux has [produced] speed-ups by up to 10%. ## Memory allocator -Using a different memory allocator for `rustc` can provide significant performance benefits. If you -want to enable the `jemalloc` allocator, you can set the `rust.jemalloc` option to `true` +Using a different memory allocator for `rustc` can provide significant performance benefits. +If you want to enable the `jemalloc` allocator, you can set the `rust.jemalloc` option to `true` in `bootstrap.toml`: ```toml @@ -53,7 +54,8 @@ rust.codegen-units-std = 1 ## Instruction set By default, `rustc` is compiled for a generic (and conservative) instruction set architecture -(depending on the selected target), to make it support as many CPUs as possible. If you want to +(depending on the selected target), to make it support as many CPUs as possible. +If you want to compile `rustc` for a specific instruction set architecture, you can set the `target_cpu` compiler option in `RUSTFLAGS`: @@ -72,14 +74,16 @@ llvm.cflags = "-march=x86-64-v3" ## Profile-guided optimization Applying profile-guided optimizations (or more generally, feedback-directed optimizations) can -produce a large increase to `rustc` performance, by up to 15% ([1], [2]). However, these techniques +produce a large increase to `rustc` performance, by up to 15% ([1], [2]). +However, these techniques are not simply enabled by a configuration option, but rather they require a complex build workflow that compiles `rustc` multiple times and profiles it on selected benchmarks. There is a tool called `opt-dist` that is used to optimize `rustc` with [PGO] (profile-guided -optimizations) and [BOLT] (a post-link binary optimizer) for builds distributed to end users. You -can examine the tool, which is located in `src/tools/opt-dist`, and build a custom PGO build -workflow based on it, or try to use it directly. Note that the tool is currently quite hardcoded to +optimizations) and [BOLT] (a post-link binary optimizer) for builds distributed to end users. +You can examine the tool, which is located in `src/tools/opt-dist`, and build a custom PGO build +workflow based on it, or try to use it directly. +Note that the tool is currently quite hardcoded to the way we use it in Rust's continuous integration workflows, and it might require some custom changes to make it work in a different environment. @@ -93,9 +97,9 @@ changes to make it work in a different environment. To use the tool, you will need to provide some external dependencies: - A Python3 interpreter (for executing `x.py`). -- Compiled LLVM toolchain, with the `llvm-profdata` binary. Optionally, if you want to use BOLT, - the `llvm-bolt` and - `merge-fdata` binaries have to be available in the toolchain. +- Compiled LLVM toolchain, with the `llvm-profdata` binary. + Optionally, if you want to use BOLT, + the `llvm-bolt` and `merge-fdata` binaries have to be available in the toolchain. These dependencies are provided to `opt-dist` by an implementation of the [`Environment`] struct. It specifies directories where will the PGO/BOLT pipeline take place, and also external dependencies From 670fec6bbd14cada71c85b4af9f92c3b48d37751 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:47:52 +0200 Subject: [PATCH 437/978] reflow --- src/doc/rustc-dev-guide/src/building/new-target.md | 3 +-- src/doc/rustc-dev-guide/src/building/optimized-build.md | 5 ++--- src/doc/rustc-dev-guide/src/building/suggested.md | 6 ++---- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/new-target.md b/src/doc/rustc-dev-guide/src/building/new-target.md index 1be83e4a5a58..73174aaa0adf 100644 --- a/src/doc/rustc-dev-guide/src/building/new-target.md +++ b/src/doc/rustc-dev-guide/src/building/new-target.md @@ -72,8 +72,7 @@ somewhat successfully, you can copy the specification into the compiler itself. You will need to add a line to the big table inside of the `supported_targets` macro in the `rustc_target::spec` module. -You will then add a corresponding file for your new target containing a -`target` function. +You will then add a corresponding file for your new target containing a `target` function. Look for existing targets to use as examples. diff --git a/src/doc/rustc-dev-guide/src/building/optimized-build.md b/src/doc/rustc-dev-guide/src/building/optimized-build.md index 4953e2004a4c..0a6b82eba46a 100644 --- a/src/doc/rustc-dev-guide/src/building/optimized-build.md +++ b/src/doc/rustc-dev-guide/src/building/optimized-build.md @@ -55,9 +55,8 @@ rust.codegen-units-std = 1 By default, `rustc` is compiled for a generic (and conservative) instruction set architecture (depending on the selected target), to make it support as many CPUs as possible. -If you want to -compile `rustc` for a specific instruction set architecture, you can set the `target_cpu` compiler -option in `RUSTFLAGS`: +If you want to compile `rustc` for a specific instruction set architecture, +you can set the `target_cpu` compiler option in `RUSTFLAGS`: ```bash RUSTFLAGS="-C target_cpu=x86-64-v3" ./x build ... diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index af4dc0ab699c..3ed4f129d144 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -118,8 +118,7 @@ requires extra disk space. Selecting `vscode` in `./x setup editor` will prompt you to create a `.vscode/settings.json` file which will configure Visual Studio code. -The recommended `rust-analyzer` settings live at -[`src/etc/rust_analyzer_settings.json`]. +The recommended `rust-analyzer` settings live at [`src/etc/rust_analyzer_settings.json`]. If running `./x check` on save is inconvenient, in VS Code you can use a [Build Task] instead: @@ -253,8 +252,7 @@ It can be configured through `.zed/settings.json`, as described [here](https://zed.dev/docs/configuring-languages). Selecting `zed` in `./x setup editor` will prompt you to create a `.zed/settings.json` file which will configure Zed with the recommended configuration. -The recommended `rust-analyzer` settings live -at [`src/etc/rust_analyzer_zed.json`]. +The recommended `rust-analyzer` settings live at [`src/etc/rust_analyzer_zed.json`]. ## Check, check, and check again From a2fa6185513bffff922988979d7ea2a7704767f7 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:49:52 +0200 Subject: [PATCH 438/978] sembr src/compiler-debugging.md --- .../rustc-dev-guide/src/compiler-debugging.md | 60 +++++++++++-------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md index 7b67c262c456..b8f6689b05b2 100644 --- a/src/doc/rustc-dev-guide/src/compiler-debugging.md +++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md @@ -1,14 +1,16 @@ # Debugging the compiler -This chapter contains a few tips to debug the compiler. These tips aim to be -useful no matter what you are working on. Some of the other chapters have +This chapter contains a few tips to debug the compiler. +These tips aim to be useful no matter what you are working on. + Some of the other chapters have advice about specific parts of the compiler (e.g. the [Queries Debugging and Testing chapter](./incrcomp-debugging.html) or the [LLVM Debugging chapter](./backend/debugging.md)). ## Configuring the compiler -By default, rustc is built without most debug information. To enable debug info, +By default, rustc is built without most debug information. +To enable debug info, set `rust.debug = true` in your bootstrap.toml. Setting `rust.debug = true` turns on many different debug options (e.g., `debug-assertions`, @@ -45,16 +47,17 @@ You will need to rebuild the compiler after changing any configuration option. ## Suppressing the ICE file By default, if rustc encounters an Internal Compiler Error (ICE) it will dump the ICE contents to an -ICE file within the current working directory named `rustc-ice--.txt`. If this is -not desirable, you can prevent the ICE file from being created with `RUSTC_ICE=0`. +ICE file within the current working directory named `rustc-ice--.txt`. +If this is not desirable, you can prevent the ICE file from being created with `RUSTC_ICE=0`. ## Getting a backtrace [getting-a-backtrace]: #getting-a-backtrace When you have an ICE (panic in the compiler), you can set -`RUST_BACKTRACE=1` to get the stack trace of the `panic!` like in -normal Rust programs. IIRC backtraces **don't work** on MinGW, -sorry. If you have trouble or the backtraces are full of `unknown`, +`RUST_BACKTRACE=1` to get the stack trace of the `panic!` like in normal Rust programs. +IIRC backtraces **don't work** on MinGW, +sorry. +If you have trouble or the backtraces are full of `unknown`, you might want to find some way to use Linux, Mac, or MSVC on Windows. In the default configuration (without `debug` set to `true`), you don't have line numbers @@ -98,9 +101,10 @@ stack backtrace: ## `-Z` flags -The compiler has a bunch of `-Z *` flags. These are unstable flags that are only -enabled on nightly. Many of them are useful for debugging. To get a full listing -of `-Z` flags, use `-Z help`. +The compiler has a bunch of `-Z *` flags. +These are unstable flags that are only enabled on nightly. +Many of them are useful for debugging. +To get a full listing of `-Z` flags, use `-Z help`. One useful flag is `-Z verbose-internals`, which generally enables printing more info that could be useful for debugging. @@ -112,7 +116,8 @@ Right below you can find elaborate explainers on a selected few. If you want to get a backtrace to the point where the compiler emits an error message, you can pass the `-Z treat-err-as-bug=n`, which will make -the compiler panic on the `nth` error. If you leave off `=n`, the compiler will +the compiler panic on the `nth` error. +If you leave off `=n`, the compiler will assume `1` for `n` and thus panic on the first error it encounters. For example: @@ -188,13 +193,12 @@ Cool, now I have a backtrace for the error! The `-Z eagerly-emit-delayed-bugs` option makes it easy to debug delayed bugs. It turns them into normal errors, i.e. makes them visible. This can be used in -combination with `-Z treat-err-as-bug` to stop at a particular delayed bug and -get a backtrace. +combination with `-Z treat-err-as-bug` to stop at a particular delayed bug and get a backtrace. ### Getting the error creation location -`-Z track-diagnostics` can help figure out where errors are emitted. It uses `#[track_caller]` -for this and prints its location alongside the error: +`-Z track-diagnostics` can help figure out where errors are emitted. +It uses `#[track_caller]` for this and prints its location alongside the error: ``` $ RUST_BACKTRACE=1 rustc +stage1 error.rs -Z track-diagnostics @@ -236,11 +240,11 @@ For details see [the guide section on tracing](./tracing.md) ## Narrowing (Bisecting) Regressions The [cargo-bisect-rustc][bisect] tool can be used as a quick and easy way to -find exactly which PR caused a change in `rustc` behavior. It automatically -downloads `rustc` PR artifacts and tests them against a project you provide -until it finds the regression. You can then look at the PR to get more context -on *why* it was changed. See [this tutorial][bisect-tutorial] on how to use -it. +find exactly which PR caused a change in `rustc` behavior. +It automatically downloads `rustc` PR artifacts and tests them against a project you provide +until it finds the regression. +You can then look at the PR to get more context on *why* it was changed. + See [this tutorial][bisect-tutorial] on how to use it. [bisect]: https://github.com/rust-lang/cargo-bisect-rustc [bisect-tutorial]: https://rust-lang.github.io/cargo-bisect-rustc/tutorial.html @@ -250,8 +254,9 @@ it. The [rustup-toolchain-install-master][rtim] tool by kennytm can be used to download the artifacts produced by Rust's CI for a specific SHA1 -- this basically corresponds to the successful landing of some PR -- and then sets -them up for your local use. This also works for artifacts produced by `@bors -try`. This is helpful when you want to examine the resulting build of a PR +them up for your local use. +This also works for artifacts produced by `@bors try`. +This is helpful when you want to examine the resulting build of a PR without doing the build yourself. [rtim]: https://github.com/kennytm/rustup-toolchain-install-master @@ -259,10 +264,12 @@ without doing the build yourself. ## `#[rustc_*]` TEST attributes The compiler defines a whole lot of internal (perma-unstable) attributes some of which are useful -for debugging by dumping extra compiler-internal information. These are prefixed with `rustc_` and +for debugging by dumping extra compiler-internal information. +These are prefixed with `rustc_` and are gated behind the internal feature `rustc_attrs` (enabled via e.g. `#![feature(rustc_attrs)]`). -For a complete and up to date list, see [`builtin_attrs`]. More specifically, the ones marked `TEST`. +For a complete and up to date list, see [`builtin_attrs`]. +More specifically, the ones marked `TEST`. Here are some notable ones: | Attribute | Description | @@ -311,7 +318,8 @@ $ firefox maybe_init_suffix.pdf # Or your favorite pdf viewer ### Debugging type layouts The internal attribute `#[rustc_layout]` can be used to dump the [`Layout`] of -the type it is attached to. For example: +the type it is attached to. +For example: ```rust #![feature(rustc_attrs)] From faea3136bba95ceefb7a5eb0c96d001bc85bc307 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:53:58 +0200 Subject: [PATCH 439/978] whitespace --- src/doc/rustc-dev-guide/src/compiler-debugging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md index b8f6689b05b2..8efcf07d5237 100644 --- a/src/doc/rustc-dev-guide/src/compiler-debugging.md +++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md @@ -2,7 +2,7 @@ This chapter contains a few tips to debug the compiler. These tips aim to be useful no matter what you are working on. - Some of the other chapters have +Some of the other chapters have advice about specific parts of the compiler (e.g. the [Queries Debugging and Testing chapter](./incrcomp-debugging.html) or the [LLVM Debugging chapter](./backend/debugging.md)). From 8c322fcdb3298e445fabb8c5cea5cae151c3daa3 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:55:09 +0200 Subject: [PATCH 440/978] sembr src/llvm-coverage-instrumentation.md --- .../src/llvm-coverage-instrumentation.md | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md index fbfcc4198de6..0dde8ed6c9ff 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -7,13 +7,13 @@ libraries and binaries with additional instructions and data, at compile time. The coverage instrumentation injects calls to the LLVM intrinsic instruction [`llvm.instrprof.increment`][llvm-instrprof-increment] at code branches (based on a MIR-based control flow analysis), and LLVM converts these to -instructions that increment static counters, when executed. The LLVM coverage -instrumentation also requires a [Coverage Map] that encodes source metadata, +instructions that increment static counters, when executed. +The LLVM coverage instrumentation also requires a [Coverage Map] that encodes source metadata, mapping counter IDs--directly and indirectly--to the file locations (with start and end line and column). -Rust libraries, with or without coverage instrumentation, can be linked into -instrumented binaries. When the program is executed and cleanly terminates, +Rust libraries, with or without coverage instrumentation, can be linked into instrumented binaries. +When the program is executed and cleanly terminates, LLVM libraries write the final counter values to a file (`default.profraw` or a custom file set through environment variable `LLVM_PROFILE_FILE`). @@ -22,8 +22,7 @@ files, with corresponding Coverage Maps (from matching binaries that produced them), and generate various reports for analysis, for example: Screenshot of sample `llvm-cov show` result, for function add_quoted_string -
+ src="img/llvm-cov-show-01.png" class="center"/>
Detailed instructions and examples are documented in the [rustc book][rustc-book-instrument-coverage]. @@ -39,8 +38,7 @@ When working on the coverage instrumentation code, it is usually necessary to This allows the compiler to produce instrumented binaries, and makes it possible to run the full coverage test suite. -Enabling debug assertions in the compiler and in LLVM is recommended, but not -mandatory. +Enabling debug assertions in the compiler and in LLVM is recommended, but not mandatory. ```toml # Similar to the "compiler" profile, but also enables debug assertions in LLVM. @@ -60,8 +58,8 @@ rust.debug-assertions = true `-C instrument-coverage` automatically enables Rust symbol mangling `v0` (as if the user specified `-C symbol-mangling-version=v0` option when invoking -`rustc`) to ensure consistent and reversible name mangling. This has two -important benefits: +`rustc`) to ensure consistent and reversible name mangling. +This has two important benefits: 1. LLVM coverage tools can analyze coverage over multiple runs, including some changes to source code; so mangled names must be consistent across compilations. @@ -71,8 +69,8 @@ important benefits: ## The LLVM profiler runtime -Coverage data is only generated by running the executable Rust program. `rustc` -statically links coverage-instrumented binaries with LLVM runtime code +Coverage data is only generated by running the executable Rust program. +`rustc` statically links coverage-instrumented binaries with LLVM runtime code ([compiler-rt][compiler-rt-profile]) that implements program hooks (such as an `exit` hook) to write the counter values to the `.profraw` file. From 48760618e8ecdd5eab2acdb4f1a9c8f7d9416b99 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 01:02:14 +0200 Subject: [PATCH 441/978] replace html with markdown --- src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md index 0dde8ed6c9ff..8e94928c8a1a 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -21,8 +21,7 @@ Developers use existing LLVM coverage analysis tools to decode `.profraw` files, with corresponding Coverage Maps (from matching binaries that produced them), and generate various reports for analysis, for example: -Screenshot of sample `llvm-cov show` result, for function add_quoted_string
+![Screenshot of sample `llvm-cov show` result, for function add_quoted_string](img/llvm-cov-show-01.png) Detailed instructions and examples are documented in the [rustc book][rustc-book-instrument-coverage]. From 0c6e040daddbaef2badd583de2beed043068fa11 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 01:03:06 +0200 Subject: [PATCH 442/978] sembr src/profiling.md --- src/doc/rustc-dev-guide/src/profiling.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/profiling.md b/src/doc/rustc-dev-guide/src/profiling.md index 06ebb8998342..66eabe7d8c93 100644 --- a/src/doc/rustc-dev-guide/src/profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling.md @@ -33,10 +33,11 @@ Since most of the time compiling rustc is spent in LLVM, the idea is that by reducing the amount of code passed to LLVM, compiling rustc gets faster. To use `cargo-llvm-lines` together with somewhat custom rustc build process, you can use -`-C save-temps` to obtain required LLVM IR. The option preserves temporary work products -created during compilation. Among those is LLVM IR that represents an input to the -optimization pipeline; ideal for our purposes. It is stored in files with `*.no-opt.bc` -extension in LLVM bitcode format. +`-C save-temps` to obtain required LLVM IR. +The option preserves temporary work products created during compilation. +Among those is LLVM IR that represents an input to the +optimization pipeline; ideal for our purposes. +It is stored in files with `*.no-opt.bc` extension in LLVM bitcode format. Example usage: ``` @@ -105,7 +106,8 @@ rust.codegen-units = 0 # num_cpus The llvm-lines output is affected by several options. `rust.optimize = false` increases it from 2.1GB to 3.5GB and `codegen-units = 0` to 4.1GB. -MIR optimizations have little impact. Compared to the default `RUSTFLAGS="-Z +MIR optimizations have little impact. +Compared to the default `RUSTFLAGS="-Z mir-opt-level=1"`, level 0 adds 0.3GB and level 2 removes 0.2GB. As of July 2022, inlining happens in LLVM and GCC codegen backends, From 809bf7922fc47eb4bf6ea59fde8db66779ae40fb Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 01:04:49 +0200 Subject: [PATCH 443/978] sembr src/tests/docker.md --- src/doc/rustc-dev-guide/src/tests/docker.md | 60 +++++++++++++-------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/docker.md b/src/doc/rustc-dev-guide/src/tests/docker.md index 436aa13545eb..94fdf34dc80d 100644 --- a/src/doc/rustc-dev-guide/src/tests/docker.md +++ b/src/doc/rustc-dev-guide/src/tests/docker.md @@ -1,12 +1,14 @@ # Testing with Docker -The [`src/ci/docker`] directory includes [Docker] image definitions for Linux-based jobs executed on GitHub Actions (non-Linux jobs run outside Docker). You can run these jobs on your local development machine, which can be -helpful to test environments different from your local system. You will -need to install Docker on a Linux, Windows, or macOS system (typically Linux +The [`src/ci/docker`] directory includes [Docker] image definitions for Linux-based jobs executed on GitHub Actions (non-Linux jobs run outside Docker). +You can run these jobs on your local development machine, which can be +helpful to test environments different from your local system. +You will need to install Docker on a Linux, Windows, or macOS system (typically Linux will be much faster than Windows or macOS because the latter use virtual machines to emulate a Linux environment). -Jobs running in CI are configured through a set of bash scripts, and it is not always trivial to reproduce their behavior locally. If you want to run a CI job locally in the simplest way possible, you can use a provided helper `citool` that tries to replicate what happens on CI as closely as possible: +Jobs running in CI are configured through a set of bash scripts, and it is not always trivial to reproduce their behavior locally. +If you want to run a CI job locally in the simplest way possible, you can use a provided helper `citool` that tries to replicate what happens on CI as closely as possible: ```bash cargo run --manifest-path src/ci/citool/Cargo.toml run-local @@ -18,39 +20,51 @@ If the above script does not work for you, you would like to have more control o ## The `run.sh` script The [`src/ci/docker/run.sh`] script is used to build a specific Docker image, run it, -build Rust within the image, and either run tests or prepare a set of archives designed for distribution. The script will mount your local Rust source tree in read-only mode, and an `obj` directory in read-write mode. All the compiler artifacts will be stored in the `obj` directory. The shell will start out in the `obj`directory. From there, it will execute `../src/ci/run.sh` which starts the build as defined by the Docker image. +build Rust within the image, and either run tests or prepare a set of archives designed for distribution. +The script will mount your local Rust source tree in read-only mode, and an `obj` directory in read-write mode. +All the compiler artifacts will be stored in the `obj` directory. +The shell will start out in the `obj`directory. +From there, it will execute `../src/ci/run.sh` which starts the build as defined by the Docker image. -You can run `src/ci/docker/run.sh ` directly. A few important notes regarding the `run.sh` script: -- When executed on CI, the script expects that all submodules are checked out. If some submodule that is accessed by the job is not available, the build will result in an error. You should thus make sure that you have all required submodules checked out locally. You can either do that manually through git, or set `build.submodules = true` in your `bootstrap.toml` and run a command such as `x build` to let bootstrap download the most important submodules (this might not be enough for the given CI job that you are trying to execute though). -- `` corresponds to a single directory located in one of the `src/ci/docker/host-*` directories. Note that image name does not necessarily correspond to a job name, as some jobs execute the same image, but with different environment variables or Docker build arguments (this is a part of the complexity that makes it difficult to run CI jobs locally). +You can run `src/ci/docker/run.sh ` directly. +A few important notes regarding the `run.sh` script: +- When executed on CI, the script expects that all submodules are checked out. + If some submodule that is accessed by the job is not available, the build will result in an error. + You should thus make sure that you have all required submodules checked out locally. + You can either do that manually through git, or set `build.submodules = true` in your `bootstrap.toml` and run a command such as `x build` to let bootstrap download the most important submodules (this might not be enough for the given CI job that you are trying to execute though). +- `` corresponds to a single directory located in one of the `src/ci/docker/host-*` directories. + Note that image name does not necessarily correspond to a job name, as some jobs execute the same image, but with different environment variables or Docker build arguments (this is a part of the complexity that makes it difficult to run CI jobs locally). - If you are executing a "dist" job (job beginning with `dist-`), you should set the `DEPLOY=1` environment variable. - If you are executing an "alternative dist" job (job beginning with `dist-` and ending with `-alt`), you should set the `DEPLOY_ALT=1` environment variable. -- Some of the std tests require IPv6 support. Docker on Linux seems to have it - disabled by default. Run the commands in [`enable-docker-ipv6.sh`] to enable - IPv6 before creating the container. This only needs to be done once. +- Some of the std tests require IPv6 support. + Docker on Linux seems to have it disabled by default. + Run the commands in [`enable-docker-ipv6.sh`] to enable IPv6 before creating the container. + This only needs to be done once. ### Interactive mode -Sometimes, it can be useful to build a specific Docker image, and then run custom commands inside it, so that you can experiment with how the given system behaves. You can do that using an interactive mode, which will +Sometimes, it can be useful to build a specific Docker image, and then run custom commands inside it, so that you can experiment with how the given system behaves. +You can do that using an interactive mode, which will start a bash shell in the container, using `src/ci/docker/run.sh --dev `. -When inside the Docker container, you can run individual commands to do specific tasks. For -example, you can run `../x test tests/ui` to just run UI tests. +When inside the Docker container, you can run individual commands to do specific tasks. +For example, you can run `../x test tests/ui` to just run UI tests. Some additional notes about using the interactive mode: - The container will be deleted automatically when you exit the shell, however - the build artifacts persist in the `obj` directory. If you are switching - between different Docker images, the artifacts from previous environments - stored in the `obj` directory may confuse the build system. Sometimes you - will need to delete parts or all of the `obj` directory before building + the build artifacts persist in the `obj` directory. + If you are switching between different Docker images, the artifacts from previous environments + stored in the `obj` directory may confuse the build system. + Sometimes you will need to delete parts or all of the `obj` directory before building inside the container. -- The container is bare-bones, with only a minimal set of packages. You may - want to install some things like `apt install less vim`. -- You can open multiple shells in the container. First you need the container +- The container is bare-bones, with only a minimal set of packages. + You may want to install some things like `apt install less vim`. +- You can open multiple shells in the container. + First you need the container name (a short hash), which is displayed in the shell prompt, or you can run - `docker container ls` outside of the container to list the available - containers. With the container name, run `docker exec -it + `docker container ls` outside of the container to list the available containers. + With the container name, run `docker exec -it /bin/bash` where `` is the container name like `4ba195e95cef`. [Docker]: https://www.docker.com/ From 06af960fba2777f8865351e4cc256f82fee911c9 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 01:10:53 +0200 Subject: [PATCH 444/978] sounds better as separate sentences --- src/doc/rustc-dev-guide/src/tests/docker.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/docker.md b/src/doc/rustc-dev-guide/src/tests/docker.md index 94fdf34dc80d..51beee8a866c 100644 --- a/src/doc/rustc-dev-guide/src/tests/docker.md +++ b/src/doc/rustc-dev-guide/src/tests/docker.md @@ -31,9 +31,11 @@ A few important notes regarding the `run.sh` script: - When executed on CI, the script expects that all submodules are checked out. If some submodule that is accessed by the job is not available, the build will result in an error. You should thus make sure that you have all required submodules checked out locally. - You can either do that manually through git, or set `build.submodules = true` in your `bootstrap.toml` and run a command such as `x build` to let bootstrap download the most important submodules (this might not be enough for the given CI job that you are trying to execute though). + You can either do that manually through git, or set `build.submodules = true` in your `bootstrap.toml` and run a command such as `x build` to let bootstrap download the most important submodules + Note that this might not be enough for the given CI job that you are trying to execute though. - `` corresponds to a single directory located in one of the `src/ci/docker/host-*` directories. - Note that image name does not necessarily correspond to a job name, as some jobs execute the same image, but with different environment variables or Docker build arguments (this is a part of the complexity that makes it difficult to run CI jobs locally). + Note that image name does not necessarily correspond to a job name, as some jobs execute the same image, but with different environment variables or Docker build arguments + This is a part of the complexity that makes it difficult to run CI jobs locally. - If you are executing a "dist" job (job beginning with `dist-`), you should set the `DEPLOY=1` environment variable. - If you are executing an "alternative dist" job (job beginning with `dist-` and ending with `-alt`), you should set the `DEPLOY_ALT=1` environment variable. - Some of the std tests require IPv6 support. From 3ea1571787bbfdbdf0596e4c73a08e1257ac89d4 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 3 Feb 2026 00:54:07 +0200 Subject: [PATCH 445/978] reflow --- src/doc/rustc-dev-guide/src/compiler-debugging.md | 3 +-- src/doc/rustc-dev-guide/src/tests/compiletest.md | 3 +-- src/doc/rustc-dev-guide/src/tracing.md | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md index 8efcf07d5237..d4c599a6edf7 100644 --- a/src/doc/rustc-dev-guide/src/compiler-debugging.md +++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md @@ -55,8 +55,7 @@ If this is not desirable, you can prevent the ICE file from being created with ` When you have an ICE (panic in the compiler), you can set `RUST_BACKTRACE=1` to get the stack trace of the `panic!` like in normal Rust programs. -IIRC backtraces **don't work** on MinGW, -sorry. +IIRC backtraces **don't work** on MinGW, sorry. If you have trouble or the backtraces are full of `unknown`, you might want to find some way to use Linux, Mac, or MSVC on Windows. diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index d7372de11ff8..959a73a5a9ad 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -277,8 +277,7 @@ the debugger currently being used: gdb is in a range (inclusive) - `min-lldb-version: 310` — ignores the test if the version of lldb is below the given version - `rust-lldb` — ignores the test if lldb is not contain the Rust plugin. - NOTE: The "Rust" version of LLDB doesn't exist anymore, so this will always be - ignored. + NOTE: The "Rust" version of LLDB doesn't exist anymore, so this will always be ignored. This should probably be removed. By passing the `--debugger` option to compiletest, you can specify a single debugger to run tests with. diff --git a/src/doc/rustc-dev-guide/src/tracing.md b/src/doc/rustc-dev-guide/src/tracing.md index 323f81dcee04..2ad035bbafbc 100644 --- a/src/doc/rustc-dev-guide/src/tracing.md +++ b/src/doc/rustc-dev-guide/src/tracing.md @@ -74,8 +74,7 @@ RUSTC_LOG=[typeck] The query arguments are included as a tracing field which means that you can filter on the debug display of the arguments. For example, the `typeck` query has an argument `key: LocalDefId` of what is being checked. -You can use a regex to match on that `LocalDefId` to log type checking for a specific -function: +You can use a regex to match on that `LocalDefId` to log type checking for a specific function: ``` RUSTC_LOG=[typeck{key=.*name_of_item.*}] From ee58df4ac93b9f4ebb24344ea48d60f2d1fdd882 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 2 Feb 2026 22:47:06 +0200 Subject: [PATCH 446/978] there is a policy now --- src/doc/rustc-dev-guide/src/crates-io.md | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/crates-io.md b/src/doc/rustc-dev-guide/src/crates-io.md index 677b1fc03134..2a7431b40310 100644 --- a/src/doc/rustc-dev-guide/src/crates-io.md +++ b/src/doc/rustc-dev-guide/src/crates-io.md @@ -3,17 +3,7 @@ The Rust compiler supports building with some dependencies from `crates.io`. Examples are `log` and `env_logger`. -In general, -you should avoid adding dependencies to the compiler for several reasons: - -- The dependency may not be of high quality or well-maintained. -- The dependency may not be using a compatible license. -- The dependency may have transitive dependencies that have one of the above - problems. - - -Note that there is no official policy for vetting new dependencies to the compiler. -Decisions are made on a case-by-case basis, during code review. +Rust Forge has [official policy for vetting new dependencies]. ## Permitted dependencies @@ -21,3 +11,4 @@ The `tidy` tool has [a list of crates that are allowed]. To add a dependency that is not already in the compiler, you will need to add it to the list. [a list of crates that are allowed]: https://github.com/rust-lang/rust/blob/9d1b2106e23b1abd32fce1f17267604a5102f57a/src/tools/tidy/src/deps.rs#L73 +[official policy for vetting new dependencies]: https://forge.rust-lang.org/compiler/third-party-out-of-tree#third-party-crates From 1c7e6161f12dfac787c16cfd254da00e6d431f58 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 2 Feb 2026 22:48:26 +0200 Subject: [PATCH 447/978] they are so many that it feels strange to list any --- src/doc/rustc-dev-guide/src/crates-io.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/crates-io.md b/src/doc/rustc-dev-guide/src/crates-io.md index 2a7431b40310..7e998020513e 100644 --- a/src/doc/rustc-dev-guide/src/crates-io.md +++ b/src/doc/rustc-dev-guide/src/crates-io.md @@ -1,7 +1,6 @@ # crates.io dependencies The Rust compiler supports building with some dependencies from `crates.io`. -Examples are `log` and `env_logger`. Rust Forge has [official policy for vetting new dependencies]. From e9965b80ff5f723d55a0a5ee5dcab63534062e34 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 2 Feb 2026 22:50:10 +0200 Subject: [PATCH 448/978] sembr src/crates-io.md --- src/doc/rustc-dev-guide/src/crates-io.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/crates-io.md b/src/doc/rustc-dev-guide/src/crates-io.md index 7e998020513e..4c6de98ab56e 100644 --- a/src/doc/rustc-dev-guide/src/crates-io.md +++ b/src/doc/rustc-dev-guide/src/crates-io.md @@ -6,8 +6,8 @@ Rust Forge has [official policy for vetting new dependencies]. ## Permitted dependencies -The `tidy` tool has [a list of crates that are allowed]. To add a -dependency that is not already in the compiler, you will need to add it to the list. +The `tidy` tool has [a list of crates that are allowed]. +To add a dependency that is not already in the compiler, you will need to add it to the list. [a list of crates that are allowed]: https://github.com/rust-lang/rust/blob/9d1b2106e23b1abd32fce1f17267604a5102f57a/src/tools/tidy/src/deps.rs#L73 [official policy for vetting new dependencies]: https://forge.rust-lang.org/compiler/third-party-out-of-tree#third-party-crates From 28feae0c875f8e95ea667abd5d32b49bcf978164 Mon Sep 17 00:00:00 2001 From: ltdk Date: Mon, 2 Feb 2026 17:34:15 -0500 Subject: [PATCH 449/978] Move bigint helper tracking issues --- library/core/src/lib.rs | 4 ++- library/core/src/num/int_macros.rs | 26 ++++++++++---------- library/core/src/num/uint_macros.rs | 24 +++++++++--------- library/coretests/tests/lib.rs | 4 ++- library/stdarch/crates/core_arch/src/lib.rs | 1 - tests/assembly-llvm/x86_64-bigint-helpers.rs | 1 - tests/codegen-llvm/bigint-helpers.rs | 1 - 7 files changed, 31 insertions(+), 30 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e8c9d26fb3b5..432ca50b3361 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -97,7 +97,6 @@ // tidy-alphabetical-start #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] -#![feature(bigint_helper_methods)] #![feature(bstr)] #![feature(bstr_internals)] #![feature(cfg_select)] @@ -107,6 +106,7 @@ #![feature(const_destruct)] #![feature(const_eval_select)] #![feature(const_select_unpredictable)] +#![feature(const_unsigned_bigint_helpers)] #![feature(core_intrinsics)] #![feature(coverage_attribute)] #![feature(disjoint_bitor)] @@ -120,6 +120,7 @@ #![feature(ptr_alignment_type)] #![feature(ptr_metadata)] #![feature(set_ptr_value)] +#![feature(signed_bigint_helpers)] #![feature(slice_ptr_get)] #![feature(str_internals)] #![feature(str_split_inclusive_remainder)] @@ -129,6 +130,7 @@ #![feature(unsafe_pinned)] #![feature(utf16_extra)] #![feature(variant_count)] +#![feature(widening_mul)] // tidy-alphabetical-end // // Language features: diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 9a27f8a0b5e6..b21865a9ae54 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2522,7 +2522,7 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(signed_bigint_helpers)] /// // Only the most significant word is signed. /// // #[doc = concat!("// 10 MAX (a = 10 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")] @@ -2544,7 +2544,7 @@ macro_rules! int_impl { /// /// assert_eq!((sum1, sum0), (6, 8)); /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "signed_bigint_helpers", issue = "151989")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2625,7 +2625,7 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(signed_bigint_helpers)] /// // Only the most significant word is signed. /// // #[doc = concat!("// 6 8 (a = 6 × 2^", stringify!($BITS), " + 8)")] @@ -2647,7 +2647,7 @@ macro_rules! int_impl { /// #[doc = concat!("assert_eq!((diff1, diff0), (10, ", stringify!($UnsignedT), "::MAX));")] /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "signed_bigint_helpers", issue = "151989")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2717,12 +2717,12 @@ macro_rules! int_impl { /// Please note that this example is shared among integer types, which is why `i32` is used. /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(widening_mul)] /// assert_eq!(5i32.widening_mul(-2), (4294967286, -1)); /// assert_eq!(1_000_000_000i32.widening_mul(-10), (2884901888, -3)); /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "widening_mul", issue = "152016")] + #[rustc_const_unstable(feature = "widening_mul", issue = "152016")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2747,7 +2747,7 @@ macro_rules! int_impl { /// Please note that this example is shared among integer types, which is why `i32` is used. /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(signed_bigint_helpers)] /// assert_eq!(5i32.carrying_mul(-2, 0), (4294967286, -1)); /// assert_eq!(5i32.carrying_mul(-2, 10), (0, 0)); /// assert_eq!(1_000_000_000i32.carrying_mul(-10, 0), (2884901888, -3)); @@ -2757,8 +2757,8 @@ macro_rules! int_impl { "(", stringify!($SelfT), "::MAX.unsigned_abs() + 1, ", stringify!($SelfT), "::MAX / 2));" )] /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "signed_bigint_helpers", issue = "151989")] + #[rustc_const_unstable(feature = "signed_bigint_helpers", issue = "151989")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2784,7 +2784,7 @@ macro_rules! int_impl { /// Please note that this example is shared among integer types, which is why `i32` is used. /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(signed_bigint_helpers)] /// assert_eq!(5i32.carrying_mul_add(-2, 0, 0), (4294967286, -1)); /// assert_eq!(5i32.carrying_mul_add(-2, 10, 10), (10, 0)); /// assert_eq!(1_000_000_000i32.carrying_mul_add(-10, 0, 0), (2884901888, -3)); @@ -2794,8 +2794,8 @@ macro_rules! int_impl { "(", stringify!($UnsignedT), "::MAX, ", stringify!($SelfT), "::MAX / 2));" )] /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "signed_bigint_helpers", issue = "151989")] + #[rustc_const_unstable(feature = "signed_bigint_helpers", issue = "151989")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index c48320c0eab3..5c263ea845cc 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2807,7 +2807,7 @@ macro_rules! uint_impl { /// assert_eq!((sum1, sum0), (9, 6)); /// ``` #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[rustc_const_unstable(feature = "const_unsigned_bigint_helpers", issue = "152015")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2899,7 +2899,7 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!((diff1, diff0), (3, ", stringify!($SelfT), "::MAX));")] /// ``` #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[rustc_const_unstable(feature = "const_unsigned_bigint_helpers", issue = "152015")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3011,14 +3011,14 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(widening_mul)] #[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".widening_mul(7), (35, 0));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_mul(", stringify!($SelfT), "::MAX), (1, ", stringify!($SelfT), "::MAX - 1));")] /// ``` /// /// Compared to other `*_mul` methods: /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(widening_mul)] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::widening_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, 3));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::overflowing_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, true));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::wrapping_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), 0);")] @@ -3028,12 +3028,12 @@ macro_rules! uint_impl { /// Please note that this example is shared among integer types, which is why `u32` is used. /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(widening_mul)] /// assert_eq!(5u32.widening_mul(2), (10, 0)); /// assert_eq!(1_000_000_000u32.widening_mul(10), (1410065408, 2)); /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "widening_mul", issue = "152016")] + #[rustc_const_unstable(feature = "widening_mul", issue = "152016")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3072,7 +3072,7 @@ macro_rules! uint_impl { /// implementing it for wider-than-native types. /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(const_unsigned_bigint_helpers)] /// fn scalar_mul_eq(little_endian_digits: &mut Vec, multiplicand: u16) { /// let mut carry = 0; /// for d in little_endian_digits.iter_mut() { @@ -3097,7 +3097,7 @@ macro_rules! uint_impl { /// except that it gives the value of the overflow instead of just whether one happened: /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(const_unsigned_bigint_helpers)] /// let r = u8::carrying_mul(7, 13, 0); /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(7, 13)); /// let r = u8::carrying_mul(13, 42, 0); @@ -3109,14 +3109,14 @@ macro_rules! uint_impl { /// [`wrapping_add`](Self::wrapping_add) methods: /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(const_unsigned_bigint_helpers)] /// assert_eq!( /// 789_u16.carrying_mul(456, 123).0, /// 789_u16.wrapping_mul(456).wrapping_add(123), /// ); /// ``` #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[rustc_const_unstable(feature = "const_unsigned_bigint_helpers", issue = "152015")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3182,7 +3182,7 @@ macro_rules! uint_impl { /// ); /// ``` #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[rustc_const_unstable(feature = "const_unsigned_bigint_helpers", issue = "152015")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 9054eada12fb..d085e4ad1a8f 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -8,7 +8,6 @@ #![feature(ascii_char_variants)] #![feature(async_iter_from_iter)] #![feature(async_iterator)] -#![feature(bigint_helper_methods)] #![feature(bool_to_result)] #![feature(bstr)] #![feature(cfg_target_has_reliable_f16_f128)] @@ -34,6 +33,7 @@ #![feature(const_result_trait_fn)] #![feature(const_select_unpredictable)] #![feature(const_trait_impl)] +#![feature(const_unsigned_bigint_helpers)] #![feature(control_flow_ok)] #![feature(core_float_math)] #![feature(core_intrinsics)] @@ -98,6 +98,7 @@ #![feature(portable_simd)] #![feature(ptr_metadata)] #![feature(result_option_map_or_default)] +#![feature(signed_bigint_helpers)] #![feature(slice_from_ptr_range)] #![feature(slice_index_methods)] #![feature(slice_internals)] @@ -122,6 +123,7 @@ #![feature(uint_gather_scatter_bits)] #![feature(unsize)] #![feature(unwrap_infallible)] +#![feature(widening_mul)] // tidy-alphabetical-end #![allow(internal_features)] #![deny(fuzzy_provenance_casts)] diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index 3992eaee30fd..039a4c4411f2 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -33,7 +33,6 @@ f16, aarch64_unstable_target_feature, target_feature_inline_always, - bigint_helper_methods, funnel_shifts, avx10_target_feature, const_trait_impl, diff --git a/tests/assembly-llvm/x86_64-bigint-helpers.rs b/tests/assembly-llvm/x86_64-bigint-helpers.rs index 9d998a31cf30..d5d1eba99f39 100644 --- a/tests/assembly-llvm/x86_64-bigint-helpers.rs +++ b/tests/assembly-llvm/x86_64-bigint-helpers.rs @@ -4,7 +4,6 @@ //@ compile-flags: -C llvm-args=-x86-asm-syntax=intel #![no_std] -#![feature(bigint_helper_methods)] // This checks that the `carrying_add` and `borrowing_sub` implementation successfully chain, // to catch issues like diff --git a/tests/codegen-llvm/bigint-helpers.rs b/tests/codegen-llvm/bigint-helpers.rs index ec70a3eabedb..404dc901de8c 100644 --- a/tests/codegen-llvm/bigint-helpers.rs +++ b/tests/codegen-llvm/bigint-helpers.rs @@ -1,7 +1,6 @@ //@ compile-flags: -C opt-level=3 #![crate_type = "lib"] -#![feature(bigint_helper_methods)] // Note that there's also an assembly test for this, which is what checks for // the `ADC` (Add with Carry) instruction on x86 now that the IR we emit uses From 1c4940b2bedafe80058fa81d283c6de32307ed4f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Feb 2026 09:29:54 +1100 Subject: [PATCH 450/978] Remove an unneeded `HashStable` derive. This has the nice side-effect of eliminating `rustc_codegen_ssa`'s dependency on `rustc_query_system`. (Indeed, looking through such dependencies was how I found this.) --- Cargo.lock | 1 - compiler/rustc_codegen_ssa/Cargo.toml | 1 - compiler/rustc_codegen_ssa/src/lib.rs | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 02459afa9072..d3bd5d7b71b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3684,7 +3684,6 @@ dependencies = [ "rustc_macros", "rustc_metadata", "rustc_middle", - "rustc_query_system", "rustc_serialize", "rustc_session", "rustc_span", diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 9c5a3d839ceb..3d045a02fef1 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -28,7 +28,6 @@ rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_macros = { path = "../rustc_macros" } rustc_metadata = { path = "../rustc_metadata" } rustc_middle = { path = "../rustc_middle" } -rustc_query_system = { path = "../rustc_query_system" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 3ffc16d49ac1..904c74944959 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -24,7 +24,7 @@ use rustc_data_structures::unord::UnordMap; use rustc_hir::CRATE_HIR_ID; use rustc_hir::attrs::{CfgEntry, NativeLibKind, WindowsSubsystemKind}; use rustc_hir::def_id::CrateNum; -use rustc_macros::{Decodable, Encodable, HashStable}; +use rustc_macros::{Decodable, Encodable}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::WorkProduct; use rustc_middle::lint::LevelAndSource; @@ -175,7 +175,7 @@ bitflags::bitflags! { } } -#[derive(Clone, Debug, Encodable, Decodable, HashStable)] +#[derive(Clone, Debug, Encodable, Decodable)] pub struct NativeLib { pub kind: NativeLibKind, pub name: Symbol, From 2b0cce040dc698332f3602db3dc7b7e5cf352b59 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 2 Feb 2026 18:13:43 -0800 Subject: [PATCH 451/978] Ignore all debuginfo tests for LLDB that we do not run in CI We only run LLDB 1500 in CI. Any test with a min-lldb-version above that is currently ignored. It's not clear any of these tests actually work with that LLDB version, and they definitely don't work on LLDB ~2100. So, ignore them until we fix debuginfo testing. --- tests/debuginfo/borrowed-enum.rs | 3 ++- tests/debuginfo/by-value-non-immediate-argument.rs | 3 ++- tests/debuginfo/coroutine-objects.rs | 3 ++- tests/debuginfo/enum-thinlto.rs | 3 ++- tests/debuginfo/function-arg-initialization.rs | 3 ++- tests/debuginfo/function-prologue-stepping-regular.rs | 3 ++- tests/debuginfo/issue-57822.rs | 3 ++- tests/debuginfo/macro-stepping.rs | 3 ++- tests/debuginfo/method-on-enum.rs | 3 ++- tests/debuginfo/msvc-pretty-enums.rs | 3 ++- tests/debuginfo/opt/dead_refs.rs | 3 ++- tests/debuginfo/option-like-enum.rs | 3 ++- tests/debuginfo/pretty-std.rs | 3 ++- tests/debuginfo/strings-and-strs.rs | 3 ++- tests/debuginfo/struct-in-enum.rs | 3 ++- tests/debuginfo/struct-style-enum.rs | 3 ++- tests/debuginfo/tuple-style-enum.rs | 3 ++- tests/debuginfo/unique-enum.rs | 3 ++- 18 files changed, 36 insertions(+), 18 deletions(-) diff --git a/tests/debuginfo/borrowed-enum.rs b/tests/debuginfo/borrowed-enum.rs index 9c6e466c43c2..b87d1f2b96d2 100644 --- a/tests/debuginfo/borrowed-enum.rs +++ b/tests/debuginfo/borrowed-enum.rs @@ -1,4 +1,5 @@ -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ compile-flags:-g //@ disable-gdb-pretty-printers diff --git a/tests/debuginfo/by-value-non-immediate-argument.rs b/tests/debuginfo/by-value-non-immediate-argument.rs index 523f6b7623d1..4ecb76ee0846 100644 --- a/tests/debuginfo/by-value-non-immediate-argument.rs +++ b/tests/debuginfo/by-value-non-immediate-argument.rs @@ -1,4 +1,5 @@ -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ min-gdb-version: 13.0 //@ compile-flags:-g //@ disable-gdb-pretty-printers diff --git a/tests/debuginfo/coroutine-objects.rs b/tests/debuginfo/coroutine-objects.rs index 598de2ee4538..783156e07b8e 100644 --- a/tests/debuginfo/coroutine-objects.rs +++ b/tests/debuginfo/coroutine-objects.rs @@ -1,4 +1,5 @@ -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb // LLDB (18.1+) now supports DW_TAG_variant_part, but there is some bug in either compiler or LLDB // with memory layout of discriminant for this particular enum diff --git a/tests/debuginfo/enum-thinlto.rs b/tests/debuginfo/enum-thinlto.rs index 4da49022630a..ef41feec6e24 100644 --- a/tests/debuginfo/enum-thinlto.rs +++ b/tests/debuginfo/enum-thinlto.rs @@ -1,4 +1,5 @@ -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ compile-flags:-g -Z thinlto //@ disable-gdb-pretty-printers //@ ignore-backends: gcc diff --git a/tests/debuginfo/function-arg-initialization.rs b/tests/debuginfo/function-arg-initialization.rs index 78fecd8a4bfe..9b20eb1b8a4f 100644 --- a/tests/debuginfo/function-arg-initialization.rs +++ b/tests/debuginfo/function-arg-initialization.rs @@ -5,7 +5,8 @@ // arguments have been properly loaded when setting the breakpoint via the // function name. -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ compile-flags:-g //@ disable-gdb-pretty-printers //@ ignore-backends: gcc diff --git a/tests/debuginfo/function-prologue-stepping-regular.rs b/tests/debuginfo/function-prologue-stepping-regular.rs index 83d5aa3c0a10..2a4a64f87303 100644 --- a/tests/debuginfo/function-prologue-stepping-regular.rs +++ b/tests/debuginfo/function-prologue-stepping-regular.rs @@ -1,7 +1,8 @@ // This test case checks if function arguments already have the correct value when breaking at the // beginning of a function. -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ ignore-gdb //@ compile-flags:-g //@ disable-gdb-pretty-printers diff --git a/tests/debuginfo/issue-57822.rs b/tests/debuginfo/issue-57822.rs index 6b030686e4ea..a970db873a28 100644 --- a/tests/debuginfo/issue-57822.rs +++ b/tests/debuginfo/issue-57822.rs @@ -1,7 +1,8 @@ // This test makes sure that the LLDB pretty printer does not throw an exception // for nested closures and coroutines. -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ compile-flags:-g //@ disable-gdb-pretty-printers //@ ignore-backends: gcc diff --git a/tests/debuginfo/macro-stepping.rs b/tests/debuginfo/macro-stepping.rs index ba3a4452041a..3f57eb9ad79b 100644 --- a/tests/debuginfo/macro-stepping.rs +++ b/tests/debuginfo/macro-stepping.rs @@ -4,7 +4,8 @@ //! and we can match on them for testing purposes. //@ ignore-android -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ min-gdb-version: 13.0 //@ aux-build:macro-stepping.rs diff --git a/tests/debuginfo/method-on-enum.rs b/tests/debuginfo/method-on-enum.rs index c7955a7e875a..6c724622a89e 100644 --- a/tests/debuginfo/method-on-enum.rs +++ b/tests/debuginfo/method-on-enum.rs @@ -1,4 +1,5 @@ -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ min-gdb-version: 13.0 //@ compile-flags:-g diff --git a/tests/debuginfo/msvc-pretty-enums.rs b/tests/debuginfo/msvc-pretty-enums.rs index efe5b066b52c..1f55adcb5c00 100644 --- a/tests/debuginfo/msvc-pretty-enums.rs +++ b/tests/debuginfo/msvc-pretty-enums.rs @@ -1,5 +1,6 @@ //@ only-msvc -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ ignore-gdb //@ compile-flags:-g diff --git a/tests/debuginfo/opt/dead_refs.rs b/tests/debuginfo/opt/dead_refs.rs index 61c39f4fb778..8653b5d3b251 100644 --- a/tests/debuginfo/opt/dead_refs.rs +++ b/tests/debuginfo/opt/dead_refs.rs @@ -1,4 +1,5 @@ -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ min-gdb-version: 13.0 //@ compile-flags: -g -Copt-level=3 //@ disable-gdb-pretty-printers diff --git a/tests/debuginfo/option-like-enum.rs b/tests/debuginfo/option-like-enum.rs index 047a738574c2..027e9657d8ab 100644 --- a/tests/debuginfo/option-like-enum.rs +++ b/tests/debuginfo/option-like-enum.rs @@ -1,4 +1,5 @@ -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ min-gdb-version: 13.0 //@ compile-flags:-g diff --git a/tests/debuginfo/pretty-std.rs b/tests/debuginfo/pretty-std.rs index d4cb2f6625f4..bf3102993d89 100644 --- a/tests/debuginfo/pretty-std.rs +++ b/tests/debuginfo/pretty-std.rs @@ -2,7 +2,8 @@ //@ ignore-windows-gnu: #128981 //@ ignore-android: FIXME(#10381) //@ compile-flags:-g -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ min-cdb-version: 10.0.18317.1001 //@ ignore-backends: gcc diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs index afb8b873ca08..165cfcd968a6 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs @@ -1,5 +1,6 @@ //@ min-gdb-version: 14.0 -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ compile-flags:-g //@ disable-gdb-pretty-printers diff --git a/tests/debuginfo/struct-in-enum.rs b/tests/debuginfo/struct-in-enum.rs index 02b2e6eb4cb7..89620c31a04f 100644 --- a/tests/debuginfo/struct-in-enum.rs +++ b/tests/debuginfo/struct-in-enum.rs @@ -1,4 +1,5 @@ -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ compile-flags:-g //@ disable-gdb-pretty-printers diff --git a/tests/debuginfo/struct-style-enum.rs b/tests/debuginfo/struct-style-enum.rs index e3d6c64c36aa..7e38a5dcd079 100644 --- a/tests/debuginfo/struct-style-enum.rs +++ b/tests/debuginfo/struct-style-enum.rs @@ -1,4 +1,5 @@ -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ compile-flags:-g //@ disable-gdb-pretty-printers //@ ignore-backends: gcc diff --git a/tests/debuginfo/tuple-style-enum.rs b/tests/debuginfo/tuple-style-enum.rs index 7541b8aa3c6b..0a06370c979e 100644 --- a/tests/debuginfo/tuple-style-enum.rs +++ b/tests/debuginfo/tuple-style-enum.rs @@ -1,4 +1,5 @@ -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ compile-flags:-g //@ disable-gdb-pretty-printers diff --git a/tests/debuginfo/unique-enum.rs b/tests/debuginfo/unique-enum.rs index 3cc9b7774193..3bc6ce259655 100644 --- a/tests/debuginfo/unique-enum.rs +++ b/tests/debuginfo/unique-enum.rs @@ -1,4 +1,5 @@ -//@ min-lldb-version: 1800 +// LLDB 1800+ tests were not tested in CI, broke, and now are disabled +//@ ignore-lldb //@ compile-flags:-g //@ disable-gdb-pretty-printers From 3a5d7df8418b6d287a9c258fc3bd5e6b2e1746dd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Feb 2026 15:46:05 +1100 Subject: [PATCH 452/978] Add a useful comment on `rustc_codegen_ssa::NativeLib`. --- compiler/rustc_codegen_ssa/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 904c74944959..5cca916c17b6 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -175,6 +175,11 @@ bitflags::bitflags! { } } +// This is the same as `rustc_session::cstore::NativeLib`, except: +// - (important) the `foreign_module` field is missing, because it contains a `DefId`, which can't +// be encoded with `FileEncoder`. +// - (less important) the `verbatim` field is a `bool` rather than an `Option`, because here +// we can treat `false` and `absent` the same. #[derive(Clone, Debug, Encodable, Decodable)] pub struct NativeLib { pub kind: NativeLibKind, From f14e3ee38ff234ca00cb73b61bf306316b9ab91d Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Thu, 15 Jan 2026 06:12:57 +0100 Subject: [PATCH 453/978] compiletest: Don't assume `aux-crate` becomes a `*.so` with `no-prefer-dynamic` Since it does not make sense to do so. If someone prefers no dynamic stuff, the last thing they want to look for is an `.so` file. Also add a regression test. Without the fix, the test fails with: error: test compilation failed although it shouldn't! --- stderr ------------------------------- error: extern location for no_prefer_dynamic_lib does not exist: .../auxiliary/libno_prefer_dynamic_lib.so --> .../no-prefer-dynamic-means-no-so.rs:9:5 | LL | no_prefer_dynamic_lib::return_42(); | ^^^^^^^^^^^^^^^^^^^^^ --- src/tools/compiletest/src/runtest.rs | 2 +- .../auxiliary/no_prefer_dynamic_lib.rs | 10 ++++++++++ .../no-prefer-dynamic-means-no-so.rs | 10 ++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 tests/ui/compiletest-self-test/auxiliary/no_prefer_dynamic_lib.rs create mode 100644 tests/ui/compiletest-self-test/no-prefer-dynamic-means-no-so.rs diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index ef90b81fb2a7..1804490a5f12 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1438,7 +1438,7 @@ impl<'test> TestCx<'test> { } else if aux_type.is_some() { panic!("aux_type {aux_type:?} not expected"); } else if aux_props.no_prefer_dynamic { - (AuxType::Dylib, None) + (AuxType::Lib, None) } else if self.config.target.contains("emscripten") || (self.config.target.contains("musl") && !aux_props.force_host diff --git a/tests/ui/compiletest-self-test/auxiliary/no_prefer_dynamic_lib.rs b/tests/ui/compiletest-self-test/auxiliary/no_prefer_dynamic_lib.rs new file mode 100644 index 000000000000..6688dadbab24 --- /dev/null +++ b/tests/ui/compiletest-self-test/auxiliary/no_prefer_dynamic_lib.rs @@ -0,0 +1,10 @@ +//@ no-prefer-dynamic + +//! Since this is `no-prefer-dynamic` we expect compiletest to _not_ look for +//! this create as `libno_prefer_dynamic_lib.so`. + +#![crate_type = "rlib"] + +pub fn return_42() -> i32 { + 42 +} diff --git a/tests/ui/compiletest-self-test/no-prefer-dynamic-means-no-so.rs b/tests/ui/compiletest-self-test/no-prefer-dynamic-means-no-so.rs new file mode 100644 index 000000000000..b7e8fae506c3 --- /dev/null +++ b/tests/ui/compiletest-self-test/no-prefer-dynamic-means-no-so.rs @@ -0,0 +1,10 @@ +//! Since we and our `aux-crate` is `no-prefer-dynamic`, we expect compiletest +//! to _not_ look for `libno_prefer_dynamic_lib.so`. + +//@ check-pass +//@ no-prefer-dynamic +//@ aux-crate: no_prefer_dynamic_lib=no_prefer_dynamic_lib.rs + +fn main() { + no_prefer_dynamic_lib::return_42(); +} From d0dc2e7c5f6770d8ed4a480f4614a4bcc0fc922c Mon Sep 17 00:00:00 2001 From: Juho Kahala <57393910+quaternic@users.noreply.github.com> Date: Tue, 3 Feb 2026 07:03:21 +0200 Subject: [PATCH 454/978] add -Zjson-target-spec to custom target workflows (#1071) With the json target specification format destabilized in https://github.com/rust-lang/rust/pull/150151, `-Zjson-target-spec` is needed for custom targets. This should resolve the CI failures seen in rust-lang/compiler-builtins#1070 --- library/compiler-builtins/.github/workflows/main.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/compiler-builtins/.github/workflows/main.yaml b/library/compiler-builtins/.github/workflows/main.yaml index 6a4c72c5bc47..1572a8ec6cd1 100644 --- a/library/compiler-builtins/.github/workflows/main.yaml +++ b/library/compiler-builtins/.github/workflows/main.yaml @@ -230,7 +230,8 @@ jobs: # poorly with build scripts) cargo build -p compiler_builtins -p libm \ --target etc/thumbv7em-none-eabi-renamed.json \ - -Zbuild-std=core + -Zbuild-std=core \ + -Zjson-target-spec # FIXME: move this target to test job once https://github.com/rust-lang/rust/pull/150138 merged. build-thumbv6k: @@ -248,7 +249,8 @@ jobs: - run: | cargo build -p compiler_builtins -p libm \ --target etc/thumbv6-none-eabi.json \ - -Zbuild-std=core + -Zbuild-std=core \ + -Zjson-target-spec benchmarks: name: Benchmarks From 2626872c300296598fc7d13c167e45249c1430ca Mon Sep 17 00:00:00 2001 From: Redddy Date: Tue, 3 Feb 2026 14:53:02 +0900 Subject: [PATCH 455/978] Add label for date reference triage --- src/doc/rustc-dev-guide/ci/date-check/src/main.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/doc/rustc-dev-guide/ci/date-check/src/main.rs b/src/doc/rustc-dev-guide/ci/date-check/src/main.rs index c9f349147e79..28d48ba4e996 100644 --- a/src/doc/rustc-dev-guide/ci/date-check/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/date-check/src/main.rs @@ -163,6 +163,9 @@ fn main() { } } println!(); + + println!("@rustbot label +C-date-reference-triage +E-easy +E-help-wanted"); + println!(); } } From 49d41d74861ad156b1cab5bef0fbec534ae8f8c8 Mon Sep 17 00:00:00 2001 From: Redddy Date: Tue, 3 Feb 2026 14:54:37 +0900 Subject: [PATCH 456/978] Add 'C-date-reference-triage' to exclude_labels --- src/doc/rustc-dev-guide/triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc-dev-guide/triagebot.toml b/src/doc/rustc-dev-guide/triagebot.toml index f894456d0de3..07118872809e 100644 --- a/src/doc/rustc-dev-guide/triagebot.toml +++ b/src/doc/rustc-dev-guide/triagebot.toml @@ -5,6 +5,7 @@ new_issue = true exclude_labels = [ "A-diagnostics", + "C-date-reference-triage", "C-tracking-issue", ] From fb2be7b1b84602692c3e26d0c6409b7a15ced231 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Tue, 3 Feb 2026 16:19:13 +0900 Subject: [PATCH 457/978] Fix rustdoc links for BoundRegionKind/BoundTyKind --- src/doc/rustc-dev-guide/src/ty-module/binders.md | 4 ++-- .../rustc-dev-guide/src/ty-module/instantiating-binders.md | 2 +- .../rustc-dev-guide/src/ty-module/param-ty-const-regions.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/ty-module/binders.md b/src/doc/rustc-dev-guide/src/ty-module/binders.md index 7fd9eeed54ac..21cf80abc6e3 100644 --- a/src/doc/rustc-dev-guide/src/ty-module/binders.md +++ b/src/doc/rustc-dev-guide/src/ty-module/binders.md @@ -48,5 +48,5 @@ This would cause all kinds of issues as the region `'^1_0` refers to a binder at [`Binder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Binder.html [`BoundVar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.BoundVar.html -[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html -[`BoundTyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundTyKind.html +[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.BoundRegionKind.html +[`BoundTyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.BoundTyKind.html diff --git a/src/doc/rustc-dev-guide/src/ty-module/instantiating-binders.md b/src/doc/rustc-dev-guide/src/ty-module/instantiating-binders.md index 3c7408465c44..82c340e87a81 100644 --- a/src/doc/rustc-dev-guide/src/ty-module/instantiating-binders.md +++ b/src/doc/rustc-dev-guide/src/ty-module/instantiating-binders.md @@ -136,7 +136,7 @@ As a concrete example, accessing the signature of a function we are type checkin [`liberate_late_bound_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.liberate_late_bound_regions [representing-types]: param-ty-const-regions.md -[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html +[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.BoundRegionKind.html [`enter_forall`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/struct.InferCtxt.html#method.enter_forall [ch_placeholders_universes]: ../borrow-check/region-inference/placeholders-and-universes.md [`instantiate_binder_with_fresh_vars`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/struct.InferCtxt.html#method.instantiate_binder_with_fresh_vars diff --git a/src/doc/rustc-dev-guide/src/ty-module/param-ty-const-regions.md b/src/doc/rustc-dev-guide/src/ty-module/param-ty-const-regions.md index ce4e887862c7..b0c793003041 100644 --- a/src/doc/rustc-dev-guide/src/ty-module/param-ty-const-regions.md +++ b/src/doc/rustc-dev-guide/src/ty-module/param-ty-const-regions.md @@ -88,7 +88,7 @@ fn foo<'a, 'b, T: 'a>(one: T, two: &'a &'b u32) -> &'b u32 { [ch_early_late_bound]: ../early-late-parameters.md [ch_binders]: ./binders.md [ch_instantiating_binders]: ./instantiating-binders.md -[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html +[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.BoundRegionKind.html [`RegionKind::EarlyParam`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.RegionKind.html#variant.ReEarlyParam [`RegionKind::LateParam`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.RegionKind.html#variant.ReLateParam [`ConstKind::Param`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ConstKind.html#variant.Param From 39a238cdba8cd33620f879724ae69a87f2057ed8 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Sat, 31 Jan 2026 06:46:57 +0900 Subject: [PATCH 458/978] Document feature gate checking --- .../rustc-dev-guide/src/feature-gate-ck.md | 132 +++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/feature-gate-ck.md b/src/doc/rustc-dev-guide/src/feature-gate-ck.md index c17747a11b75..c840118075e2 100644 --- a/src/doc/rustc-dev-guide/src/feature-gate-ck.md +++ b/src/doc/rustc-dev-guide/src/feature-gate-ck.md @@ -1,3 +1,133 @@ # Feature Gate Checking -**TODO**: this chapter [#1158](https://github.com/rust-lang/rustc-dev-guide/issues/1158) +Feature gates prevent usage of unstable language and library features without a +nightly-only `#![feature(...)]` opt-in. This chapter documents the implementation +of feature gating: where gates are defined, how they are enabled, and how usage +is verified. + +## Feature Definitions + +All feature gate definitions are located in the `rustc_feature` crate: + +- **Unstable features** are declared in [`rustc_feature/src/unstable.rs`] via + the `declare_features!` macro. This associates features with issue numbers and + tracking metadata. +- **Accepted features** (stabilized) are listed in [`rustc_feature/src/accepted.rs`]. +- **Removed features** (explicitly disallowed) are listed in [`rustc_feature/src/removed.rs`]. +- **Gated built-in attributes and cfgs** are declared in [`rustc_feature/src/builtin_attrs.rs`]. + +The [`rustc_feature::Features`] type represents the **active feature set** for a +crate. Helpers like `enabled`, `incomplete`, and `internal` are used during +compilation to check status. + +## Collecting Features + +Before AST validation or expansion, `rustc` collects crate-level +`#![feature(...)]` attributes to build the active `Features` set. + +- The collection happens in [`rustc_expand/src/config.rs`] in [`features`]. +- Each `#![feature]` entry is classified against the `unstable`, `accepted`, and + `removed` tables: + - **Removed** features cause an immediate error. + - **Accepted** features are recorded but do not require nightly. On + stable/beta they trigger the "already stabilized" diagnostic. + - **Unstable** features are recorded as enabled. + - Unknown features are treated as **library features** and validated later. +- With `-Z allow-features=...`, any **unstable** or **unknown** feature + not in the allowlist is rejected. +- [`RUSTC_BOOTSTRAP`] feeds into `UnstableFeatures::from_environment`. This + variable controls whether the compiler is treated as "nightly", allowing + feature gates to be bypassed during bootstrapping or explicitly disabled (`-1`). + +## Parser Gating + +Some syntax is detected and gated during parsing. The parser records spans for +later checking to keep diagnostics consistent and deferred until after parsing. + +- [`rustc_session/src/parse.rs`] defines [`GatedSpans`] and the `gate` method. +- The parser uses it in [`rustc_parse/src/parser/*`] when it encounters + syntax that requires a gate (e.g., `async for`, `yield`, experimental patterns). + +## Checking Pass + +The central logic lives in [`rustc_ast_passes/src/feature_gate.rs`], primarily +in `check_crate` and its AST visitor. + +### `check_crate` + +`check_crate` performs high-level validation: + +- `maybe_stage_features`: Rejects `#![feature]` on stable/beta. +- `check_incompatible_features`: Ensures incompatible feature combinations + (declared in `rustc_feature::INCOMPATIBLE_FEATURES`) are not used together. +- `check_new_solver_banned_features`: Bans features incompatible with + certain compiler modes (e.g., the next trait solver). +- **Parser-gated spans**: Processes the `GatedSpans` recorded during parsing. + +### AST Visitor + +A `PostExpansionVisitor` walks the expanded AST to check constructs that are +easier to validate after expansion. + +- The visitor uses helper macros (`gate!`, `gate_alt!`, `gate_multi!`) to check: + 1. Is the feature enabled? + 2. Does `span.allows_unstable` permit it (for internal compiler macros)? +- Examples include `trait_alias`, `decl_macro`, `extern types`, and various + `impl Trait` forms. + +### Checking `GatedSpans` + +`check_crate` iterates over `sess.psess.gated_spans`: + +- The `gate_all!` macro emits diagnostics for each gated span if the feature is + not enabled. +- Some gates have extra logic (e.g., `yield` can be allowed by `coroutines` or + `gen_blocks`). +- Legacy gates (e.g., `box_patterns`, `try_blocks`) may use a separate path that + emits future-incompatibility warnings instead of hard errors. + +## Attributes and `cfg` + +Beyond syntax, rustc also gates attributes and `cfg` options. + +### Built-in attributes + +- [`rustc_ast_passes::check_attribute`] inspects attributes against + `BUILTIN_ATTRIBUTE_MAP`. +- If the attribute is `AttributeGate::Gated` and the feature isn’t enabled, + `feature_err` is emitted. + +### `cfg` options + +- [`rustc_attr_parsing/src/attributes/cfg.rs`] defines + `find_gated_cfg`/`gate_cfg` to reject gated `cfg`s. +- `gate_cfg` respects `Span::allows_unstable`, allowing internal compiler + macros to bypass `cfg` gates when marked with `#[allow_internal_unstable]`. +- The gated cfg list is defined in [`rustc_feature/src/builtin_attrs.rs`]. + +## Diagnostics + +Diagnostic helpers are located in [`rustc_session/src/parse.rs`]. + +- `feature_err` and `feature_warn` emit standardized diagnostics, attaching the + tracking issue number where possible. +- `Span::allows_unstable` in [`rustc_span/src/lib.rs`] checks if a span originates + from a macro marked with `#[allow_internal_unstable]`. This allows internal + macros to use unstable features on stable channels while enforcing gates for + user code. + +[`rustc_feature/src/unstable.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_feature/src/unstable.rs +[`rustc_feature/src/removed.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_feature/src/removed.rs +[`rustc_feature/src/accepted.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_feature/src/accepted.rs +[`rustc_feature/src/builtin_attrs.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_feature/src/builtin_attrs.rs +[`rustc_feature::Features`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_feature/struct.Features.html +[`rustc_expand/src/config.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_expand/src/config.rs +[`features`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/config/fn.features.html +[`RUSTC_BOOTSTRAP`]: https://doc.rust-lang.org/beta/unstable-book/compiler-environment-variables/RUSTC_BOOTSTRAP.html +[`rustc_session/src/parse.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_session/src/parse.rs +[`GatedSpans`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/parse/struct.GatedSpans.html +[`rustc_ast_passes/src/feature_gate.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_ast_passes/src/feature_gate.rs +[`rustc_parse/src/parser/*`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/index.html +[`rustc_ast_passes::check_attribute`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast_passes/feature_gate/fn.check_attribute.html +[`rustc_attr_parsing/src/attributes/cfg.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_attr_parsing/src/attributes/cfg.rs +[`rustc_span/src/lib.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_span/src/lib.rs From f3b9e8a09fc87d7e2c71db9e3343fefebbc95dbb Mon Sep 17 00:00:00 2001 From: Redddy Date: Tue, 3 Feb 2026 14:24:48 +0900 Subject: [PATCH 459/978] Clarify description of new solver banned features Co-authored-by: Tshepang Mbambo --- src/doc/rustc-dev-guide/src/feature-gate-ck.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/feature-gate-ck.md b/src/doc/rustc-dev-guide/src/feature-gate-ck.md index c840118075e2..8a93fbc7561f 100644 --- a/src/doc/rustc-dev-guide/src/feature-gate-ck.md +++ b/src/doc/rustc-dev-guide/src/feature-gate-ck.md @@ -61,7 +61,7 @@ in `check_crate` and its AST visitor. - `check_incompatible_features`: Ensures incompatible feature combinations (declared in `rustc_feature::INCOMPATIBLE_FEATURES`) are not used together. - `check_new_solver_banned_features`: Bans features incompatible with - certain compiler modes (e.g., the next trait solver). + compiler mode for the next trait solver. - **Parser-gated spans**: Processes the `GatedSpans` recorded during parsing. ### AST Visitor From 33b2fcb1e78aae68474ba38f9fd5d38352abf20e Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Tue, 3 Feb 2026 14:36:17 +0900 Subject: [PATCH 460/978] Rename `feature-gate-ck.md` to `feature-gate-check.md` --- src/doc/rustc-dev-guide/src/SUMMARY.md | 2 +- .../src/{feature-gate-ck.md => feature-gate-check.md} | 0 src/doc/rustc-dev-guide/src/syntax-intro.md | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename src/doc/rustc-dev-guide/src/{feature-gate-ck.md => feature-gate-check.md} (100%) diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 5342c54607b7..22f4da50b62c 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -124,7 +124,7 @@ - [`#[test]` implementation](./test-implementation.md) - [Panic implementation](./panic-implementation.md) - [AST validation](./ast-validation.md) - - [Feature gate checking](./feature-gate-ck.md) + - [Feature gate checking](./feature-gate-check.md) - [Lang Items](./lang-items.md) - [The HIR (High-level IR)](./hir.md) - [Lowering AST to HIR](./hir/lowering.md) diff --git a/src/doc/rustc-dev-guide/src/feature-gate-ck.md b/src/doc/rustc-dev-guide/src/feature-gate-check.md similarity index 100% rename from src/doc/rustc-dev-guide/src/feature-gate-ck.md rename to src/doc/rustc-dev-guide/src/feature-gate-check.md diff --git a/src/doc/rustc-dev-guide/src/syntax-intro.md b/src/doc/rustc-dev-guide/src/syntax-intro.md index 0f5a91ee50d8..a5a8bab14971 100644 --- a/src/doc/rustc-dev-guide/src/syntax-intro.md +++ b/src/doc/rustc-dev-guide/src/syntax-intro.md @@ -13,7 +13,7 @@ And parsing requires macro expansion, which in turn may require parsing the outp [AST]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html [macro expansion]: ./macro-expansion.md -[feature-gate checking]: ./feature-gate-ck.md +[feature-gate checking]: ./feature-gate-check.md [lexing, parsing]: ./the-parser.md [name resolution]: ./name-resolution.md [validation]: ./ast-validation.md From 11ac5bd665e9a7cc9cd4db873e1db5b6b8ef6478 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Tue, 3 Feb 2026 14:41:54 +0900 Subject: [PATCH 461/978] Clarify and reorganize feature-gate-check doc --- .../rustc-dev-guide/src/feature-gate-check.md | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/feature-gate-check.md b/src/doc/rustc-dev-guide/src/feature-gate-check.md index 8a93fbc7561f..591231c0229f 100644 --- a/src/doc/rustc-dev-guide/src/feature-gate-check.md +++ b/src/doc/rustc-dev-guide/src/feature-gate-check.md @@ -5,6 +5,8 @@ nightly-only `#![feature(...)]` opt-in. This chapter documents the implementatio of feature gating: where gates are defined, how they are enabled, and how usage is verified. + + ## Feature Definitions All feature gate definitions are located in the `rustc_feature` crate: @@ -30,7 +32,10 @@ Before AST validation or expansion, `rustc` collects crate-level `removed` tables: - **Removed** features cause an immediate error. - **Accepted** features are recorded but do not require nightly. On - stable/beta they trigger the "already stabilized" diagnostic. + stable/beta, `maybe_stage_features` in + [`rustc_ast_passes/src/feature_gate.rs`] emits the non-nightly + diagnostic and lists stable features, which is where the "already + stabilized" messaging comes from. - **Unstable** features are recorded as enabled. - Unknown features are treated as **library features** and validated later. - With `-Z allow-features=...`, any **unstable** or **unknown** feature @@ -62,18 +67,8 @@ in `check_crate` and its AST visitor. (declared in `rustc_feature::INCOMPATIBLE_FEATURES`) are not used together. - `check_new_solver_banned_features`: Bans features incompatible with compiler mode for the next trait solver. -- **Parser-gated spans**: Processes the `GatedSpans` recorded during parsing. - -### AST Visitor - -A `PostExpansionVisitor` walks the expanded AST to check constructs that are -easier to validate after expansion. - -- The visitor uses helper macros (`gate!`, `gate_alt!`, `gate_multi!`) to check: - 1. Is the feature enabled? - 2. Does `span.allows_unstable` permit it (for internal compiler macros)? -- Examples include `trait_alias`, `decl_macro`, `extern types`, and various - `impl Trait` forms. +- **Parser-gated spans**: Processes the `GatedSpans` recorded during parsing + (see [Checking `GatedSpans`](#checking-gatedspans)). ### Checking `GatedSpans` @@ -86,6 +81,17 @@ easier to validate after expansion. - Legacy gates (e.g., `box_patterns`, `try_blocks`) may use a separate path that emits future-incompatibility warnings instead of hard errors. +### AST Visitor + +A `PostExpansionVisitor` walks the expanded AST to check constructs that are +easier to validate after expansion. + +- The visitor uses helper macros (`gate!`, `gate_alt!`, `gate_multi!`) to check: + 1. Is the feature enabled? + 2. Does `span.allows_unstable` permit it (for internal compiler macros)? +- Examples include `trait_alias`, `decl_macro`, `extern types`, and various + `impl Trait` forms. + ## Attributes and `cfg` Beyond syntax, rustc also gates attributes and `cfg` options. @@ -99,8 +105,8 @@ Beyond syntax, rustc also gates attributes and `cfg` options. ### `cfg` options -- [`rustc_attr_parsing/src/attributes/cfg.rs`] defines - `find_gated_cfg`/`gate_cfg` to reject gated `cfg`s. +- [`rustc_attr_parsing/src/attributes/cfg.rs`] defines `gate_cfg` and uses + [`rustc_feature::find_gated_cfg`] to reject gated `cfg`s. - `gate_cfg` respects `Span::allows_unstable`, allowing internal compiler macros to bypass `cfg` gates when marked with `#[allow_internal_unstable]`. - The gated cfg list is defined in [`rustc_feature/src/builtin_attrs.rs`]. @@ -130,4 +136,5 @@ Diagnostic helpers are located in [`rustc_session/src/parse.rs`]. [`rustc_parse/src/parser/*`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/index.html [`rustc_ast_passes::check_attribute`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast_passes/feature_gate/fn.check_attribute.html [`rustc_attr_parsing/src/attributes/cfg.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_attr_parsing/src/attributes/cfg.rs +[`rustc_feature::find_gated_cfg`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_feature/fn.find_gated_cfg.html [`rustc_span/src/lib.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_span/src/lib.rs From c07f10c2c1296431efba33bb52c64ee72eb7146f Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 1 Feb 2026 14:25:18 +0100 Subject: [PATCH 462/978] Convert to inline diagnostics in `rustc_driver_impl` --- Cargo.lock | 1 - compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/messages.ftl | 29 ------------ compiler/rustc_driver_impl/src/lib.rs | 3 -- .../src/session_diagnostics.rs | 44 +++++++++++-------- 5 files changed, 25 insertions(+), 53 deletions(-) delete mode 100644 compiler/rustc_driver_impl/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 234d709f3c31..91fce715c8cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3789,7 +3789,6 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", - "rustc_fluent_macro", "rustc_hir_analysis", "rustc_hir_pretty", "rustc_hir_typeck", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index c160240a18a7..d97c552b412b 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -21,7 +21,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir_analysis = { path = "../rustc_hir_analysis" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_hir_typeck = { path = "../rustc_hir_typeck" } diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl deleted file mode 100644 index b62cdc35f513..000000000000 --- a/compiler/rustc_driver_impl/messages.ftl +++ /dev/null @@ -1,29 +0,0 @@ -driver_impl_cant_emit_mir = could not emit MIR: {$error} - -driver_impl_ice = the compiler unexpectedly panicked. this is a bug. -driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url} -driver_impl_ice_bug_report_internal_feature = using internal features is not supported and expected to cause internal compiler errors when used incorrectly -driver_impl_ice_bug_report_update_note = please make sure that you have updated to the latest nightly -driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden - -driver_impl_ice_flags = compiler flags: {$flags} -driver_impl_ice_path = please attach the file at `{$path}` to your bug report -driver_impl_ice_path_error = the ICE couldn't be written to `{$path}`: {$error} -driver_impl_ice_path_error_env = the environment variable `RUSTC_ICE` is set to `{$env_var}` -driver_impl_ice_version = rustc {$version} running on {$triple} - -driver_impl_rlink_corrupt_file = corrupt metadata encountered in `{$file}` - -driver_impl_rlink_empty_version_number = the input does not contain version number - -driver_impl_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}` - -driver_impl_rlink_no_a_file = rlink must be a file - -driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}` - -driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}` - -driver_impl_rlink_wrong_file_type = the input does not look like a .rlink file - -driver_impl_unstable_feature_usage = cannot dump feature usage metrics: {$error} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 38ee87601614..a0cb29ef15cf 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -108,15 +108,12 @@ use crate::session_diagnostics::{ RLinkWrongFileType, RlinkCorruptFile, RlinkNotAFile, RlinkUnableToRead, UnstableFeatureUsage, }; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn default_translator() -> Translator { Translator::with_fallback_bundle(DEFAULT_LOCALE_RESOURCES.to_vec(), false) } pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ // tidy-alphabetical-start - crate::DEFAULT_LOCALE_RESOURCE, rustc_ast_lowering::DEFAULT_LOCALE_RESOURCE, rustc_ast_passes::DEFAULT_LOCALE_RESOURCE, rustc_attr_parsing::DEFAULT_LOCALE_RESOURCE, diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs index 774221fd396a..565c176645de 100644 --- a/compiler/rustc_driver_impl/src/session_diagnostics.rs +++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs @@ -3,82 +3,88 @@ use std::error::Error; use rustc_macros::{Diagnostic, Subdiagnostic}; #[derive(Diagnostic)] -#[diag(driver_impl_cant_emit_mir)] +#[diag("could not emit MIR: {$error}")] pub struct CantEmitMIR { pub error: std::io::Error, } #[derive(Diagnostic)] -#[diag(driver_impl_rlink_unable_to_read)] +#[diag("failed to read rlink file: `{$err}`")] pub(crate) struct RlinkUnableToRead { pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(driver_impl_rlink_wrong_file_type)] +#[diag("the input does not look like a .rlink file")] pub(crate) struct RLinkWrongFileType; #[derive(Diagnostic)] -#[diag(driver_impl_rlink_empty_version_number)] +#[diag("the input does not contain version number")] pub(crate) struct RLinkEmptyVersionNumber; #[derive(Diagnostic)] -#[diag(driver_impl_rlink_encoding_version_mismatch)] +#[diag( + ".rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`" +)] pub(crate) struct RLinkEncodingVersionMismatch { pub version_array: String, pub rlink_version: u32, } #[derive(Diagnostic)] -#[diag(driver_impl_rlink_rustc_version_mismatch)] +#[diag( + ".rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`" +)] pub(crate) struct RLinkRustcVersionMismatch<'a> { pub rustc_version: String, pub current_version: &'a str, } #[derive(Diagnostic)] -#[diag(driver_impl_rlink_no_a_file)] +#[diag("rlink must be a file")] pub(crate) struct RlinkNotAFile; #[derive(Diagnostic)] -#[diag(driver_impl_rlink_corrupt_file)] +#[diag("corrupt metadata encountered in `{$file}`")] pub(crate) struct RlinkCorruptFile<'a> { pub file: &'a std::path::Path, } #[derive(Diagnostic)] -#[diag(driver_impl_ice)] +#[diag("the compiler unexpectedly panicked. this is a bug.")] pub(crate) struct Ice; #[derive(Diagnostic)] -#[diag(driver_impl_ice_bug_report)] +#[diag("we would appreciate a bug report: {$bug_report_url}")] pub(crate) struct IceBugReport<'a> { pub bug_report_url: &'a str, } #[derive(Diagnostic)] -#[diag(driver_impl_ice_bug_report_update_note)] +#[diag("please make sure that you have updated to the latest nightly")] pub(crate) struct UpdateNightlyNote; #[derive(Diagnostic)] -#[diag(driver_impl_ice_bug_report_internal_feature)] +#[diag( + "using internal features is not supported and expected to cause internal compiler errors when used incorrectly" +)] pub(crate) struct IceBugReportInternalFeature; #[derive(Diagnostic)] -#[diag(driver_impl_ice_version)] +#[diag("rustc {$version} running on {$triple}")] pub(crate) struct IceVersion<'a> { pub version: &'a str, pub triple: &'a str, } #[derive(Diagnostic)] -#[diag(driver_impl_ice_path)] +#[diag("please attach the file at `{$path}` to your bug report")] pub(crate) struct IcePath { pub path: std::path::PathBuf, } #[derive(Diagnostic)] -#[diag(driver_impl_ice_path_error)] +#[diag("the ICE couldn't be written to `{$path}`: {$error}")] pub(crate) struct IcePathError { pub path: std::path::PathBuf, pub error: String, @@ -87,23 +93,23 @@ pub(crate) struct IcePathError { } #[derive(Subdiagnostic)] -#[note(driver_impl_ice_path_error_env)] +#[note("the environment variable `RUSTC_ICE` is set to `{$env_var}`")] pub(crate) struct IcePathErrorEnv { pub env_var: std::path::PathBuf, } #[derive(Diagnostic)] -#[diag(driver_impl_ice_flags)] +#[diag("compiler flags: {$flags}")] pub(crate) struct IceFlags { pub flags: String, } #[derive(Diagnostic)] -#[diag(driver_impl_ice_exclude_cargo_defaults)] +#[diag("some of the compiler flags provided by cargo are hidden")] pub(crate) struct IceExcludeCargoDefaults; #[derive(Diagnostic)] -#[diag(driver_impl_unstable_feature_usage)] +#[diag("cannot dump feature usage metrics: {$error}")] pub(crate) struct UnstableFeatureUsage { pub error: Box, } From 079913ec7169bae6f48528d40da03a5da321dbe4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 3 Feb 2026 09:02:27 +0100 Subject: [PATCH 463/978] disable socket tests in Miri --- library/std/tests/windows_unix_socket.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/tests/windows_unix_socket.rs b/library/std/tests/windows_unix_socket.rs index 18f4c52e72c2..1f20cf586ca2 100644 --- a/library/std/tests/windows_unix_socket.rs +++ b/library/std/tests/windows_unix_socket.rs @@ -1,4 +1,5 @@ #![cfg(windows)] +#![cfg(not(miri))] // no socket support in Miri #![feature(windows_unix_domain_sockets)] // Now only test windows_unix_domain_sockets feature // in the future, will test both unix and windows uds From 89771a79fae2da3fe8197eac10f997b4c066189f Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Tue, 3 Feb 2026 17:06:53 +0900 Subject: [PATCH 464/978] Add cross-links between feature gate docs --- src/doc/rustc-dev-guide/src/feature-gate-check.md | 4 ++++ src/doc/rustc-dev-guide/src/feature-gates.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/feature-gate-check.md b/src/doc/rustc-dev-guide/src/feature-gate-check.md index 591231c0229f..c5a499f5708c 100644 --- a/src/doc/rustc-dev-guide/src/feature-gate-check.md +++ b/src/doc/rustc-dev-guide/src/feature-gate-check.md @@ -1,5 +1,8 @@ # Feature Gate Checking +For the how-to steps to add, remove, rename, or stabilize feature gates, +see [Feature gates][feature-gates]. + Feature gates prevent usage of unstable language and library features without a nightly-only `#![feature(...)]` opt-in. This chapter documents the implementation of feature gating: where gates are defined, how they are enabled, and how usage @@ -138,3 +141,4 @@ Diagnostic helpers are located in [`rustc_session/src/parse.rs`]. [`rustc_attr_parsing/src/attributes/cfg.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_attr_parsing/src/attributes/cfg.rs [`rustc_feature::find_gated_cfg`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_feature/fn.find_gated_cfg.html [`rustc_span/src/lib.rs`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_span/src/lib.rs +[feature-gates]: ./feature-gates.md diff --git a/src/doc/rustc-dev-guide/src/feature-gates.md b/src/doc/rustc-dev-guide/src/feature-gates.md index d2a517360714..76bf111fe772 100644 --- a/src/doc/rustc-dev-guide/src/feature-gates.md +++ b/src/doc/rustc-dev-guide/src/feature-gates.md @@ -3,9 +3,13 @@ This chapter is intended to provide basic help for adding, removing, and modifying feature gates. +For how rustc enforces and checks feature gates in the compiler pipeline, +see [Feature Gate Checking][feature-gate-check]. + Note that this is specific to *language* feature gates; *library* feature gates use [a different mechanism][libs-gate]. +[feature-gate-check]: ./feature-gate-check.md [libs-gate]: ./stability.md ## Adding a feature gate From e9ec12a2256471dcf0d6227e7ec13d6ea49fd7c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 27 Jan 2026 19:00:26 +0200 Subject: [PATCH 465/978] Fix postcard test too --- .../crates/proc-macro-srv-cli/tests/bidirectional_postcard.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/tests/bidirectional_postcard.rs b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/tests/bidirectional_postcard.rs index 33ca1d791de7..ba9657a9bb45 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/tests/bidirectional_postcard.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/tests/bidirectional_postcard.rs @@ -1,4 +1,8 @@ #![cfg(feature = "sysroot-abi")] +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] + +#[cfg(feature = "in-rust-tree")] +extern crate rustc_driver as _; mod common { pub(crate) mod utils; From a9f81ea43e45eb4d64c93099be6b7d2e47a9290b Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 3 Feb 2026 09:59:11 +0100 Subject: [PATCH 466/978] Convert to inline diagnostics in `rustc_attr_parsing` --- Cargo.lock | 2 - compiler/rustc_attr_parsing/Cargo.toml | 1 - compiler/rustc_attr_parsing/messages.ftl | 246 ----------------- .../rustc_attr_parsing/src/attributes/cfg.rs | 4 +- .../src/attributes/link_attrs.rs | 13 +- compiler/rustc_attr_parsing/src/lib.rs | 2 - .../src/session_diagnostics.rs | 250 ++++++++++-------- compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - 9 files changed, 142 insertions(+), 378 deletions(-) delete mode 100644 compiler/rustc_attr_parsing/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 234d709f3c31..04d65e0a4999 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3543,7 +3543,6 @@ dependencies = [ "rustc_ast_pretty", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_hir", "rustc_lexer", "rustc_macros", @@ -3780,7 +3779,6 @@ dependencies = [ "rustc_ast_lowering", "rustc_ast_passes", "rustc_ast_pretty", - "rustc_attr_parsing", "rustc_borrowck", "rustc_builtin_macros", "rustc_codegen_ssa", diff --git a/compiler/rustc_attr_parsing/Cargo.toml b/compiler/rustc_attr_parsing/Cargo.toml index 79193f394fe4..411f3f5ccbd1 100644 --- a/compiler/rustc_attr_parsing/Cargo.toml +++ b/compiler/rustc_attr_parsing/Cargo.toml @@ -10,7 +10,6 @@ rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl deleted file mode 100644 index 3e4c1a9dfad8..000000000000 --- a/compiler/rustc_attr_parsing/messages.ftl +++ /dev/null @@ -1,246 +0,0 @@ -attr_parsing_as_needed_compatibility = - linking modifier `as-needed` is only compatible with `dylib`, `framework` and `raw-dylib` linking kinds - -attr_parsing_bundle_needs_static = - linking modifier `bundle` is only compatible with `static` linking kind - -attr_parsing_cfg_attr_bad_delim = wrong `cfg_attr` delimiters - -attr_parsing_deprecated_item_suggestion = - suggestions on deprecated items are unstable - .help = add `#![feature(deprecated_suggestion)]` to the crate root - .note = see #94785 for more details - -attr_parsing_doc_alias_bad_char = - {$char_} character isn't allowed in {$attr_str} - -attr_parsing_doc_alias_empty = - {$attr_str} attribute cannot have empty value - -attr_parsing_doc_alias_malformed = - doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]` - -attr_parsing_doc_alias_start_end = - {$attr_str} cannot start or end with ' ' - -attr_parsing_doc_attr_not_crate_level = - `#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute - -attr_parsing_doc_attribute_not_attribute = - nonexistent builtin attribute `{$attribute}` used in `#[doc(attribute = "...")]` - .help = only existing builtin attributes are allowed in core/std - -attr_parsing_doc_keyword_not_keyword = - nonexistent keyword `{$keyword}` used in `#[doc(keyword = "...")]` - .help = only existing keywords are allowed in core/std - -attr_parsing_empty_confusables = - expected at least one confusable name - -attr_parsing_empty_link_name = - link name must not be empty - .label = empty link name - -attr_parsing_expected_single_version_literal = - expected single version literal - -attr_parsing_expected_version_literal = - expected a version literal - -attr_parsing_expects_feature_list = - `{$name}` expects a list of feature names - -attr_parsing_expects_features = - `{$name}` expects feature names - -attr_parsing_import_name_type_raw = - import name type can only be used with link kind `raw-dylib` - -attr_parsing_import_name_type_x86 = - import name type is only supported on x86 - -attr_parsing_incompatible_wasm_link = - `wasm_import_module` is incompatible with other arguments in `#[link]` attributes - -attr_parsing_incorrect_repr_format_align_one_arg = - incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses - -attr_parsing_incorrect_repr_format_expect_literal_integer = - incorrect `repr(align)` attribute format: `align` expects a literal integer as argument - -attr_parsing_incorrect_repr_format_generic = - incorrect `repr({$repr_arg})` attribute format - .suggestion = use parentheses instead - -attr_parsing_incorrect_repr_format_packed_expect_integer = - incorrect `repr(packed)` attribute format: `packed` expects a literal integer as argument - -attr_parsing_incorrect_repr_format_packed_one_or_zero_arg = - incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all - -attr_parsing_invalid_alignment_value = - invalid alignment value: {$error_part} - -attr_parsing_invalid_attr_unsafe = `{$name}` is not an unsafe attribute - .label = this is not an unsafe attribute - .suggestion = remove the `unsafe(...)` - .note = extraneous unsafe is not allowed in attributes - -attr_parsing_invalid_issue_string = - `issue` must be a non-zero numeric string or "none" - .must_not_be_zero = `issue` must not be "0", use "none" instead - .empty = cannot parse integer from empty string - .invalid_digit = invalid digit found in string - .pos_overflow = number too large to fit in target type - .neg_overflow = number too small to fit in target type - -attr_parsing_invalid_link_modifier = - invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed - -attr_parsing_invalid_meta_item = expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found {$descr} - .remove_neg_sugg = negative numbers are not literals, try removing the `-` sign - .quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal - .label = {$descr}s are not allowed here - -attr_parsing_invalid_predicate = - invalid predicate `{$predicate}` - -attr_parsing_invalid_repr_align_need_arg = - invalid `repr(align)` attribute: `align` needs an argument - .suggestion = supply an argument here - -attr_parsing_invalid_repr_generic = - invalid `repr({$repr_arg})` attribute: {$error_part} - -attr_parsing_invalid_repr_hint_no_paren = - invalid representation hint: `{$name}` does not take a parenthesized argument list - -attr_parsing_invalid_repr_hint_no_value = - invalid representation hint: `{$name}` does not take a value - -attr_parsing_invalid_since = - 'since' must be a Rust version number, such as "1.31.0" - -attr_parsing_invalid_target = `#[{$name}]` attribute cannot be used on {$target} - .help = `#[{$name}]` can {$only}be applied to {$applied} - .suggestion = remove the attribute - -attr_parsing_limit_invalid = - `limit` must be a non-negative integer - .label = {$error_str} -attr_parsing_link_arg_unstable = - link kind `link-arg` is unstable - -attr_parsing_link_cfg_unstable = - link cfg is unstable - -attr_parsing_link_framework_apple = - link kind `framework` is only supported on Apple targets - -attr_parsing_link_ordinal_out_of_range = ordinal value in `link_ordinal` is too large: `{$ordinal}` - .note = the value may not exceed `u16::MAX` - -attr_parsing_link_requires_name = - `#[link]` attribute requires a `name = "string"` argument - .label = missing `name` argument - -attr_parsing_meta_bad_delim = wrong meta list delimiters -attr_parsing_meta_bad_delim_suggestion = the delimiters should be `(` and `)` - -attr_parsing_missing_feature = - missing 'feature' - -attr_parsing_missing_issue = - missing 'issue' - -attr_parsing_missing_note = - missing 'note' - -attr_parsing_missing_since = - missing 'since' - -attr_parsing_multiple_modifiers = - multiple `{$modifier}` modifiers in a single `modifiers` argument - -attr_parsing_multiple_stability_levels = - multiple stability levels - -attr_parsing_naked_functions_incompatible_attribute = - attribute incompatible with `#[unsafe(naked)]` - .label = the `{$attr}` attribute is incompatible with `#[unsafe(naked)]` - .naked_attribute = function marked with `#[unsafe(naked)]` here - -attr_parsing_non_ident_feature = - 'feature' is not an identifier - -attr_parsing_null_on_export = `export_name` may not contain null characters - -attr_parsing_null_on_link_section = `link_section` may not contain null characters - -attr_parsing_null_on_objc_class = `objc::class!` may not contain null characters - -attr_parsing_null_on_objc_selector = `objc::selector!` may not contain null characters - -attr_parsing_objc_class_expected_string_literal = `objc::class!` expected a string literal - -attr_parsing_objc_selector_expected_string_literal = `objc::selector!` expected a string literal - -attr_parsing_raw_dylib_elf_unstable = - link kind `raw-dylib` is unstable on ELF platforms - -attr_parsing_raw_dylib_no_nul = - link name must not contain NUL characters if link kind is `raw-dylib` - -attr_parsing_raw_dylib_only_windows = - link kind `raw-dylib` is only supported on Windows targets - -attr_parsing_repr_ident = - meta item in `repr` must be an identifier - -attr_parsing_rustc_allowed_unstable_pairing = - `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute - -attr_parsing_rustc_promotable_pairing = - `rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute - -attr_parsing_rustc_scalable_vector_count_out_of_range = element count in `rustc_scalable_vector` is too large: `{$n}` - .note = the value may not exceed `u16::MAX` - -attr_parsing_soft_no_args = - `soft` should not have any arguments - -attr_parsing_stability_outside_std = stability attributes may not be used outside of the standard library - -attr_parsing_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes - .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) - -attr_parsing_unknown_version_literal = - unknown version literal format, assuming it refers to a future version - -attr_parsing_unrecognized_repr_hint = - unrecognized representation hint - .help = valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` - .note = for more information, visit - -attr_parsing_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe - .label = usage of unsafe attribute -attr_parsing_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)` - -attr_parsing_unstable_cfg_target_compact = - compact `cfg(target(..))` is experimental and subject to change - -attr_parsing_unstable_feature_bound_incompatible_stability = item annotated with `#[unstable_feature_bound]` should not be stable - .help = if this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]` - -attr_parsing_unsupported_instruction_set = target `{$current_target}` does not support `#[instruction_set({$instruction_set}::*)]` - -attr_parsing_unsupported_literal_suggestion = - consider removing the prefix - -attr_parsing_unused_multiple = - multiple `{$name}` attributes - .suggestion = remove this attribute - .note = attribute also specified here - -attr_parsing_whole_archive_needs_static = - linking modifier `whole-archive` is only compatible with `static` linking kind diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 3a540d80998d..ca6bfdbeaf5f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -25,7 +25,7 @@ use crate::session_diagnostics::{ AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg, ParsedDescription, }; -use crate::{AttributeParser, fluent_generated, parse_version, session_diagnostics}; +use crate::{AttributeParser, parse_version, session_diagnostics}; pub const CFG_TEMPLATE: AttributeTemplate = template!( List: &["predicate"], @@ -141,7 +141,7 @@ fn parse_cfg_entry_target( cx.sess(), sym::cfg_target_compact, meta_span, - fluent_generated::attr_parsing_unstable_cfg_target_compact, + "compact `cfg(target(..))` is experimental and subject to change", ) .emit(); } diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 548f53a986b8..02723e96ad19 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -10,7 +10,6 @@ use rustc_target::spec::{Arch, BinaryFormat}; use super::prelude::*; use super::util::parse_single_integer; use crate::attributes::cfg::parse_cfg_entry; -use crate::fluent_generated; use crate::session_diagnostics::{ AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ImportNameTypeRaw, ImportNameTypeX86, IncompatibleWasmLink, InvalidLinkModifier, LinkFrameworkApple, LinkOrdinalOutOfRange, @@ -305,7 +304,7 @@ impl LinkParser { sess, sym::raw_dylib_elf, nv.value_span, - fluent_generated::attr_parsing_raw_dylib_elf_unstable, + "link kind `raw-dylib` is unstable on ELF platforms", ) .emit(); } else { @@ -320,7 +319,7 @@ impl LinkParser { sess, sym::link_arg_attribute, nv.value_span, - fluent_generated::attr_parsing_link_arg_unstable, + "link kind `link-arg` is unstable", ) .emit(); } @@ -385,13 +384,7 @@ impl LinkParser { return true; }; if !features.link_cfg() { - feature_err( - sess, - sym::link_cfg, - item.span(), - fluent_generated::attr_parsing_link_cfg_unstable, - ) - .emit(); + feature_err(sess, sym::link_cfg, item.span(), "link cfg is unstable").emit(); } *cfg = parse_cfg_entry(cx, link_cfg).ok(); true diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index 349e6c234520..fe050250e354 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -113,5 +113,3 @@ pub use attributes::util::{is_builtin_attr, parse_version}; pub use context::{Early, Late, OmitDoc, ShouldEmit}; pub use interface::AttributeParser; pub use session_diagnostics::ParsedDescription; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index f9748542beb9..4055b7463f30 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -11,10 +11,8 @@ use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; use rustc_target::spec::TargetTuple; -use crate::fluent_generated as fluent; - #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_predicate, code = E0537)] +#[diag("invalid predicate `{$predicate}`", code = E0537)] pub(crate) struct InvalidPredicate { #[primary_span] pub span: Span, @@ -23,7 +21,7 @@ pub(crate) struct InvalidPredicate { } #[derive(Diagnostic)] -#[diag(attr_parsing_doc_alias_empty)] +#[diag("{$attr_str} attribute cannot have empty value")] pub(crate) struct DocAliasEmpty<'a> { #[primary_span] pub span: Span, @@ -31,7 +29,7 @@ pub(crate) struct DocAliasEmpty<'a> { } #[derive(Diagnostic)] -#[diag(attr_parsing_doc_alias_bad_char)] +#[diag("{$char_} character isn't allowed in {$attr_str}")] pub(crate) struct DocAliasBadChar<'a> { #[primary_span] pub span: Span, @@ -40,7 +38,7 @@ pub(crate) struct DocAliasBadChar<'a> { } #[derive(Diagnostic)] -#[diag(attr_parsing_doc_alias_start_end)] +#[diag("{$attr_str} cannot start or end with ' '")] pub(crate) struct DocAliasStartEnd<'a> { #[primary_span] pub span: Span, @@ -48,7 +46,7 @@ pub(crate) struct DocAliasStartEnd<'a> { } #[derive(Diagnostic)] -#[diag(attr_parsing_doc_attr_not_crate_level)] +#[diag("`#![doc({$attr_name} = \"...\")]` isn't allowed as a crate-level attribute")] pub(crate) struct DocAttrNotCrateLevel { #[primary_span] pub span: Span, @@ -56,8 +54,8 @@ pub(crate) struct DocAttrNotCrateLevel { } #[derive(Diagnostic)] -#[diag(attr_parsing_doc_keyword_not_keyword)] -#[help] +#[diag("nonexistent keyword `{$keyword}` used in `#[doc(keyword = \"...\")]`")] +#[help("only existing keywords are allowed in core/std")] pub(crate) struct DocKeywordNotKeyword { #[primary_span] pub span: Span, @@ -65,8 +63,8 @@ pub(crate) struct DocKeywordNotKeyword { } #[derive(Diagnostic)] -#[diag(attr_parsing_doc_attribute_not_attribute)] -#[help] +#[diag("nonexistent builtin attribute `{$attribute}` used in `#[doc(attribute = \"...\")]`")] +#[help("only existing builtin attributes are allowed in core/std")] pub(crate) struct DocAttributeNotAttribute { #[primary_span] pub span: Span, @@ -74,28 +72,28 @@ pub(crate) struct DocAttributeNotAttribute { } #[derive(Diagnostic)] -#[diag(attr_parsing_missing_since, code = E0542)] +#[diag("missing 'since'", code = E0542)] pub(crate) struct MissingSince { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_missing_note, code = E0543)] +#[diag("missing 'note'", code = E0543)] pub(crate) struct MissingNote { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_multiple_stability_levels, code = E0544)] +#[diag("multiple stability levels", code = E0544)] pub(crate) struct MultipleStabilityLevels { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_issue_string, code = E0545)] +#[diag("`issue` must be a non-zero numeric string or \"none\"", code = E0545)] pub(crate) struct InvalidIssueString { #[primary_span] pub span: Span, @@ -108,31 +106,31 @@ pub(crate) struct InvalidIssueString { // translatable. #[derive(Subdiagnostic)] pub(crate) enum InvalidIssueStringCause { - #[label(attr_parsing_must_not_be_zero)] + #[label("`issue` must not be \"0\", use \"none\" instead")] MustNotBeZero { #[primary_span] span: Span, }, - #[label(attr_parsing_empty)] + #[label("cannot parse integer from empty string")] Empty { #[primary_span] span: Span, }, - #[label(attr_parsing_invalid_digit)] + #[label("invalid digit found in string")] InvalidDigit { #[primary_span] span: Span, }, - #[label(attr_parsing_pos_overflow)] + #[label("number too large to fit in target type")] PosOverflow { #[primary_span] span: Span, }, - #[label(attr_parsing_neg_overflow)] + #[label("number too small to fit in target type")] NegOverflow { #[primary_span] span: Span, @@ -153,21 +151,21 @@ impl InvalidIssueStringCause { } #[derive(Diagnostic)] -#[diag(attr_parsing_missing_feature, code = E0546)] +#[diag("missing 'feature'", code = E0546)] pub(crate) struct MissingFeature { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_non_ident_feature, code = E0546)] +#[diag("'feature' is not an identifier", code = E0546)] pub(crate) struct NonIdentFeature { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_missing_issue, code = E0547)] +#[diag("missing 'issue'", code = E0547)] pub(crate) struct MissingIssue { #[primary_span] pub span: Span, @@ -176,20 +174,20 @@ pub(crate) struct MissingIssue { // FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`? // It is more similar to `IncorrectReprFormatGeneric`. #[derive(Diagnostic)] -#[diag(attr_parsing_incorrect_repr_format_packed_one_or_zero_arg, code = E0552)] +#[diag("incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all", code = E0552)] pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_incorrect_repr_format_packed_expect_integer, code = E0552)] +#[diag("incorrect `repr(packed)` attribute format: `packed` expects a literal integer as argument", code = E0552)] pub(crate) struct IncorrectReprFormatPackedExpectInteger { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_repr_hint_no_paren, code = E0552)] +#[diag("invalid representation hint: `{$name}` does not take a parenthesized argument list", code = E0552)] pub(crate) struct InvalidReprHintNoParen { #[primary_span] pub span: Span, @@ -198,7 +196,7 @@ pub(crate) struct InvalidReprHintNoParen { } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_repr_hint_no_value, code = E0552)] +#[diag("invalid representation hint: `{$name}` does not take a value", code = E0552)] pub(crate) struct InvalidReprHintNoValue { #[primary_span] pub span: Span, @@ -207,15 +205,19 @@ pub(crate) struct InvalidReprHintNoValue { } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_repr_align_need_arg, code = E0589)] +#[diag("invalid `repr(align)` attribute: `align` needs an argument", code = E0589)] pub(crate) struct InvalidReprAlignNeedArg { #[primary_span] - #[suggestion(code = "align(...)", applicability = "has-placeholders")] + #[suggestion( + "supply an argument here", + code = "align(...)", + applicability = "has-placeholders" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_repr_generic, code = E0589)] +#[diag("invalid `repr({$repr_arg})` attribute: {$error_part}", code = E0589)] pub(crate) struct InvalidReprGeneric<'a> { #[primary_span] pub span: Span, @@ -225,21 +227,21 @@ pub(crate) struct InvalidReprGeneric<'a> { } #[derive(Diagnostic)] -#[diag(attr_parsing_incorrect_repr_format_align_one_arg, code = E0693)] +#[diag("incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses", code = E0693)] pub(crate) struct IncorrectReprFormatAlignOneArg { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_incorrect_repr_format_expect_literal_integer, code = E0693)] +#[diag("incorrect `repr(align)` attribute format: `align` expects a literal integer as argument", code = E0693)] pub(crate) struct IncorrectReprFormatExpectInteger { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_incorrect_repr_format_generic, code = E0693)] +#[diag("incorrect `repr({$repr_arg})` attribute format", code = E0693)] pub(crate) struct IncorrectReprFormatGeneric { #[primary_span] pub span: Span, @@ -253,7 +255,7 @@ pub(crate) struct IncorrectReprFormatGeneric { #[derive(Subdiagnostic)] pub(crate) enum IncorrectReprFormatGenericCause { #[suggestion( - attr_parsing_suggestion, + "use parentheses instead", code = "{name}({value})", applicability = "machine-applicable" )] @@ -269,7 +271,7 @@ pub(crate) enum IncorrectReprFormatGenericCause { }, #[suggestion( - attr_parsing_suggestion, + "use parentheses instead", code = "{name}({value})", applicability = "machine-applicable" )] @@ -298,48 +300,48 @@ impl IncorrectReprFormatGenericCause { } #[derive(Diagnostic)] -#[diag(attr_parsing_rustc_promotable_pairing, code = E0717)] +#[diag("`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute", code = E0717)] pub(crate) struct RustcPromotablePairing { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_rustc_allowed_unstable_pairing, code = E0789)] +#[diag("`rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute", code = E0789)] pub(crate) struct RustcAllowedUnstablePairing { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_deprecated_item_suggestion)] +#[diag("suggestions on deprecated items are unstable")] pub(crate) struct DeprecatedItemSuggestion { #[primary_span] pub span: Span, - #[help] + #[help("add `#![feature(deprecated_suggestion)]` to the crate root")] pub is_nightly: bool, - #[note] + #[note("see #94785 for more details")] pub details: (), } #[derive(Diagnostic)] -#[diag(attr_parsing_expected_single_version_literal)] +#[diag("expected single version literal")] pub(crate) struct ExpectedSingleVersionLiteral { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_expected_version_literal)] +#[diag("expected a version literal")] pub(crate) struct ExpectedVersionLiteral { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_expects_feature_list)] +#[diag("`{$name}` expects a list of feature names")] pub(crate) struct ExpectsFeatureList { #[primary_span] pub span: Span, @@ -348,7 +350,7 @@ pub(crate) struct ExpectsFeatureList { } #[derive(Diagnostic)] -#[diag(attr_parsing_expects_features)] +#[diag("`{$name}` expects feature names")] pub(crate) struct ExpectsFeatures { #[primary_span] pub span: Span, @@ -357,21 +359,21 @@ pub(crate) struct ExpectsFeatures { } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_since)] +#[diag("'since' must be a Rust version number, such as \"1.31.0\"")] pub(crate) struct InvalidSince { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_soft_no_args)] +#[diag("`soft` should not have any arguments")] pub(crate) struct SoftNoArgs { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_unknown_version_literal)] +#[diag("unknown version literal format, assuming it refers to a future version")] pub(crate) struct UnknownVersionLiteral { #[primary_span] pub span: Span, @@ -379,78 +381,83 @@ pub(crate) struct UnknownVersionLiteral { // FIXME(jdonszelmann) duplicated from `rustc_passes`, remove once `check_attr` is integrated. #[derive(Diagnostic)] -#[diag(attr_parsing_unused_multiple)] +#[diag("multiple `{$name}` attributes")] pub(crate) struct UnusedMultiple { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] pub this: Span, - #[note] + #[note("attribute also specified here")] pub other: Span, pub name: Symbol, } #[derive(Diagnostic)] -#[diag(attr_parsing_null_on_export, code = E0648)] +#[diag("`export_name` may not contain null characters", code = E0648)] pub(crate) struct NullOnExport { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_null_on_link_section, code = E0648)] +#[diag("`link_section` may not contain null characters", code = E0648)] pub(crate) struct NullOnLinkSection { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_null_on_objc_class)] +#[diag("`objc::class!` may not contain null characters")] pub(crate) struct NullOnObjcClass { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_null_on_objc_selector)] +#[diag("`objc::selector!` may not contain null characters")] pub(crate) struct NullOnObjcSelector { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_objc_class_expected_string_literal)] +#[diag("`objc::class!` expected a string literal")] pub(crate) struct ObjcClassExpectedStringLiteral { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_objc_selector_expected_string_literal)] +#[diag("`objc::selector!` expected a string literal")] pub(crate) struct ObjcSelectorExpectedStringLiteral { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_stability_outside_std, code = E0734)] +#[diag("stability attributes may not be used outside of the standard library", code = E0734)] pub(crate) struct StabilityOutsideStd { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_empty_confusables)] +#[diag("expected at least one confusable name")] pub(crate) struct EmptyConfusables { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[help] -#[diag(attr_parsing_invalid_target)] +#[help("`#[{$name}]` can {$only}be applied to {$applied}")] +#[diag("`#[{$name}]` attribute cannot be used on {$target}")] pub(crate) struct InvalidTarget { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove the attribute", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub span: Span, pub name: AttrPath, pub target: &'static str, @@ -459,7 +466,7 @@ pub(crate) struct InvalidTarget { } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_alignment_value, code = E0589)] +#[diag("invalid alignment value: {$error_part}", code = E0589)] pub(crate) struct InvalidAlignmentValue { #[primary_span] pub span: Span, @@ -467,43 +474,49 @@ pub(crate) struct InvalidAlignmentValue { } #[derive(Diagnostic)] -#[diag(attr_parsing_repr_ident, code = E0565)] +#[diag("meta item in `repr` must be an identifier", code = E0565)] pub(crate) struct ReprIdent { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_unrecognized_repr_hint, code = E0552)] -#[help] -#[note] +#[diag("unrecognized representation hint", code = E0552)] +#[help( + "valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`" +)] +#[note( + "for more information, visit " +)] pub(crate) struct UnrecognizedReprHint { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_unstable_feature_bound_incompatible_stability)] -#[help] +#[diag("item annotated with `#[unstable_feature_bound]` should not be stable")] +#[help( + "if this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`" +)] pub(crate) struct UnstableFeatureBoundIncompatibleStability { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_naked_functions_incompatible_attribute, code = E0736)] +#[diag("attribute incompatible with `#[unsafe(naked)]`", code = E0736)] pub(crate) struct NakedFunctionIncompatibleAttribute { #[primary_span] - #[label] + #[label("the `{$attr}` attribute is incompatible with `#[unsafe(naked)]`")] pub span: Span, - #[label(attr_parsing_naked_attribute)] + #[label("function marked with `#[unsafe(naked)]` here")] pub naked_span: Span, pub attr: String, } #[derive(Diagnostic)] -#[diag(attr_parsing_link_ordinal_out_of_range)] -#[note] +#[diag("ordinal value in `link_ordinal` is too large: `{$ordinal}`")] +#[note("the value may not exceed `u16::MAX`")] pub(crate) struct LinkOrdinalOutOfRange { #[primary_span] pub span: Span, @@ -511,8 +524,8 @@ pub(crate) struct LinkOrdinalOutOfRange { } #[derive(Diagnostic)] -#[diag(attr_parsing_rustc_scalable_vector_count_out_of_range)] -#[note] +#[diag("element count in `rustc_scalable_vector` is too large: `{$n}`")] +#[note("the value may not exceed `u16::MAX`")] pub(crate) struct RustcScalableVectorCountOutOfRange { #[primary_span] pub span: Span, @@ -586,7 +599,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { if let Some(start_point_span) = byte_string { diag.span_suggestion( start_point_span, - fluent::attr_parsing_unsupported_literal_suggestion, + "consider removing the prefix", "", Applicability::MaybeIncorrect, ); @@ -751,30 +764,27 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_attr_unsafe)] -#[note] +#[diag("`{$name}` is not an unsafe attribute")] +#[note("extraneous unsafe is not allowed in attributes")] pub(crate) struct InvalidAttrUnsafe { #[primary_span] - #[label] + #[label("this is not an unsafe attribute")] pub span: Span, pub name: AttrPath, } #[derive(Diagnostic)] -#[diag(attr_parsing_unsafe_attr_outside_unsafe)] +#[diag("unsafe attribute used without unsafe")] pub(crate) struct UnsafeAttrOutsideUnsafe { #[primary_span] - #[label] + #[label("usage of unsafe attribute")] pub span: Span, #[subdiagnostic] pub suggestion: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion( - attr_parsing_unsafe_attr_outside_unsafe_suggestion, - applicability = "machine-applicable" -)] +#[multipart_suggestion("wrap the attribute in `unsafe(...)`", applicability = "machine-applicable")] pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { #[suggestion_part(code = "unsafe(")] pub left: Span, @@ -783,7 +793,7 @@ pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { } #[derive(Diagnostic)] -#[diag(attr_parsing_meta_bad_delim)] +#[diag("wrong meta list delimiters")] pub(crate) struct MetaBadDelim { #[primary_span] pub span: Span, @@ -793,7 +803,7 @@ pub(crate) struct MetaBadDelim { #[derive(Subdiagnostic)] #[multipart_suggestion( - attr_parsing_meta_bad_delim_suggestion, + "the delimiters should be `(` and `)`", applicability = "machine-applicable" )] pub(crate) struct MetaBadDelimSugg { @@ -804,7 +814,7 @@ pub(crate) struct MetaBadDelimSugg { } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_meta_item)] +#[diag("expected a literal (`1u8`, `1.0f32`, `\"string\"`, etc.) here, found {$descr}")] pub(crate) struct InvalidMetaItem { #[primary_span] pub span: Span, @@ -813,12 +823,15 @@ pub(crate) struct InvalidMetaItem { pub quote_ident_sugg: Option, #[subdiagnostic] pub remove_neg_sugg: Option, - #[label] + #[label("{$descr}s are not allowed here")] pub label: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion(attr_parsing_quote_ident_sugg, applicability = "machine-applicable")] +#[multipart_suggestion( + "surround the identifier with quotation marks to make it into a string literal", + applicability = "machine-applicable" +)] pub(crate) struct InvalidMetaItemQuoteIdentSugg { #[suggestion_part(code = "\"")] pub before: Span, @@ -827,73 +840,80 @@ pub(crate) struct InvalidMetaItemQuoteIdentSugg { } #[derive(Subdiagnostic)] -#[multipart_suggestion(attr_parsing_remove_neg_sugg, applicability = "machine-applicable")] +#[multipart_suggestion( + "negative numbers are not literals, try removing the `-` sign", + applicability = "machine-applicable" +)] pub(crate) struct InvalidMetaItemRemoveNegSugg { #[suggestion_part(code = "")] pub negative_sign: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_suffixed_literal_in_attribute)] -#[help] +#[diag("suffixed literals are not allowed in attributes")] +#[help( + "instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)" +)] pub(crate) struct SuffixedLiteralInAttribute { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_empty_link_name, code = E0454)] +#[diag("link name must not be empty", code = E0454)] pub(crate) struct EmptyLinkName { #[primary_span] - #[label] + #[label("empty link name")] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_link_framework_apple, code = E0455)] +#[diag("link kind `framework` is only supported on Apple targets", code = E0455)] pub(crate) struct LinkFrameworkApple { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_incompatible_wasm_link)] +#[diag("`wasm_import_module` is incompatible with other arguments in `#[link]` attributes")] pub(crate) struct IncompatibleWasmLink { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_link_requires_name, code = E0459)] +#[diag("`#[link]` attribute requires a `name = \"string\"` argument", code = E0459)] pub(crate) struct LinkRequiresName { #[primary_span] - #[label] + #[label("missing `name` argument")] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_raw_dylib_no_nul)] +#[diag("link name must not contain NUL characters if link kind is `raw-dylib`")] pub(crate) struct RawDylibNoNul { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_raw_dylib_only_windows, code = E0455)] +#[diag("link kind `raw-dylib` is only supported on Windows targets", code = E0455)] pub(crate) struct RawDylibOnlyWindows { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_invalid_link_modifier)] +#[diag( + "invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed" +)] pub(crate) struct InvalidLinkModifier { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_multiple_modifiers)] +#[diag("multiple `{$modifier}` modifiers in a single `modifiers` argument")] pub(crate) struct MultipleModifiers { #[primary_span] pub span: Span, @@ -901,52 +921,54 @@ pub(crate) struct MultipleModifiers { } #[derive(Diagnostic)] -#[diag(attr_parsing_import_name_type_x86)] +#[diag("import name type is only supported on x86")] pub(crate) struct ImportNameTypeX86 { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_bundle_needs_static)] +#[diag("linking modifier `bundle` is only compatible with `static` linking kind")] pub(crate) struct BundleNeedsStatic { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_whole_archive_needs_static)] +#[diag("linking modifier `whole-archive` is only compatible with `static` linking kind")] pub(crate) struct WholeArchiveNeedsStatic { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_as_needed_compatibility)] +#[diag( + "linking modifier `as-needed` is only compatible with `dylib`, `framework` and `raw-dylib` linking kinds" +)] pub(crate) struct AsNeededCompatibility { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_import_name_type_raw)] +#[diag("import name type can only be used with link kind `raw-dylib`")] pub(crate) struct ImportNameTypeRaw { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_limit_invalid)] +#[diag("`limit` must be a non-negative integer")] pub(crate) struct LimitInvalid<'a> { #[primary_span] pub span: Span, - #[label] + #[label("{$error_str}")] pub value_span: Span, pub error_str: &'a str, } #[derive(Diagnostic)] -#[diag(attr_parsing_cfg_attr_bad_delim)] +#[diag("wrong `cfg_attr` delimiters")] pub(crate) struct CfgAttrBadDelim { #[primary_span] pub span: Span, @@ -955,14 +977,16 @@ pub(crate) struct CfgAttrBadDelim { } #[derive(Diagnostic)] -#[diag(attr_parsing_doc_alias_malformed)] +#[diag( + "doc alias attribute expects a string `#[doc(alias = \"a\")]` or a list of strings `#[doc(alias(\"a\", \"b\"))]`" +)] pub(crate) struct DocAliasMalformed { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(attr_parsing_unsupported_instruction_set)] +#[diag("target `{$current_target}` does not support `#[instruction_set({$instruction_set}::*)]`")] pub(crate) struct UnsupportedInstructionSet<'a> { #[primary_span] pub span: Span, diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index c160240a18a7..49b73e4392d1 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -12,7 +12,6 @@ rustc_ast = { path = "../rustc_ast" } rustc_ast_lowering = { path = "../rustc_ast_lowering" } rustc_ast_passes = { path = "../rustc_ast_passes" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } -rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_borrowck = { path = "../rustc_borrowck" } rustc_builtin_macros = { path = "../rustc_builtin_macros" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 38ee87601614..6738504e7219 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -119,7 +119,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ crate::DEFAULT_LOCALE_RESOURCE, rustc_ast_lowering::DEFAULT_LOCALE_RESOURCE, rustc_ast_passes::DEFAULT_LOCALE_RESOURCE, - rustc_attr_parsing::DEFAULT_LOCALE_RESOURCE, rustc_borrowck::DEFAULT_LOCALE_RESOURCE, rustc_builtin_macros::DEFAULT_LOCALE_RESOURCE, rustc_codegen_ssa::DEFAULT_LOCALE_RESOURCE, From e58538c55257e73f789bd671c8d96f0fecd4ff49 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 1 Feb 2026 22:18:59 +1100 Subject: [PATCH 467/978] Rename `collect_active_jobs` to several distinct names --- compiler/rustc_interface/src/util.rs | 2 +- compiler/rustc_query_impl/src/plumbing.rs | 40 ++++++++++++++----- compiler/rustc_query_system/src/query/job.rs | 4 +- compiler/rustc_query_system/src/query/mod.rs | 5 ++- .../rustc_query_system/src/query/plumbing.rs | 22 ++++++---- 5 files changed, 52 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 249368fd1194..25f59f0e89df 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -254,7 +254,7 @@ internal compiler error: query cycle handler thread panicked, aborting process"; || { // Ensure there were no errors collecting all active jobs. // We need the complete map to ensure we find a cycle to break. - QueryCtxt::new(tcx).collect_active_jobs(false).expect( + QueryCtxt::new(tcx).collect_active_jobs_from_all_queries(false).expect( "failed to collect active queries in deadlock handler", ) }, diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 8be45d1fb464..d1721f1f455f 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -50,7 +50,9 @@ impl<'tcx> QueryCtxt<'tcx> { } fn depth_limit_error(self, job: QueryJobId) { - let query_map = self.collect_active_jobs(true).expect("failed to collect active queries"); + let query_map = self + .collect_active_jobs_from_all_queries(true) + .expect("failed to collect active queries"); let (info, depth) = job.find_dep_kind_root(query_map); let suggested_limit = match self.tcx.recursion_limit() { @@ -98,7 +100,7 @@ impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> { tls::with_related_context(self.tcx, |icx| icx.query) } - /// Returns a map of currently active query jobs. + /// Returns a map of currently active query jobs, collected from all queries. /// /// If `require_complete` is `true`, this function locks all shards of the /// query results to produce a complete map, which always returns `Ok`. @@ -108,12 +110,15 @@ impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> { /// Prefer passing `false` to `require_complete` to avoid potential deadlocks, /// especially when called from within a deadlock handler, unless a /// complete map is needed and no deadlock is possible at this call site. - fn collect_active_jobs(self, require_complete: bool) -> Result, QueryMap<'tcx>> { + fn collect_active_jobs_from_all_queries( + self, + require_complete: bool, + ) -> Result, QueryMap<'tcx>> { let mut jobs = QueryMap::default(); let mut complete = true; - for collect in super::COLLECT_ACTIVE_JOBS.iter() { - if collect(self.tcx, &mut jobs, require_complete).is_none() { + for gather_fn in crate::PER_QUERY_GATHER_ACTIVE_JOBS_FNS.iter() { + if gather_fn(self.tcx, &mut jobs, require_complete).is_none() { complete = false; } } @@ -731,7 +736,10 @@ macro_rules! define_queries { } } - pub(crate) fn collect_active_jobs<'tcx>( + /// Internal per-query plumbing for collecting the set of active jobs for this query. + /// + /// Should only be called through `PER_QUERY_GATHER_ACTIVE_JOBS_FNS`. + pub(crate) fn gather_active_jobs<'tcx>( tcx: TyCtxt<'tcx>, qmap: &mut QueryMap<'tcx>, require_complete: bool, @@ -741,12 +749,15 @@ macro_rules! define_queries { let name = stringify!($name); $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name) }; - let res = tcx.query_system.states.$name.collect_active_jobs( + + // Call `gather_active_jobs_inner` to do the actual work. + let res = tcx.query_system.states.$name.gather_active_jobs_inner( tcx, make_frame, qmap, require_complete, ); + // this can be called during unwinding, and the function has a `try_`-prefix, so // don't `unwrap()` here, just manually check for `None` and do best-effort error // reporting. @@ -816,10 +827,17 @@ macro_rules! define_queries { // These arrays are used for iteration and can't be indexed by `DepKind`. - const COLLECT_ACTIVE_JOBS: &[ - for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<'tcx>, bool) -> Option<()> - ] = - &[$(query_impl::$name::collect_active_jobs),*]; + /// Used by `collect_active_jobs_from_all_queries` to iterate over all + /// queries, and gather the active jobs for each query. + /// + /// (We arbitrarily use the word "gather" when collecting the jobs for + /// each individual query, so that we have distinct function names to + /// grep for.) + const PER_QUERY_GATHER_ACTIVE_JOBS_FNS: &[ + for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<'tcx>, require_complete: bool) -> Option<()> + ] = &[ + $(query_impl::$name::gather_active_jobs),* + ]; const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[ for<'tcx> fn(TyCtxt<'tcx>, &mut QueryKeyStringCache) diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 82b23b022c37..50cb58f0b4d5 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -32,6 +32,8 @@ impl<'tcx> QueryInfo> { } } +/// Map from query job IDs to job information collected by +/// [`QueryContext::collect_active_jobs_from_all_queries`]. pub type QueryMap<'tcx> = FxHashMap>; /// A value uniquely identifying an active query job. @@ -613,7 +615,7 @@ pub fn print_query_stack<'tcx, Qcx: QueryContext<'tcx>>( let mut count_total = 0; // Make use of a partial query map if we fail to take locks collecting active queries. - let query_map = match qcx.collect_active_jobs(false) { + let query_map = match qcx.collect_active_jobs_from_all_queries(false) { Ok(query_map) => query_map, Err(query_map) => query_map, }; diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 54e5fa4d7229..dbf7395bd61a 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -166,7 +166,10 @@ pub trait QueryContext<'tcx>: HasDepContext { /// Get the query information from the TLS context. fn current_query_job(self) -> Option; - fn collect_active_jobs(self, require_complete: bool) -> Result, QueryMap<'tcx>>; + fn collect_active_jobs_from_all_queries( + self, + require_complete: bool, + ) -> Result, QueryMap<'tcx>>; /// Load a side effect associated to the node in the previous session. fn load_side_effect( diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 472839116107..fcd2e80a4fdc 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -11,7 +11,6 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::hash_table::{self, Entry, HashTable}; use rustc_data_structures::sharded::{self, Sharded}; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::sync::LockGuard; use rustc_data_structures::{outline, sync}; use rustc_errors::{Diag, FatalError, StashKey}; use rustc_span::{DUMMY_SP, Span}; @@ -79,7 +78,10 @@ where self.active.lock_shards().all(|shard| shard.is_empty()) } - pub fn collect_active_jobs( + /// Internal plumbing for collecting the set of active jobs for this query. + /// + /// Should only be called from `gather_active_jobs`. + pub fn gather_active_jobs_inner( &self, qcx: Qcx, make_frame: fn(Qcx, K) -> QueryStackFrame>, @@ -88,23 +90,26 @@ where ) -> Option<()> { let mut active = Vec::new(); - let mut collect = |iter: LockGuard<'_, HashTable<(K, ActiveKeyStatus<'tcx>)>>| { - for (k, v) in iter.iter() { + // Helper to gather active jobs from a single shard. + let mut gather_shard_jobs = |shard: &HashTable<(K, ActiveKeyStatus<'tcx>)>| { + for (k, v) in shard.iter() { if let ActiveKeyStatus::Started(ref job) = *v { active.push((*k, job.clone())); } } }; + // Lock shards and gather jobs from each shard. if require_complete { for shard in self.active.lock_shards() { - collect(shard); + gather_shard_jobs(&shard); } } else { // We use try_lock_shards here since we are called from the // deadlock handler, and this shouldn't be locked. for shard in self.active.try_lock_shards() { - collect(shard?); + let shard = shard?; + gather_shard_jobs(&shard); } } @@ -294,7 +299,10 @@ where { // Ensure there was no errors collecting all active jobs. // We need the complete map to ensure we find a cycle to break. - let query_map = qcx.collect_active_jobs(false).ok().expect("failed to collect active queries"); + let query_map = qcx + .collect_active_jobs_from_all_queries(false) + .ok() + .expect("failed to collect active queries"); let error = try_execute.find_cycle_in_stack(query_map, &qcx.current_query_job(), span); (mk_cycle(query, qcx, error.lift()), None) From f8fe49ea9e1c997c689df921e0da2460545e9c39 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 3 Feb 2026 10:18:22 +0100 Subject: [PATCH 468/978] Introduce `inline_fluent` macro --- compiler/rustc_attr_parsing/src/attributes/cfg.rs | 4 ++-- .../rustc_attr_parsing/src/attributes/link_attrs.rs | 8 +++++--- compiler/rustc_errors/src/translation.rs | 11 +++++++++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index ca6bfdbeaf5f..3d885135cbe0 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -3,7 +3,7 @@ use std::convert::identity; use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::DelimSpan; use rustc_ast::{AttrItem, Attribute, CRATE_NODE_ID, LitKind, ast, token}; -use rustc_errors::{Applicability, PResult}; +use rustc_errors::{Applicability, PResult, inline_fluent}; use rustc_feature::{ AttrSuggestionStyle, AttributeTemplate, Features, GatedCfg, find_gated_cfg, template, }; @@ -141,7 +141,7 @@ fn parse_cfg_entry_target( cx.sess(), sym::cfg_target_compact, meta_span, - "compact `cfg(target(..))` is experimental and subject to change", + inline_fluent!("compact `cfg(target(..))` is experimental and subject to change"), ) .emit(); } diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 02723e96ad19..c9da2f3b14bf 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -1,3 +1,4 @@ +use rustc_errors::inline_fluent; use rustc_feature::Features; use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection}; use rustc_hir::attrs::*; @@ -304,7 +305,7 @@ impl LinkParser { sess, sym::raw_dylib_elf, nv.value_span, - "link kind `raw-dylib` is unstable on ELF platforms", + inline_fluent!("link kind `raw-dylib` is unstable on ELF platforms"), ) .emit(); } else { @@ -319,7 +320,7 @@ impl LinkParser { sess, sym::link_arg_attribute, nv.value_span, - "link kind `link-arg` is unstable", + inline_fluent!("link kind `link-arg` is unstable"), ) .emit(); } @@ -384,7 +385,8 @@ impl LinkParser { return true; }; if !features.link_cfg() { - feature_err(sess, sym::link_cfg, item.span(), "link cfg is unstable").emit(); + feature_err(sess, sym::link_cfg, item.span(), inline_fluent!("link cfg is unstable")) + .emit(); } *cfg = parse_cfg_entry(cx, link_cfg).ok(); true diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index 0ee2b7b06090..aba79c30f3a3 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -166,3 +166,14 @@ impl Translator { } } } + +/// This macro creates a translatable `DiagMessage` from a literal string. +/// It should be used in places where a translatable message is needed, but struct diagnostics are undesired. +/// +/// This is a macro because in the future we may want to globally register these messages. +#[macro_export] +macro_rules! inline_fluent { + ($inline: literal) => { + rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed($inline)) + }; +} From 6b3d1e060490bd735fb3cd6048532297369a1893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 3 Feb 2026 11:47:30 +0100 Subject: [PATCH 469/978] Update Cargo.lock It probably wasn't committed after an earlier change. --- src/ci/citool/Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ci/citool/Cargo.lock b/src/ci/citool/Cargo.lock index 9e1ded4d3f7c..fe1c92f049e0 100644 --- a/src/ci/citool/Cargo.lock +++ b/src/ci/citool/Cargo.lock @@ -66,9 +66,9 @@ checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "askama" -version = "0.15.1" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7125972258312e79827b60c9eb93938334100245081cf701a2dee981b17427" +checksum = "08e1676b346cadfec169374f949d7490fd80a24193d37d2afce0c047cf695e57" dependencies = [ "askama_macros", "itoa", @@ -79,9 +79,9 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.15.1" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba5e7259a1580c61571e3116ebaaa01e3c001b2132b17c4cc5c70780ca3e994" +checksum = "7661ff56517787343f376f75db037426facd7c8d3049cef8911f1e75016f3a37" dependencies = [ "askama_parser", "basic-toml", @@ -96,18 +96,18 @@ dependencies = [ [[package]] name = "askama_macros" -version = "0.15.1" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "236ce20b77cb13506eaf5024899f4af6e12e8825f390bd943c4c37fd8f322e46" +checksum = "713ee4dbfd1eb719c2dab859465b01fa1d21cb566684614a713a6b7a99a4e47b" dependencies = [ "askama_derive", ] [[package]] name = "askama_parser" -version = "0.15.1" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c63392767bb2df6aa65a6e1e3b80fd89bb7af6d58359b924c0695620f1512e" +checksum = "1d62d674238a526418b30c0def480d5beadb9d8964e7f38d635b03bf639c704c" dependencies = [ "rustc-hash", "serde", From cb9c43b7e867299db5284bffce1f498356e5167f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 3 Feb 2026 11:47:53 +0100 Subject: [PATCH 470/978] Show largest job duration changes in hours and minutes, rather than just seconds --- src/ci/citool/src/analysis.rs | 31 ++++++++++++++++++++++++++----- src/ci/citool/src/main.rs | 4 ++-- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 39b115154f9f..e91d27a36092 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -194,8 +194,8 @@ pub fn output_test_diffs( report_test_diffs(aggregated_test_diffs, job_metrics, job_info_resolver); } -/// Prints the ten largest differences in bootstrap durations. -pub fn output_largest_duration_changes( +/// Prints the ten largest differences in job durations. +pub fn output_largest_job_duration_changes( job_metrics: &HashMap, job_info_resolver: &mut JobInfoResolver, ) { @@ -237,11 +237,11 @@ pub fn output_largest_duration_changes( println!("# Job duration changes"); for (index, entry) in changes.into_iter().take(10).enumerate() { println!( - "{}. {}: {:.1}s -> {:.1}s ({:+.1}%)", + "{}. {}: {} -> {} ({:+.1}%)", index + 1, format_job_link(job_info_resolver, job_metrics, entry.job), - entry.before.as_secs_f64(), - entry.after.as_secs_f64(), + format_duration(entry.before), + format_duration(entry.after), entry.change ); } @@ -256,6 +256,27 @@ mostly for t-infra members, for simpler debugging of potential CI slow-downs."# }); } +fn format_duration(duration: Duration) -> String { + let total_secs = duration.as_secs(); + let hours = total_secs / 3600; + let minutes = (total_secs % 3600) / 60; + let seconds = total_secs % 60; + + let mut res = String::new(); + + if hours > 0 { + res.push_str(&format!("{hours}h ")); + } + if minutes > 0 { + res.push_str(&format!("{minutes}m ")); + } + if hours == 0 && seconds > 0 { + res.push_str(&format!("{seconds}s")); + } + + res.trim().to_string() +} + #[derive(Default)] struct TestSuiteRecord { passed: u64, diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 01c0650b3c98..9b9cbe3862e3 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -17,7 +17,7 @@ use clap::Parser; use jobs::JobDatabase; use serde_yaml::Value; -use crate::analysis::{output_largest_duration_changes, output_test_diffs}; +use crate::analysis::{output_largest_job_duration_changes, output_test_diffs}; use crate::cpu_usage::load_cpu_usage; use crate::datadog::upload_datadog_metric; use crate::github::JobInfoResolver; @@ -205,7 +205,7 @@ And then open `test-dashboard/index.html` in your browser to see an overview of ); }); - output_largest_duration_changes(&metrics, &mut job_info_resolver); + output_largest_job_duration_changes(&metrics, &mut job_info_resolver); Ok(()) } From 5405e5d06e7b2fede8cfba16a5bd140a8ebeb4f0 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Tue, 3 Feb 2026 11:52:00 +0000 Subject: [PATCH 471/978] Suppress unused_mut lint if mutation fails due to borrowck error Remedying the borrowck error will likely result in the mut becoming used. --- compiler/rustc_borrowck/src/lib.rs | 11 +++++++++++ .../unused/mut-used-despite-borrowck-error.rs | 19 +++++++++++++++++++ .../mut-used-despite-borrowck-error.stderr | 13 +++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 tests/ui/lint/unused/mut-used-despite-borrowck-error.rs create mode 100644 tests/ui/lint/unused/mut-used-despite-borrowck-error.stderr diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 7c5cbc58e25c..946c1c093fd7 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1207,6 +1207,17 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { "access_place: suppressing error place_span=`{:?}` kind=`{:?}`", place_span, kind ); + + // If the place is being mutated, then mark it as such anyway in order to suppress the + // `unused_mut` lint, which is likely incorrect once the access place error has been + // resolved. + if rw == ReadOrWrite::Write(WriteKind::Mutate) + && let Ok(root_place) = + self.is_mutable(place_span.0.as_ref(), is_local_mutation_allowed) + { + self.add_used_mut(root_place, state); + } + return; } diff --git a/tests/ui/lint/unused/mut-used-despite-borrowck-error.rs b/tests/ui/lint/unused/mut-used-despite-borrowck-error.rs new file mode 100644 index 000000000000..7f1a51bc8510 --- /dev/null +++ b/tests/ui/lint/unused/mut-used-despite-borrowck-error.rs @@ -0,0 +1,19 @@ +//! Do not fire unused_mut lint when mutation of the bound variable fails due to a borrow-checking +//! error. +//! +//! Regression test for https://github.com/rust-lang/rust/issues/152024 +//@ compile-flags: -W unused_mut + +struct Thing; +impl Drop for Thing { + fn drop(&mut self) {} +} + +fn main() { + let mut t; + let mut b = None; + loop { + t = Thing; //~ ERROR cannot assign to `t` because it is borrowed + b.insert(&t); + } +} diff --git a/tests/ui/lint/unused/mut-used-despite-borrowck-error.stderr b/tests/ui/lint/unused/mut-used-despite-borrowck-error.stderr new file mode 100644 index 000000000000..c03cf3f7c609 --- /dev/null +++ b/tests/ui/lint/unused/mut-used-despite-borrowck-error.stderr @@ -0,0 +1,13 @@ +error[E0506]: cannot assign to `t` because it is borrowed + --> $DIR/mut-used-despite-borrowck-error.rs:16:9 + | +LL | t = Thing; + | ^ `t` is assigned to here but it was already borrowed +LL | b.insert(&t); + | - -- `t` is borrowed here + | | + | borrow later used here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0506`. From 0418f9aa42a9c9e7ca38a8c2a4a1e275c68a5154 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 3 Feb 2026 22:53:38 +1100 Subject: [PATCH 472/978] coverage: Add a test case for a previously-unknown span mismatch --- .../rustc_mir_transform/src/coverage/spans.rs | 8 ++-- .../context-mismatch-issue-147339.cov-map | 40 +++++++++++++++++++ .../context-mismatch-issue-147339.coverage | 28 +++++++++++++ .../macros/context-mismatch-issue-147339.rs | 20 ++++++++++ 4 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 tests/coverage/macros/context-mismatch-issue-147339.cov-map create mode 100644 tests/coverage/macros/context-mismatch-issue-147339.coverage create mode 100644 tests/coverage/macros/context-mismatch-issue-147339.rs diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index b1ce0069b43a..bdc861e2cece 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -55,12 +55,10 @@ pub(super) fn extract_refined_covspans<'tcx>( } // Each pushed covspan should have the same context as the body span. - // If it somehow doesn't, discard the covspan, or panic in debug builds. + // If it somehow doesn't, discard the covspan. if !body_span.eq_ctxt(covspan_span) { - debug_assert!( - false, - "span context mismatch: body_span={body_span:?}, covspan.span={covspan_span:?}" - ); + // FIXME(Zalathar): Investigate how and why this is triggered + // by `tests/coverage/macros/context-mismatch-issue-147339.rs`. return false; } diff --git a/tests/coverage/macros/context-mismatch-issue-147339.cov-map b/tests/coverage/macros/context-mismatch-issue-147339.cov-map new file mode 100644 index 000000000000..7aa829cab72b --- /dev/null +++ b/tests/coverage/macros/context-mismatch-issue-147339.cov-map @@ -0,0 +1,40 @@ +Function name: context_mismatch_issue_147339::a (unused) +Raw bytes (14): 0x[01, 01, 00, 02, 00, 0c, 27, 00, 35, 00, 00, 3b, 00, 3c] +Number of files: 1 +- file 0 => $DIR/context-mismatch-issue-147339.rs +Number of expressions: 0 +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 12, 39) to (start + 0, 53) +- Code(Zero) at (prev + 0, 59) to (start + 0, 60) +Highest counter ID seen: (none) + +Function name: context_mismatch_issue_147339::b (unused) +Raw bytes (14): 0x[01, 01, 00, 02, 00, 0c, 27, 00, 35, 00, 00, 3b, 00, 3c] +Number of files: 1 +- file 0 => $DIR/context-mismatch-issue-147339.rs +Number of expressions: 0 +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 12, 39) to (start + 0, 53) +- Code(Zero) at (prev + 0, 59) to (start + 0, 60) +Highest counter ID seen: (none) + +Function name: context_mismatch_issue_147339::c (unused) +Raw bytes (14): 0x[01, 01, 00, 02, 00, 0c, 27, 00, 35, 00, 00, 3b, 00, 3c] +Number of files: 1 +- file 0 => $DIR/context-mismatch-issue-147339.rs +Number of expressions: 0 +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 12, 39) to (start + 0, 53) +- Code(Zero) at (prev + 0, 59) to (start + 0, 60) +Highest counter ID seen: (none) + +Function name: context_mismatch_issue_147339::main +Raw bytes (14): 0x[01, 01, 00, 02, 01, 14, 01, 00, 0a, 01, 00, 0c, 00, 0d] +Number of files: 1 +- file 0 => $DIR/context-mismatch-issue-147339.rs +Number of expressions: 0 +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 20, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 12) to (start + 0, 13) +Highest counter ID seen: c0 + diff --git a/tests/coverage/macros/context-mismatch-issue-147339.coverage b/tests/coverage/macros/context-mismatch-issue-147339.coverage new file mode 100644 index 000000000000..9b4fc67b8dff --- /dev/null +++ b/tests/coverage/macros/context-mismatch-issue-147339.coverage @@ -0,0 +1,28 @@ + LL| |//@ edition: 2024 + LL| | + LL| |// These nested macro expansions were found to cause span refinement to produce + LL| |// spans with a context that doesn't match the function body span, triggering + LL| |// a defensive check that discards the span. + LL| |// + LL| |// Reported in . + LL| | + LL| |macro_rules! foo { + LL| | ($($m:ident $($f:ident $v:tt)+),*) => { + LL| | $($(macro_rules! $f { () => { $v } })+)* + LL| 0| $(macro_rules! $m { () => { $(fn $f() -> i32 { $v })+ } })* + ------------------ + | Unexecuted instantiation: context_mismatch_issue_147339::a + ------------------ + | Unexecuted instantiation: context_mismatch_issue_147339::b + ------------------ + | Unexecuted instantiation: context_mismatch_issue_147339::c + ------------------ + LL| | } + LL| |} + LL| | + LL| |foo!(m a 1 b 2, n c 3); + LL| |m!(); + LL| |n!(); + LL| | + LL| 1|fn main() {} + diff --git a/tests/coverage/macros/context-mismatch-issue-147339.rs b/tests/coverage/macros/context-mismatch-issue-147339.rs new file mode 100644 index 000000000000..80e744afc7c6 --- /dev/null +++ b/tests/coverage/macros/context-mismatch-issue-147339.rs @@ -0,0 +1,20 @@ +//@ edition: 2024 + +// These nested macro expansions were found to cause span refinement to produce +// spans with a context that doesn't match the function body span, triggering +// a defensive check that discards the span. +// +// Reported in . + +macro_rules! foo { + ($($m:ident $($f:ident $v:tt)+),*) => { + $($(macro_rules! $f { () => { $v } })+)* + $(macro_rules! $m { () => { $(fn $f() -> i32 { $v })+ } })* + } +} + +foo!(m a 1 b 2, n c 3); +m!(); +n!(); + +fn main() {} From 5e30860d311ff54116711ee3381dcea218ae870c Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 3 Feb 2026 13:24:04 +0100 Subject: [PATCH 473/978] Don't check variables in subdiagnostic messages --- compiler/rustc_macros/src/diagnostics/diagnostic.rs | 4 ++-- .../rustc_macros/src/diagnostics/diagnostic_builder.rs | 6 +++--- compiler/rustc_macros/src/diagnostics/message.rs | 9 +++++++-- compiler/rustc_macros/src/diagnostics/subdiagnostic.rs | 9 +++------ 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index b4270f45422e..e8356655dd9f 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -31,7 +31,7 @@ impl<'a> DiagnosticDerive<'a> { return DiagnosticDeriveError::ErrorHandled.to_compile_error(); }; messages.borrow_mut().push(message.clone()); - let message = message.diag_message(variant); + let message = message.diag_message(Some(variant)); let init = quote! { let mut diag = rustc_errors::Diag::new( @@ -97,7 +97,7 @@ impl<'a> LintDiagnosticDerive<'a> { return DiagnosticDeriveError::ErrorHandled.to_compile_error(); }; messages.borrow_mut().push(message.clone()); - let message = message.diag_message(variant); + let message = message.diag_message(Some(variant)); let primary_message = quote! { diag.primary_message(#message); }; diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index e6d9409a1fa3..6107b181eea2 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -456,7 +456,7 @@ impl DiagnosticDeriveVariantBuilder { applicability.set_once(quote! { #static_applicability }, span); } - let message = slug.diag_message(variant); + let message = slug.diag_message(Some(variant)); let applicability = applicability .value() .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified }); @@ -487,7 +487,7 @@ impl DiagnosticDeriveVariantBuilder { variant: &VariantInfo<'_>, ) -> TokenStream { let fn_name = format_ident!("span_{}", kind); - let message = message.diag_message(variant); + let message = message.diag_message(Some(variant)); quote! { diag.#fn_name( #field_binding, @@ -504,7 +504,7 @@ impl DiagnosticDeriveVariantBuilder { message: Message, variant: &VariantInfo<'_>, ) -> TokenStream { - let message = message.diag_message(variant); + let message = message.diag_message(Some(variant)); quote! { diag.#kind(#message); } diff --git a/compiler/rustc_macros/src/diagnostics/message.rs b/compiler/rustc_macros/src/diagnostics/message.rs index 153abecf8937..6c8aded89f16 100644 --- a/compiler/rustc_macros/src/diagnostics/message.rs +++ b/compiler/rustc_macros/src/diagnostics/message.rs @@ -14,13 +14,18 @@ pub(crate) enum Message { } impl Message { - pub(crate) fn diag_message(&self, variant: &VariantInfo<'_>) -> TokenStream { + /// Get the diagnostic message for this diagnostic + /// The passed `variant` is used to check whether all variables in the message are used. + /// For subdiagnostics, we cannot check this. + pub(crate) fn diag_message(&self, variant: Option<&VariantInfo<'_>>) -> TokenStream { match self { Message::Slug(slug) => { quote! { crate::fluent_generated::#slug } } Message::Inline(message_span, message) => { - verify_fluent_message(*message_span, &message, variant); + if let Some(variant) = variant { + verify_fluent_message(*message_span, &message, variant); + } quote! { rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed(#message)) } } } diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index adc968dacd5c..ac1fa984664c 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -75,7 +75,7 @@ impl SubdiagnosticDerive { has_subdiagnostic: false, is_enum, }; - builder.into_tokens(variant).unwrap_or_else(|v| v.to_compile_error()) + builder.into_tokens().unwrap_or_else(|v| v.to_compile_error()) }); quote! { @@ -497,10 +497,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } } - pub(crate) fn into_tokens( - &mut self, - variant: &VariantInfo<'_>, - ) -> Result { + pub(crate) fn into_tokens(&mut self) -> Result { let kind_slugs = self.identify_kind()?; let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect(); @@ -538,7 +535,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let mut calls = TokenStream::new(); for (kind, slug) in kind_slugs { let message = format_ident!("__message"); - let message_stream = slug.diag_message(variant); + let message_stream = slug.diag_message(None); calls.extend(quote! { let #message = #diag.eagerly_translate(#message_stream); }); let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); From 30f82aac5bb7f4a1c47f5e0c07f100eca045009d Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 3 Feb 2026 14:01:05 +0100 Subject: [PATCH 474/978] Convert to inline diagnostics in `rustc_query_system` --- Cargo.lock | 2 -- compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_query_system/Cargo.toml | 1 - compiler/rustc_query_system/messages.ftl | 30 ---------------- compiler/rustc_query_system/src/error.rs | 46 ++++++++++++++---------- compiler/rustc_query_system/src/lib.rs | 2 -- 7 files changed, 27 insertions(+), 56 deletions(-) delete mode 100644 compiler/rustc_query_system/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 234d709f3c31..618f3f67fd04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3812,7 +3812,6 @@ dependencies = [ "rustc_pattern_analysis", "rustc_privacy", "rustc_public", - "rustc_query_system", "rustc_resolve", "rustc_session", "rustc_span", @@ -4572,7 +4571,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_hashes", "rustc_hir", "rustc_index", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index c160240a18a7..0f8b65c47b06 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -44,7 +44,6 @@ rustc_passes = { path = "../rustc_passes" } rustc_pattern_analysis = { path = "../rustc_pattern_analysis" } rustc_privacy = { path = "../rustc_privacy" } rustc_public = { path = "../rustc_public", features = ["rustc_internal"] } -rustc_query_system = { path = "../rustc_query_system" } rustc_resolve = { path = "../rustc_resolve" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 38ee87601614..c72dc35064b0 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -142,7 +142,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_passes::DEFAULT_LOCALE_RESOURCE, rustc_pattern_analysis::DEFAULT_LOCALE_RESOURCE, rustc_privacy::DEFAULT_LOCALE_RESOURCE, - rustc_query_system::DEFAULT_LOCALE_RESOURCE, rustc_resolve::DEFAULT_LOCALE_RESOURCE, rustc_session::DEFAULT_LOCALE_RESOURCE, rustc_trait_selection::DEFAULT_LOCALE_RESOURCE, diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index 0ad8143c5a4f..761a299eab77 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -11,7 +11,6 @@ rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } diff --git a/compiler/rustc_query_system/messages.ftl b/compiler/rustc_query_system/messages.ftl deleted file mode 100644 index d2ab2d34c5fc..000000000000 --- a/compiler/rustc_query_system/messages.ftl +++ /dev/null @@ -1,30 +0,0 @@ -query_system_cycle = cycle detected when {$stack_bottom} - .note = see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -query_system_cycle_recursive_trait_alias = trait aliases cannot be recursive - -query_system_cycle_recursive_ty_alias = type aliases cannot be recursive -query_system_cycle_recursive_ty_alias_help1 = consider using a struct, enum, or union instead to break the cycle -query_system_cycle_recursive_ty_alias_help2 = see for more information - -query_system_cycle_stack_middle = ...which requires {$desc}... - -query_system_cycle_stack_multiple = ...which again requires {$stack_bottom}, completing the cycle - -query_system_cycle_stack_single = ...which immediately requires {$stack_bottom} again - -query_system_cycle_usage = cycle used when {$usage} - -query_system_increment_compilation = internal compiler error: encountered incremental compilation error with {$dep_node} - -query_system_increment_compilation_note1 = please follow the instructions below to create a bug report with the provided information -query_system_increment_compilation_note2 = for incremental compilation bugs, having a reproduction is vital -query_system_increment_compilation_note3 = an ideal reproduction consists of the code before and some patch that then triggers the bug when applied and compiled again -query_system_increment_compilation_note4 = as a workaround, you can run {$run_cmd} to allow your project to compile - -query_system_overflow_note = query depth increased by {$depth} when {$desc} - -query_system_query_overflow = queries overflow the depth limit! - .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`) - -query_system_reentrant = internal compiler error: reentrant incremental verify failure, suppressing message diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs index 4b1effe2b33d..55f2feba0d86 100644 --- a/compiler/rustc_query_system/src/error.rs +++ b/compiler/rustc_query_system/src/error.rs @@ -4,7 +4,7 @@ use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; #[derive(Subdiagnostic)] -#[note(query_system_cycle_stack_middle)] +#[note("...which requires {$desc}...")] pub(crate) struct CycleStack { #[primary_span] pub span: Span, @@ -13,24 +13,26 @@ pub(crate) struct CycleStack { #[derive(Subdiagnostic)] pub(crate) enum StackCount { - #[note(query_system_cycle_stack_single)] + #[note("...which immediately requires {$stack_bottom} again")] Single, - #[note(query_system_cycle_stack_multiple)] + #[note("...which again requires {$stack_bottom}, completing the cycle")] Multiple, } #[derive(Subdiagnostic)] pub(crate) enum Alias { - #[note(query_system_cycle_recursive_ty_alias)] - #[help(query_system_cycle_recursive_ty_alias_help1)] - #[help(query_system_cycle_recursive_ty_alias_help2)] + #[note("type aliases cannot be recursive")] + #[help("consider using a struct, enum, or union instead to break the cycle")] + #[help( + "see for more information" + )] Ty, - #[note(query_system_cycle_recursive_trait_alias)] + #[note("trait aliases cannot be recursive")] Trait, } #[derive(Subdiagnostic)] -#[note(query_system_cycle_usage)] +#[note("cycle used when {$usage}")] pub(crate) struct CycleUsage { #[primary_span] pub span: Span, @@ -38,7 +40,7 @@ pub(crate) struct CycleUsage { } #[derive(Diagnostic)] -#[diag(query_system_cycle, code = E0391)] +#[diag("cycle detected when {$stack_bottom}", code = E0391)] pub(crate) struct Cycle { #[primary_span] pub span: Span, @@ -51,28 +53,34 @@ pub(crate) struct Cycle { pub alias: Option, #[subdiagnostic] pub cycle_usage: Option, - #[note] + #[note( + "see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information" + )] pub note_span: (), } #[derive(Diagnostic)] -#[diag(query_system_reentrant)] +#[diag("internal compiler error: reentrant incremental verify failure, suppressing message")] pub(crate) struct Reentrant; #[derive(Diagnostic)] -#[diag(query_system_increment_compilation)] -#[note(query_system_increment_compilation_note1)] -#[note(query_system_increment_compilation_note2)] -#[note(query_system_increment_compilation_note3)] -#[note(query_system_increment_compilation_note4)] +#[diag("internal compiler error: encountered incremental compilation error with {$dep_node}")] +#[note("please follow the instructions below to create a bug report with the provided information")] +#[note("for incremental compilation bugs, having a reproduction is vital")] +#[note( + "an ideal reproduction consists of the code before and some patch that then triggers the bug when applied and compiled again" +)] +#[note("as a workaround, you can run {$run_cmd} to allow your project to compile")] pub(crate) struct IncrementCompilation { pub run_cmd: String, pub dep_node: String, } #[derive(Diagnostic)] -#[help] -#[diag(query_system_query_overflow)] +#[help( + "consider increasing the recursion limit by adding a `#![recursion_limit = \"{$suggested_limit}\"]` attribute to your crate (`{$crate_name}`)" +)] +#[diag("queries overflow the depth limit!")] pub struct QueryOverflow { #[primary_span] pub span: Span, @@ -83,7 +91,7 @@ pub struct QueryOverflow { } #[derive(Subdiagnostic)] -#[note(query_system_overflow_note)] +#[note("query depth increased by {$depth} when {$desc}")] pub struct QueryOverflowNote { pub desc: String, pub depth: usize, diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index cdfe3454061c..d1907a8c582d 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -14,5 +14,3 @@ mod values; pub use error::{QueryOverflow, QueryOverflowNote}; pub use values::Value; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } From b668057d794d87de368156626504d721ffa1c767 Mon Sep 17 00:00:00 2001 From: Jamie Hill-Daniel Date: Fri, 30 Jan 2026 03:06:46 +0000 Subject: [PATCH 475/978] Port `rustc_mir` to attribute parser --- Cargo.lock | 2 +- .../src/attributes/rustc_internal.rs | 93 +++++++++++++++++- compiler/rustc_attr_parsing/src/context.rs | 8 +- .../src/session_diagnostics.rs | 4 + .../rustc_hir/src/attrs/data_structures.rs | 18 ++++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + .../rustc_hir/src/attrs/pretty_printing.rs | 9 ++ compiler/rustc_mir_dataflow/Cargo.toml | 2 +- compiler/rustc_mir_dataflow/messages.ftl | 12 --- compiler/rustc_mir_dataflow/src/errors.rs | 32 +------ .../src/framework/graphviz.rs | 94 +++++-------------- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 71 ++++++-------- compiler/rustc_passes/src/check_attr.rs | 1 + 13 files changed, 186 insertions(+), 161 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 234d709f3c31..ffd11e46d98b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4338,11 +4338,11 @@ dependencies = [ "polonius-engine", "regex", "rustc_abi", - "rustc_ast", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", "rustc_graphviz", + "rustc_hir", "rustc_index", "rustc_macros", "rustc_middle", diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 250bceecbd65..8961dc47706f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1,5 +1,7 @@ +use std::path::PathBuf; + use rustc_ast::{LitIntType, LitKind, MetaItemLit}; -use rustc_hir::attrs::RustcLayoutType; +use rustc_hir::attrs::{BorrowckGraphvizFormatKind, RustcLayoutType, RustcMirKind}; use rustc_session::errors; use super::prelude::*; @@ -357,7 +359,6 @@ impl CombineAttributeParser for RustcLayoutParser { const TEMPLATE: AttributeTemplate = template!(List: &["abi", "align", "size", "homogenous_aggregate", "debug"]); - fn extend( cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser, @@ -397,6 +398,94 @@ impl CombineAttributeParser for RustcLayoutParser { } } +pub(crate) struct RustcMirParser; + +impl CombineAttributeParser for RustcMirParser { + const PATH: &[rustc_span::Symbol] = &[sym::rustc_mir]; + + type Item = RustcMirKind; + + const CONVERT: ConvertFn = |items, _| AttributeKind::RustcMir(items); + + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + ]); + + const TEMPLATE: AttributeTemplate = template!(List: &["arg1, arg2, ..."]); + + fn extend( + cx: &mut AcceptContext<'_, '_, S>, + args: &ArgParser, + ) -> impl IntoIterator { + let Some(list) = args.list() else { + cx.expected_list(cx.attr_span, args); + return ThinVec::new(); + }; + + list.mixed() + .filter_map(|arg| arg.meta_item()) + .filter_map(|mi| { + if let Some(ident) = mi.ident() { + match ident.name { + sym::rustc_peek_maybe_init => Some(RustcMirKind::PeekMaybeInit), + sym::rustc_peek_maybe_uninit => Some(RustcMirKind::PeekMaybeUninit), + sym::rustc_peek_liveness => Some(RustcMirKind::PeekLiveness), + sym::stop_after_dataflow => Some(RustcMirKind::StopAfterDataflow), + sym::borrowck_graphviz_postflow => { + let Some(nv) = mi.args().name_value() else { + cx.expected_name_value( + mi.span(), + Some(sym::borrowck_graphviz_postflow), + ); + return None; + }; + let Some(path) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, None); + return None; + }; + let path = PathBuf::from(path.to_string()); + if path.file_name().is_some() { + Some(RustcMirKind::BorrowckGraphvizPostflow { path }) + } else { + cx.expected_filename_literal(nv.value_span); + None + } + } + sym::borrowck_graphviz_format => { + let Some(nv) = mi.args().name_value() else { + cx.expected_name_value( + mi.span(), + Some(sym::borrowck_graphviz_format), + ); + return None; + }; + let Some(format) = nv.value_as_ident() else { + cx.expected_identifier(nv.value_span); + return None; + }; + match format.name { + sym::two_phase => Some(RustcMirKind::BorrowckGraphvizFormat { + format: BorrowckGraphvizFormatKind::TwoPhase, + }), + _ => { + cx.expected_specific_argument(format.span, &[sym::two_phase]); + None + } + } + } + _ => None, + } + } else { + None + } + }) + .collect() + } +} pub(crate) struct RustcNonConstTraitMethodParser; impl NoArgsAttributeParser for RustcNonConstTraitMethodParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index f340b393567e..322e189e6d12 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -81,7 +81,7 @@ use crate::attributes::rustc_internal::{ RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, RustcLegacyConstGenericsParser, RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, RustcLintQueryInstabilityParser, RustcLintUntrackedQueryInformationParser, RustcMainParser, - RustcMustImplementOneOfParser, RustcNeverReturnsNullPointerParser, + RustcMirParser, RustcMustImplementOneOfParser, RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser, RustcNonConstTraitMethodParser, RustcNounwindParser, RustcObjectLifetimeDefaultParser, RustcOffloadKernelParser, RustcScalableVectorParser, RustcSimdMonomorphizeLaneLimitParser, @@ -202,6 +202,7 @@ attribute_parsers!( Combine, Combine, Combine, + Combine, Combine, Combine, // tidy-alphabetical-end @@ -517,6 +518,11 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { ) } + /// Error that a filename string literal was expected. + pub(crate) fn expected_filename_literal(&self, span: Span) { + self.emit_parse_error(span, AttributeParseErrorReason::ExpectedFilenameLiteral); + } + pub(crate) fn expected_integer_literal(&self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedIntegerLiteral) } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index f9748542beb9..e67fc95e2806 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -524,6 +524,7 @@ pub(crate) enum AttributeParseErrorReason<'a> { ExpectedStringLiteral { byte_string: Option, }, + ExpectedFilenameLiteral, ExpectedIntegerLiteral, ExpectedIntegerLiteralInRange { lower_bound: isize, @@ -597,6 +598,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { diag.span_label(self.span, "expected a string literal here"); } } + AttributeParseErrorReason::ExpectedFilenameLiteral => { + diag.span_label(self.span, "expected a filename string literal here"); + } AttributeParseErrorReason::ExpectedIntegerLiteral => { diag.span_label(self.span, "expected an integer literal here"); } diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index fba53c913e16..6138ffc8d954 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -699,6 +699,21 @@ pub enum RustcLayoutType { Debug, } +#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute, PartialEq, Eq)] +pub enum RustcMirKind { + PeekMaybeInit, + PeekMaybeUninit, + PeekLiveness, + StopAfterDataflow, + BorrowckGraphvizPostflow { path: PathBuf }, + BorrowckGraphvizFormat { format: BorrowckGraphvizFormatKind }, +} + +#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute, PartialEq, Eq)] +pub enum BorrowckGraphvizFormatKind { + TwoPhase, +} + /// Represents parsed *built-in* inert attributes. /// /// ## Overview @@ -1090,6 +1105,9 @@ pub enum AttributeKind { /// Represents `#[rustc_main]`. RustcMain, + /// Represents `#[rustc_mir]`. + RustcMir(ThinVec), + /// Represents `#[rustc_must_implement_one_of]` RustcMustImplementOneOf { attr_span: Span, fn_names: ThinVec }, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 26e5fc6e6257..7ec1920152a5 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -122,6 +122,7 @@ impl AttributeKind { RustcLintUntrackedQueryInformation => Yes, RustcMacroTransparency(..) => Yes, RustcMain => No, + RustcMir(..) => Yes, RustcMustImplementOneOf { .. } => No, RustcNeverReturnsNullPointer => Yes, RustcNoImplicitAutorefs => Yes, diff --git a/compiler/rustc_hir/src/attrs/pretty_printing.rs b/compiler/rustc_hir/src/attrs/pretty_printing.rs index c2ad644688fc..bd268d2c423f 100644 --- a/compiler/rustc_hir/src/attrs/pretty_printing.rs +++ b/compiler/rustc_hir/src/attrs/pretty_printing.rs @@ -1,5 +1,6 @@ use std::num::NonZero; use std::ops::Deref; +use std::path::PathBuf; use rustc_abi::Align; use rustc_ast::attr::data_structures::CfgEntry; @@ -96,7 +97,15 @@ impl PrintAttribute for FxIndexMap { p.word("]"); } } +impl PrintAttribute for PathBuf { + fn should_render(&self) -> bool { + true + } + fn print_attribute(&self, p: &mut Printer) { + p.word(self.display().to_string()); + } +} macro_rules! print_skip { ($($t: ty),* $(,)?) => {$( impl PrintAttribute for $t { diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml index 9621f9f20bdc..e41d5da71397 100644 --- a/compiler/rustc_mir_dataflow/Cargo.toml +++ b/compiler/rustc_mir_dataflow/Cargo.toml @@ -8,11 +8,11 @@ edition = "2024" polonius-engine = "0.13.0" regex = "1" rustc_abi = { path = "../rustc_abi" } -rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_graphviz = { path = "../rustc_graphviz" } +rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_mir_dataflow/messages.ftl b/compiler/rustc_mir_dataflow/messages.ftl index 5698367e42ba..3783c647b03e 100644 --- a/compiler/rustc_mir_dataflow/messages.ftl +++ b/compiler/rustc_mir_dataflow/messages.ftl @@ -1,9 +1,3 @@ -mir_dataflow_duplicate_values_for = - duplicate values for `{$name}` - -mir_dataflow_path_must_end_in_filename = - path must end in a filename - mir_dataflow_peek_argument_not_a_local = rustc_peek: argument was not a local @@ -19,11 +13,5 @@ mir_dataflow_peek_must_be_not_temporary = mir_dataflow_peek_must_be_place_or_ref_place = rustc_peek: argument expression must be either `place` or `&place` -mir_dataflow_requires_an_argument = - `{$name}` requires an argument - mir_dataflow_stop_after_dataflow_ended_compilation = stop_after_dataflow ended compilation - -mir_dataflow_unknown_formatter = - unknown formatter diff --git a/compiler/rustc_mir_dataflow/src/errors.rs b/compiler/rustc_mir_dataflow/src/errors.rs index cfacc0ec370c..9d8c34c8a1f3 100644 --- a/compiler/rustc_mir_dataflow/src/errors.rs +++ b/compiler/rustc_mir_dataflow/src/errors.rs @@ -1,35 +1,5 @@ use rustc_macros::Diagnostic; -use rustc_span::{Span, Symbol}; - -#[derive(Diagnostic)] -#[diag(mir_dataflow_path_must_end_in_filename)] -pub(crate) struct PathMustEndInFilename { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(mir_dataflow_unknown_formatter)] -pub(crate) struct UnknownFormatter { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(mir_dataflow_duplicate_values_for)] -pub(crate) struct DuplicateValuesFor { - #[primary_span] - pub span: Span, - pub name: Symbol, -} - -#[derive(Diagnostic)] -#[diag(mir_dataflow_requires_an_argument)] -pub(crate) struct RequiresAnArgument { - #[primary_span] - pub span: Span, - pub name: Symbol, -} +use rustc_span::Span; #[derive(Diagnostic)] #[diag(mir_dataflow_stop_after_dataflow_ended_compilation)] diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 22bff3806b15..c4b9b4ce6416 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -7,6 +7,9 @@ use std::sync::OnceLock; use std::{io, ops, str}; use regex::Regex; +use rustc_graphviz as dot; +use rustc_hir::attrs::{AttributeKind, BorrowckGraphvizFormatKind, RustcMirKind}; +use rustc_hir::find_attr; use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::{ self, BasicBlock, Body, Location, MirDumper, graphviz_safe_def_name, traversal, @@ -14,17 +17,12 @@ use rustc_middle::mir::{ use rustc_middle::ty::TyCtxt; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_span::def_id::DefId; -use rustc_span::{Symbol, sym}; use tracing::debug; -use {rustc_ast as ast, rustc_graphviz as dot}; use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext}; use super::{ Analysis, CallReturnPlaces, Direction, Results, ResultsCursor, ResultsVisitor, visit_results, }; -use crate::errors::{ - DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter, -}; /// Writes a DOT file containing the results of a dataflow analysis if the user requested it via /// `rustc_mir` attributes and `-Z dump-mir-dataflow`. The `Result` in and the `Results` out are @@ -43,10 +41,7 @@ where use std::io::Write; let def_id = body.source.def_id(); - let Ok(attrs) = RustcMirAttrs::parse(tcx, def_id) else { - // Invalid `rustc_mir` attrs are reported in `RustcMirAttrs::parse` - return Ok(()); - }; + let attrs = RustcMirAttrs::parse(tcx, def_id); let file = try { match attrs.output_path(A::NAME) { @@ -72,10 +67,7 @@ where Err(e) => return Err(e), }; - let style = match attrs.formatter { - Some(sym::two_phase) => OutputStyle::BeforeAndAfter, - _ => OutputStyle::AfterOnly, - }; + let style = attrs.formatter.unwrap_or(OutputStyle::AfterOnly); let mut buf = Vec::new(); @@ -98,71 +90,33 @@ where #[derive(Default)] struct RustcMirAttrs { basename_and_suffix: Option, - formatter: Option, + formatter: Option, } impl RustcMirAttrs { - fn parse(tcx: TyCtxt<'_>, def_id: DefId) -> Result { - let mut result = Ok(()); + fn parse(tcx: TyCtxt<'_>, def_id: DefId) -> Self { let mut ret = RustcMirAttrs::default(); - let rustc_mir_attrs = tcx - .get_attrs(def_id, sym::rustc_mir) - .flat_map(|attr| attr.meta_item_list().into_iter().flat_map(|v| v.into_iter())); - - for attr in rustc_mir_attrs { - let attr_result = match attr.name() { - Some(name @ sym::borrowck_graphviz_postflow) => { - Self::set_field(&mut ret.basename_and_suffix, tcx, name, &attr, |s| { - let path = PathBuf::from(s.to_string()); - match path.file_name() { - Some(_) => Ok(path), - None => { - tcx.dcx().emit_err(PathMustEndInFilename { span: attr.span() }); - Err(()) + let attrs = tcx.get_all_attrs(def_id); + if let Some(rustc_mir_attrs) = find_attr!(attrs, AttributeKind::RustcMir(kind) => kind) { + for attr in rustc_mir_attrs { + match attr { + RustcMirKind::BorrowckGraphvizPostflow { path } => { + ret.basename_and_suffix = Some(path.clone()); + } + RustcMirKind::BorrowckGraphvizFormat { format } => { + ret.formatter = match format { + BorrowckGraphvizFormatKind::TwoPhase => { + Some(OutputStyle::BeforeAndAfter) } - } - }) - } - Some(name @ sym::borrowck_graphviz_format) => { - Self::set_field(&mut ret.formatter, tcx, name, &attr, |s| match s { - sym::two_phase => Ok(s), - _ => { - tcx.dcx().emit_err(UnknownFormatter { span: attr.span() }); - Err(()) - } - }) - } - _ => Ok(()), - }; - - result = result.and(attr_result); + }; + } + _ => (), + }; + } } - result.map(|()| ret) - } - - fn set_field( - field: &mut Option, - tcx: TyCtxt<'_>, - name: Symbol, - attr: &ast::MetaItemInner, - mapper: impl FnOnce(Symbol) -> Result, - ) -> Result<(), ()> { - if field.is_some() { - tcx.dcx().emit_err(DuplicateValuesFor { span: attr.span(), name }); - - return Err(()); - } - - if let Some(s) = attr.value_str() { - *field = Some(mapper(s)?); - Ok(()) - } else { - tcx.dcx() - .emit_err(RequiresAnArgument { span: attr.span(), name: attr.name().unwrap() }); - Err(()) - } + ret } /// Returns the path where dataflow results should be written, or `None` diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index a899ec1fa884..1c5b38361669 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -1,8 +1,8 @@ -use rustc_ast::MetaItem; +use rustc_hir::attrs::{AttributeKind, RustcMirKind}; +use rustc_hir::find_attr; use rustc_middle::mir::{self, Body, Local, Location}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::def_id::DefId; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Span, sym}; use tracing::{debug, info}; use crate::errors::{ @@ -14,52 +14,37 @@ use crate::impls::{MaybeInitializedPlaces, MaybeLiveLocals, MaybeUninitializedPl use crate::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex}; use crate::{Analysis, JoinSemiLattice, ResultsCursor}; -fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option { - for attr in tcx.get_attrs(def_id, sym::rustc_mir) { - let items = attr.meta_item_list(); - for item in items.iter().flat_map(|l| l.iter()) { - match item.meta_item() { - Some(mi) if mi.has_name(name) => return Some(mi.clone()), - _ => continue, - } - } - } - None -} - pub fn sanity_check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let def_id = body.source.def_id(); - if !tcx.has_attr(def_id, sym::rustc_mir) { - debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); - return; - } else { + let attrs = tcx.get_all_attrs(def_id); + if let Some(kind) = find_attr!(attrs, AttributeKind::RustcMir(kind) => kind) { + let move_data = MoveData::gather_moves(body, tcx, |_| true); debug!("running rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); - } + if kind.contains(&RustcMirKind::PeekMaybeInit) { + let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) + .iterate_to_fixpoint(tcx, body, None) + .into_results_cursor(body); + sanity_check_via_rustc_peek(tcx, flow_inits); + } - let move_data = MoveData::gather_moves(body, tcx, |_| true); + if kind.contains(&RustcMirKind::PeekMaybeUninit) { + let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data) + .iterate_to_fixpoint(tcx, body, None) + .into_results_cursor(body); + sanity_check_via_rustc_peek(tcx, flow_uninits); + } - if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() { - let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) - .iterate_to_fixpoint(tcx, body, None) - .into_results_cursor(body); - sanity_check_via_rustc_peek(tcx, flow_inits); - } + if kind.contains(&RustcMirKind::PeekLiveness) { + let flow_liveness = + MaybeLiveLocals.iterate_to_fixpoint(tcx, body, None).into_results_cursor(body); + sanity_check_via_rustc_peek(tcx, flow_liveness); + } - if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_uninit).is_some() { - let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data) - .iterate_to_fixpoint(tcx, body, None) - .into_results_cursor(body); - sanity_check_via_rustc_peek(tcx, flow_uninits); - } - - if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_liveness).is_some() { - let flow_liveness = - MaybeLiveLocals.iterate_to_fixpoint(tcx, body, None).into_results_cursor(body); - sanity_check_via_rustc_peek(tcx, flow_liveness); - } - - if has_rustc_mir_with(tcx, def_id, sym::stop_after_dataflow).is_some() { - tcx.dcx().emit_fatal(StopAfterDataFlowEndedCompilation); + if kind.contains(&RustcMirKind::StopAfterDataflow) { + tcx.dcx().emit_fatal(StopAfterDataFlowEndedCompilation); + } + } else { + debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index bd02bc551756..dd16092c99f9 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -309,6 +309,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcLintUntrackedQueryInformation | AttributeKind::RustcMacroTransparency(_) | AttributeKind::RustcMain + | AttributeKind::RustcMir(_) | AttributeKind::RustcNeverReturnsNullPointer | AttributeKind::RustcNoImplicitAutorefs | AttributeKind::RustcNonConstTraitMethod From 1722b8e06b3c334b77024f4d8d8de4a832f10df9 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 3 Feb 2026 15:14:49 +0100 Subject: [PATCH 476/978] Convert to inline diagnostics in `rustc_infer` --- Cargo.lock | 2 -- compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_infer/Cargo.toml | 1 - compiler/rustc_infer/messages.ftl | 5 ----- compiler/rustc_infer/src/errors.rs | 8 ++++---- compiler/rustc_infer/src/lib.rs | 2 -- 7 files changed, 4 insertions(+), 16 deletions(-) delete mode 100644 compiler/rustc_infer/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 234d709f3c31..111e5afb3e7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3795,7 +3795,6 @@ dependencies = [ "rustc_hir_typeck", "rustc_incremental", "rustc_index", - "rustc_infer", "rustc_interface", "rustc_lexer", "rustc_lint", @@ -4093,7 +4092,6 @@ version = "0.0.0" dependencies = [ "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index c160240a18a7..b688a6710a8e 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -27,7 +27,6 @@ rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_hir_typeck = { path = "../rustc_hir_typeck" } rustc_incremental = { path = "../rustc_incremental" } rustc_index = { path = "../rustc_index" } -rustc_infer = { path = "../rustc_infer" } rustc_interface = { path = "../rustc_interface" } rustc_lexer = { path = "../rustc_lexer" } rustc_lint = { path = "../rustc_lint" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 38ee87601614..ce6de3e2a1f8 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -129,7 +129,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE, rustc_hir_typeck::DEFAULT_LOCALE_RESOURCE, rustc_incremental::DEFAULT_LOCALE_RESOURCE, - rustc_infer::DEFAULT_LOCALE_RESOURCE, rustc_interface::DEFAULT_LOCALE_RESOURCE, rustc_lint::DEFAULT_LOCALE_RESOURCE, rustc_metadata::DEFAULT_LOCALE_RESOURCE, diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 08c036148849..c4fbe89315db 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -10,7 +10,6 @@ doctest = false # tidy-alphabetical-start rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl deleted file mode 100644 index e51734ff7a77..000000000000 --- a/compiler/rustc_infer/messages.ftl +++ /dev/null @@ -1,5 +0,0 @@ -infer_opaque_hidden_type = - opaque type's hidden type cannot be another opaque type from the same scope - .label = one of the two opaque types used here has to be outside its defining scope - .opaque_type = opaque type whose hidden type is being assigned - .hidden_type = opaque type being used as hidden type diff --git a/compiler/rustc_infer/src/errors.rs b/compiler/rustc_infer/src/errors.rs index 76ea9c3433d3..7c6e3b4ef314 100644 --- a/compiler/rustc_infer/src/errors.rs +++ b/compiler/rustc_infer/src/errors.rs @@ -2,13 +2,13 @@ use rustc_macros::Diagnostic; use rustc_span::Span; #[derive(Diagnostic)] -#[diag(infer_opaque_hidden_type)] +#[diag("opaque type's hidden type cannot be another opaque type from the same scope")] pub(crate) struct OpaqueHiddenTypeDiag { #[primary_span] - #[label] + #[label("one of the two opaque types used here has to be outside its defining scope")] pub span: Span, - #[note(infer_opaque_type)] + #[note("opaque type whose hidden type is being assigned")] pub opaque_type: Span, - #[note(infer_hidden_type)] + #[note("opaque type being used as hidden type")] pub hidden_type: Span, } diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 05ea0f813818..2a1733ef63cb 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -22,5 +22,3 @@ mod errors; pub mod infer; pub mod traits; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } From 4e4192aa48ccb1955b945b0e898decbd73007d27 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 3 Feb 2026 16:07:12 +0100 Subject: [PATCH 477/978] Try to fix `rustdoc-gui/globals.goml` flakyness --- tests/rustdoc-gui/globals.goml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/rustdoc-gui/globals.goml b/tests/rustdoc-gui/globals.goml index 4f12175f6ab2..7fd9c5bfb6f2 100644 --- a/tests/rustdoc-gui/globals.goml +++ b/tests/rustdoc-gui/globals.goml @@ -6,7 +6,7 @@ include: "utils.goml" // URL query go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=sa" wait-for: "#search-tabs" -assert-window-property-false: {"searchIndex": null} +wait-for-window-property-false: {"searchIndex": null} // Form input go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" From dfc60ae100f424d28bb9d00979e17846335ac8a9 Mon Sep 17 00:00:00 2001 From: lapla Date: Wed, 4 Feb 2026 00:22:00 +0900 Subject: [PATCH 478/978] Distinguish error message for `#[diagnostic::on_const]` on const trait impls --- compiler/rustc_passes/messages.ftl | 4 ++++ compiler/rustc_passes/src/check_attr.rs | 18 +++++++++++++++++- .../on_const/misplaced_attr.rs | 2 +- .../on_const/misplaced_attr.stderr | 4 ++-- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index f8ff46189c05..ab89af226793 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -87,6 +87,10 @@ passes_deprecated_annotation_has_no_effect = passes_deprecated_attribute = deprecated attribute must be paired with either stable or unstable attribute +passes_diagnostic_diagnostic_on_const_only_for_non_const_trait_impls = + `#[diagnostic::on_const]` can only be applied to non-const trait impls + .label = this is a const trait impl + passes_diagnostic_diagnostic_on_const_only_for_trait_impls = `#[diagnostic::on_const]` can only be applied to trait impls .label = not a trait impl diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 8cf68b280850..552985003fb5 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -67,6 +67,13 @@ struct DiagnosticOnConstOnlyForTraitImpls { item_span: Span, } +#[derive(LintDiagnostic)] +#[diag(passes_diagnostic_diagnostic_on_const_only_for_non_const_trait_impls)] +struct DiagnosticOnConstOnlyForNonConstTraitImpls { + #[label] + item_span: Span, +} + fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) -> Target { match impl_item.kind { hir::ImplItemKind::Const(..) => Target::AssocConst, @@ -629,7 +636,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> { if target == (Target::Impl { of_trait: true }) { match item.unwrap() { ItemLike::Item(it) => match it.expect_impl().constness { - Constness::Const => {} + Constness::Const => { + let item_span = self.tcx.hir_span(hir_id); + self.tcx.emit_node_span_lint( + MISPLACED_DIAGNOSTIC_ATTRIBUTES, + hir_id, + attr_span, + DiagnosticOnConstOnlyForNonConstTraitImpls { item_span }, + ); + return; + } Constness::NotConst => return, }, ItemLike::ForeignItem => {} diff --git a/tests/ui/diagnostic_namespace/on_const/misplaced_attr.rs b/tests/ui/diagnostic_namespace/on_const/misplaced_attr.rs index c0af549e2d01..f7babae3aa7c 100644 --- a/tests/ui/diagnostic_namespace/on_const/misplaced_attr.rs +++ b/tests/ui/diagnostic_namespace/on_const/misplaced_attr.rs @@ -6,7 +6,7 @@ pub struct Foo; #[diagnostic::on_const(message = "tadaa", note = "boing")] -//~^ ERROR: `#[diagnostic::on_const]` can only be applied to trait impls +//~^ ERROR: `#[diagnostic::on_const]` can only be applied to non-const trait impls impl const PartialEq for Foo { fn eq(&self, _other: &Foo) -> bool { true diff --git a/tests/ui/diagnostic_namespace/on_const/misplaced_attr.stderr b/tests/ui/diagnostic_namespace/on_const/misplaced_attr.stderr index baa0b11f798b..f92ea501696e 100644 --- a/tests/ui/diagnostic_namespace/on_const/misplaced_attr.stderr +++ b/tests/ui/diagnostic_namespace/on_const/misplaced_attr.stderr @@ -13,14 +13,14 @@ note: the lint level is defined here LL | #![deny(misplaced_diagnostic_attributes)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `#[diagnostic::on_const]` can only be applied to trait impls +error: `#[diagnostic::on_const]` can only be applied to non-const trait impls --> $DIR/misplaced_attr.rs:8:1 | LL | #[diagnostic::on_const(message = "tadaa", note = "boing")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | impl const PartialEq for Foo { - | ---------------------------- not a trait impl + | ---------------------------- this is a const trait impl error: `#[diagnostic::on_const]` can only be applied to trait impls --> $DIR/misplaced_attr.rs:16:1 From 27f97d7f7162f8f6c2250e6778e462e3738ed285 Mon Sep 17 00:00:00 2001 From: Henner Zeller Date: Tue, 3 Feb 2026 07:19:56 -0800 Subject: [PATCH 479/978] RwLock: refine documentation to emphasize non-reentrancy guarantees This addresses the need for clarification brought up in an issue. Specifically, it notes that some implementations may choose to panic if they detect deadlock situations during recursive locking attempts for both `read()` and `write()` calls. * Provide an example highlighting that multiple read locks can be held across different threads simultaneously. * Remove the example that shows a situation that can potentially deadlock. (as demonstrated in the very same documentation a few paragraphs above) * Improve documentation regarding the possibility of panics during recursive read or write lock attempts. Issues: Ambiguity in RwLock documentation about multiple read() calls... Signed-off-by: Henner Zeller --- library/std/src/sync/poison/rwlock.rs | 48 +++++++++++++++++---------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs index acfeb96900cc..c01ee17eecda 100644 --- a/library/std/src/sync/poison/rwlock.rs +++ b/library/std/src/sync/poison/rwlock.rs @@ -56,24 +56,36 @@ use crate::sys::sync as sys; /// # Examples /// /// ``` -/// use std::sync::RwLock; +/// use std::sync::{Arc, RwLock}; +/// use std::thread; +/// use std::time::Duration; /// -/// let lock = RwLock::new(5); +/// let data = Arc::new(RwLock::new(5)); /// -/// // many reader locks can be held at once -/// { -/// let r1 = lock.read().unwrap(); -/// let r2 = lock.read().unwrap(); -/// assert_eq!(*r1, 5); -/// assert_eq!(*r2, 5); -/// } // read locks are dropped at this point +/// // Multiple readers can access in parallel. +/// for i in 0..3 { +/// let lock_clone = Arc::clone(&data); /// -/// // only one write lock may be held, however -/// { -/// let mut w = lock.write().unwrap(); -/// *w += 1; -/// assert_eq!(*w, 6); -/// } // write lock is dropped here +/// thread::spawn(move || { +/// let value = lock_clone.read().unwrap(); +/// +/// println!("Reader {}: Read value {}, now holding lock...", i, *value); +/// +/// // Simulating a long read operation +/// thread::sleep(Duration::from_secs(1)); +/// +/// println!("Reader {}: Dropping lock.", i); +/// // Read lock unlocked when going out of scope. +/// }); +/// } +/// +/// thread::sleep(Duration::from_millis(100)); // Wait for readers to start +/// +/// // While all readers can proceed, a call to .write() has to wait for +// // current active reader locks. +/// let mut writable_data = data.write().unwrap(); +/// println!("Writer proceeds..."); +/// *writable_data += 1; /// ``` /// /// [`Mutex`]: super::Mutex @@ -370,7 +382,8 @@ impl RwLock { /// /// # Panics /// - /// This function might panic when called if the lock is already held by the current thread. + /// This function might panic when called if the lock is already held by the current thread + /// in read or write mode. /// /// # Examples /// @@ -467,7 +480,8 @@ impl RwLock { /// /// # Panics /// - /// This function might panic when called if the lock is already held by the current thread. + /// This function might panic when called if the lock is already held by the current thread + /// in read or write mode. /// /// # Examples /// From 6c4abb7fabc807c8e73f72d06a06ca7479c8c397 Mon Sep 17 00:00:00 2001 From: sgasho Date: Wed, 4 Feb 2026 00:58:34 +0900 Subject: [PATCH 480/978] Fix some autodiff tests require Clto=fat --- tests/run-make/autodiff/type-trees/array-typetree/rmake.rs | 2 +- .../run-make/autodiff/type-trees/mixed-struct-typetree/rmake.rs | 1 + tests/run-make/autodiff/type-trees/nott-flag/rmake.rs | 2 ++ tests/run-make/autodiff/type-trees/recursion-typetree/rmake.rs | 2 +- .../autodiff/type-trees/scalar-types/f128-typetree/rmake.rs | 2 +- .../autodiff/type-trees/scalar-types/f16-typetree/rmake.rs | 2 +- .../autodiff/type-trees/scalar-types/f32-typetree/rmake.rs | 2 +- .../autodiff/type-trees/scalar-types/f64-typetree/rmake.rs | 2 +- .../autodiff/type-trees/scalar-types/i32-typetree/rmake.rs | 2 +- tests/run-make/autodiff/type-trees/slice-typetree/rmake.rs | 2 +- tests/run-make/autodiff/type-trees/struct-typetree/rmake.rs | 2 +- tests/run-make/autodiff/type-trees/tuple-typetree/rmake.rs | 2 +- 12 files changed, 13 insertions(+), 10 deletions(-) diff --git a/tests/run-make/autodiff/type-trees/array-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/array-typetree/rmake.rs index 20b6a0669062..41805d26c6f7 100644 --- a/tests/run-make/autodiff/type-trees/array-typetree/rmake.rs +++ b/tests/run-make/autodiff/type-trees/array-typetree/rmake.rs @@ -4,6 +4,6 @@ use run_make_support::{llvm_filecheck, rfs, rustc}; fn main() { - rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + rustc().input("test.rs").arg("-Zautodiff=Enable").arg("-Clto=fat").emit("llvm-ir").run(); llvm_filecheck().patterns("array.check").stdin_buf(rfs::read("test.ll")).run(); } diff --git a/tests/run-make/autodiff/type-trees/mixed-struct-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/mixed-struct-typetree/rmake.rs index 1c19963bc361..d740596907a3 100644 --- a/tests/run-make/autodiff/type-trees/mixed-struct-typetree/rmake.rs +++ b/tests/run-make/autodiff/type-trees/mixed-struct-typetree/rmake.rs @@ -9,6 +9,7 @@ fn main() { .arg("-Zautodiff=Enable") .arg("-Zautodiff=NoPostopt") .opt_level("0") + .arg("-Clto=fat") .emit("llvm-ir") .run(); diff --git a/tests/run-make/autodiff/type-trees/nott-flag/rmake.rs b/tests/run-make/autodiff/type-trees/nott-flag/rmake.rs index de540b990cab..2e93d586a353 100644 --- a/tests/run-make/autodiff/type-trees/nott-flag/rmake.rs +++ b/tests/run-make/autodiff/type-trees/nott-flag/rmake.rs @@ -8,6 +8,7 @@ fn main() { rustc() .input("test.rs") .arg("-Zautodiff=Enable,NoTT") + .arg("-Clto=fat") .emit("llvm-ir") .arg("-o") .arg("nott.ll") @@ -17,6 +18,7 @@ fn main() { rustc() .input("test.rs") .arg("-Zautodiff=Enable") + .arg("-Clto=fat") .emit("llvm-ir") .arg("-o") .arg("with_tt.ll") diff --git a/tests/run-make/autodiff/type-trees/recursion-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/recursion-typetree/rmake.rs index 78718f3a2159..af1eb4197b3b 100644 --- a/tests/run-make/autodiff/type-trees/recursion-typetree/rmake.rs +++ b/tests/run-make/autodiff/type-trees/recursion-typetree/rmake.rs @@ -4,6 +4,6 @@ use run_make_support::{llvm_filecheck, rfs, rustc}; fn main() { - rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + rustc().input("test.rs").arg("-Zautodiff=Enable").arg("-Clto=fat").emit("llvm-ir").run(); llvm_filecheck().patterns("recursion.check").stdin_buf(rfs::read("test.ll")).run(); } diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f128-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/scalar-types/f128-typetree/rmake.rs index 44320ecdd571..b1672cddb811 100644 --- a/tests/run-make/autodiff/type-trees/scalar-types/f128-typetree/rmake.rs +++ b/tests/run-make/autodiff/type-trees/scalar-types/f128-typetree/rmake.rs @@ -5,7 +5,7 @@ use run_make_support::{llvm_filecheck, rfs, rustc}; fn main() { // Compile with TypeTree enabled and emit LLVM IR - rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + rustc().input("test.rs").arg("-Zautodiff=Enable").arg("-Clto=fat").emit("llvm-ir").run(); // Check that f128 TypeTree metadata is correctly generated llvm_filecheck().patterns("f128.check").stdin_buf(rfs::read("test.ll")).run(); diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f16-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/scalar-types/f16-typetree/rmake.rs index 0aebdbf55209..3e308a91aaff 100644 --- a/tests/run-make/autodiff/type-trees/scalar-types/f16-typetree/rmake.rs +++ b/tests/run-make/autodiff/type-trees/scalar-types/f16-typetree/rmake.rs @@ -5,7 +5,7 @@ use run_make_support::{llvm_filecheck, rfs, rustc}; fn main() { // Compile with TypeTree enabled and emit LLVM IR - rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + rustc().input("test.rs").arg("-Zautodiff=Enable").arg("-Clto=fat").emit("llvm-ir").run(); // Check that f16 TypeTree metadata is correctly generated llvm_filecheck().patterns("f16.check").stdin_buf(rfs::read("test.ll")).run(); diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f32-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/scalar-types/f32-typetree/rmake.rs index ee3ab753bf50..3faba69f5bdd 100644 --- a/tests/run-make/autodiff/type-trees/scalar-types/f32-typetree/rmake.rs +++ b/tests/run-make/autodiff/type-trees/scalar-types/f32-typetree/rmake.rs @@ -5,7 +5,7 @@ use run_make_support::{llvm_filecheck, rfs, rustc}; fn main() { // Compile with TypeTree enabled and emit LLVM IR - rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + rustc().input("test.rs").arg("-Zautodiff=Enable").arg("-Clto=fat").emit("llvm-ir").run(); // Check that f32 TypeTree metadata is correctly generated llvm_filecheck().patterns("f32.check").stdin_buf(rfs::read("test.ll")).run(); diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f64-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/scalar-types/f64-typetree/rmake.rs index 5fac9b23bc80..4f1c2cec51c4 100644 --- a/tests/run-make/autodiff/type-trees/scalar-types/f64-typetree/rmake.rs +++ b/tests/run-make/autodiff/type-trees/scalar-types/f64-typetree/rmake.rs @@ -5,7 +5,7 @@ use run_make_support::{llvm_filecheck, rfs, rustc}; fn main() { // Compile with TypeTree enabled and emit LLVM IR - rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + rustc().input("test.rs").arg("-Zautodiff=Enable").arg("-Clto=fat").emit("llvm-ir").run(); // Check that f64 TypeTree metadata is correctly generated llvm_filecheck().patterns("f64.check").stdin_buf(rfs::read("test.ll")).run(); diff --git a/tests/run-make/autodiff/type-trees/scalar-types/i32-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/scalar-types/i32-typetree/rmake.rs index a40fd55d88ad..328d690f29c8 100644 --- a/tests/run-make/autodiff/type-trees/scalar-types/i32-typetree/rmake.rs +++ b/tests/run-make/autodiff/type-trees/scalar-types/i32-typetree/rmake.rs @@ -5,7 +5,7 @@ use run_make_support::{llvm_filecheck, rfs, rustc}; fn main() { // Compile with TypeTree enabled and emit LLVM IR - rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + rustc().input("test.rs").arg("-Zautodiff=Enable").arg("-Clto=fat").emit("llvm-ir").run(); // Check that i32 TypeTree metadata is correctly generated llvm_filecheck().patterns("i32.check").stdin_buf(rfs::read("test.ll")).run(); diff --git a/tests/run-make/autodiff/type-trees/slice-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/slice-typetree/rmake.rs index b81fb50bf1a7..0cc6b42a0317 100644 --- a/tests/run-make/autodiff/type-trees/slice-typetree/rmake.rs +++ b/tests/run-make/autodiff/type-trees/slice-typetree/rmake.rs @@ -4,6 +4,6 @@ use run_make_support::{llvm_filecheck, rfs, rustc}; fn main() { - rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + rustc().input("test.rs").arg("-Zautodiff=Enable").arg("-Clto=fat").emit("llvm-ir").run(); llvm_filecheck().patterns("slice.check").stdin_buf(rfs::read("test.ll")).run(); } diff --git a/tests/run-make/autodiff/type-trees/struct-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/struct-typetree/rmake.rs index 0af1b65ee181..10499712d1e3 100644 --- a/tests/run-make/autodiff/type-trees/struct-typetree/rmake.rs +++ b/tests/run-make/autodiff/type-trees/struct-typetree/rmake.rs @@ -4,6 +4,6 @@ use run_make_support::{llvm_filecheck, rfs, rustc}; fn main() { - rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + rustc().input("test.rs").arg("-Zautodiff=Enable").arg("-Clto=fat").emit("llvm-ir").run(); llvm_filecheck().patterns("struct.check").stdin_buf(rfs::read("test.ll")).run(); } diff --git a/tests/run-make/autodiff/type-trees/tuple-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/tuple-typetree/rmake.rs index 76913828901c..4c0458f588a8 100644 --- a/tests/run-make/autodiff/type-trees/tuple-typetree/rmake.rs +++ b/tests/run-make/autodiff/type-trees/tuple-typetree/rmake.rs @@ -4,6 +4,6 @@ use run_make_support::{llvm_filecheck, rfs, rustc}; fn main() { - rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + rustc().input("test.rs").arg("-Zautodiff=Enable").arg("-Clto=fat").emit("llvm-ir").run(); llvm_filecheck().patterns("tuple.check").stdin_buf(rfs::read("test.ll")).run(); } From 5e5772d11f3ffd6e9dc4e5e14dd075db8f10976f Mon Sep 17 00:00:00 2001 From: Snehal Date: Tue, 3 Feb 2026 15:32:52 +0000 Subject: [PATCH 481/978] aarch64: Guard RCPC3 intrinsics with target_has_atomic = "64" The `vldap1` and `vstl1` RCPC3 intrinsics introduced in standard library unconditionally use `AtomicI64`. This breaks builds on target that do not support 64-bit atomics, such as `aarch64-unknown-none` with `max-atomic-width` set to 0. This commit adds a `#[cfg(target_has_atomic = "64")]` guard to these intrinsics --- .../core_arch/src/aarch64/neon/generated.rs | 15 +++++++++++++++ .../stdarch-gen-arm/spec/neon/aarch64.spec.yml | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index 3d5d07ac1b4e..a81914af7838 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -12858,6 +12858,7 @@ pub unsafe fn vld4q_u64(a: *const u64) -> uint64x2x4_t { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(ldap1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub unsafe fn vldap1_lane_s64(ptr: *const i64, src: int64x1_t) -> int64x1_t { static_assert!(LANE == 0); let atomic_src = crate::sync::atomic::AtomicI64::from_ptr(ptr as *mut i64); @@ -12876,6 +12877,7 @@ pub unsafe fn vldap1_lane_s64(ptr: *const i64, src: int64x1_t) #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(ldap1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub unsafe fn vldap1q_lane_s64(ptr: *const i64, src: int64x2_t) -> int64x2_t { static_assert_uimm_bits!(LANE, 1); let atomic_src = crate::sync::atomic::AtomicI64::from_ptr(ptr as *mut i64); @@ -12894,6 +12896,7 @@ pub unsafe fn vldap1q_lane_s64(ptr: *const i64, src: int64x2_t) #[target_feature(enable = "neon,rcpc3")] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(ldap1, LANE = 0))] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub unsafe fn vldap1q_lane_f64(ptr: *const f64, src: float64x2_t) -> float64x2_t { static_assert_uimm_bits!(LANE, 1); transmute(vldap1q_lane_s64::(ptr as *mut i64, transmute(src))) @@ -12907,6 +12910,7 @@ pub unsafe fn vldap1q_lane_f64(ptr: *const f64, src: float64x2_ #[target_feature(enable = "neon,rcpc3")] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(ldap1, LANE = 0))] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub unsafe fn vldap1_lane_u64(ptr: *const u64, src: uint64x1_t) -> uint64x1_t { static_assert!(LANE == 0); transmute(vldap1_lane_s64::(ptr as *mut i64, transmute(src))) @@ -12920,6 +12924,7 @@ pub unsafe fn vldap1_lane_u64(ptr: *const u64, src: uint64x1_t) #[target_feature(enable = "neon,rcpc3")] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(ldap1, LANE = 0))] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub unsafe fn vldap1q_lane_u64(ptr: *const u64, src: uint64x2_t) -> uint64x2_t { static_assert_uimm_bits!(LANE, 1); transmute(vldap1q_lane_s64::(ptr as *mut i64, transmute(src))) @@ -12933,6 +12938,7 @@ pub unsafe fn vldap1q_lane_u64(ptr: *const u64, src: uint64x2_t #[target_feature(enable = "neon,rcpc3")] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(ldap1, LANE = 0))] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub unsafe fn vldap1_lane_p64(ptr: *const p64, src: poly64x1_t) -> poly64x1_t { static_assert!(LANE == 0); transmute(vldap1_lane_s64::(ptr as *mut i64, transmute(src))) @@ -12946,6 +12952,7 @@ pub unsafe fn vldap1_lane_p64(ptr: *const p64, src: poly64x1_t) #[target_feature(enable = "neon,rcpc3")] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(ldap1, LANE = 0))] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub unsafe fn vldap1q_lane_p64(ptr: *const p64, src: poly64x2_t) -> poly64x2_t { static_assert_uimm_bits!(LANE, 1); transmute(vldap1q_lane_s64::(ptr as *mut i64, transmute(src))) @@ -27122,6 +27129,7 @@ pub unsafe fn vst4q_u64(a: *mut u64, b: uint64x2x4_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1_lane_f64(ptr: *mut f64, val: float64x1_t) { static_assert!(LANE == 0); unsafe { vstl1_lane_s64::(ptr as *mut i64, transmute(val)) } @@ -27133,6 +27141,7 @@ pub fn vstl1_lane_f64(ptr: *mut f64, val: float64x1_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1q_lane_f64(ptr: *mut f64, val: float64x2_t) { static_assert_uimm_bits!(LANE, 1); unsafe { vstl1q_lane_s64::(ptr as *mut i64, transmute(val)) } @@ -27144,6 +27153,7 @@ pub fn vstl1q_lane_f64(ptr: *mut f64, val: float64x2_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1_lane_u64(ptr: *mut u64, val: uint64x1_t) { static_assert!(LANE == 0); unsafe { vstl1_lane_s64::(ptr as *mut i64, transmute(val)) } @@ -27155,6 +27165,7 @@ pub fn vstl1_lane_u64(ptr: *mut u64, val: uint64x1_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1q_lane_u64(ptr: *mut u64, val: uint64x2_t) { static_assert_uimm_bits!(LANE, 1); unsafe { vstl1q_lane_s64::(ptr as *mut i64, transmute(val)) } @@ -27166,6 +27177,7 @@ pub fn vstl1q_lane_u64(ptr: *mut u64, val: uint64x2_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1_lane_p64(ptr: *mut p64, val: poly64x1_t) { static_assert!(LANE == 0); unsafe { vstl1_lane_s64::(ptr as *mut i64, transmute(val)) } @@ -27177,6 +27189,7 @@ pub fn vstl1_lane_p64(ptr: *mut p64, val: poly64x1_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1q_lane_p64(ptr: *mut p64, val: poly64x2_t) { static_assert_uimm_bits!(LANE, 1); unsafe { vstl1q_lane_s64::(ptr as *mut i64, transmute(val)) } @@ -27188,6 +27201,7 @@ pub fn vstl1q_lane_p64(ptr: *mut p64, val: poly64x2_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1_lane_s64(ptr: *mut i64, val: int64x1_t) { static_assert!(LANE == 0); let atomic_dst = ptr as *mut crate::sync::atomic::AtomicI64; @@ -27203,6 +27217,7 @@ pub fn vstl1_lane_s64(ptr: *mut i64, val: int64x1_t) { #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(stl1, LANE = 0))] #[rustc_legacy_const_generics(2)] #[unstable(feature = "stdarch_neon_feat_lrcpc3", issue = "none")] +#[cfg(target_has_atomic = "64")] pub fn vstl1q_lane_s64(ptr: *mut i64, val: int64x2_t) { static_assert_uimm_bits!(LANE, 1); let atomic_dst = ptr as *mut crate::sync::atomic::AtomicI64; diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml index a099c2c8d694..1c95bbe3d3a6 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml @@ -70,6 +70,10 @@ aarch64-stable-jscvt: &aarch64-stable-jscvt neon-unstable-feat-lrcpc3: &neon-unstable-feat-lrcpc3 FnCall: [unstable, ['feature = "stdarch_neon_feat_lrcpc3"', 'issue = "none"']] +# #[cfg(target_has_atomic = "64")] +cfg-target-has-atomic-64: &cfg-target-has-atomic-64 + FnCall: [cfg, ['target_has_atomic = "64"']] + # #[unstable(feature = "stdarch_neon_fp8", issue = "none")] neon-unstable-fp8: &neon-unstable-fp8 FnCall: [unstable, ['feature = "stdarch_neon_fp8"', 'issue = "none"']] @@ -4418,6 +4422,7 @@ intrinsics: - FnCall: [cfg_attr, [{FnCall: [all, [test, {FnCall: [not, ['target_env= "msvc"']]}]]}, {FnCall: [assert_instr, [ldap1, 'LANE = 0']]}]] - FnCall: [rustc_legacy_const_generics, ["2"]] - *neon-unstable-feat-lrcpc3 + - *cfg-target-has-atomic-64 types: - ['*const i64', int64x1_t, 'static_assert!', 'LANE == 0'] - ['*const i64', int64x2_t,'static_assert_uimm_bits!', 'LANE, 1'] @@ -4448,6 +4453,7 @@ intrinsics: - FnCall: [target_feature, ['enable = "neon,rcpc3"']] - FnCall: [cfg_attr, [{FnCall: [all, [test, {FnCall: [not, ['target_env= "msvc"']]}]]}, {FnCall: [assert_instr, [ldap1, 'LANE = 0']]}]] - *neon-unstable-feat-lrcpc3 + - *cfg-target-has-atomic-64 types: - ['*const u64', uint64x1_t,'static_assert!', 'LANE == 0',''] #- ['*const f64', float64x1_t,'static_assert!', 'LANE == 0',''] # Fails due to bad IR gen from rust @@ -4474,6 +4480,7 @@ intrinsics: - FnCall: [cfg_attr, [{FnCall: [all, [test, {FnCall: [not, ['target_env= "msvc"']]}]]}, {FnCall: [assert_instr, [stl1, 'LANE = 0']]}]] - FnCall: [rustc_legacy_const_generics, ["2"]] - *neon-unstable-feat-lrcpc3 + - *cfg-target-has-atomic-64 types: - ['*mut i64', int64x1_t,'static_assert!', 'LANE == 0'] - ['*mut i64', int64x2_t,'static_assert_uimm_bits!', 'LANE, 1'] @@ -4502,6 +4509,7 @@ intrinsics: - FnCall: [cfg_attr, [{FnCall: [all, [test, {FnCall: [not, ['target_env= "msvc"']]}]]}, {FnCall: [assert_instr, [stl1, 'LANE = 0']]}]] - FnCall: [rustc_legacy_const_generics, ["2"]] - *neon-unstable-feat-lrcpc3 + - *cfg-target-has-atomic-64 types: - ['*mut u64', uint64x1_t, 'static_assert!', 'LANE == 0',''] - ['*mut f64', float64x1_t,'static_assert!', 'LANE == 0',''] From d329971fc2356d96d8f8900eb5afe1bb92768543 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 4 Feb 2026 00:22:14 +0900 Subject: [PATCH 482/978] avoid semicolon suggestion when tail expr is error add a link to the issue fix test stderr --- .../src/error_reporting/traits/suggestions.rs | 4 ++- ...cover-from-semicolon-trailing-undefined.rs | 12 +++++++++ ...r-from-semicolon-trailing-undefined.stderr | 26 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/ui/type/recover-from-semicolon-trailing-undefined.rs create mode 100644 tests/ui/type/recover-from-semicolon-trailing-undefined.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index d54f3812350d..22fa437ed5c7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -954,7 +954,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let new_obligation = self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred_and_self); - if self.predicate_must_hold_modulo_regions(&new_obligation) { + if !matches!(tail_expr.kind, hir::ExprKind::Err(_)) + && self.predicate_must_hold_modulo_regions(&new_obligation) + { err.span_suggestion_short( stmt.span.with_lo(tail_expr.span.hi()), "remove this semicolon", diff --git a/tests/ui/type/recover-from-semicolon-trailing-undefined.rs b/tests/ui/type/recover-from-semicolon-trailing-undefined.rs new file mode 100644 index 000000000000..3e2860eb1343 --- /dev/null +++ b/tests/ui/type/recover-from-semicolon-trailing-undefined.rs @@ -0,0 +1,12 @@ +//@ compile-flags: -Znext-solver=globally + +// Regression test for https://github.com/rust-lang/rust/issues/151610 + +fn main() { + let x_str = { + x!("{}", x); + //~^ ERROR cannot find macro `x` in this scope + }; + println!("{}", x_str); + //~^ ERROR `()` doesn't implement `std::fmt::Display` +} diff --git a/tests/ui/type/recover-from-semicolon-trailing-undefined.stderr b/tests/ui/type/recover-from-semicolon-trailing-undefined.stderr new file mode 100644 index 000000000000..6a8295d49338 --- /dev/null +++ b/tests/ui/type/recover-from-semicolon-trailing-undefined.stderr @@ -0,0 +1,26 @@ +error: cannot find macro `x` in this scope + --> $DIR/recover-from-semicolon-trailing-undefined.rs:7:9 + | +LL | x!("{}", x); + | ^ + +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/recover-from-semicolon-trailing-undefined.rs:10:20 + | +LL | let x_str = { + | _________________- +LL | | x!("{}", x); +LL | | +LL | | }; + | |_____- this block is missing a tail expression +LL | println!("{}", x_str); + | -- ^^^^^ `()` cannot be formatted with the default formatter + | | + | required by this formatting parameter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. From 19e4108ed1418a8e320230ffa886f6096164576d Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 2 Feb 2026 22:47:05 +0100 Subject: [PATCH 483/978] Use DEVELOPER_DIR instead of a custom xcode-select script `DEVELOPER_DIR` is the standard environment variable for overriding the Xcode version, there is no need to invoke `xcode-select --switch` manually to do this. The variable is documented in both `man xcode-select` and `man xcrun`. --- .github/workflows/ci.yml | 3 --- src/ci/citool/tests/jobs.rs | 2 +- src/ci/citool/tests/test-jobs.yml | 4 ++-- src/ci/github-actions/jobs.yml | 8 ++++---- src/ci/scripts/select-xcode.sh | 11 ----------- 5 files changed, 7 insertions(+), 21 deletions(-) delete mode 100755 src/ci/scripts/select-xcode.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e6a00bb42785..4409d4f33afc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -165,9 +165,6 @@ jobs: - name: install sccache run: src/ci/scripts/install-sccache.sh - - name: select Xcode - run: src/ci/scripts/select-xcode.sh - - name: install clang run: src/ci/scripts/install-clang.sh diff --git a/src/ci/citool/tests/jobs.rs b/src/ci/citool/tests/jobs.rs index 6787f00d9af8..b0309c52003f 100644 --- a/src/ci/citool/tests/jobs.rs +++ b/src/ci/citool/tests/jobs.rs @@ -6,7 +6,7 @@ const TEST_JOBS_YML_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/tes fn auto_jobs() { let stdout = get_matrix("push", "commit", "refs/heads/automation/bors/auto"); insta::assert_snapshot!(stdout, @r#" - jobs=[{"name":"aarch64-gnu","full_name":"auto - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"x86_64-gnu-llvm-18-1","full_name":"auto - x86_64-gnu-llvm-18-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DOCKER_SCRIPT":"stage_2_test_set1.sh","IMAGE":"x86_64-gnu-llvm-18","READ_ONLY_SRC":"0","RUST_BACKTRACE":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"aarch64-apple","full_name":"auto - aarch64-apple","os":"macos-14","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","MACOSX_DEPLOYMENT_TARGET":11.0,"MACOSX_STD_DEPLOYMENT_TARGET":11.0,"NO_DEBUG_ASSERTIONS":1,"NO_LLVM_ASSERTIONS":1,"NO_OVERFLOW_CHECKS":1,"RUSTC_RETRY_LINKER_ON_SEGFAULT":1,"RUST_CONFIGURE_ARGS":"--enable-sanitizers --enable-profiler --set rust.jemalloc","SCRIPT":"./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin","SELECT_XCODE":"/Applications/Xcode_15.4.app","TOOLSTATE_PUBLISH":1,"USE_XCODE_CLANG":1}},{"name":"dist-i686-msvc","full_name":"auto - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}},{"name":"pr-check-1","full_name":"auto - pr-check-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"pr-check-2","full_name":"auto - pr-check-2","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"tidy","full_name":"auto - tidy","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true,"doc_url":"https://foo.bar"}] + jobs=[{"name":"aarch64-gnu","full_name":"auto - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"x86_64-gnu-llvm-18-1","full_name":"auto - x86_64-gnu-llvm-18-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DOCKER_SCRIPT":"stage_2_test_set1.sh","IMAGE":"x86_64-gnu-llvm-18","READ_ONLY_SRC":"0","RUST_BACKTRACE":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"aarch64-apple","full_name":"auto - aarch64-apple","os":"macos-14","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DEVELOPER_DIR":"/Applications/Xcode_15.4.app/Contents/Developer","MACOSX_DEPLOYMENT_TARGET":11.0,"MACOSX_STD_DEPLOYMENT_TARGET":11.0,"NO_DEBUG_ASSERTIONS":1,"NO_LLVM_ASSERTIONS":1,"NO_OVERFLOW_CHECKS":1,"RUSTC_RETRY_LINKER_ON_SEGFAULT":1,"RUST_CONFIGURE_ARGS":"--enable-sanitizers --enable-profiler --set rust.jemalloc","SCRIPT":"./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin","TOOLSTATE_PUBLISH":1,"USE_XCODE_CLANG":1}},{"name":"dist-i686-msvc","full_name":"auto - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}},{"name":"pr-check-1","full_name":"auto - pr-check-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"pr-check-2","full_name":"auto - pr-check-2","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"tidy","full_name":"auto - tidy","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true,"doc_url":"https://foo.bar"}] run_type=auto "#); } diff --git a/src/ci/citool/tests/test-jobs.yml b/src/ci/citool/tests/test-jobs.yml index e26104905491..95cd328e7848 100644 --- a/src/ci/citool/tests/test-jobs.yml +++ b/src/ci/citool/tests/test-jobs.yml @@ -33,7 +33,7 @@ envs: # Ensure that host tooling is tested on our minimum supported macOS version. MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_15.2.app + DEVELOPER_DIR: /Applications/Xcode_15.2.app/Contents/Developer NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 @@ -112,7 +112,7 @@ auto: --enable-profiler --set rust.jemalloc RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - SELECT_XCODE: /Applications/Xcode_15.4.app + DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer USE_XCODE_CLANG: 1 # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else # supports the hardware, so only need to test it there. diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 6e07ffc43bc2..6f333ecde79b 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -459,7 +459,7 @@ auto: # Ensure that host tooling is built to support our minimum support macOS version. MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_15.4.app + DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer USE_XCODE_CLANG: 1 DIST_REQUIRE_ALL_TOOLS: 1 CODEGEN_BACKENDS: llvm,cranelift @@ -475,7 +475,7 @@ auto: # FIXME(madsmtm): This might be redundant, as we're not building host tooling here (?) MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_15.2.app + DEVELOPER_DIR: /Applications/Xcode_15.2.app/Contents/Developer <<: *job-macos - name: dist-aarch64-apple @@ -496,7 +496,7 @@ auto: # supports the hardware. MACOSX_DEPLOYMENT_TARGET: 11.0 MACOSX_STD_DEPLOYMENT_TARGET: 11.0 - SELECT_XCODE: /Applications/Xcode_15.4.app + DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer USE_XCODE_CLANG: 1 DIST_REQUIRE_ALL_TOOLS: 1 CODEGEN_BACKENDS: llvm,cranelift @@ -511,7 +511,7 @@ auto: --enable-sanitizers --enable-profiler --set rust.jemalloc - SELECT_XCODE: /Applications/Xcode_15.4.app + DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer USE_XCODE_CLANG: 1 # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else # supports the hardware, so only need to test it there. diff --git a/src/ci/scripts/select-xcode.sh b/src/ci/scripts/select-xcode.sh deleted file mode 100755 index 569c4a4136d9..000000000000 --- a/src/ci/scripts/select-xcode.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -# This script selects the Xcode instance to use. - -set -euo pipefail -IFS=$'\n\t' - -source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" - -if isMacOS; then - sudo xcode-select -s "${SELECT_XCODE}" -fi From c9f4f7f4436bf4023bacdd0f201eaf680eb967c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 31 Jan 2026 05:52:38 +0100 Subject: [PATCH 484/978] Move the query list to `queries.rs` --- compiler/rustc_middle/src/{query/mod.rs => queries.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename compiler/rustc_middle/src/{query/mod.rs => queries.rs} (100%) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/queries.rs similarity index 100% rename from compiler/rustc_middle/src/query/mod.rs rename to compiler/rustc_middle/src/queries.rs From 590fa1e6cb42ffdec1857d03ebeb26b5e9ab43c1 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 3 Feb 2026 21:31:28 +0100 Subject: [PATCH 485/978] Convert to inline diagnostics in `rustc_ty_utils` --- Cargo.lock | 2 - compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_ty_utils/Cargo.toml | 1 - compiler/rustc_ty_utils/messages.ftl | 61 ----------------------- compiler/rustc_ty_utils/src/errors.rs | 72 ++++++++++++++------------- compiler/rustc_ty_utils/src/lib.rs | 2 - 7 files changed, 38 insertions(+), 102 deletions(-) delete mode 100644 compiler/rustc_ty_utils/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 91fce715c8cd..ee6b26aeebc5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3817,7 +3817,6 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_trait_selection", - "rustc_ty_utils", "serde_json", "shlex", "tracing", @@ -4809,7 +4808,6 @@ dependencies = [ "rustc_abi", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hashes", "rustc_hir", "rustc_index", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index d97c552b412b..0c07c23c6394 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -49,7 +49,6 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -rustc_ty_utils = { path = "../rustc_ty_utils" } serde_json = "1.0.59" shlex = "1.0" tracing = { version = "0.1.35" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index b163ae2068a6..49a100fd6757 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -143,7 +143,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_resolve::DEFAULT_LOCALE_RESOURCE, rustc_session::DEFAULT_LOCALE_RESOURCE, rustc_trait_selection::DEFAULT_LOCALE_RESOURCE, - rustc_ty_utils::DEFAULT_LOCALE_RESOURCE, // tidy-alphabetical-end ]; diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml index ce08b300cc80..682cf941561f 100644 --- a/compiler/rustc_ty_utils/Cargo.toml +++ b/compiler/rustc_ty_utils/Cargo.toml @@ -9,7 +9,6 @@ itertools = "0.12" rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } diff --git a/compiler/rustc_ty_utils/messages.ftl b/compiler/rustc_ty_utils/messages.ftl deleted file mode 100644 index c1684bfb43b6..000000000000 --- a/compiler/rustc_ty_utils/messages.ftl +++ /dev/null @@ -1,61 +0,0 @@ -ty_utils_address_and_deref_not_supported = dereferencing or taking the address is not supported in generic constants - -ty_utils_adt_not_supported = struct/enum construction is not supported in generic constants - -ty_utils_array_not_supported = array construction is not supported in generic constants - -ty_utils_assign_not_supported = assignment is not supported in generic constants - -ty_utils_binary_not_supported = unsupported binary operation in generic constants - -ty_utils_block_not_supported = blocks are not supported in generic constants - -ty_utils_borrow_not_supported = borrowing is not supported in generic constants - -ty_utils_box_not_supported = allocations are not allowed in generic constants - -ty_utils_by_use_not_supported = .use is not allowed in generic constants - -ty_utils_closure_and_return_not_supported = closures and function keywords are not supported in generic constants - -ty_utils_const_block_not_supported = const blocks are not supported in generic constants - -ty_utils_control_flow_not_supported = control flow is not supported in generic constants - -ty_utils_field_not_supported = field access is not supported in generic constants - -ty_utils_generic_constant_too_complex = overly complex generic constant - .help = consider moving this anonymous constant into a `const` function - .maybe_supported = this operation may be supported in the future - -ty_utils_impl_trait_duplicate_arg = non-defining opaque type use in defining scope - .label = generic argument `{$arg}` used twice - .note = for this opaque type - -ty_utils_impl_trait_not_param = non-defining opaque type use in defining scope - .label = argument `{$arg}` is not a generic parameter - .note = for this opaque type - -ty_utils_index_not_supported = indexing is not supported in generic constants - -ty_utils_inline_asm_not_supported = assembly is not supported in generic constants - -ty_utils_logical_op_not_supported = unsupported operation in generic constants, short-circuiting operations would imply control flow - -ty_utils_loop_not_supported = loops and loop control flow are not supported in generic constants - -ty_utils_needs_drop_overflow = overflow while checking whether `{$query_ty}` requires drop - -ty_utils_never_to_any_not_supported = coercing the `never` type is not supported in generic constants - -ty_utils_non_primitive_simd_type = monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}` - -ty_utils_operation_not_supported = unsupported operation in generic constants - -ty_utils_pointer_not_supported = pointer casts are not allowed in generic constants - -ty_utils_tuple_not_supported = tuple construction is not supported in generic constants - -ty_utils_unexpected_fnptr_associated_item = `FnPtr` trait with unexpected associated item - -ty_utils_yield_not_supported = coroutine control flow is not allowed in generic constants diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs index f92c405242ce..ccea5a49bd7c 100644 --- a/compiler/rustc_ty_utils/src/errors.rs +++ b/compiler/rustc_ty_utils/src/errors.rs @@ -6,18 +6,18 @@ use rustc_middle::ty::{GenericArg, Ty}; use rustc_span::Span; #[derive(Diagnostic)] -#[diag(ty_utils_needs_drop_overflow)] +#[diag("overflow while checking whether `{$query_ty}` requires drop")] pub(crate) struct NeedsDropOverflow<'tcx> { pub query_ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(ty_utils_generic_constant_too_complex)] -#[help] +#[diag("overly complex generic constant")] +#[help("consider moving this anonymous constant into a `const` function")] pub(crate) struct GenericConstantTooComplex { #[primary_span] pub span: Span, - #[note(ty_utils_maybe_supported)] + #[note("this operation may be supported in the future")] pub maybe_supported: bool, #[subdiagnostic] pub sub: GenericConstantTooComplexSub, @@ -25,84 +25,88 @@ pub(crate) struct GenericConstantTooComplex { #[derive(Subdiagnostic)] pub(crate) enum GenericConstantTooComplexSub { - #[label(ty_utils_borrow_not_supported)] + #[label("borrowing is not supported in generic constants")] BorrowNotSupported(#[primary_span] Span), - #[label(ty_utils_address_and_deref_not_supported)] + #[label("dereferencing or taking the address is not supported in generic constants")] AddressAndDerefNotSupported(#[primary_span] Span), - #[label(ty_utils_array_not_supported)] + #[label("array construction is not supported in generic constants")] ArrayNotSupported(#[primary_span] Span), - #[label(ty_utils_block_not_supported)] + #[label("blocks are not supported in generic constants")] BlockNotSupported(#[primary_span] Span), - #[label(ty_utils_never_to_any_not_supported)] + #[label("coercing the `never` type is not supported in generic constants")] NeverToAnyNotSupported(#[primary_span] Span), - #[label(ty_utils_tuple_not_supported)] + #[label("tuple construction is not supported in generic constants")] TupleNotSupported(#[primary_span] Span), - #[label(ty_utils_index_not_supported)] + #[label("indexing is not supported in generic constants")] IndexNotSupported(#[primary_span] Span), - #[label(ty_utils_field_not_supported)] + #[label("field access is not supported in generic constants")] FieldNotSupported(#[primary_span] Span), - #[label(ty_utils_const_block_not_supported)] + #[label("const blocks are not supported in generic constants")] ConstBlockNotSupported(#[primary_span] Span), - #[label(ty_utils_adt_not_supported)] + #[label("struct/enum construction is not supported in generic constants")] AdtNotSupported(#[primary_span] Span), - #[label(ty_utils_pointer_not_supported)] + #[label("pointer casts are not allowed in generic constants")] PointerNotSupported(#[primary_span] Span), - #[label(ty_utils_yield_not_supported)] + #[label("coroutine control flow is not allowed in generic constants")] YieldNotSupported(#[primary_span] Span), - #[label(ty_utils_loop_not_supported)] + #[label("loops and loop control flow are not supported in generic constants")] LoopNotSupported(#[primary_span] Span), - #[label(ty_utils_box_not_supported)] + #[label("allocations are not allowed in generic constants")] BoxNotSupported(#[primary_span] Span), - #[label(ty_utils_binary_not_supported)] + #[label("unsupported binary operation in generic constants")] BinaryNotSupported(#[primary_span] Span), - #[label(ty_utils_by_use_not_supported)] + #[label(".use is not allowed in generic constants")] ByUseNotSupported(#[primary_span] Span), - #[label(ty_utils_logical_op_not_supported)] + #[label( + "unsupported operation in generic constants, short-circuiting operations would imply control flow" + )] LogicalOpNotSupported(#[primary_span] Span), - #[label(ty_utils_assign_not_supported)] + #[label("assignment is not supported in generic constants")] AssignNotSupported(#[primary_span] Span), - #[label(ty_utils_closure_and_return_not_supported)] + #[label("closures and function keywords are not supported in generic constants")] ClosureAndReturnNotSupported(#[primary_span] Span), - #[label(ty_utils_control_flow_not_supported)] + #[label("control flow is not supported in generic constants")] ControlFlowNotSupported(#[primary_span] Span), - #[label(ty_utils_inline_asm_not_supported)] + #[label("assembly is not supported in generic constants")] InlineAsmNotSupported(#[primary_span] Span), - #[label(ty_utils_operation_not_supported)] + #[label("unsupported operation in generic constants")] OperationNotSupported(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(ty_utils_unexpected_fnptr_associated_item)] +#[diag("`FnPtr` trait with unexpected associated item")] pub(crate) struct UnexpectedFnPtrAssociatedItem { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ty_utils_non_primitive_simd_type)] +#[diag( + "monomorphising SIMD type `{$ty}` with a non-primitive-scalar (integer/float/pointer) element type `{$e_ty}`" +)] pub(crate) struct NonPrimitiveSimdType<'tcx> { pub ty: Ty<'tcx>, pub e_ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(ty_utils_impl_trait_duplicate_arg)] +#[diag("non-defining opaque type use in defining scope")] pub(crate) struct DuplicateArg<'tcx> { pub arg: GenericArg<'tcx>, #[primary_span] - #[label] + #[label("generic argument `{$arg}` used twice")] pub span: Span, - #[note] + #[note("for this opaque type")] pub opaque_span: Span, } #[derive(Diagnostic)] -#[diag(ty_utils_impl_trait_not_param, code = E0792)] +#[diag("non-defining opaque type use in defining scope", code = E0792)] pub(crate) struct NotParam<'tcx> { pub arg: GenericArg<'tcx>, #[primary_span] - #[label] + #[label("argument `{$arg}` is not a generic parameter")] pub span: Span, - #[note] + #[note("for this opaque type")] pub opaque_span: Span, } diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index d8b50b2d2e42..9f8f3b240890 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -31,8 +31,6 @@ pub mod sig_types; mod structural_match; mod ty; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn provide(providers: &mut Providers) { abi::provide(providers); assoc::provide(providers); From 247a022957f27f064cb468e0bbba3c3dee10e066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 31 Jan 2026 06:45:46 +0100 Subject: [PATCH 486/978] Fix references and remove inner `queries` module --- compiler/rustc_macros/src/query.rs | 4 +- .../src/rmeta/decoder/cstore_impl.rs | 7 +- compiler/rustc_middle/src/lib.rs | 2 + compiler/rustc_middle/src/queries.rs | 24 +-- compiler/rustc_middle/src/query/erase.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 23 +++ compiler/rustc_middle/src/query/plumbing.rs | 178 +++++++++--------- compiler/rustc_middle/src/util/mod.rs | 4 +- compiler/rustc_query_impl/src/lib.rs | 7 +- compiler/rustc_query_impl/src/plumbing.rs | 12 +- tests/ui-fulldeps/obtain-borrowck.rs | 2 +- 11 files changed, 136 insertions(+), 129 deletions(-) create mode 100644 compiler/rustc_middle/src/query/mod.rs diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 0e2b16d72eb1..bc6f856e8683 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -289,7 +289,7 @@ fn add_query_desc_cached_impl( cached.extend(quote! { #[allow(unused_variables, unused_braces, rustc::pass_by_value)] #[inline] - pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::query::queries::#name::Key<'tcx>) -> bool { + pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::queries::#name::Key<'tcx>) -> bool { #ra_hint #expr } @@ -301,7 +301,7 @@ fn add_query_desc_cached_impl( let desc = quote! { #[allow(unused_variables)] - pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::query::queries::#name::Key<'tcx>) -> String { + pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::queries::#name::Key<'tcx>) -> String { let (#tcx, #key) = (tcx, key); format!(#desc) } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 7bd3f7db55f9..b1f3bafd92fb 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -11,7 +11,8 @@ use rustc_middle::bug; use rustc_middle::metadata::{AmbigModChild, ModChild}; use rustc_middle::middle::exported_symbols::ExportedSymbol; use rustc_middle::middle::stability::DeprecationEntry; -use rustc_middle::query::{ExternProviders, LocalCrate}; +use rustc_middle::queries::ExternProviders; +use rustc_middle::query::LocalCrate; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::util::Providers; @@ -134,8 +135,8 @@ macro_rules! provide_one { ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => $compute:block) => { fn $name<'tcx>( $tcx: TyCtxt<'tcx>, - def_id_arg: rustc_middle::query::queries::$name::Key<'tcx>, - ) -> rustc_middle::query::queries::$name::ProvidedValue<'tcx> { + def_id_arg: rustc_middle::queries::$name::Key<'tcx>, + ) -> rustc_middle::queries::$name::ProvidedValue<'tcx> { let _prof_timer = $tcx.prof.generic_activity(concat!("metadata_decode_entry_", stringify!($name))); diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 5682c21e4353..bb94b4c927ae 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -86,6 +86,8 @@ mod values; #[macro_use] pub mod query; #[macro_use] +pub mod queries; +#[macro_use] pub mod dep_graph; // Allows macros to refer to this crate as `::rustc_middle` diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index c9291d89be8a..3ade5cab0915 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -100,8 +100,6 @@ use rustc_span::{DUMMY_SP, LocalExpnId, Span, Symbol}; use rustc_target::spec::PanicStrategy; use {rustc_abi as abi, rustc_ast as ast, rustc_hir as hir}; -pub use self::keys::{AsLocalKey, Key, LocalCrate}; -pub use self::plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk}; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintExpectation; use crate::metadata::ModChild; @@ -120,7 +118,10 @@ use crate::mir::interpret::{ use crate::mir::mono::{ CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions, NormalizationErrorInMono, }; -use crate::query::plumbing::CyclePlaceholder; +use crate::query::plumbing::{ + CyclePlaceholder, IntoQueryParam, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, +}; +use crate::query::{AsLocalKey, describe_as_module}; use crate::traits::query::{ CanonicalAliasGoal, CanonicalDropckOutlivesGoal, CanonicalImpliedOutlivesBoundsGoal, CanonicalMethodAutoderefStepsGoal, CanonicalPredicateGoal, CanonicalTypeOpAscribeUserTypeGoal, @@ -142,14 +143,6 @@ use crate::ty::{ }; use crate::{dep_graph, mir, thir}; -mod arena_cached; -pub mod erase; -pub(crate) mod inner; -mod keys; -pub mod on_disk_cache; -#[macro_use] -pub mod plumbing; - // Each of these queries corresponds to a function pointer field in the // `Providers` struct for requesting a value of that type, and a method // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way @@ -2783,12 +2776,3 @@ rustc_queries! { rustc_with_all_queries! { define_callbacks! } rustc_feedable_queries! { define_feedable! } - -fn describe_as_module(def_id: impl Into, tcx: TyCtxt<'_>) -> String { - let def_id = def_id.into(); - if def_id.is_top_level_module() { - "top-level module".to_string() - } else { - format!("module `{}`", tcx.def_path_str(def_id)) - } -} diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 32071595ec28..99b1f6d8c251 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -15,7 +15,7 @@ use rustc_span::source_map::Spanned; use crate::mir::interpret::EvalToValTreeResult; use crate::mir::mono::{MonoItem, NormalizationErrorInMono}; -use crate::query::CyclePlaceholder; +use crate::query::plumbing::CyclePlaceholder; use crate::traits::solve; use crate::ty::adjustment::CoerceUnsizedInfo; use crate::ty::{self, Ty, TyCtxt}; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs new file mode 100644 index 000000000000..f0121eab053b --- /dev/null +++ b/compiler/rustc_middle/src/query/mod.rs @@ -0,0 +1,23 @@ +use rustc_hir::def_id::LocalDefId; + +pub use self::keys::{AsLocalKey, Key, LocalCrate}; +pub use self::plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk}; +pub use crate::queries::Providers; +use crate::ty::TyCtxt; + +pub(crate) mod arena_cached; +pub mod erase; +pub(crate) mod inner; +mod keys; +pub mod on_disk_cache; +#[macro_use] +pub mod plumbing; + +pub fn describe_as_module(def_id: impl Into, tcx: TyCtxt<'_>) -> String { + let def_id = def_id.into(); + if def_id.is_top_level_module() { + "top-level module".to_string() + } else { + format!("module `{}`", tcx.def_path_str(def_id)) + } +} diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 78879dc9da9a..66e7c55a9d2b 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -12,10 +12,10 @@ pub use sealed::IntoQueryParam; use crate::dep_graph; use crate::dep_graph::DepKind; -use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; -use crate::query::{ +use crate::queries::{ ExternProviders, PerQueryVTables, Providers, QueryArenas, QueryCaches, QueryEngine, QueryStates, }; +use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; use crate::ty::TyCtxt; pub type WillCacheOnDiskForKeyFn<'tcx, Key> = fn(tcx: TyCtxt<'tcx>, key: &Key) -> bool; @@ -227,8 +227,8 @@ macro_rules! separate_provide_extern_decl { ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => { for<'tcx> fn( TyCtxt<'tcx>, - queries::$name::Key<'tcx>, - ) -> queries::$name::ProvidedValue<'tcx> + $name::Key<'tcx>, + ) -> $name::ProvidedValue<'tcx> }; ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { separate_provide_extern_decl!([$($modifiers)*][$($args)*]) @@ -266,94 +266,90 @@ macro_rules! define_callbacks { [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty, )* ) => { + $(#[allow(unused_lifetimes)] pub mod $name { + use super::*; + use $crate::query::erase::{self, Erased}; - #[allow(unused_lifetimes)] - pub mod queries { - $(pub mod $name { - use super::super::*; - use $crate::query::erase::{self, Erased}; + pub type Key<'tcx> = $($K)*; + pub type Value<'tcx> = $V; - pub type Key<'tcx> = $($K)*; - pub type Value<'tcx> = $V; + pub type LocalKey<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*); - pub type LocalKey<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*); + /// This type alias specifies the type returned from query providers and the type + /// used for decoding. For regular queries this is the declared returned type `V`, + /// but `arena_cache` will use `::Provided` instead. + pub type ProvidedValue<'tcx> = query_if_arena!( + [$($modifiers)*] + (<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided) + ($V) + ); - /// This type alias specifies the type returned from query providers and the type - /// used for decoding. For regular queries this is the declared returned type `V`, - /// but `arena_cache` will use `::Provided` instead. - pub type ProvidedValue<'tcx> = query_if_arena!( - [$($modifiers)*] - (<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided) - ($V) - ); + /// This function takes `ProvidedValue` and converts it to an erased `Value` by + /// allocating it on an arena if the query has the `arena_cache` modifier. The + /// value is then erased and returned. This will happen when computing the query + /// using a provider or decoding a stored result. + #[inline(always)] + pub fn provided_to_erased<'tcx>( + _tcx: TyCtxt<'tcx>, + provided_value: ProvidedValue<'tcx>, + ) -> Erased> { + // Store the provided value in an arena and get a reference + // to it, for queries with `arena_cache`. + let value: Value<'tcx> = query_if_arena!([$($modifiers)*] + { + use $crate::query::arena_cached::ArenaCached; - /// This function takes `ProvidedValue` and converts it to an erased `Value` by - /// allocating it on an arena if the query has the `arena_cache` modifier. The - /// value is then erased and returned. This will happen when computing the query - /// using a provider or decoding a stored result. - #[inline(always)] - pub fn provided_to_erased<'tcx>( - _tcx: TyCtxt<'tcx>, - provided_value: ProvidedValue<'tcx>, - ) -> Erased> { - // Store the provided value in an arena and get a reference - // to it, for queries with `arena_cache`. - let value: Value<'tcx> = query_if_arena!([$($modifiers)*] - { - use $crate::query::arena_cached::ArenaCached; - - if mem::needs_drop::<<$V as ArenaCached<'tcx>>::Allocated>() { - <$V as ArenaCached>::alloc_in_arena( - |v| _tcx.query_system.arenas.$name.alloc(v), - provided_value, - ) - } else { - <$V as ArenaCached>::alloc_in_arena( - |v| _tcx.arena.dropless.alloc(v), - provided_value, - ) - } + if mem::needs_drop::<<$V as ArenaCached<'tcx>>::Allocated>() { + <$V as ArenaCached>::alloc_in_arena( + |v| _tcx.query_system.arenas.$name.alloc(v), + provided_value, + ) + } else { + <$V as ArenaCached>::alloc_in_arena( + |v| _tcx.arena.dropless.alloc(v), + provided_value, + ) } - // Otherwise, the provided value is the value. - (provided_value) - ); - erase::erase_val(value) + } + // Otherwise, the provided value is the value. + (provided_value) + ); + erase::erase_val(value) + } + + pub type Storage<'tcx> = <$($K)* as $crate::query::Key>::Cache>; + + // Ensure that keys grow no larger than 88 bytes by accident. + // Increase this limit if necessary, but do try to keep the size low if possible + #[cfg(target_pointer_width = "64")] + const _: () = { + if size_of::>() > 88 { + panic!("{}", concat!( + "the query `", + stringify!($name), + "` has a key type `", + stringify!($($K)*), + "` that is too large" + )); } + }; - pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache>; - - // Ensure that keys grow no larger than 88 bytes by accident. - // Increase this limit if necessary, but do try to keep the size low if possible - #[cfg(target_pointer_width = "64")] - const _: () = { - if size_of::>() > 88 { - panic!("{}", concat!( - "the query `", - stringify!($name), - "` has a key type `", - stringify!($($K)*), - "` that is too large" - )); - } - }; - - // Ensure that values grow no larger than 64 bytes by accident. - // Increase this limit if necessary, but do try to keep the size low if possible - #[cfg(target_pointer_width = "64")] - #[cfg(not(feature = "rustc_randomized_layouts"))] - const _: () = { - if size_of::>() > 64 { - panic!("{}", concat!( - "the query `", - stringify!($name), - "` has a value type `", - stringify!($V), - "` that is too large" - )); - } - }; - })* - } + // Ensure that values grow no larger than 64 bytes by accident. + // Increase this limit if necessary, but do try to keep the size low if possible + #[cfg(target_pointer_width = "64")] + #[cfg(not(feature = "rustc_randomized_layouts"))] + const _: () = { + if size_of::>() > 64 { + panic!("{}", concat!( + "the query `", + stringify!($name), + "` has a value type `", + stringify!($V), + "` that is too large" + )); + } + }; + })* /// Holds per-query arenas for queries with the `arena_cache` modifier. #[derive(Default)] @@ -371,7 +367,7 @@ macro_rules! define_callbacks { #[derive(Default)] pub struct QueryCaches<'tcx> { - $($(#[$attr])* pub $name: queries::$name::Storage<'tcx>,)* + $($(#[$attr])* pub $name: $name::Storage<'tcx>,)* } impl<'tcx> TyCtxtEnsureOk<'tcx> { @@ -438,7 +434,7 @@ macro_rules! define_callbacks { /// ("Per" just makes this pluralized name more visually distinct.) pub struct PerQueryVTables<'tcx> { $( - pub $name: ::rustc_middle::query::plumbing::QueryVTable<'tcx, queries::$name::Storage<'tcx>>, + pub $name: ::rustc_middle::query::plumbing::QueryVTable<'tcx, $name::Storage<'tcx>>, )* } @@ -452,8 +448,8 @@ macro_rules! define_callbacks { pub struct Providers { $(pub $name: for<'tcx> fn( TyCtxt<'tcx>, - queries::$name::LocalKey<'tcx>, - ) -> queries::$name::ProvidedValue<'tcx>,)* + $name::LocalKey<'tcx>, + ) -> $name::ProvidedValue<'tcx>,)* } pub struct ExternProviders { @@ -490,7 +486,7 @@ macro_rules! define_callbacks { $(pub $name: for<'tcx> fn( TyCtxt<'tcx>, Span, - queries::$name::Key<'tcx>, + $name::Key<'tcx>, QueryMode, ) -> Option<$crate::query::erase::Erased<$V>>,)* } @@ -502,11 +498,11 @@ macro_rules! define_feedable { $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> { $(#[$attr])* #[inline(always)] - pub fn $name(self, value: queries::$name::ProvidedValue<'tcx>) { + pub fn $name(self, value: $name::ProvidedValue<'tcx>) { let key = self.key().into_query_param(); let tcx = self.tcx; - let erased_value = queries::$name::provided_to_erased(tcx, value); + let erased_value = $name::provided_to_erased(tcx, value); let dep_kind: dep_graph::DepKind = dep_graph::dep_kinds::$name; diff --git a/compiler/rustc_middle/src/util/mod.rs b/compiler/rustc_middle/src/util/mod.rs index d5076a278eab..0bbe3856033b 100644 --- a/compiler/rustc_middle/src/util/mod.rs +++ b/compiler/rustc_middle/src/util/mod.rs @@ -2,7 +2,7 @@ pub mod bug; #[derive(Default, Copy, Clone)] pub struct Providers { - pub queries: crate::query::Providers, - pub extern_queries: crate::query::ExternProviders, + pub queries: crate::queries::Providers, + pub extern_queries: crate::queries::ExternProviders, pub hooks: crate::hooks::Providers, } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index bd69c99a32dc..baa37111c807 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -13,11 +13,12 @@ use rustc_data_structures::stable_hasher::HashStable; use rustc_data_structures::sync::AtomicU64; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::{self, DepKind, DepKindVTable, DepNodeIndex}; +use rustc_middle::queries::{ + self, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates, +}; +use rustc_middle::query::AsLocalKey; use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; use rustc_middle::query::plumbing::{QuerySystem, QuerySystemFns, QueryVTable}; -use rustc_middle::query::{ - AsLocalKey, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates, queries, -}; use rustc_middle::ty::TyCtxt; use rustc_query_system::Value; use rustc_query_system::dep_graph::SerializedDepNodeIndex; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index d1721f1f455f..9ffea692df3a 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -648,7 +648,7 @@ macro_rules! define_queries { query_state: std::mem::offset_of!(QueryStates<'tcx>, $name), query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name), will_cache_on_disk_for_key_fn: should_ever_cache_on_disk!([$($modifiers)*] { - Some(::rustc_middle::query::cached::$name) + Some(queries::cached::$name) } { None }), @@ -672,7 +672,7 @@ macro_rules! define_queries { try_load_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] { Some(|tcx, key, prev_index, index| { // Check the `cache_on_disk_if` condition for this key. - if !::rustc_middle::query::cached::$name(tcx, key) { + if !queries::cached::$name(tcx, key) { return None; } @@ -687,7 +687,7 @@ macro_rules! define_queries { }), is_loadable_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] { Some(|tcx, key, index| -> bool { - ::rustc_middle::query::cached::$name(tcx, key) && + ::rustc_middle::queries::cached::$name(tcx, key) && $crate::plumbing::loadable_from_disk(tcx, index) }) } { @@ -747,7 +747,7 @@ macro_rules! define_queries { let make_frame = |tcx, key| { let kind = rustc_middle::dep_graph::dep_kinds::$name; let name = stringify!($name); - $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name) + $crate::plumbing::create_query_frame(tcx, queries::descs::$name, key, kind, name) }; // Call `gather_active_jobs_inner` to do the actual work. @@ -817,8 +817,8 @@ macro_rules! define_queries { } } - pub fn make_query_vtables<'tcx>() -> ::rustc_middle::query::PerQueryVTables<'tcx> { - ::rustc_middle::query::PerQueryVTables { + pub fn make_query_vtables<'tcx>() -> queries::PerQueryVTables<'tcx> { + queries::PerQueryVTables { $( $name: query_impl::$name::make_query_vtable(), )* diff --git a/tests/ui-fulldeps/obtain-borrowck.rs b/tests/ui-fulldeps/obtain-borrowck.rs index a562d0ccd3df..ea2dab614ec1 100644 --- a/tests/ui-fulldeps/obtain-borrowck.rs +++ b/tests/ui-fulldeps/obtain-borrowck.rs @@ -37,7 +37,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_interface::Config; use rustc_interface::interface::Compiler; -use rustc_middle::query::queries::mir_borrowck::ProvidedValue; +use rustc_middle::queries::mir_borrowck::ProvidedValue; use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_session::Session; From 9de16dd3eb3ff76198125d30db0b787198855427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 3 Feb 2026 10:13:45 +0100 Subject: [PATCH 487/978] Remove imports in `queries` only used by `define_callbacks!` --- compiler/rustc_middle/src/queries.rs | 9 +++----- compiler/rustc_middle/src/query/mod.rs | 1 + compiler/rustc_middle/src/query/plumbing.rs | 24 ++++++++++----------- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 3ade5cab0915..ca8e5e90318d 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -49,7 +49,7 @@ //! ## Query Expansion and Code Generation //! //! The [`rustc_macros::rustc_queries`] macro expands each query definition into: -//! - A method on [`TyCtxt`] (and [`TyCtxtAt`]) for invoking the query. +//! - A method on [`TyCtxt`] (and [`crate::query::TyCtxtAt`]) for invoking the query. //! - Provider traits and structs for supplying the query's value. //! - Caching and dependency graph integration. //! - Support for incremental compilation, disk caching, and arena allocation as controlled by the modifiers. @@ -87,7 +87,6 @@ use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, Trait use rustc_index::IndexVec; use rustc_lint_defs::LintId; use rustc_macros::rustc_queries; -use rustc_query_system::query::{QueryMode, QueryState}; use rustc_session::Limits; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::cstore::{ @@ -118,10 +117,8 @@ use crate::mir::interpret::{ use crate::mir::mono::{ CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions, NormalizationErrorInMono, }; -use crate::query::plumbing::{ - CyclePlaceholder, IntoQueryParam, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk, -}; -use crate::query::{AsLocalKey, describe_as_module}; +use crate::query::describe_as_module; +use crate::query::plumbing::CyclePlaceholder; use crate::traits::query::{ CanonicalAliasGoal, CanonicalDropckOutlivesGoal, CanonicalImpliedOutlivesBoundsGoal, CanonicalMethodAutoderefStepsGoal, CanonicalPredicateGoal, CanonicalTypeOpAscribeUserTypeGoal, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index f0121eab053b..24a38e70ff6f 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1,4 +1,5 @@ use rustc_hir::def_id::LocalDefId; +pub use rustc_query_system::query::{QueryMode, QueryState}; pub use self::keys::{AsLocalKey, Key, LocalCrate}; pub use self::plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk}; diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 66e7c55a9d2b..0b7dc3092719 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -189,8 +189,8 @@ macro_rules! query_ensure_select { } macro_rules! query_helper_param_ty { - (DefId) => { impl IntoQueryParam }; - (LocalDefId) => { impl IntoQueryParam }; + (DefId) => { impl $crate::query::IntoQueryParam }; + (LocalDefId) => { impl $crate::query::IntoQueryParam }; ($K:ty) => { $K }; } @@ -213,7 +213,7 @@ macro_rules! local_key_if_separate_extern { $($K)* }; ([(separate_provide_extern) $($rest:tt)*] $($K:tt)*) => { - <$($K)* as AsLocalKey>::LocalKey + <$($K)* as $crate::query::AsLocalKey>::LocalKey }; ([$other:tt $($modifiers:tt)*] $($K:tt)*) => { local_key_if_separate_extern!([$($modifiers)*] $($K)*) @@ -370,7 +370,7 @@ macro_rules! define_callbacks { $($(#[$attr])* pub $name: $name::Storage<'tcx>,)* } - impl<'tcx> TyCtxtEnsureOk<'tcx> { + impl<'tcx> $crate::query::TyCtxtEnsureOk<'tcx> { $($(#[$attr])* #[inline(always)] pub fn $name( @@ -382,13 +382,13 @@ macro_rules! define_callbacks { self.tcx, self.tcx.query_system.fns.engine.$name, &self.tcx.query_system.caches.$name, - key.into_query_param(), + $crate::query::IntoQueryParam::into_query_param(key), false, ) })* } - impl<'tcx> TyCtxtEnsureDone<'tcx> { + impl<'tcx> $crate::query::TyCtxtEnsureDone<'tcx> { $($(#[$attr])* #[inline(always)] pub fn $name(self, key: query_helper_param_ty!($($K)*)) { @@ -396,7 +396,7 @@ macro_rules! define_callbacks { self.tcx, self.tcx.query_system.fns.engine.$name, &self.tcx.query_system.caches.$name, - key.into_query_param(), + $crate::query::IntoQueryParam::into_query_param(key), true, ); })* @@ -412,7 +412,7 @@ macro_rules! define_callbacks { })* } - impl<'tcx> TyCtxtAt<'tcx> { + impl<'tcx> $crate::query::TyCtxtAt<'tcx> { $($(#[$attr])* #[inline(always)] pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V @@ -424,7 +424,7 @@ macro_rules! define_callbacks { self.tcx.query_system.fns.engine.$name, &self.tcx.query_system.caches.$name, self.span, - key.into_query_param(), + $crate::query::IntoQueryParam::into_query_param(key), )) })* } @@ -441,7 +441,7 @@ macro_rules! define_callbacks { #[derive(Default)] pub struct QueryStates<'tcx> { $( - pub $name: QueryState<'tcx, $($K)*>, + pub $name: $crate::query::QueryState<'tcx, $($K)*>, )* } @@ -487,7 +487,7 @@ macro_rules! define_callbacks { TyCtxt<'tcx>, Span, $name::Key<'tcx>, - QueryMode, + $crate::query::QueryMode, ) -> Option<$crate::query::erase::Erased<$V>>,)* } }; @@ -495,7 +495,7 @@ macro_rules! define_callbacks { macro_rules! define_feedable { ($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => { - $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> { + $(impl<'tcx, K: $crate::query::IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> { $(#[$attr])* #[inline(always)] pub fn $name(self, value: $name::ProvidedValue<'tcx>) { From 80a4257fdfd47a05839d94c50fcd9427c330f355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 3 Feb 2026 21:46:06 +0100 Subject: [PATCH 488/978] Weaken `assert_dep_node_not_yet_allocated_in_current_session` for multiple threads --- compiler/rustc_codegen_ssa/src/base.rs | 2 +- .../rustc_query_system/src/dep_graph/graph.rs | 29 ++++++++++++++----- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 43767dff92bf..85c8890d661c 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -1111,7 +1111,7 @@ pub fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> // know that later). If we are not doing LTO, there is only one optimized // version of each module, so we re-use that. let dep_node = cgu.codegen_dep_node(tcx); - tcx.dep_graph.assert_dep_node_not_yet_allocated_in_current_session(&dep_node, || { + tcx.dep_graph.assert_dep_node_not_yet_allocated_in_current_session(tcx.sess, &dep_node, || { format!( "CompileCodegenUnit dep-node for CGU `{}` already exists before marking.", cgu.name() diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 06e576baf22a..450f4e546456 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -336,13 +336,17 @@ impl DepGraphData { // in `DepGraph::try_mark_green()`. // 2. Two distinct query keys get mapped to the same `DepNode` // (see for example #48923). - self.assert_dep_node_not_yet_allocated_in_current_session(&key, || { - format!( - "forcing query with already existing `DepNode`\n\ + self.assert_dep_node_not_yet_allocated_in_current_session( + cx.dep_context().sess(), + &key, + || { + format!( + "forcing query with already existing `DepNode`\n\ - query-key: {arg:?}\n\ - dep-node: {key:?}" - ) - }); + ) + }, + ); let with_deps = |task_deps| D::with_deps(task_deps, || task(cx, arg)); let (result, edges) = if cx.dep_context().is_eval_always(key.kind) { @@ -627,12 +631,20 @@ impl DepGraph { impl DepGraphData { fn assert_dep_node_not_yet_allocated_in_current_session( &self, + sess: &Session, dep_node: &DepNode, msg: impl FnOnce() -> S, ) { if let Some(prev_index) = self.previous.node_to_index_opt(dep_node) { - let current = self.colors.get(prev_index); - assert_matches!(current, DepNodeColor::Unknown, "{}", msg()) + let color = self.colors.get(prev_index); + let ok = match color { + DepNodeColor::Unknown => true, + DepNodeColor::Red => false, + DepNodeColor::Green(..) => sess.threads() > 1, // Other threads may mark this green + }; + if !ok { + panic!("{}", msg()) + } } else if let Some(nodes_in_current_session) = &self.current.nodes_in_current_session { outline(|| { let seen = nodes_in_current_session.lock().contains_key(dep_node); @@ -1035,11 +1047,12 @@ impl DepGraph { pub fn assert_dep_node_not_yet_allocated_in_current_session( &self, + sess: &Session, dep_node: &DepNode, msg: impl FnOnce() -> S, ) { if let Some(data) = &self.data { - data.assert_dep_node_not_yet_allocated_in_current_session(dep_node, msg) + data.assert_dep_node_not_yet_allocated_in_current_session(sess, dep_node, msg) } } From d8d4d4029fdcd993a77c9f1943cede7a7fe4c628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 21 Jan 2026 19:11:08 +0100 Subject: [PATCH 489/978] Handle race when coloring nodes concurrently as both green and red --- .../rustc_query_system/src/dep_graph/graph.rs | 46 +++++++++++-------- .../src/dep_graph/serialized.rs | 23 ++++------ 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 06e576baf22a..248bd37df7a3 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -776,17 +776,22 @@ impl DepGraphData { } } - fn promote_node_and_deps_to_current(&self, prev_index: SerializedDepNodeIndex) -> DepNodeIndex { + fn promote_node_and_deps_to_current( + &self, + prev_index: SerializedDepNodeIndex, + ) -> Option { self.current.debug_assert_not_in_new_nodes(&self.previous, prev_index); let dep_node_index = self.current.encoder.send_promoted(prev_index, &self.colors); #[cfg(debug_assertions)] - self.current.record_edge( - dep_node_index, - *self.previous.index_to_node(prev_index), - self.previous.fingerprint_by_index(prev_index), - ); + if let Some(dep_node_index) = dep_node_index { + self.current.record_edge( + dep_node_index, + *self.previous.index_to_node(prev_index), + self.previous.fingerprint_by_index(prev_index), + ); + } dep_node_index } @@ -1006,8 +1011,10 @@ impl DepGraphData { // There may be multiple threads trying to mark the same dep node green concurrently // We allocating an entry for the node in the current dependency graph and - // adding all the appropriate edges imported from the previous graph - let dep_node_index = self.promote_node_and_deps_to_current(prev_dep_node_index); + // adding all the appropriate edges imported from the previous graph. + // + // `no_hash` nodes may fail this promotion due to already being conservatively colored red. + let dep_node_index = self.promote_node_and_deps_to_current(prev_dep_node_index)?; // ... and finally storing a "Green" entry in the color map. // Multiple threads can all write the same color here @@ -1377,26 +1384,27 @@ impl DepNodeColorMap { } /// This tries to atomically mark a node green and assign `index` as the new - /// index. This returns `Ok` if `index` gets assigned, otherwise it returns - /// the already allocated index in `Err`. - #[inline] - pub(super) fn try_mark_green( + /// index if `green` is true, otherwise it will try to atomicaly mark it red. + /// + /// This returns `Ok` if `index` gets assigned or the node is marked red, otherwise it returns + /// the already allocated index in `Err` if it is green already. If it was already + /// red, `Err(None)` is returned. + #[inline(always)] + pub(super) fn try_mark( &self, prev_index: SerializedDepNodeIndex, index: DepNodeIndex, - ) -> Result<(), DepNodeIndex> { + green: bool, + ) -> Result<(), Option> { let value = &self.values[prev_index]; match value.compare_exchange( COMPRESSED_UNKNOWN, - index.as_u32(), + if green { index.as_u32() } else { COMPRESSED_RED }, Ordering::Relaxed, Ordering::Relaxed, ) { Ok(_) => Ok(()), - Err(v) => Err({ - assert_ne!(v, COMPRESSED_RED, "tried to mark a red node as green"); - DepNodeIndex::from_u32(v) - }), + Err(v) => Err(if v == COMPRESSED_RED { None } else { Some(DepNodeIndex::from_u32(v)) }), } } @@ -1419,7 +1427,7 @@ impl DepNodeColorMap { pub(super) fn insert_red(&self, index: SerializedDepNodeIndex) { let value = self.values[index].swap(COMPRESSED_RED, Ordering::Release); // Sanity check for duplicate nodes - assert_eq!(value, COMPRESSED_UNKNOWN, "trying to encode a dep node twice"); + assert_eq!(value, COMPRESSED_UNKNOWN, "tried to color an already colored node as red"); } } diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index aa4c928d3cdc..3b5954fc8f94 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -898,15 +898,12 @@ impl GraphEncoder { let index = self.status.next_index(&mut *local); - if is_green { - // Use `try_mark_green` to avoid racing when `send_promoted` is called concurrently - // on the same index. - match colors.try_mark_green(prev_index, index) { - Ok(()) => (), - Err(dep_node_index) => return dep_node_index, - } - } else { - colors.insert_red(prev_index); + // Use `try_mark` to avoid racing when `send_promoted` is called concurrently + // on the same index. + match colors.try_mark(prev_index, index, is_green) { + Ok(()) => (), + Err(None) => panic!("dep node {:?} is unexpectedly red", prev_index), + Err(Some(dep_node_index)) => return dep_node_index, } self.status.bump_index(&mut *local); @@ -918,13 +915,13 @@ impl GraphEncoder { /// from the previous dep graph and expects all edges to already have a new dep node index /// assigned. /// - /// This will also ensure the dep node is marked green. + /// This will also ensure the dep node is marked green if `Some` is returned. #[inline] pub(crate) fn send_promoted( &self, prev_index: SerializedDepNodeIndex, colors: &DepNodeColorMap, - ) -> DepNodeIndex { + ) -> Option { let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph"); let mut local = self.status.local.borrow_mut(); @@ -932,7 +929,7 @@ impl GraphEncoder { // Use `try_mark_green` to avoid racing when `send_promoted` or `send_and_color` // is called concurrently on the same index. - match colors.try_mark_green(prev_index, index) { + match colors.try_mark(prev_index, index, true) { Ok(()) => { self.status.bump_index(&mut *local); self.status.encode_promoted_node( @@ -942,7 +939,7 @@ impl GraphEncoder { colors, &mut *local, ); - index + Some(index) } Err(dep_node_index) => dep_node_index, } From 8b5be2b271010576a22e168103206b683aab0065 Mon Sep 17 00:00:00 2001 From: Hanna Kruppe Date: Tue, 3 Feb 2026 22:35:09 +0100 Subject: [PATCH 490/978] Implement stdio FD constants --- library/std/src/os/fd/mod.rs | 5 ++++ library/std/src/os/fd/stdio.rs | 53 ++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 library/std/src/os/fd/stdio.rs diff --git a/library/std/src/os/fd/mod.rs b/library/std/src/os/fd/mod.rs index 95cf4932e6e2..473d7ae3e2ae 100644 --- a/library/std/src/os/fd/mod.rs +++ b/library/std/src/os/fd/mod.rs @@ -16,6 +16,9 @@ mod owned; #[cfg(not(target_os = "trusty"))] mod net; +// Implementation of stdio file descriptor constants. +mod stdio; + #[cfg(test)] mod tests; @@ -24,3 +27,5 @@ mod tests; pub use owned::*; #[stable(feature = "os_fd", since = "1.66.0")] pub use raw::*; +#[unstable(feature = "stdio_fd_consts", issue = "150836")] +pub use stdio::*; diff --git a/library/std/src/os/fd/stdio.rs b/library/std/src/os/fd/stdio.rs new file mode 100644 index 000000000000..c50cbd39849b --- /dev/null +++ b/library/std/src/os/fd/stdio.rs @@ -0,0 +1,53 @@ +use super::BorrowedFd; + +/// The file descriptor for the standard input stream of the current process. +/// +/// See [`io::stdin()`][`crate::io::stdin`] for the higher level handle, which should be preferred +/// whenever possible. See [`STDERR`] for why the file descriptor might be required and caveats. +#[unstable(feature = "stdio_fd_consts", issue = "150836")] +pub const STDIN: BorrowedFd<'static> = unsafe { BorrowedFd::borrow_raw(0) }; + +/// The file descriptor for the standard output stream of the current process. +/// +/// See [`io::stdout()`][`crate::io::stdout`] for the higher level handle, which should be preferred +/// whenever possible. See [`STDERR`] for why the file descriptor might be required and caveats. In +/// addition to the issues discussed there, note that [`Stdout`][`crate::io::Stdout`] is buffered by +/// default, and writing to the file descriptor will bypass this buffer. +#[unstable(feature = "stdio_fd_consts", issue = "150836")] +pub const STDOUT: BorrowedFd<'static> = unsafe { BorrowedFd::borrow_raw(1) }; + +/// The file descriptor for the standard error stream of the current process. +/// +/// See [`io::stderr()`][`crate::io::stderr`] for the higher level handle, which should be preferred +/// whenever possible. However, there are situations where touching the `std::io` handles (or most +/// other parts of the standard library) risks deadlocks or other subtle bugs. For example: +/// +/// - Global allocators must be careful to [avoid reentrancy][global-alloc-reentrancy], and the +/// `std::io` handles may allocate memory on (some) accesses. +/// - Signal handlers must be *async-signal-safe*, which rules out panicking, taking locks (may +/// deadlock if the signal handler interrupted a thread holding that lock), allocating memory, or +/// anything else that is not explicitly declared async-signal-safe. +/// - `CommandExt::pre_exec` callbacks can safely panic (with some limitations), but otherwise must +/// abide by similar limitations as signal handlers. In particular, at the time these callbacks +/// run, the stdio file descriptors have already been replaced, but the locks protecting the +/// `std::io` handles may be permanently locked if another thread held the lock at `fork()` time. +/// +/// In these and similar cases, direct access to the file descriptor may be required. However, in +/// most cases, using the `std::io` handles and accessing the file descriptor via the `AsFd` +/// implementations is preferable, as it enables cooperation with the standard library's locking and +/// buffering. +/// +/// # I/O safety +/// +/// This is a `BorrowedFd<'static>` because the standard input/output/error streams are shared +/// resources that must remain available for the lifetime of the process. This is only true when +/// linking `std`, and may not always hold for [code running before `main()`][before-after-main] or +/// in `no_std` environments. It is [unsound][io-safety] to close these file descriptors. Safe +/// patterns for changing these file descriptors are available on Unix via the `StdioExt` extension +/// trait. +/// +/// [before-after-main]: ../../../std/index.html#use-before-and-after-main +/// [io-safety]: ../../../std/io/index.html#io-safety +/// [global-alloc-reentrancy]: ../../../std/alloc/trait.GlobalAlloc.html#re-entrance +#[unstable(feature = "stdio_fd_consts", issue = "150836")] +pub const STDERR: BorrowedFd<'static> = unsafe { BorrowedFd::borrow_raw(2) }; From d457ffd4f4589dfdd1f8fd2ef1c3d784018cf127 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 3 Feb 2026 22:44:03 +0100 Subject: [PATCH 491/978] Convert to inline diagnostics in `rustc_monomorphize` --- Cargo.lock | 2 - compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_monomorphize/Cargo.toml | 1 - compiler/rustc_monomorphize/messages.ftl | 82 ---------------- compiler/rustc_monomorphize/src/errors.rs | 109 ++++++++++++++++------ compiler/rustc_monomorphize/src/lib.rs | 2 - 7 files changed, 82 insertions(+), 116 deletions(-) delete mode 100644 compiler/rustc_monomorphize/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 91fce715c8cd..b7dd59d857fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3805,7 +3805,6 @@ dependencies = [ "rustc_mir_build", "rustc_mir_dataflow", "rustc_mir_transform", - "rustc_monomorphize", "rustc_parse", "rustc_passes", "rustc_pattern_analysis", @@ -4384,7 +4383,6 @@ dependencies = [ "rustc_abi", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index d97c552b412b..28972d1c35ec 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -37,7 +37,6 @@ rustc_middle = { path = "../rustc_middle" } rustc_mir_build = { path = "../rustc_mir_build" } rustc_mir_dataflow = { path = "../rustc_mir_dataflow" } rustc_mir_transform = { path = "../rustc_mir_transform" } -rustc_monomorphize = { path = "../rustc_monomorphize" } rustc_parse = { path = "../rustc_parse" } rustc_passes = { path = "../rustc_passes" } rustc_pattern_analysis = { path = "../rustc_pattern_analysis" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index b163ae2068a6..80724c6a24f5 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -134,7 +134,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_mir_build::DEFAULT_LOCALE_RESOURCE, rustc_mir_dataflow::DEFAULT_LOCALE_RESOURCE, rustc_mir_transform::DEFAULT_LOCALE_RESOURCE, - rustc_monomorphize::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE, rustc_passes::DEFAULT_LOCALE_RESOURCE, rustc_pattern_analysis::DEFAULT_LOCALE_RESOURCE, diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index 0829d52283ab..552c092ef7c4 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -8,7 +8,6 @@ edition = "2024" rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl deleted file mode 100644 index 9c791208c093..000000000000 --- a/compiler/rustc_monomorphize/messages.ftl +++ /dev/null @@ -1,82 +0,0 @@ -monomorphize_abi_error_disabled_vector_type = - this function {$is_call -> - [true] call - *[false] definition - } uses {$is_scalable -> - [true] scalable - *[false] SIMD - } vector type `{$ty}` which (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled{$is_call -> - [true] {" "}in the caller - *[false] {""} - } - .label = function {$is_call -> - [true] called - *[false] defined - } here - .help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`) - -monomorphize_abi_error_unsupported_unsized_parameter = - this function {$is_call -> - [true] call - *[false] definition - } uses unsized type `{$ty}` which is not supported with the chosen ABI - .label = function {$is_call -> - [true] called - *[false] defined - } here - .help = only rustic ABIs support unsized parameters - -monomorphize_abi_error_unsupported_vector_type = - this function {$is_call -> - [true] call - *[false] definition - } uses SIMD vector type `{$ty}` which is not currently supported with the chosen ABI - .label = function {$is_call -> - [true] called - *[false] defined - } here - -monomorphize_abi_required_target_feature = - this function {$is_call -> - [true] call - *[false] definition - } uses ABI "{$abi}" which requires the `{$required_feature}` target feature, which is not enabled{$is_call -> - [true] {" "}in the caller - *[false] {""} - } - .label = function {$is_call -> - [true] called - *[false] defined - } here - .help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`) - -monomorphize_couldnt_dump_mono_stats = - unexpected error occurred while dumping monomorphization stats: {$error} - -monomorphize_encountered_error_while_instantiating = - the above error was encountered while instantiating `{$kind} {$instance}` - -monomorphize_encountered_error_while_instantiating_global_asm = - the above error was encountered while instantiating `global_asm` - -monomorphize_large_assignments = - moving {$size} bytes - .label = value moved from here - .note = the current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` - -monomorphize_no_optimized_mir = - missing optimized MIR for `{$instance}` in the crate `{$crate_name}` - .note = missing optimized MIR for this item (was the crate `{$crate_name}` compiled with `--emit=metadata`?) - -monomorphize_recursion_limit = - reached the recursion limit while instantiating `{$instance}` - .note = `{$def_path_str}` defined here - -monomorphize_start_not_found = using `fn main` requires the standard library - .help = use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself, usually with `#[no_mangle]` - -monomorphize_static_initializer_cyclic = static initializer forms a cycle involving `{$head}` - .label = part of this cycle - .note = cyclic static initializers are not supported for target `{$target}` - -monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 723649f22117..d045ae0b92cb 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -3,37 +3,41 @@ use rustc_middle::ty::{Instance, Ty}; use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] -#[diag(monomorphize_recursion_limit)] +#[diag("reached the recursion limit while instantiating `{$instance}`")] pub(crate) struct RecursionLimit<'tcx> { #[primary_span] pub span: Span, pub instance: Instance<'tcx>, - #[note] + #[note("`{$def_path_str}` defined here")] pub def_span: Span, pub def_path_str: String, } #[derive(Diagnostic)] -#[diag(monomorphize_no_optimized_mir)] +#[diag("missing optimized MIR for `{$instance}` in the crate `{$crate_name}`")] pub(crate) struct NoOptimizedMir { - #[note] + #[note( + "missing optimized MIR for this item (was the crate `{$crate_name}` compiled with `--emit=metadata`?)" + )] pub span: Span, pub crate_name: Symbol, pub instance: String, } #[derive(LintDiagnostic)] -#[diag(monomorphize_large_assignments)] -#[note] +#[diag("moving {$size} bytes")] +#[note( + "the current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = \"...\"]`" +)] pub(crate) struct LargeAssignmentsLint { - #[label] + #[label("value moved from here")] pub span: Span, pub size: u64, pub limit: u64, } #[derive(Diagnostic)] -#[diag(monomorphize_symbol_already_defined)] +#[diag("symbol `{$symbol}` is already defined")] pub(crate) struct SymbolAlreadyDefined { #[primary_span] pub span: Option, @@ -41,13 +45,13 @@ pub(crate) struct SymbolAlreadyDefined { } #[derive(Diagnostic)] -#[diag(monomorphize_couldnt_dump_mono_stats)] +#[diag("unexpected error occurred while dumping monomorphization stats: {$error}")] pub(crate) struct CouldntDumpMonoStats { pub error: String, } #[derive(Diagnostic)] -#[diag(monomorphize_encountered_error_while_instantiating)] +#[diag("the above error was encountered while instantiating `{$kind} {$instance}`")] pub(crate) struct EncounteredErrorWhileInstantiating<'tcx> { #[primary_span] pub span: Span, @@ -56,23 +60,41 @@ pub(crate) struct EncounteredErrorWhileInstantiating<'tcx> { } #[derive(Diagnostic)] -#[diag(monomorphize_encountered_error_while_instantiating_global_asm)] +#[diag("the above error was encountered while instantiating `global_asm`")] pub(crate) struct EncounteredErrorWhileInstantiatingGlobalAsm { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(monomorphize_start_not_found)] -#[help] +#[diag("using `fn main` requires the standard library")] +#[help( + "use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself, usually with `#[no_mangle]`" +)] pub(crate) struct StartNotFound; #[derive(Diagnostic)] -#[diag(monomorphize_abi_error_disabled_vector_type)] -#[help] +#[diag("this function {$is_call -> + [true] call + *[false] definition +} uses {$is_scalable -> + [true] scalable + *[false] SIMD +} vector type `{$ty}` which (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled{$is_call -> + [true] {\" \"}in the caller + *[false] {\"\"} +}")] +#[help( + "consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable=\"{$required_feature}\")]`)" +)] pub(crate) struct AbiErrorDisabledVectorType<'a> { #[primary_span] - #[label] + #[label( + "function {$is_call -> + [true] called + *[false] defined + } here" + )] pub span: Span, pub required_feature: &'a str, pub ty: Ty<'a>, @@ -83,11 +105,21 @@ pub(crate) struct AbiErrorDisabledVectorType<'a> { } #[derive(Diagnostic)] -#[diag(monomorphize_abi_error_unsupported_unsized_parameter)] -#[help] +#[diag( + "this function {$is_call -> + [true] call + *[false] definition + } uses unsized type `{$ty}` which is not supported with the chosen ABI" +)] +#[help("only rustic ABIs support unsized parameters")] pub(crate) struct AbiErrorUnsupportedUnsizedParameter<'a> { #[primary_span] - #[label] + #[label( + "function {$is_call -> + [true] called + *[false] defined + } here" + )] pub span: Span, pub ty: Ty<'a>, /// Whether this is a problem at a call site or at a declaration. @@ -95,10 +127,20 @@ pub(crate) struct AbiErrorUnsupportedUnsizedParameter<'a> { } #[derive(Diagnostic)] -#[diag(monomorphize_abi_error_unsupported_vector_type)] +#[diag( + "this function {$is_call -> + [true] call + *[false] definition + } uses SIMD vector type `{$ty}` which is not currently supported with the chosen ABI" +)] pub(crate) struct AbiErrorUnsupportedVectorType<'a> { #[primary_span] - #[label] + #[label( + "function {$is_call -> + [true] called + *[false] defined + } here" + )] pub span: Span, pub ty: Ty<'a>, /// Whether this is a problem at a call site or at a declaration. @@ -106,11 +148,24 @@ pub(crate) struct AbiErrorUnsupportedVectorType<'a> { } #[derive(Diagnostic)] -#[diag(monomorphize_abi_required_target_feature)] -#[help] +#[diag("this function {$is_call -> + [true] call + *[false] definition +} uses ABI \"{$abi}\" which requires the `{$required_feature}` target feature, which is not enabled{$is_call -> + [true] {\" \"}in the caller + *[false] {\"\"} +}")] +#[help( + "consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable=\"{$required_feature}\")]`)" +)] pub(crate) struct AbiRequiredTargetFeature<'a> { #[primary_span] - #[label] + #[label( + "function {$is_call -> +[true] called +*[false] defined +} here" + )] pub span: Span, pub required_feature: &'a str, pub abi: &'a str, @@ -119,12 +174,12 @@ pub(crate) struct AbiRequiredTargetFeature<'a> { } #[derive(Diagnostic)] -#[diag(monomorphize_static_initializer_cyclic)] -#[note] +#[diag("static initializer forms a cycle involving `{$head}`")] +#[note("cyclic static initializers are not supported for target `{$target}`")] pub(crate) struct StaticInitializerCyclic<'a> { #[primary_span] pub span: Span, - #[label] + #[label("part of this cycle")] pub labels: Vec, pub head: &'a str, pub target: &'a str, diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 30f6934bb937..51753563b67c 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -20,8 +20,6 @@ mod mono_checks; mod partitioning; mod util; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - fn custom_coerce_unsize_info<'tcx>( tcx: TyCtxtAt<'tcx>, source_ty: Ty<'tcx>, From ef7a7809c743baff98aaa7dcea49e1fafdde190b Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 30 Jan 2026 17:50:52 +0100 Subject: [PATCH 492/978] add test for simd from array repeat codegen --- tests/codegen-llvm/simd/array-repeat.rs | 40 +++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 tests/codegen-llvm/simd/array-repeat.rs diff --git a/tests/codegen-llvm/simd/array-repeat.rs b/tests/codegen-llvm/simd/array-repeat.rs new file mode 100644 index 000000000000..691167f86662 --- /dev/null +++ b/tests/codegen-llvm/simd/array-repeat.rs @@ -0,0 +1,40 @@ +//@ add-minicore +//@ revisions: X86 AARCH64 RISCV S390X +//@ [X86] compile-flags: -Copt-level=3 --target=x86_64-unknown-linux-gnu +//@ [X86] needs-llvm-components: x86 +//@ [AARCH64] compile-flags: -Copt-level=3 --target=aarch64-unknown-linux-gnu +//@ [AARCH64] needs-llvm-components: aarch64 +//@ [RISCV] compile-flags: -Copt-level=3 --target riscv64gc-unknown-linux-gnu -Ctarget-feature=+v +//@ [RISCV] needs-llvm-components: riscv +//@ [S390X] compile-flags: -Copt-level=3 --target s390x-unknown-linux-gnu -Ctarget-feature=+vector +//@ [S390X] needs-llvm-components: systemz +#![crate_type = "lib"] +#![feature(repr_simd)] +#![feature(no_core)] +#![no_std] +#![no_core] +extern crate minicore; +use minicore::*; + +#[repr(simd)] +pub struct Simd(pub [T; N]); + +pub type u8x16 = Simd; + +// Regression test for https://github.com/rust-lang/rust/issues/97804. + +#[unsafe(no_mangle)] +fn foo(v: u16, p: &mut [u8; 16]) { + // An array repeat transmuted into a SIMD type should emit a canonical LLVM splat sequence: + // + // CHECK-LABEL: foo + // CHECK: start + // CHECK-NEXT: %0 = insertelement <8 x i16> poison, i16 %v, i64 0 + // CHECK-NEXT: %1 = shufflevector <8 x i16> %0, <8 x i16> poison, <8 x i32> zeroinitializer + // CHECK-NEXT: store <8 x i16> %1, ptr %p, align 1 + // CHECK-NEXT: ret void + unsafe { + let v: u8x16 = mem::transmute([v; 8]); + *p = mem::transmute(v); + } +} From 4cacfc00bcb875c04318b516139d0d8cf559ff7c Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 3 Feb 2026 15:08:00 +0100 Subject: [PATCH 493/978] Convert to inline diagnostics in `rustc_incremental` --- Cargo.lock | 2 - compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_incremental/Cargo.toml | 1 - compiler/rustc_incremental/messages.ftl | 102 ---------------------- compiler/rustc_incremental/src/errors.rs | 106 +++++++++++++---------- compiler/rustc_incremental/src/lib.rs | 2 - 7 files changed, 62 insertions(+), 153 deletions(-) delete mode 100644 compiler/rustc_incremental/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 2be69cf0b23b..2bcf7d52310e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3789,7 +3789,6 @@ dependencies = [ "rustc_hir_analysis", "rustc_hir_pretty", "rustc_hir_typeck", - "rustc_incremental", "rustc_index", "rustc_interface", "rustc_lexer", @@ -4048,7 +4047,6 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_fs_util", "rustc_graphviz", "rustc_hashes", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index bdc577622b24..f888c54cefcd 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -23,7 +23,6 @@ rustc_feature = { path = "../rustc_feature" } rustc_hir_analysis = { path = "../rustc_hir_analysis" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_hir_typeck = { path = "../rustc_hir_typeck" } -rustc_incremental = { path = "../rustc_incremental" } rustc_index = { path = "../rustc_index" } rustc_interface = { path = "../rustc_interface" } rustc_lexer = { path = "../rustc_lexer" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index cdc9959605c1..cdf636f97d45 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -124,7 +124,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_expand::DEFAULT_LOCALE_RESOURCE, rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE, rustc_hir_typeck::DEFAULT_LOCALE_RESOURCE, - rustc_incremental::DEFAULT_LOCALE_RESOURCE, rustc_interface::DEFAULT_LOCALE_RESOURCE, rustc_lint::DEFAULT_LOCALE_RESOURCE, rustc_metadata::DEFAULT_LOCALE_RESOURCE, diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml index db0a58418875..ae96cc62e54a 100644 --- a/compiler/rustc_incremental/Cargo.toml +++ b/compiler/rustc_incremental/Cargo.toml @@ -9,7 +9,6 @@ rand = "0.9.0" rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_graphviz = { path = "../rustc_graphviz" } rustc_hashes = { path = "../rustc_hashes" } diff --git a/compiler/rustc_incremental/messages.ftl b/compiler/rustc_incremental/messages.ftl deleted file mode 100644 index bbc1fab05dfe..000000000000 --- a/compiler/rustc_incremental/messages.ftl +++ /dev/null @@ -1,102 +0,0 @@ -incremental_assert_loaded = - we asserted that an existing incremental cache directory should be successfully loaded, but it was not - -incremental_assert_not_loaded = - we asserted that the incremental cache should not be loaded, but it was loaded - -incremental_assertion_auto = - `except` specified DepNodes that can not be affected for "{$name}": "{$e}" - -incremental_associated_value_expected = expected an associated value - -incremental_associated_value_expected_for = associated value expected for `{$ident}` - -incremental_canonicalize_path = incremental compilation: error canonicalizing path `{$path}`: {$err} - -incremental_cargo_help_1 = - incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental) -incremental_cargo_help_2 = - the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir) - -incremental_copy_workproduct_to_cache = - error copying object file `{$from}` to incremental directory as `{$to}`: {$err} - -incremental_corrupt_file = corrupt incremental compilation artifact found at `{$path}`. This file will automatically be ignored and deleted. If you see this message repeatedly or can provoke it without manually manipulating the compiler's artifacts, please file an issue. The incremental compilation system relies on hardlinks and filesystem locks behaving correctly, and may not deal well with OS crashes, so whatever information you can provide about your filesystem or other state may be very relevant. - -incremental_create_dep_graph = failed to create dependency graph at `{$path}`: {$err} - -incremental_create_incr_comp_dir = - could not create incremental compilation {$tag} directory `{$path}`: {$err} - -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_delete_full = error deleting incremental compilation session directory `{$path}`: {$err} - -incremental_delete_incompatible = - failed to delete invalidated or incompatible incremental compilation session directory contents `{$path}`: {$err} - -incremental_delete_lock = - error deleting lock file for incremental compilation session directory `{$path}`: {$err} - -incremental_delete_old = unable to delete old {$name} at `{$path}`: {$err} - -incremental_delete_partial = failed to delete partly initialized session dir `{$path}`: {$err} - -incremental_delete_workproduct = file-system error deleting outdated file `{$path}`: {$err} - -incremental_finalize = error finalizing incremental compilation session directory `{$path}`: {$err} - -incremental_finalized_gc_failed = - failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err} - -incremental_hard_link_failed = - hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}` - -incremental_invalid_gc_failed = - failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err} - -incremental_load_dep_graph = could not load dep-graph from `{$path}`: {$err} - -incremental_lock_unsupported = - the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation - -incremental_missing_depnode = missing `DepNode` variant - -incremental_missing_if_this_changed = no `#[rustc_if_this_changed]` annotation detected - -incremental_move_dep_graph = failed to move dependency graph from `{$from}` to `{$to}`: {$err} - -incremental_no_cfg = no cfg attribute - -incremental_no_path = no path from `{$source}` to `{$target}` - -incremental_not_clean = `{$dep_node_str}` should be clean but is not - -incremental_not_dirty = `{$dep_node_str}` should be dirty but is not - -incremental_not_loaded = `{$dep_node_str}` should have been loaded from disk but it was not - -incremental_ok = OK - -incremental_repeated_depnode_label = dep-node label `{$label}` is repeated - -incremental_session_gc_failed = - failed to garbage collect incremental compilation session directory `{$path}`: {$err} - -incremental_unchecked_clean = found unchecked `#[rustc_clean]` attribute - -incremental_undefined_clean_dirty_assertions = - clean/dirty auto-assertions not yet defined for {$kind} - -incremental_undefined_clean_dirty_assertions_item = - clean/dirty auto-assertions not yet defined for Node::Item.node={$kind} - -incremental_unknown_rustc_clean_argument = unknown `rustc_clean` argument - -incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name} - -incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized - -incremental_write_new = failed to write {$name} to `{$path}`: {$err} diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs index dbc72d085be9..65109fdec03a 100644 --- a/compiler/rustc_incremental/src/errors.rs +++ b/compiler/rustc_incremental/src/errors.rs @@ -4,7 +4,7 @@ use rustc_macros::Diagnostic; use rustc_span::{Ident, Span, Symbol}; #[derive(Diagnostic)] -#[diag(incremental_unrecognized_depnode)] +#[diag("unrecognized `DepNode` variant: {$name}")] pub(crate) struct UnrecognizedDepNode { #[primary_span] pub span: Span, @@ -12,28 +12,28 @@ pub(crate) struct UnrecognizedDepNode { } #[derive(Diagnostic)] -#[diag(incremental_missing_depnode)] +#[diag("missing `DepNode` variant")] pub(crate) struct MissingDepNode { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(incremental_missing_if_this_changed)] +#[diag("no `#[rustc_if_this_changed]` annotation detected")] pub(crate) struct MissingIfThisChanged { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(incremental_ok)] +#[diag("OK")] pub(crate) struct Ok { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(incremental_no_path)] +#[diag("no path from `{$source}` to `{$target}`")] pub(crate) struct NoPath { #[primary_span] pub span: Span, @@ -42,7 +42,7 @@ pub(crate) struct NoPath { } #[derive(Diagnostic)] -#[diag(incremental_assertion_auto)] +#[diag("`except` specified DepNodes that can not be affected for \"{$name}\": \"{$e}\"")] pub(crate) struct AssertionAuto<'a> { #[primary_span] pub span: Span, @@ -51,7 +51,7 @@ pub(crate) struct AssertionAuto<'a> { } #[derive(Diagnostic)] -#[diag(incremental_undefined_clean_dirty_assertions_item)] +#[diag("clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}")] pub(crate) struct UndefinedCleanDirtyItem { #[primary_span] pub span: Span, @@ -59,7 +59,7 @@ pub(crate) struct UndefinedCleanDirtyItem { } #[derive(Diagnostic)] -#[diag(incremental_undefined_clean_dirty_assertions)] +#[diag("clean/dirty auto-assertions not yet defined for {$kind}")] pub(crate) struct UndefinedCleanDirty { #[primary_span] pub span: Span, @@ -67,7 +67,7 @@ pub(crate) struct UndefinedCleanDirty { } #[derive(Diagnostic)] -#[diag(incremental_repeated_depnode_label)] +#[diag("dep-node label `{$label}` is repeated")] pub(crate) struct RepeatedDepNodeLabel<'a> { #[primary_span] pub span: Span, @@ -75,7 +75,7 @@ pub(crate) struct RepeatedDepNodeLabel<'a> { } #[derive(Diagnostic)] -#[diag(incremental_unrecognized_depnode_label)] +#[diag("dep-node label `{$label}` not recognized")] pub(crate) struct UnrecognizedDepNodeLabel<'a> { #[primary_span] pub span: Span, @@ -83,7 +83,7 @@ pub(crate) struct UnrecognizedDepNodeLabel<'a> { } #[derive(Diagnostic)] -#[diag(incremental_not_dirty)] +#[diag("`{$dep_node_str}` should be dirty but is not")] pub(crate) struct NotDirty<'a> { #[primary_span] pub span: Span, @@ -91,7 +91,7 @@ pub(crate) struct NotDirty<'a> { } #[derive(Diagnostic)] -#[diag(incremental_not_clean)] +#[diag("`{$dep_node_str}` should be clean but is not")] pub(crate) struct NotClean<'a> { #[primary_span] pub span: Span, @@ -99,7 +99,7 @@ pub(crate) struct NotClean<'a> { } #[derive(Diagnostic)] -#[diag(incremental_not_loaded)] +#[diag("`{$dep_node_str}` should have been loaded from disk but it was not")] pub(crate) struct NotLoaded<'a> { #[primary_span] pub span: Span, @@ -107,21 +107,21 @@ pub(crate) struct NotLoaded<'a> { } #[derive(Diagnostic)] -#[diag(incremental_unknown_rustc_clean_argument)] +#[diag("unknown `rustc_clean` argument")] pub(crate) struct UnknownRustcCleanArgument { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(incremental_no_cfg)] +#[diag("no cfg attribute")] pub(crate) struct NoCfg { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(incremental_associated_value_expected_for)] +#[diag("associated value expected for `{$ident}`")] pub(crate) struct AssociatedValueExpectedFor { #[primary_span] pub span: Span, @@ -129,21 +129,21 @@ pub(crate) struct AssociatedValueExpectedFor { } #[derive(Diagnostic)] -#[diag(incremental_associated_value_expected)] +#[diag("expected an associated value")] pub(crate) struct AssociatedValueExpected { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(incremental_unchecked_clean)] +#[diag("found unchecked `#[rustc_clean]` attribute")] pub(crate) struct UncheckedClean { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(incremental_delete_old)] +#[diag("unable to delete old {$name} at `{$path}`: {$err}")] pub(crate) struct DeleteOld<'a> { pub name: &'a str, pub path: PathBuf, @@ -151,7 +151,7 @@ pub(crate) struct DeleteOld<'a> { } #[derive(Diagnostic)] -#[diag(incremental_create_new)] +#[diag("failed to create {$name} at `{$path}`: {$err}")] pub(crate) struct CreateNew<'a> { pub name: &'a str, pub path: PathBuf, @@ -159,7 +159,7 @@ pub(crate) struct CreateNew<'a> { } #[derive(Diagnostic)] -#[diag(incremental_write_new)] +#[diag("failed to write {$name} to `{$path}`: {$err}")] pub(crate) struct WriteNew<'a> { pub name: &'a str, pub path: PathBuf, @@ -167,14 +167,14 @@ pub(crate) struct WriteNew<'a> { } #[derive(Diagnostic)] -#[diag(incremental_canonicalize_path)] +#[diag("incremental compilation: error canonicalizing path `{$path}`: {$err}")] pub(crate) struct CanonicalizePath { pub path: PathBuf, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_create_incr_comp_dir)] +#[diag("could not create incremental compilation {$tag} directory `{$path}`: {$err}")] pub(crate) struct CreateIncrCompDir<'a> { pub tag: &'a str, pub path: &'a Path, @@ -182,96 +182,112 @@ pub(crate) struct CreateIncrCompDir<'a> { } #[derive(Diagnostic)] -#[diag(incremental_create_lock)] +#[diag("incremental compilation: could not create session directory lock file: {$lock_err}")] pub(crate) struct CreateLock<'a> { pub lock_err: std::io::Error, pub session_dir: &'a Path, - #[note(incremental_lock_unsupported)] + #[note( + "the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation" + )] pub is_unsupported_lock: bool, - #[help(incremental_cargo_help_1)] - #[help(incremental_cargo_help_2)] + #[help( + "incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)" + )] + #[help( + "the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)" + )] pub is_cargo: bool, } #[derive(Diagnostic)] -#[diag(incremental_delete_lock)] +#[diag("error deleting lock file for incremental compilation session directory `{$path}`: {$err}")] pub(crate) struct DeleteLock<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_hard_link_failed)] +#[diag( + "hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`" +)] pub(crate) struct HardLinkFailed<'a> { pub path: &'a Path, } #[derive(Diagnostic)] -#[diag(incremental_delete_partial)] +#[diag("failed to delete partly initialized session dir `{$path}`: {$err}")] pub(crate) struct DeletePartial<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_delete_full)] +#[diag("error deleting incremental compilation session directory `{$path}`: {$err}")] pub(crate) struct DeleteFull<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_finalize)] +#[diag("error finalizing incremental compilation session directory `{$path}`: {$err}")] pub(crate) struct Finalize<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_invalid_gc_failed)] +#[diag( + "failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err}" +)] pub(crate) struct InvalidGcFailed<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_finalized_gc_failed)] +#[diag( + "failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err}" +)] pub(crate) struct FinalizedGcFailed<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_session_gc_failed)] +#[diag("failed to garbage collect incremental compilation session directory `{$path}`: {$err}")] pub(crate) struct SessionGcFailed<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_assert_not_loaded)] +#[diag("we asserted that the incremental cache should not be loaded, but it was loaded")] pub(crate) struct AssertNotLoaded; #[derive(Diagnostic)] -#[diag(incremental_assert_loaded)] +#[diag( + "we asserted that an existing incremental cache directory should be successfully loaded, but it was not" +)] pub(crate) struct AssertLoaded; #[derive(Diagnostic)] -#[diag(incremental_delete_incompatible)] +#[diag( + "failed to delete invalidated or incompatible incremental compilation session directory contents `{$path}`: {$err}" +)] pub(crate) struct DeleteIncompatible { pub path: PathBuf, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_load_dep_graph)] +#[diag("could not load dep-graph from `{$path}`: {$err}")] pub(crate) struct LoadDepGraph { pub path: PathBuf, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_move_dep_graph)] +#[diag("failed to move dependency graph from `{$from}` to `{$to}`: {$err}")] pub(crate) struct MoveDepGraph<'a> { pub from: &'a Path, pub to: &'a Path, @@ -279,14 +295,14 @@ pub(crate) struct MoveDepGraph<'a> { } #[derive(Diagnostic)] -#[diag(incremental_create_dep_graph)] +#[diag("failed to create dependency graph at `{$path}`: {$err}")] pub(crate) struct CreateDepGraph<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_copy_workproduct_to_cache)] +#[diag("error copying object file `{$from}` to incremental directory as `{$to}`: {$err}")] pub(crate) struct CopyWorkProductToCache<'a> { pub from: &'a Path, pub to: &'a Path, @@ -294,14 +310,16 @@ pub(crate) struct CopyWorkProductToCache<'a> { } #[derive(Diagnostic)] -#[diag(incremental_delete_workproduct)] +#[diag("file-system error deleting outdated file `{$path}`: {$err}")] pub(crate) struct DeleteWorkProduct<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(incremental_corrupt_file)] +#[diag( + "corrupt incremental compilation artifact found at `{$path}`. This file will automatically be ignored and deleted. If you see this message repeatedly or can provoke it without manually manipulating the compiler's artifacts, please file an issue. The incremental compilation system relies on hardlinks and filesystem locks behaving correctly, and may not deal well with OS crashes, so whatever information you can provide about your filesystem or other state may be very relevant." +)] pub(crate) struct CorruptFile<'a> { pub path: &'a Path, } diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index e750810c0119..591ade379e6a 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -21,5 +21,3 @@ pub fn provide(providers: &mut Providers) { providers.hooks.save_dep_graph = |tcx| tcx.sess.time("serialize_dep_graph", || persist::save_dep_graph(tcx)); } - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } From 4fdd085e2879417094636f252c476f5d1f7737be Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 3 Feb 2026 23:01:11 +0100 Subject: [PATCH 494/978] Convert to inline diagnostics in `rustc_mir_dataflow` --- Cargo.lock | 2 -- compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_mir_dataflow/Cargo.toml | 1 - compiler/rustc_mir_dataflow/messages.ftl | 17 ----------------- compiler/rustc_mir_dataflow/src/errors.rs | 12 ++++++------ compiler/rustc_mir_dataflow/src/lib.rs | 2 -- 7 files changed, 6 insertions(+), 30 deletions(-) delete mode 100644 compiler/rustc_mir_dataflow/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 2be69cf0b23b..659118e47ff5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3799,7 +3799,6 @@ dependencies = [ "rustc_metadata", "rustc_middle", "rustc_mir_build", - "rustc_mir_dataflow", "rustc_mir_transform", "rustc_monomorphize", "rustc_parse", @@ -4333,7 +4332,6 @@ dependencies = [ "rustc_abi", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_graphviz", "rustc_hir", "rustc_index", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index bdc577622b24..7f01b0e5bd96 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -33,7 +33,6 @@ rustc_macros = { path = "../rustc_macros" } rustc_metadata = { path = "../rustc_metadata" } rustc_middle = { path = "../rustc_middle" } rustc_mir_build = { path = "../rustc_mir_build" } -rustc_mir_dataflow = { path = "../rustc_mir_dataflow" } rustc_mir_transform = { path = "../rustc_mir_transform" } rustc_monomorphize = { path = "../rustc_monomorphize" } rustc_parse = { path = "../rustc_parse" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index cdc9959605c1..55f78f0e01ab 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -130,7 +130,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_metadata::DEFAULT_LOCALE_RESOURCE, rustc_middle::DEFAULT_LOCALE_RESOURCE, rustc_mir_build::DEFAULT_LOCALE_RESOURCE, - rustc_mir_dataflow::DEFAULT_LOCALE_RESOURCE, rustc_mir_transform::DEFAULT_LOCALE_RESOURCE, rustc_monomorphize::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE, diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml index e41d5da71397..156caa7030a0 100644 --- a/compiler/rustc_mir_dataflow/Cargo.toml +++ b/compiler/rustc_mir_dataflow/Cargo.toml @@ -10,7 +10,6 @@ regex = "1" rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_graphviz = { path = "../rustc_graphviz" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } diff --git a/compiler/rustc_mir_dataflow/messages.ftl b/compiler/rustc_mir_dataflow/messages.ftl deleted file mode 100644 index 3783c647b03e..000000000000 --- a/compiler/rustc_mir_dataflow/messages.ftl +++ /dev/null @@ -1,17 +0,0 @@ -mir_dataflow_peek_argument_not_a_local = - rustc_peek: argument was not a local - -mir_dataflow_peek_argument_untracked = - rustc_peek: argument untracked - -mir_dataflow_peek_bit_not_set = - rustc_peek: bit not set - -mir_dataflow_peek_must_be_not_temporary = - dataflow::sanity_check cannot feed a non-temp to rustc_peek - -mir_dataflow_peek_must_be_place_or_ref_place = - rustc_peek: argument expression must be either `place` or `&place` - -mir_dataflow_stop_after_dataflow_ended_compilation = - stop_after_dataflow ended compilation diff --git a/compiler/rustc_mir_dataflow/src/errors.rs b/compiler/rustc_mir_dataflow/src/errors.rs index 9d8c34c8a1f3..051c0305cf2b 100644 --- a/compiler/rustc_mir_dataflow/src/errors.rs +++ b/compiler/rustc_mir_dataflow/src/errors.rs @@ -2,39 +2,39 @@ use rustc_macros::Diagnostic; use rustc_span::Span; #[derive(Diagnostic)] -#[diag(mir_dataflow_stop_after_dataflow_ended_compilation)] +#[diag("stop_after_dataflow ended compilation")] pub(crate) struct StopAfterDataFlowEndedCompilation; #[derive(Diagnostic)] -#[diag(mir_dataflow_peek_must_be_place_or_ref_place)] +#[diag("rustc_peek: argument expression must be either `place` or `&place`")] pub(crate) struct PeekMustBePlaceOrRefPlace { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_dataflow_peek_must_be_not_temporary)] +#[diag("dataflow::sanity_check cannot feed a non-temp to rustc_peek")] pub(crate) struct PeekMustBeNotTemporary { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_dataflow_peek_bit_not_set)] +#[diag("rustc_peek: bit not set")] pub(crate) struct PeekBitNotSet { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_dataflow_peek_argument_not_a_local)] +#[diag("rustc_peek: argument was not a local")] pub(crate) struct PeekArgumentNotALocal { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_dataflow_peek_argument_untracked)] +#[diag("rustc_peek: argument untracked")] pub(crate) struct PeekArgumentUntracked { #[primary_span] pub span: Span, diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 485925e7b50c..5f1cf1250152 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -34,8 +34,6 @@ pub mod rustc_peek; mod un_derefer; pub mod value_analysis; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub struct MoveDataTypingEnv<'tcx> { pub move_data: MoveData<'tcx>, pub typing_env: ty::TypingEnv<'tcx>, From 828bead9e33014793e32ba8d32eab270cc03a58d Mon Sep 17 00:00:00 2001 From: Jamie Hill-Daniel Date: Tue, 3 Feb 2026 14:16:06 +0000 Subject: [PATCH 495/978] Use glob imports for attribute parsers --- compiler/rustc_attr_parsing/src/context.rs | 118 ++++++--------------- 1 file changed, 35 insertions(+), 83 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 322e189e6d12..fa9f5b585926 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -16,90 +16,42 @@ use rustc_session::lint::{Lint, LintId}; use rustc_span::{ErrorGuaranteed, Span, Symbol}; use crate::AttributeParser; -use crate::attributes::allow_unstable::{ - AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser, -}; -use crate::attributes::body::CoroutineParser; -use crate::attributes::cfi_encoding::CfiEncodingParser; -use crate::attributes::codegen_attrs::{ - ColdParser, CoverageParser, EiiForeignItemParser, ExportNameParser, ForceTargetFeatureParser, - NakedParser, NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser, - PatchableFunctionEntryParser, RustcPassIndirectlyInNonRusticAbisParser, SanitizeParser, - TargetFeatureParser, ThreadLocalParser, TrackCallerParser, UsedParser, -}; -use crate::attributes::confusables::ConfusablesParser; -use crate::attributes::crate_level::{ - CrateNameParser, CrateTypeParser, MoveSizeLimitParser, NeedsPanicRuntimeParser, - NoBuiltinsParser, NoCoreParser, NoMainParser, NoStdParser, PanicRuntimeParser, - PatternComplexityLimitParser, ProfilerRuntimeParser, RecursionLimitParser, - RustcCoherenceIsCoreParser, RustcPreserveUbChecksParser, TypeLengthLimitParser, - WindowsSubsystemParser, -}; -use crate::attributes::debugger::DebuggerViualizerParser; -use crate::attributes::deprecation::DeprecationParser; -use crate::attributes::do_not_recommend::DoNotRecommendParser; -use crate::attributes::doc::DocParser; -use crate::attributes::dummy::DummyParser; -use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; -use crate::attributes::instruction_set::InstructionSetParser; -use crate::attributes::link_attrs::{ - CompilerBuiltinsParser, ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, - LinkOrdinalParser, LinkParser, LinkSectionParser, LinkageParser, NeedsAllocatorParser, - StdInternalSymbolParser, -}; -use crate::attributes::lint_helpers::{ - AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser, - RustcShouldNotBeCalledOnConstItems, -}; -use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser}; -use crate::attributes::macro_attrs::{ - AllowInternalUnsafeParser, CollapseDebugInfoParser, MacroEscapeParser, MacroExportParser, - MacroUseParser, -}; -use crate::attributes::must_not_suspend::MustNotSuspendParser; -use crate::attributes::must_use::MustUseParser; -use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser; -use crate::attributes::no_link::NoLinkParser; -use crate::attributes::non_exhaustive::NonExhaustiveParser; +// Glob imports to avoid big, bitrotty import lists +use crate::attributes::allow_unstable::*; +use crate::attributes::body::*; +use crate::attributes::cfi_encoding::*; +use crate::attributes::codegen_attrs::*; +use crate::attributes::confusables::*; +use crate::attributes::crate_level::*; +use crate::attributes::debugger::*; +use crate::attributes::deprecation::*; +use crate::attributes::do_not_recommend::*; +use crate::attributes::doc::*; +use crate::attributes::dummy::*; +use crate::attributes::inline::*; +use crate::attributes::instruction_set::*; +use crate::attributes::link_attrs::*; +use crate::attributes::lint_helpers::*; +use crate::attributes::loop_match::*; +use crate::attributes::macro_attrs::*; +use crate::attributes::must_not_suspend::*; +use crate::attributes::must_use::*; +use crate::attributes::no_implicit_prelude::*; +use crate::attributes::no_link::*; +use crate::attributes::non_exhaustive::*; use crate::attributes::path::PathParser as PathAttributeParser; -use crate::attributes::pin_v2::PinV2Parser; -use crate::attributes::proc_macro_attrs::{ - ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser, -}; -use crate::attributes::prototype::CustomMirParser; -use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser}; -use crate::attributes::rustc_allocator::{ - RustcAllocatorParser, RustcAllocatorZeroedParser, RustcAllocatorZeroedVariantParser, - RustcDeallocatorParser, RustcReallocatorParser, -}; -use crate::attributes::rustc_dump::{ - RustcDumpDefParentsParser, RustcDumpItemBoundsParser, RustcDumpPredicatesParser, - RustcDumpUserArgsParser, RustcDumpVtableParser, -}; -use crate::attributes::rustc_internal::{ - RustcHasIncoherentInherentImplsParser, RustcHiddenTypeOfOpaquesParser, RustcLayoutParser, - RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, - RustcLegacyConstGenericsParser, RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, - RustcLintQueryInstabilityParser, RustcLintUntrackedQueryInformationParser, RustcMainParser, - RustcMirParser, RustcMustImplementOneOfParser, RustcNeverReturnsNullPointerParser, - RustcNoImplicitAutorefsParser, RustcNonConstTraitMethodParser, RustcNounwindParser, - RustcObjectLifetimeDefaultParser, RustcOffloadKernelParser, RustcScalableVectorParser, - RustcSimdMonomorphizeLaneLimitParser, -}; -use crate::attributes::semantics::MayDangleParser; -use crate::attributes::stability::{ - BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser, -}; -use crate::attributes::test_attrs::{ - IgnoreParser, RustcVarianceOfOpaquesParser, RustcVarianceParser, ShouldPanicParser, -}; -use crate::attributes::traits::{ - AllowIncoherentImplParser, CoinductiveParser, DenyExplicitImplParser, - DynIncompatibleTraitParser, FundamentalParser, MarkerParser, ParenSugarParser, PointeeParser, - SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser, - UnsafeSpecializationMarkerParser, -}; -use crate::attributes::transparency::TransparencyParser; +use crate::attributes::pin_v2::*; +use crate::attributes::proc_macro_attrs::*; +use crate::attributes::prototype::*; +use crate::attributes::repr::*; +use crate::attributes::rustc_allocator::*; +use crate::attributes::rustc_dump::*; +use crate::attributes::rustc_internal::*; +use crate::attributes::semantics::*; +use crate::attributes::stability::*; +use crate::attributes::test_attrs::*; +use crate::attributes::traits::*; +use crate::attributes::transparency::*; use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs}; use crate::parser::{ArgParser, RefPathParser}; use crate::session_diagnostics::{ From cdd0ede64037938b5ef89da2b5ac3c77ea7c6375 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 3 Feb 2026 16:09:21 -0800 Subject: [PATCH 496/978] bootstrap: always propagate `CARGO_TARGET_{host}_LINKER` We were already setting `CARGO_TARGET_{target}_LINKER` when there is a setting in `bootstrap.toml`, and when the host and target are the same, this is also used for build scripts and proc-macros. However, the host value wasn't set when building for any other target, and Cargo would see that as a fingerprint change for those build artifacts, rebuilding them. If we always set the `CARGO_TARGET_{host}_LINKER`, then those build scripts will keep a consistent Cargo fingerprint, so they'll remain cached no matter how we're alternating targets. --- src/bootstrap/src/core/builder/cargo.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 7150b2b0d59f..488125863ee0 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -10,7 +10,7 @@ use crate::core::build_steps::tool::SourceType; use crate::core::config::SplitDebuginfo; use crate::core::config::flags::Color; use crate::utils::build_stamp; -use crate::utils::helpers::{self, LldThreads, check_cfg_arg, linker_args, linker_flags}; +use crate::utils::helpers::{self, LldThreads, check_cfg_arg, linker_flags}; use crate::{ BootstrapCommand, CLang, Compiler, Config, DryRun, EXTRA_CHECK_CFGS, GitRepo, Mode, RemapScheme, TargetSelection, command, prepare_behaviour_dump_dir, t, @@ -310,7 +310,15 @@ impl Cargo { } } - for arg in linker_args(builder, compiler.host, LldThreads::Yes) { + // We need to set host linker flags for compiling build scripts and proc-macros. + // This is done the same way as the target linker flags below, so cargo won't see + // any fingerprint difference between host==target versus cross-compiled targets + // when it comes to those host build artifacts. + if let Some(host_linker) = builder.linker(compiler.host) { + let host = crate::envify(&compiler.host.triple); + self.command.env(format!("CARGO_TARGET_{host}_LINKER"), host_linker); + } + for arg in linker_flags(builder, compiler.host, LldThreads::Yes) { self.hostflags.arg(&arg); } @@ -319,11 +327,11 @@ impl Cargo { self.command.env(format!("CARGO_TARGET_{target}_LINKER"), target_linker); } // We want to set -Clinker using Cargo, therefore we only call `linker_flags` and not - // `linker_args` here. + // `linker_args` here. Cargo will pass that to both rustc and rustdoc invocations. for flag in linker_flags(builder, target, LldThreads::Yes) { self.rustflags.arg(&flag); } - for arg in linker_args(builder, target, LldThreads::Yes) { + for arg in linker_flags(builder, target, LldThreads::Yes) { self.rustdocflags.arg(&arg); } From d9516977cdb8b03c21231af19f6bb7a12d821bbc Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 3 Feb 2026 20:37:23 +1100 Subject: [PATCH 497/978] Tidy up re-exports in `rustc_middle::dep_graph` --- compiler/rustc_middle/src/dep_graph/dep_node.rs | 6 ++---- compiler/rustc_middle/src/dep_graph/mod.rs | 9 +++++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index f5ed0570667c..834f6b16c29a 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -2,10 +2,8 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId}; use rustc_hir::definitions::DefPathHash; use rustc_hir::{HirId, ItemLocalId, OwnerId}; -pub use rustc_query_system::dep_graph::DepNode; -use rustc_query_system::dep_graph::FingerprintStyle; -pub use rustc_query_system::dep_graph::dep_node::DepKind; -pub(crate) use rustc_query_system::dep_graph::{DepContext, DepNodeParams}; +use rustc_query_system::dep_graph::dep_node::DepKind; +use rustc_query_system::dep_graph::{DepContext, DepNode, DepNodeParams, FingerprintStyle}; use rustc_span::Symbol; use crate::mir::mono::MonoItem; diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index f28ba10d52e2..08b0fada0c06 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -8,14 +8,15 @@ use crate::ty::{self, TyCtxt}; #[macro_use] mod dep_node; -pub use dep_node::{DepKind, DepNode, DepNodeExt, dep_kind_from_label, dep_kinds, label_strs}; -pub(crate) use dep_node::{make_compile_codegen_unit, make_compile_mono_item, make_metadata}; pub use rustc_query_system::dep_graph::debug::{DepNodeFilter, EdgeFilter}; pub use rustc_query_system::dep_graph::{ - DepContext, DepGraphQuery, DepNodeIndex, Deps, SerializedDepGraph, SerializedDepNodeIndex, - TaskDepsRef, WorkProduct, WorkProductId, WorkProductMap, hash_result, + DepContext, DepGraphQuery, DepKind, DepNode, DepNodeIndex, Deps, SerializedDepGraph, + SerializedDepNodeIndex, TaskDepsRef, WorkProduct, WorkProductId, WorkProductMap, hash_result, }; +pub use self::dep_node::{DepNodeExt, dep_kind_from_label, dep_kinds, label_strs}; +pub(crate) use self::dep_node::{make_compile_codegen_unit, make_compile_mono_item, make_metadata}; + pub type DepGraph = rustc_query_system::dep_graph::DepGraph; pub type DepKindVTable<'tcx> = rustc_query_system::dep_graph::DepKindVTable>; From 7b01330133c134a29dca3f9abd42e6ba92df4561 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 3 Feb 2026 20:39:03 +1100 Subject: [PATCH 498/978] Move trait impls into a `dep_node_key` submodule --- .../rustc_middle/src/dep_graph/dep_node.rs | 226 +---------------- .../src/dep_graph/dep_node_key.rs | 228 ++++++++++++++++++ compiler/rustc_middle/src/dep_graph/mod.rs | 1 + 3 files changed, 231 insertions(+), 224 deletions(-) create mode 100644 compiler/rustc_middle/src/dep_graph/dep_node_key.rs diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 834f6b16c29a..5f90d1b67d9d 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -1,9 +1,7 @@ -use rustc_data_structures::fingerprint::Fingerprint; -use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId}; +use rustc_hir::def_id::DefId; use rustc_hir::definitions::DefPathHash; -use rustc_hir::{HirId, ItemLocalId, OwnerId}; use rustc_query_system::dep_graph::dep_node::DepKind; -use rustc_query_system::dep_graph::{DepContext, DepNode, DepNodeParams, FingerprintStyle}; +use rustc_query_system::dep_graph::{DepContext, DepNode, FingerprintStyle}; use rustc_span::Symbol; use crate::mir::mono::MonoItem; @@ -174,223 +172,3 @@ pub fn dep_kind_from_label(label: &str) -> DepKind { dep_kind_from_label_string(label) .unwrap_or_else(|_| panic!("Query label {label} does not exist")) } - -impl<'tcx> DepNodeParams> for () { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::Unit - } - - #[inline(always)] - fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint { - Fingerprint::ZERO - } - - #[inline(always)] - fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option { - Some(()) - } -} - -impl<'tcx> DepNodeParams> for DefId { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::DefPathHash - } - - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - tcx.def_path_hash(*self).0 - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - tcx.def_path_str(*self) - } - - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - dep_node.extract_def_id(tcx) - } -} - -impl<'tcx> DepNodeParams> for LocalDefId { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::DefPathHash - } - - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - self.to_def_id().to_fingerprint(tcx) - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - self.to_def_id().to_debug_str(tcx) - } - - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - dep_node.extract_def_id(tcx).map(|id| id.expect_local()) - } -} - -impl<'tcx> DepNodeParams> for OwnerId { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::DefPathHash - } - - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - self.to_def_id().to_fingerprint(tcx) - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - self.to_def_id().to_debug_str(tcx) - } - - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - dep_node.extract_def_id(tcx).map(|id| OwnerId { def_id: id.expect_local() }) - } -} - -impl<'tcx> DepNodeParams> for CrateNum { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::DefPathHash - } - - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - let def_id = self.as_def_id(); - def_id.to_fingerprint(tcx) - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - tcx.crate_name(*self).to_string() - } - - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - dep_node.extract_def_id(tcx).map(|id| id.krate) - } -} - -impl<'tcx> DepNodeParams> for (DefId, DefId) { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::Opaque - } - - // We actually would not need to specialize the implementation of this - // method but it's faster to combine the hashes than to instantiate a full - // hashing context and stable-hashing state. - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - let (def_id_0, def_id_1) = *self; - - let def_path_hash_0 = tcx.def_path_hash(def_id_0); - let def_path_hash_1 = tcx.def_path_hash(def_id_1); - - def_path_hash_0.0.combine(def_path_hash_1.0) - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - let (def_id_0, def_id_1) = *self; - - format!("({}, {})", tcx.def_path_debug_str(def_id_0), tcx.def_path_debug_str(def_id_1)) - } -} - -impl<'tcx> DepNodeParams> for HirId { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::HirId - } - - // We actually would not need to specialize the implementation of this - // method but it's faster to combine the hashes than to instantiate a full - // hashing context and stable-hashing state. - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - let HirId { owner, local_id } = *self; - let def_path_hash = tcx.def_path_hash(owner.to_def_id()); - Fingerprint::new( - // `owner` is local, so is completely defined by the local hash - def_path_hash.local_hash(), - local_id.as_u32() as u64, - ) - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - let HirId { owner, local_id } = *self; - format!("{}.{}", tcx.def_path_str(owner), local_id.as_u32()) - } - - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - if tcx.fingerprint_style(dep_node.kind) == FingerprintStyle::HirId { - let (local_hash, local_id) = Fingerprint::from(dep_node.hash).split(); - let def_path_hash = DefPathHash::new(tcx.stable_crate_id(LOCAL_CRATE), local_hash); - let def_id = tcx.def_path_hash_to_def_id(def_path_hash)?.expect_local(); - let local_id = local_id - .as_u64() - .try_into() - .unwrap_or_else(|_| panic!("local id should be u32, found {local_id:?}")); - Some(HirId { owner: OwnerId { def_id }, local_id: ItemLocalId::from_u32(local_id) }) - } else { - None - } - } -} - -impl<'tcx> DepNodeParams> for ModDefId { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::DefPathHash - } - - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - self.to_def_id().to_fingerprint(tcx) - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - self.to_def_id().to_debug_str(tcx) - } - - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - DefId::recover(tcx, dep_node).map(ModDefId::new_unchecked) - } -} - -impl<'tcx> DepNodeParams> for LocalModDefId { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::DefPathHash - } - - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - self.to_def_id().to_fingerprint(tcx) - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - self.to_def_id().to_debug_str(tcx) - } - - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - LocalDefId::recover(tcx, dep_node).map(LocalModDefId::new_unchecked) - } -} diff --git a/compiler/rustc_middle/src/dep_graph/dep_node_key.rs b/compiler/rustc_middle/src/dep_graph/dep_node_key.rs new file mode 100644 index 000000000000..7574fc7e4a7b --- /dev/null +++ b/compiler/rustc_middle/src/dep_graph/dep_node_key.rs @@ -0,0 +1,228 @@ +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId}; +use rustc_hir::definitions::DefPathHash; +use rustc_hir::{HirId, ItemLocalId, OwnerId}; +use rustc_query_system::dep_graph::{DepContext, DepNode, DepNodeParams, FingerprintStyle}; + +use crate::dep_graph::DepNodeExt; +use crate::ty::TyCtxt; + +impl<'tcx> DepNodeParams> for () { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::Unit + } + + #[inline(always)] + fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint { + Fingerprint::ZERO + } + + #[inline(always)] + fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option { + Some(()) + } +} + +impl<'tcx> DepNodeParams> for DefId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + tcx.def_path_hash(*self).0 + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + tcx.def_path_str(*self) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + dep_node.extract_def_id(tcx) + } +} + +impl<'tcx> DepNodeParams> for LocalDefId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + dep_node.extract_def_id(tcx).map(|id| id.expect_local()) + } +} + +impl<'tcx> DepNodeParams> for OwnerId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + dep_node.extract_def_id(tcx).map(|id| OwnerId { def_id: id.expect_local() }) + } +} + +impl<'tcx> DepNodeParams> for CrateNum { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + let def_id = self.as_def_id(); + def_id.to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + tcx.crate_name(*self).to_string() + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + dep_node.extract_def_id(tcx).map(|id| id.krate) + } +} + +impl<'tcx> DepNodeParams> for (DefId, DefId) { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::Opaque + } + + // We actually would not need to specialize the implementation of this + // method but it's faster to combine the hashes than to instantiate a full + // hashing context and stable-hashing state. + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + let (def_id_0, def_id_1) = *self; + + let def_path_hash_0 = tcx.def_path_hash(def_id_0); + let def_path_hash_1 = tcx.def_path_hash(def_id_1); + + def_path_hash_0.0.combine(def_path_hash_1.0) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + let (def_id_0, def_id_1) = *self; + + format!("({}, {})", tcx.def_path_debug_str(def_id_0), tcx.def_path_debug_str(def_id_1)) + } +} + +impl<'tcx> DepNodeParams> for HirId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::HirId + } + + // We actually would not need to specialize the implementation of this + // method but it's faster to combine the hashes than to instantiate a full + // hashing context and stable-hashing state. + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + let HirId { owner, local_id } = *self; + let def_path_hash = tcx.def_path_hash(owner.to_def_id()); + Fingerprint::new( + // `owner` is local, so is completely defined by the local hash + def_path_hash.local_hash(), + local_id.as_u32() as u64, + ) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + let HirId { owner, local_id } = *self; + format!("{}.{}", tcx.def_path_str(owner), local_id.as_u32()) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + if tcx.fingerprint_style(dep_node.kind) == FingerprintStyle::HirId { + let (local_hash, local_id) = Fingerprint::from(dep_node.hash).split(); + let def_path_hash = DefPathHash::new(tcx.stable_crate_id(LOCAL_CRATE), local_hash); + let def_id = tcx.def_path_hash_to_def_id(def_path_hash)?.expect_local(); + let local_id = local_id + .as_u64() + .try_into() + .unwrap_or_else(|_| panic!("local id should be u32, found {local_id:?}")); + Some(HirId { owner: OwnerId { def_id }, local_id: ItemLocalId::from_u32(local_id) }) + } else { + None + } + } +} + +impl<'tcx> DepNodeParams> for ModDefId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + DefId::recover(tcx, dep_node).map(ModDefId::new_unchecked) + } +} + +impl<'tcx> DepNodeParams> for LocalModDefId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + LocalDefId::recover(tcx, dep_node).map(LocalModDefId::new_unchecked) + } +} diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 08b0fada0c06..1056fa9b4462 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -7,6 +7,7 @@ use crate::ty::{self, TyCtxt}; #[macro_use] mod dep_node; +mod dep_node_key; pub use rustc_query_system::dep_graph::debug::{DepNodeFilter, EdgeFilter}; pub use rustc_query_system::dep_graph::{ From 4429f0916cef234bf83327c020becd3c66e5834b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 3 Feb 2026 20:41:37 +1100 Subject: [PATCH 499/978] Rename trait `DepNodeParams` to `DepNodeKey` --- .../src/dep_graph/dep_node_key.rs | 20 +++++++++---------- compiler/rustc_middle/src/query/inner.rs | 4 ++-- compiler/rustc_query_impl/src/plumbing.rs | 2 +- .../src/dep_graph/dep_node.rs | 19 ++++++++++-------- .../rustc_query_system/src/dep_graph/mod.rs | 2 +- .../src/query/dispatcher.rs | 4 ++-- .../rustc_query_system/src/query/plumbing.rs | 2 +- compiler/rustc_span/src/def_id.rs | 2 +- 8 files changed, 29 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node_key.rs b/compiler/rustc_middle/src/dep_graph/dep_node_key.rs index 7574fc7e4a7b..e2fcd82c896a 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node_key.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node_key.rs @@ -2,12 +2,12 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId}; use rustc_hir::definitions::DefPathHash; use rustc_hir::{HirId, ItemLocalId, OwnerId}; -use rustc_query_system::dep_graph::{DepContext, DepNode, DepNodeParams, FingerprintStyle}; +use rustc_query_system::dep_graph::{DepContext, DepNode, DepNodeKey, FingerprintStyle}; use crate::dep_graph::DepNodeExt; use crate::ty::TyCtxt; -impl<'tcx> DepNodeParams> for () { +impl<'tcx> DepNodeKey> for () { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::Unit @@ -24,7 +24,7 @@ impl<'tcx> DepNodeParams> for () { } } -impl<'tcx> DepNodeParams> for DefId { +impl<'tcx> DepNodeKey> for DefId { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::DefPathHash @@ -46,7 +46,7 @@ impl<'tcx> DepNodeParams> for DefId { } } -impl<'tcx> DepNodeParams> for LocalDefId { +impl<'tcx> DepNodeKey> for LocalDefId { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::DefPathHash @@ -68,7 +68,7 @@ impl<'tcx> DepNodeParams> for LocalDefId { } } -impl<'tcx> DepNodeParams> for OwnerId { +impl<'tcx> DepNodeKey> for OwnerId { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::DefPathHash @@ -90,7 +90,7 @@ impl<'tcx> DepNodeParams> for OwnerId { } } -impl<'tcx> DepNodeParams> for CrateNum { +impl<'tcx> DepNodeKey> for CrateNum { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::DefPathHash @@ -113,7 +113,7 @@ impl<'tcx> DepNodeParams> for CrateNum { } } -impl<'tcx> DepNodeParams> for (DefId, DefId) { +impl<'tcx> DepNodeKey> for (DefId, DefId) { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::Opaque @@ -140,7 +140,7 @@ impl<'tcx> DepNodeParams> for (DefId, DefId) { } } -impl<'tcx> DepNodeParams> for HirId { +impl<'tcx> DepNodeKey> for HirId { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::HirId @@ -183,7 +183,7 @@ impl<'tcx> DepNodeParams> for HirId { } } -impl<'tcx> DepNodeParams> for ModDefId { +impl<'tcx> DepNodeKey> for ModDefId { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::DefPathHash @@ -205,7 +205,7 @@ impl<'tcx> DepNodeParams> for ModDefId { } } -impl<'tcx> DepNodeParams> for LocalModDefId { +impl<'tcx> DepNodeKey> for LocalModDefId { #[inline(always)] fn fingerprint_style() -> FingerprintStyle { FingerprintStyle::DefPathHash diff --git a/compiler/rustc_middle/src/query/inner.rs b/compiler/rustc_middle/src/query/inner.rs index bc0b34b67f12..32fe0737ec12 100644 --- a/compiler/rustc_middle/src/query/inner.rs +++ b/compiler/rustc_middle/src/query/inner.rs @@ -1,7 +1,7 @@ //! Helper functions that serve as the immediate implementation of //! `tcx.$query(..)` and its variations. -use rustc_query_system::dep_graph::{DepKind, DepNodeParams}; +use rustc_query_system::dep_graph::{DepKind, DepNodeKey}; use rustc_query_system::query::{QueryCache, QueryMode, try_get_cached}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; @@ -86,7 +86,7 @@ pub(crate) fn query_feed<'tcx, Cache>( value: Cache::Value, ) where Cache: QueryCache, - Cache::Key: DepNodeParams>, + Cache::Key: DepNodeKey>, { let format_value = query_vtable.format_value; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index d1721f1f455f..a7fde9e3ca9a 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -24,7 +24,7 @@ use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::print::with_reduced_queries; use rustc_middle::ty::tls::{self, ImplicitCtxt}; use rustc_middle::ty::{self, TyCtxt}; -use rustc_query_system::dep_graph::{DepNodeParams, FingerprintStyle, HasDepContext}; +use rustc_query_system::dep_graph::{DepNodeKey, FingerprintStyle, HasDepContext}; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ QueryCache, QueryContext, QueryDispatcher, QueryJobId, QueryMap, QuerySideEffect, diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index b9d35bc5a937..e18483d0b435 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -124,7 +124,7 @@ impl DepNode { pub fn construct(tcx: Tcx, kind: DepKind, arg: &Key) -> DepNode where Tcx: super::DepContext, - Key: DepNodeParams, + Key: DepNodeKey, { let hash = arg.to_fingerprint(tcx); let dep_node = DepNode { kind, hash: hash.into() }; @@ -167,13 +167,15 @@ impl fmt::Debug for DepNode { } } -pub trait DepNodeParams: fmt::Debug + Sized { +/// Trait for query keys as seen by dependency-node tracking. +pub trait DepNodeKey: fmt::Debug + Sized { fn fingerprint_style() -> FingerprintStyle; - /// This method turns the parameters of a DepNodeConstructor into an opaque - /// Fingerprint to be used in DepNode. - /// Not all DepNodeParams support being turned into a Fingerprint (they - /// don't need to if the corresponding DepNode is anonymous). + /// This method turns a query key into an opaque `Fingerprint` to be used + /// in `DepNode`. + /// + /// Not all `DepNodeKey` impls support being turned into a `Fingerprint` + /// (they don't need to if the corresponding `DepNode` is anonymous). fn to_fingerprint(&self, _: Tcx) -> Fingerprint { panic!("Not implemented. Accidentally called on anonymous node?") } @@ -189,7 +191,8 @@ pub trait DepNodeParams: fmt::Debug + Sized { fn recover(tcx: Tcx, dep_node: &DepNode) -> Option; } -impl DepNodeParams for T +// Blanket impl of `DepNodeKey`, which is specialized by other impls elsewhere. +impl DepNodeKey for T where T: for<'a> HashStable> + fmt::Debug, { @@ -239,7 +242,7 @@ pub struct DepKindVTable { /// Indicates whether and how the query key can be recovered from its hashed fingerprint. /// - /// The [`DepNodeParams`] trait determines the fingerprint style for each key type. + /// The [`DepNodeKey`] trait determines the fingerprint style for each key type. pub fingerprint_style: FingerprintStyle, /// The red/green evaluation system will try to mark a specific DepNode in the diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index c3ac1c7bc2d5..f2cb01d5e9b4 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -7,7 +7,7 @@ mod serialized; use std::panic; -pub use dep_node::{DepKind, DepKindVTable, DepNode, DepNodeParams, WorkProductId}; +pub use dep_node::{DepKind, DepKindVTable, DepNode, DepNodeKey, WorkProductId}; pub(crate) use graph::DepGraphData; pub use graph::{DepGraph, DepNodeIndex, TaskDepsRef, WorkProduct, WorkProductMap, hash_result}; pub use query::DepGraphQuery; diff --git a/compiler/rustc_query_system/src/query/dispatcher.rs b/compiler/rustc_query_system/src/query/dispatcher.rs index bcd3d0322d07..840b09024ffa 100644 --- a/compiler/rustc_query_system/src/query/dispatcher.rs +++ b/compiler/rustc_query_system/src/query/dispatcher.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_span::ErrorGuaranteed; use super::QueryStackFrameExtra; -use crate::dep_graph::{DepKind, DepNode, DepNodeParams, HasDepContext, SerializedDepNodeIndex}; +use crate::dep_graph::{DepKind, DepNode, DepNodeKey, HasDepContext, SerializedDepNodeIndex}; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; use crate::query::{CycleError, CycleErrorHandling, DepNodeIndex, QueryContext, QueryState}; @@ -33,7 +33,7 @@ pub trait QueryDispatcher<'tcx>: Copy + 'tcx { // `Key` and `Value` are `Copy` instead of `Clone` to ensure copying them stays cheap, // but it isn't necessary. - type Key: DepNodeParams> + Eq + Hash + Copy + Debug; + type Key: DepNodeKey> + Eq + Hash + Copy + Debug; type Value: Copy; type Cache: QueryCache; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index fcd2e80a4fdc..32c4f6e1c847 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -18,7 +18,7 @@ use tracing::instrument; use super::{QueryDispatcher, QueryStackDeferred, QueryStackFrameExtra}; use crate::dep_graph::{ - DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams, HasDepContext, + DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeKey, HasDepContext, }; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index a0ccf8d7e798..82d455ab54f0 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -540,7 +540,7 @@ macro_rules! typed_def_id { } // N.B.: when adding new typed `DefId`s update the corresponding trait impls in -// `rustc_middle::dep_graph::def_node` for `DepNodeParams`. +// `rustc_middle::dep_graph::dep_node_key` for `DepNodeKey`. typed_def_id! { ModDefId, LocalModDefId } impl LocalModDefId { From 07e4a994d61dccda69135a7b50ce69f6d93deec8 Mon Sep 17 00:00:00 2001 From: Usman Akinyemi Date: Thu, 29 Jan 2026 14:07:41 +0530 Subject: [PATCH 500/978] citool: report debuginfo test statistics Extend CI postprocessing to aggregate pass/fail/ignored counts for debuginfo tests. Tests are identified via their reported suite names (e.g. debuginfo-gdb, debuginfo-lldb or debuginfo-cdb). Signed-off-by: Usman Akinyemi --- src/build_helper/src/metrics.rs | 23 +++++++++++++++++++++++ src/ci/citool/src/analysis.rs | 30 +++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/build_helper/src/metrics.rs b/src/build_helper/src/metrics.rs index 07157e364158..98dd952033e5 100644 --- a/src/build_helper/src/metrics.rs +++ b/src/build_helper/src/metrics.rs @@ -111,6 +111,29 @@ pub struct JsonStepSystemStats { pub cpu_utilization_percent: f64, } +#[derive(Eq, Hash, PartialEq, Debug)] +pub enum DebuggerKind { + Gdb, + Lldb, + Cdb, +} + +impl DebuggerKind { + pub fn debuginfo_kind(name: &str) -> Option { + let name = name.to_ascii_lowercase(); + + if name.contains("debuginfo-gdb") { + Some(DebuggerKind::Gdb) + } else if name.contains("debuginfo-lldb") { + Some(DebuggerKind::Lldb) + } else if name.contains("debuginfo-cdb") { + Some(DebuggerKind::Cdb) + } else { + None + } + } +} + fn null_as_f64_nan<'de, D: serde::Deserializer<'de>>(d: D) -> Result { use serde::Deserialize as _; Option::::deserialize(d).map(|f| f.unwrap_or(f64::NAN)) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 39b115154f9f..ec65d9dcb528 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; use std::time::Duration; use build_helper::metrics::{ - BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, escape_step_name, + BuildStep, DebuggerKind, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, escape_step_name, format_build_steps, }; @@ -139,11 +139,39 @@ fn record_test_suites(metrics: &JsonRoot) { let table = render_table(aggregated); println!("\n# Test results\n"); println!("{table}"); + report_debuginfo_statistics(&suites); } else { eprintln!("No test suites found in metrics"); } } +fn report_debuginfo_statistics(suites: &[&TestSuite]) { + let mut debugger_test_record: HashMap = HashMap::new(); + for suite in suites { + if let TestSuiteMetadata::Compiletest { .. } = suite.metadata { + for test in &suite.tests { + if let Some(kind) = DebuggerKind::debuginfo_kind(&test.name) { + let record = + debugger_test_record.entry(kind).or_insert(TestSuiteRecord::default()); + match test.outcome { + TestOutcome::Passed => record.passed += 1, + TestOutcome::Ignored { .. } => record.ignored += 1, + TestOutcome::Failed => record.failed += 1, + } + } + } + } + } + + println!("## DebugInfo Test Statistics"); + for (kind, record) in debugger_test_record { + println!( + "- {:?}: Passed ✅={}, Failed ❌={}, Ignored 🚫={}", + kind, record.passed, record.failed, record.ignored + ); + } +} + fn render_table(suites: BTreeMap) -> String { use std::fmt::Write; From dcdffe8d808b84f2208c0dcb817bc46b0242e34a Mon Sep 17 00:00:00 2001 From: cezarbbb Date: Mon, 12 Jan 2026 14:48:05 +0800 Subject: [PATCH 501/978] link modifier `export-symbols`: export all global symbols from selected uptream c static libraries --- .../src/attributes/link_attrs.rs | 21 +++- .../src/session_diagnostics.rs | 9 +- compiler/rustc_codegen_ssa/src/back/link.rs | 95 +++++++++++++++++-- .../rustc_hir/src/attrs/data_structures.rs | 6 +- compiler/rustc_interface/src/tests.rs | 18 ++-- compiler/rustc_metadata/src/native_libs.rs | 2 +- .../rustc_session/src/config/native_libs.rs | 15 ++- compiler/rustc_span/src/symbol.rs | 1 + .../cdylib-export-c-library-symbols/foo.c | 1 + .../cdylib-export-c-library-symbols/foo.rs | 10 ++ .../foo_export.rs | 10 ++ .../cdylib-export-c-library-symbols/rmake.rs | 36 +++++++ ...ure-gate-link-arg-attribute.in_flag.stderr | 2 +- tests/ui/link-native-libs/link-arg-error2.rs | 5 + .../link-native-libs/link-arg-error2.stderr | 2 + .../ui/link-native-libs/link-arg-from-rs2.rs | 7 ++ .../link-native-libs/link-arg-from-rs2.stderr | 8 ++ .../link-attr-validation-late.stderr | 6 +- .../modifiers-bad.blank.stderr | 2 +- .../modifiers-bad.no-prefix.stderr | 2 +- .../modifiers-bad.prefix-only.stderr | 2 +- .../modifiers-bad.unknown.stderr | 2 +- 22 files changed, 226 insertions(+), 36 deletions(-) create mode 100644 tests/run-make/cdylib-export-c-library-symbols/foo.c create mode 100644 tests/run-make/cdylib-export-c-library-symbols/foo.rs create mode 100644 tests/run-make/cdylib-export-c-library-symbols/foo_export.rs create mode 100644 tests/run-make/cdylib-export-c-library-symbols/rmake.rs create mode 100644 tests/ui/link-native-libs/link-arg-error2.rs create mode 100644 tests/ui/link-native-libs/link-arg-error2.stderr create mode 100644 tests/ui/link-native-libs/link-arg-from-rs2.rs create mode 100644 tests/ui/link-native-libs/link-arg-from-rs2.stderr diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index c9da2f3b14bf..6c52be9bd229 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -12,10 +12,10 @@ use super::prelude::*; use super::util::parse_single_integer; use crate::attributes::cfg::parse_cfg_entry; use crate::session_diagnostics::{ - AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ImportNameTypeRaw, ImportNameTypeX86, - IncompatibleWasmLink, InvalidLinkModifier, LinkFrameworkApple, LinkOrdinalOutOfRange, - LinkRequiresName, MultipleModifiers, NullOnLinkSection, RawDylibNoNul, RawDylibOnlyWindows, - WholeArchiveNeedsStatic, + AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ExportSymbolsNeedsStatic, + ImportNameTypeRaw, ImportNameTypeX86, IncompatibleWasmLink, InvalidLinkModifier, + LinkFrameworkApple, LinkOrdinalOutOfRange, LinkRequiresName, MultipleModifiers, + NullOnLinkSection, RawDylibNoNul, RawDylibOnlyWindows, WholeArchiveNeedsStatic, }; pub(crate) struct LinkNameParser; @@ -165,6 +165,14 @@ impl CombineAttributeParser for LinkParser { cx.emit_err(BundleNeedsStatic { span }); } + (sym::export_symbols, Some(NativeLibKind::Static { export_symbols, .. })) => { + assign_modifier(export_symbols) + } + + (sym::export_symbols, _) => { + cx.emit_err(ExportSymbolsNeedsStatic { span }); + } + (sym::verbatim, _) => assign_modifier(&mut verbatim), ( @@ -190,6 +198,7 @@ impl CombineAttributeParser for LinkParser { span, &[ sym::bundle, + sym::export_symbols, sym::verbatim, sym::whole_dash_archive, sym::as_dash_needed, @@ -285,7 +294,9 @@ impl LinkParser { }; let link_kind = match link_kind { - kw::Static => NativeLibKind::Static { bundle: None, whole_archive: None }, + kw::Static => { + NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None } + } sym::dylib => NativeLibKind::Dylib { as_needed: None }, sym::framework => { if !sess.target.is_like_darwin { diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index fb4d9c660a19..b0a334210f74 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -909,7 +909,7 @@ pub(crate) struct RawDylibOnlyWindows { #[derive(Diagnostic)] #[diag( - "invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed" + "invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed, export-symbols" )] pub(crate) struct InvalidLinkModifier { #[primary_span] @@ -938,6 +938,13 @@ pub(crate) struct BundleNeedsStatic { pub span: Span, } +#[derive(Diagnostic)] +#[diag("linking modifier `export-symbols` is only compatible with `static` linking kind")] +pub(crate) struct ExportSymbolsNeedsStatic { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag("linking modifier `whole-archive` is only compatible with `static` linking kind")] pub(crate) struct WholeArchiveNeedsStatic { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index c8109db86e2f..5a732382c981 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -11,10 +11,11 @@ use std::{env, fmt, fs, io, mem, str}; use find_msvc_tools; use itertools::Itertools; +use object::{Object, ObjectSection, ObjectSymbol}; use regex::Regex; use rustc_arena::TypedArena; use rustc_attr_parsing::eval_config_entry; -use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{DiagCtxtHandle, LintDiagnostic}; @@ -2185,6 +2186,71 @@ fn add_rpath_args( } } +fn add_c_staticlib_symbols( + sess: &Session, + lib: &NativeLib, + out: &mut Vec<(String, SymbolExportKind)>, +) -> io::Result<()> { + let file_path = find_native_static_library(lib.name.as_str(), lib.verbatim, sess); + + let archive_map = unsafe { Mmap::map(File::open(&file_path)?)? }; + + let archive = object::read::archive::ArchiveFile::parse(&*archive_map) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + + for member in archive.members() { + let member = member.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + + let data = member + .data(&*archive_map) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + + // clang LTO: raw LLVM bitcode + if data.starts_with(b"BC\xc0\xde") { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "LLVM bitcode object in C static library (LTO not supported)", + )); + } + + let object = object::File::parse(&*data) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + + // gcc / clang ELF / Mach-O LTO + if object.sections().any(|s| { + s.name().map(|n| n.starts_with(".gnu.lto_") || n == ".llvm.lto").unwrap_or(false) + }) { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "LTO object in C static library is not supported", + )); + } + + for symbol in object.symbols() { + if symbol.scope() != object::SymbolScope::Dynamic { + continue; + } + + let name = match symbol.name() { + Ok(n) => n, + Err(_) => continue, + }; + + let export_kind = match symbol.kind() { + object::SymbolKind::Text => SymbolExportKind::Text, + object::SymbolKind::Data => SymbolExportKind::Data, + _ => continue, + }; + + // FIXME:The symbol mangle rules are slightly different in Windows(32-bit) and Apple. + // Need to be resolved. + out.push((name.to_string(), export_kind)); + } + } + + Ok(()) +} + /// Produce the linker command line containing linker path and arguments. /// /// When comments in the function say "order-(in)dependent" they mean order-dependence between @@ -2217,6 +2283,25 @@ fn linker_with_args( ); let link_output_kind = link_output_kind(sess, crate_type); + let mut export_symbols = codegen_results.crate_info.exported_symbols[&crate_type].clone(); + + if crate_type == CrateType::Cdylib { + let mut seen = FxHashSet::default(); + + for lib in &codegen_results.crate_info.used_libraries { + if let NativeLibKind::Static { export_symbols: Some(true), .. } = lib.kind + && seen.insert((lib.name, lib.verbatim)) + { + if let Err(err) = add_c_staticlib_symbols(&sess, lib, &mut export_symbols) { + sess.dcx().fatal(format!( + "failed to process C static library `{}`: {}", + lib.name, err + )); + } + } + } + } + // ------------ Early order-dependent options ------------ // If we're building something like a dynamic library then some platforms @@ -2224,11 +2309,7 @@ fn linker_with_args( // dynamic library. // Must be passed before any libraries to prevent the symbols to export from being thrown away, // at least on some platforms (e.g. windows-gnu). - cmd.export_symbols( - tmpdir, - crate_type, - &codegen_results.crate_info.exported_symbols[&crate_type], - ); + cmd.export_symbols(tmpdir, crate_type, &export_symbols); // Can be used for adding custom CRT objects or overriding order-dependent options above. // FIXME: In practice built-in target specs use this for arbitrary order-independent options, @@ -2678,7 +2759,7 @@ fn add_native_libs_from_crate( let name = lib.name.as_str(); let verbatim = lib.verbatim; match lib.kind { - NativeLibKind::Static { bundle, whole_archive } => { + NativeLibKind::Static { bundle, whole_archive, .. } => { if link_static { let bundle = bundle.unwrap_or(true); let whole_archive = whole_archive == Some(true); diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 6138ffc8d954..a53eff4637ff 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -331,6 +331,8 @@ pub enum NativeLibKind { bundle: Option, /// Whether to link static library without throwing any object files away whole_archive: Option, + /// Whether to export c static library symbols + export_symbols: Option, }, /// Dynamic library (e.g. `libfoo.so` on Linux) /// or an import library corresponding to a dynamic library (e.g. `foo.lib` on Windows/MSVC). @@ -363,8 +365,8 @@ pub enum NativeLibKind { impl NativeLibKind { pub fn has_modifiers(&self) -> bool { match self { - NativeLibKind::Static { bundle, whole_archive } => { - bundle.is_some() || whole_archive.is_some() + NativeLibKind::Static { bundle, whole_archive, export_symbols } => { + bundle.is_some() || whole_archive.is_some() || export_symbols.is_some() } NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 0f60e86e0ca3..b0272d726bc3 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -379,7 +379,7 @@ fn test_native_libs_tracking_hash_different_values() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { @@ -401,7 +401,7 @@ fn test_native_libs_tracking_hash_different_values() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { @@ -423,13 +423,13 @@ fn test_native_libs_tracking_hash_different_values() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { name: String::from("b"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { @@ -445,7 +445,7 @@ fn test_native_libs_tracking_hash_different_values() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { @@ -467,7 +467,7 @@ fn test_native_libs_tracking_hash_different_values() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { @@ -501,7 +501,7 @@ fn test_native_libs_tracking_hash_different_order() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { @@ -528,7 +528,7 @@ fn test_native_libs_tracking_hash_different_order() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { @@ -549,7 +549,7 @@ fn test_native_libs_tracking_hash_different_order() { NativeLib { name: String::from("a"), new_name: None, - kind: NativeLibKind::Static { bundle: None, whole_archive: None }, + kind: NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None }, verbatim: None, }, NativeLib { diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index b160b3fe9bb3..0c06d1be9a3f 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -161,7 +161,7 @@ fn find_bundled_library( tcx: TyCtxt<'_>, ) -> Option { let sess = tcx.sess; - if let NativeLibKind::Static { bundle: Some(true) | None, whole_archive } = kind + if let NativeLibKind::Static { bundle: Some(true) | None, whole_archive, .. } = kind && tcx.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::StaticLib)) && (sess.opts.unstable_opts.packed_bundled_libs || has_cfg || whole_archive == Some(true)) { diff --git a/compiler/rustc_session/src/config/native_libs.rs b/compiler/rustc_session/src/config/native_libs.rs index 71d3e222c8a1..28e2d0f94104 100644 --- a/compiler/rustc_session/src/config/native_libs.rs +++ b/compiler/rustc_session/src/config/native_libs.rs @@ -53,7 +53,9 @@ fn parse_native_lib(cx: &ParseNativeLibCx<'_>, value: &str) -> NativeLib { let NativeLibParts { kind, modifiers, name, new_name } = split_native_lib_value(value); let kind = kind.map_or(NativeLibKind::Unspecified, |kind| match kind { - "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, + "static" => { + NativeLibKind::Static { bundle: None, whole_archive: None, export_symbols: None } + } "dylib" => NativeLibKind::Dylib { as_needed: None }, "framework" => NativeLibKind::Framework { as_needed: None }, "link-arg" => { @@ -105,7 +107,7 @@ fn parse_and_apply_modifier(cx: &ParseNativeLibCx<'_>, modifier: &str, native_li Some(("-", m)) => (m, false), _ => cx.early_dcx.early_fatal( "invalid linking modifier syntax, expected '+' or '-' prefix \ - before one of: bundle, verbatim, whole-archive, as-needed", + before one of: bundle, verbatim, whole-archive, as-needed, export-symbols", ), }; @@ -125,6 +127,13 @@ fn parse_and_apply_modifier(cx: &ParseNativeLibCx<'_>, modifier: &str, native_li ("bundle", _) => early_dcx .early_fatal("linking modifier `bundle` is only compatible with `static` linking kind"), + ("export-symbols", NativeLibKind::Static { export_symbols, .. }) => { + assign_modifier(export_symbols) + } + ("export-symbols", _) => early_dcx.early_fatal( + "linking modifier `export-symbols` is only compatible with `static` linking kind", + ), + ("verbatim", _) => assign_modifier(&mut native_lib.verbatim), ("whole-archive", NativeLibKind::Static { whole_archive, .. }) => { @@ -151,7 +160,7 @@ fn parse_and_apply_modifier(cx: &ParseNativeLibCx<'_>, modifier: &str, native_li _ => early_dcx.early_fatal(format!( "unknown linking modifier `{modifier}`, expected one \ - of: bundle, verbatim, whole-archive, as-needed" + of: bundle, verbatim, whole-archive, as-needed, export-symbols" )), } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b0ef95d10ffa..c88dd0948b2a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1002,6 +1002,7 @@ symbols! { explicit_tail_calls, export_name, export_stable, + export_symbols: "export-symbols", expr, expr_2021, expr_fragment_specifier_2024, diff --git a/tests/run-make/cdylib-export-c-library-symbols/foo.c b/tests/run-make/cdylib-export-c-library-symbols/foo.c new file mode 100644 index 000000000000..a062aca03b31 --- /dev/null +++ b/tests/run-make/cdylib-export-c-library-symbols/foo.c @@ -0,0 +1 @@ +void my_function() {} diff --git a/tests/run-make/cdylib-export-c-library-symbols/foo.rs b/tests/run-make/cdylib-export-c-library-symbols/foo.rs new file mode 100644 index 000000000000..ac641aaed00f --- /dev/null +++ b/tests/run-make/cdylib-export-c-library-symbols/foo.rs @@ -0,0 +1,10 @@ +extern "C" { + pub fn my_function(); +} + +#[no_mangle] +pub extern "C" fn rust_entry() { + unsafe { + my_function(); + } +} diff --git a/tests/run-make/cdylib-export-c-library-symbols/foo_export.rs b/tests/run-make/cdylib-export-c-library-symbols/foo_export.rs new file mode 100644 index 000000000000..1eda294ef41c --- /dev/null +++ b/tests/run-make/cdylib-export-c-library-symbols/foo_export.rs @@ -0,0 +1,10 @@ +extern "C" { + fn my_function(); +} + +#[no_mangle] +pub extern "C" fn rust_entry() { + unsafe { + my_function(); + } +} diff --git a/tests/run-make/cdylib-export-c-library-symbols/rmake.rs b/tests/run-make/cdylib-export-c-library-symbols/rmake.rs new file mode 100644 index 000000000000..cb237eceedad --- /dev/null +++ b/tests/run-make/cdylib-export-c-library-symbols/rmake.rs @@ -0,0 +1,36 @@ +//@ ignore-nvptx64 +//@ ignore-wasm +//@ ignore-cross-compile +// FIXME:The symbol mangle rules are slightly different in Windows(32-bit) and Apple. +// Need to be resolved. +//@ ignore-windows +//@ ignore-apple +// Reason: the compiled binary is executed + +use run_make_support::{build_native_static_lib, cc, dynamic_lib_name, is_darwin, llvm_nm, rustc}; + +fn main() { + cc().input("foo.c").arg("-c").out_exe("foo.o").run(); + build_native_static_lib("foo"); + + rustc().input("foo.rs").arg("-lstatic=foo").crate_type("cdylib").run(); + + let out = llvm_nm() + .input(dynamic_lib_name("foo")) + .run() + .assert_stdout_not_contains_regex("T *my_function"); + + rustc().input("foo_export.rs").arg("-lstatic:+export-symbols=foo").crate_type("cdylib").run(); + + if is_darwin() { + let out = llvm_nm() + .input(dynamic_lib_name("foo_export")) + .run() + .assert_stdout_contains("T _my_function"); + } else { + let out = llvm_nm() + .input(dynamic_lib_name("foo_export")) + .run() + .assert_stdout_contains("T my_function"); + } +} diff --git a/tests/ui/feature-gates/feature-gate-link-arg-attribute.in_flag.stderr b/tests/ui/feature-gates/feature-gate-link-arg-attribute.in_flag.stderr index 4d65db3c66d0..218a4769d954 100644 --- a/tests/ui/feature-gates/feature-gate-link-arg-attribute.in_flag.stderr +++ b/tests/ui/feature-gates/feature-gate-link-arg-attribute.in_flag.stderr @@ -1,2 +1,2 @@ -error: unknown linking modifier `link-arg`, expected one of: bundle, verbatim, whole-archive, as-needed +error: unknown linking modifier `link-arg`, expected one of: bundle, verbatim, whole-archive, as-needed, export-symbols diff --git a/tests/ui/link-native-libs/link-arg-error2.rs b/tests/ui/link-native-libs/link-arg-error2.rs new file mode 100644 index 000000000000..a51dec0614b5 --- /dev/null +++ b/tests/ui/link-native-libs/link-arg-error2.rs @@ -0,0 +1,5 @@ +//@ compile-flags: -l link-arg:+export-symbols=arg -Z unstable-options + +fn main() {} + +//~? ERROR linking modifier `export-symbols` is only compatible with `static` linking kind diff --git a/tests/ui/link-native-libs/link-arg-error2.stderr b/tests/ui/link-native-libs/link-arg-error2.stderr new file mode 100644 index 000000000000..61bcf7dba282 --- /dev/null +++ b/tests/ui/link-native-libs/link-arg-error2.stderr @@ -0,0 +1,2 @@ +error: linking modifier `export-symbols` is only compatible with `static` linking kind + diff --git a/tests/ui/link-native-libs/link-arg-from-rs2.rs b/tests/ui/link-native-libs/link-arg-from-rs2.rs new file mode 100644 index 000000000000..3074fec6c1c8 --- /dev/null +++ b/tests/ui/link-native-libs/link-arg-from-rs2.rs @@ -0,0 +1,7 @@ +#![feature(link_arg_attribute)] + +#[link(kind = "link-arg", name = "arg", modifiers = "+export-symbols")] +//~^ ERROR linking modifier `export-symbols` is only compatible with `static` linking kind +extern "C" {} + +pub fn main() {} diff --git a/tests/ui/link-native-libs/link-arg-from-rs2.stderr b/tests/ui/link-native-libs/link-arg-from-rs2.stderr new file mode 100644 index 000000000000..af3b25253e05 --- /dev/null +++ b/tests/ui/link-native-libs/link-arg-from-rs2.stderr @@ -0,0 +1,8 @@ +error: linking modifier `export-symbols` is only compatible with `static` linking kind + --> $DIR/link-arg-from-rs2.rs:3:53 + | +LL | #[link(kind = "link-arg", name = "arg", modifiers = "+export-symbols")] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/link-native-libs/link-attr-validation-late.stderr b/tests/ui/link-native-libs/link-attr-validation-late.stderr index b09431f923aa..4a4a19375207 100644 --- a/tests/ui/link-native-libs/link-attr-validation-late.stderr +++ b/tests/ui/link-native-libs/link-attr-validation-late.stderr @@ -178,13 +178,13 @@ LL | #[link(name = "...", wasm_import_module())] | = note: for more information, visit -error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed +error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed, export-symbols --> $DIR/link-attr-validation-late.rs:31:34 | LL | #[link(name = "...", modifiers = "")] | ^^ -error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed +error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed, export-symbols --> $DIR/link-attr-validation-late.rs:32:34 | LL | #[link(name = "...", modifiers = "no-plus-minus")] @@ -196,7 +196,7 @@ error[E0539]: malformed `link` attribute input LL | #[link(name = "...", modifiers = "+unknown")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------^^ | | - | valid arguments are "bundle", "verbatim", "whole-archive" or "as-needed" + | valid arguments are "bundle", "export-symbols", "verbatim", "whole-archive" or "as-needed" | = note: for more information, visit diff --git a/tests/ui/link-native-libs/modifiers-bad.blank.stderr b/tests/ui/link-native-libs/modifiers-bad.blank.stderr index ea36af0b4cfa..6a1953e008ee 100644 --- a/tests/ui/link-native-libs/modifiers-bad.blank.stderr +++ b/tests/ui/link-native-libs/modifiers-bad.blank.stderr @@ -1,2 +1,2 @@ -error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed +error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed, export-symbols diff --git a/tests/ui/link-native-libs/modifiers-bad.no-prefix.stderr b/tests/ui/link-native-libs/modifiers-bad.no-prefix.stderr index ea36af0b4cfa..6a1953e008ee 100644 --- a/tests/ui/link-native-libs/modifiers-bad.no-prefix.stderr +++ b/tests/ui/link-native-libs/modifiers-bad.no-prefix.stderr @@ -1,2 +1,2 @@ -error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed +error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed, export-symbols diff --git a/tests/ui/link-native-libs/modifiers-bad.prefix-only.stderr b/tests/ui/link-native-libs/modifiers-bad.prefix-only.stderr index 1e701374688f..46720cf0b15e 100644 --- a/tests/ui/link-native-libs/modifiers-bad.prefix-only.stderr +++ b/tests/ui/link-native-libs/modifiers-bad.prefix-only.stderr @@ -1,2 +1,2 @@ -error: unknown linking modifier ``, expected one of: bundle, verbatim, whole-archive, as-needed +error: unknown linking modifier ``, expected one of: bundle, verbatim, whole-archive, as-needed, export-symbols diff --git a/tests/ui/link-native-libs/modifiers-bad.unknown.stderr b/tests/ui/link-native-libs/modifiers-bad.unknown.stderr index 75950ad9c64c..d47694a5aeca 100644 --- a/tests/ui/link-native-libs/modifiers-bad.unknown.stderr +++ b/tests/ui/link-native-libs/modifiers-bad.unknown.stderr @@ -1,2 +1,2 @@ -error: unknown linking modifier `ferris`, expected one of: bundle, verbatim, whole-archive, as-needed +error: unknown linking modifier `ferris`, expected one of: bundle, verbatim, whole-archive, as-needed, export-symbols From ac160bba1244aa1309cfa60cf0abd3c1a0aa3668 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Tue, 3 Feb 2026 21:19:37 +0800 Subject: [PATCH 502/978] ci: Optimize loongarch64-linux dist builders Tune the build configuration for loongarch64-linux targets to speed up rustc. Changes include: - Enable jemalloc and rust thin-lto. - Set codegen-units=1 and disable debug assertions. These changes reduce rustc-perf compile time by ~17%. --- src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile | 5 ++++- src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile index 4b86ed32fd55..96acc5e97e94 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile @@ -50,6 +50,9 @@ ENV RUST_CONFIGURE_ARGS \ --enable-full-tools \ --enable-profiler \ --enable-sanitizers \ - --disable-docs + --disable-docs \ + --set rust.jemalloc \ + --set rust.lto=thin \ + --set rust.codegen-units=1 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $TARGETS diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile index 763b29ae1c5e..44efc1089017 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile @@ -33,6 +33,9 @@ ENV RUST_CONFIGURE_ARGS \ --enable-profiler \ --enable-sanitizers \ --disable-docs \ + --set rust.jemalloc \ + --set rust.lto=thin \ + --set rust.codegen-units=1 \ --set target.loongarch64-unknown-linux-musl.crt-static=false \ --musl-root-loongarch64=/x-tools/loongarch64-unknown-linux-musl/loongarch64-unknown-linux-musl/sysroot/usr From ddd8f92c8d34860c7be94ed9b4b02b4c18430128 Mon Sep 17 00:00:00 2001 From: delta17920 Date: Wed, 4 Feb 2026 03:33:25 +0000 Subject: [PATCH 503/978] moved 8 tests to organized locations --- .../{issues/issue-3026.rs => borrowck/borrow-box-in-map-3026.rs} | 0 .../{issues/issue-3121.rs => match/match-nested-enum-box-3121.rs} | 0 .../issue-3029.rs => panics/vec-extend-after-panic-3029.rs} | 0 .../{issues/issue-2904.rs => resolve/enum-variant-import-2904.rs} | 0 .../issue-2708.rs => resolve/struct-function-same-name-2708.rs} | 0 .../issue-2895.rs => structs/struct-size-with-drop-2895.rs} | 0 .../issue-2935.rs => traits/trait-object-method-call-2935.rs} | 0 .../issue-3052.rs => traits/trait-object-type-alias-3052.rs} | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{issues/issue-3026.rs => borrowck/borrow-box-in-map-3026.rs} (100%) rename tests/ui/{issues/issue-3121.rs => match/match-nested-enum-box-3121.rs} (100%) rename tests/ui/{issues/issue-3029.rs => panics/vec-extend-after-panic-3029.rs} (100%) rename tests/ui/{issues/issue-2904.rs => resolve/enum-variant-import-2904.rs} (100%) rename tests/ui/{issues/issue-2708.rs => resolve/struct-function-same-name-2708.rs} (100%) rename tests/ui/{issues/issue-2895.rs => structs/struct-size-with-drop-2895.rs} (100%) rename tests/ui/{issues/issue-2935.rs => traits/trait-object-method-call-2935.rs} (100%) rename tests/ui/{issues/issue-3052.rs => traits/trait-object-type-alias-3052.rs} (100%) diff --git a/tests/ui/issues/issue-3026.rs b/tests/ui/borrowck/borrow-box-in-map-3026.rs similarity index 100% rename from tests/ui/issues/issue-3026.rs rename to tests/ui/borrowck/borrow-box-in-map-3026.rs diff --git a/tests/ui/issues/issue-3121.rs b/tests/ui/match/match-nested-enum-box-3121.rs similarity index 100% rename from tests/ui/issues/issue-3121.rs rename to tests/ui/match/match-nested-enum-box-3121.rs diff --git a/tests/ui/issues/issue-3029.rs b/tests/ui/panics/vec-extend-after-panic-3029.rs similarity index 100% rename from tests/ui/issues/issue-3029.rs rename to tests/ui/panics/vec-extend-after-panic-3029.rs diff --git a/tests/ui/issues/issue-2904.rs b/tests/ui/resolve/enum-variant-import-2904.rs similarity index 100% rename from tests/ui/issues/issue-2904.rs rename to tests/ui/resolve/enum-variant-import-2904.rs diff --git a/tests/ui/issues/issue-2708.rs b/tests/ui/resolve/struct-function-same-name-2708.rs similarity index 100% rename from tests/ui/issues/issue-2708.rs rename to tests/ui/resolve/struct-function-same-name-2708.rs diff --git a/tests/ui/issues/issue-2895.rs b/tests/ui/structs/struct-size-with-drop-2895.rs similarity index 100% rename from tests/ui/issues/issue-2895.rs rename to tests/ui/structs/struct-size-with-drop-2895.rs diff --git a/tests/ui/issues/issue-2935.rs b/tests/ui/traits/trait-object-method-call-2935.rs similarity index 100% rename from tests/ui/issues/issue-2935.rs rename to tests/ui/traits/trait-object-method-call-2935.rs diff --git a/tests/ui/issues/issue-3052.rs b/tests/ui/traits/trait-object-type-alias-3052.rs similarity index 100% rename from tests/ui/issues/issue-3052.rs rename to tests/ui/traits/trait-object-type-alias-3052.rs From 8e62b1d0e119e498ad51f44475b376b20d60fea8 Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 4 Feb 2026 03:55:50 +0000 Subject: [PATCH 504/978] Fix set_times_nofollow for directory on windows --- library/std/src/fs/tests.rs | 51 +++++++++++++++++++++++++++++++ library/std/src/sys/fs/windows.rs | 4 +-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 6d0b261dcadc..42f3ccc340b2 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -2301,6 +2301,57 @@ fn test_fs_set_times() { } } +#[test] +fn test_fs_set_times_on_dir() { + #[cfg(target_vendor = "apple")] + use crate::os::darwin::fs::FileTimesExt; + #[cfg(windows)] + use crate::os::windows::fs::FileTimesExt; + + let tmp = tmpdir(); + let dir_path = tmp.join("testdir"); + fs::create_dir(&dir_path).unwrap(); + + let mut times = FileTimes::new(); + let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345); + let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321); + times = times.set_accessed(accessed).set_modified(modified); + + #[cfg(any(windows, target_vendor = "apple"))] + let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123); + #[cfg(any(windows, target_vendor = "apple"))] + { + times = times.set_created(created); + } + + match fs::set_times(&dir_path, times) { + // Allow unsupported errors on platforms which don't support setting times. + #[cfg(not(any( + windows, + all( + unix, + not(any( + target_os = "android", + target_os = "redox", + target_os = "espidf", + target_os = "horizon" + )) + ) + )))] + Err(e) if e.kind() == ErrorKind::Unsupported => return, + Err(e) => panic!("error setting directory times: {e:?}"), + Ok(_) => {} + } + + let metadata = fs::metadata(&dir_path).unwrap(); + assert_eq!(metadata.accessed().unwrap(), accessed); + assert_eq!(metadata.modified().unwrap(), modified); + #[cfg(any(windows, target_vendor = "apple"))] + { + assert_eq!(metadata.created().unwrap(), created); + } +} + #[test] fn test_fs_set_times_follows_symlink() { #[cfg(target_vendor = "apple")] diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index fc8aec2f3f7c..74854cdeb498 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -1556,7 +1556,7 @@ pub fn set_perm(p: &WCStr, perm: FilePermissions) -> io::Result<()> { pub fn set_times(p: &WCStr, times: FileTimes) -> io::Result<()> { let mut opts = OpenOptions::new(); - opts.write(true); + opts.access_mode(c::FILE_WRITE_ATTRIBUTES); opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS); let file = File::open_native(p, &opts)?; file.set_times(times) @@ -1564,7 +1564,7 @@ pub fn set_times(p: &WCStr, times: FileTimes) -> io::Result<()> { pub fn set_times_nofollow(p: &WCStr, times: FileTimes) -> io::Result<()> { let mut opts = OpenOptions::new(); - opts.write(true); + opts.access_mode(c::FILE_WRITE_ATTRIBUTES); // `FILE_FLAG_OPEN_REPARSE_POINT` for no_follow behavior opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | c::FILE_FLAG_OPEN_REPARSE_POINT); let file = File::open_native(p, &opts)?; From 158410457f147dfb5a0c3fa84f81a5b3d0582ade Mon Sep 17 00:00:00 2001 From: delta17920 Date: Wed, 4 Feb 2026 03:35:11 +0000 Subject: [PATCH 505/978] renamed few tests --- tests/ui/borrowck/borrow-box-in-map-3026.rs | 2 + tests/ui/match/match-nested-enum-box-3121.rs | 29 +++-- .../ui/panics/vec-extend-after-panic-3029.rs | 2 + tests/ui/resolve/enum-variant-import-2904.rs | 102 +++++++++++------- .../resolve/struct-function-same-name-2708.rs | 12 +-- .../ui/structs/struct-size-with-drop-2895.rs | 4 +- .../traits/trait-object-method-call-2935.rs | 12 ++- .../ui/traits/trait-object-type-alias-3052.rs | 5 +- 8 files changed, 103 insertions(+), 65 deletions(-) diff --git a/tests/ui/borrowck/borrow-box-in-map-3026.rs b/tests/ui/borrowck/borrow-box-in-map-3026.rs index 05dc46c3cc09..dd63075eecba 100644 --- a/tests/ui/borrowck/borrow-box-in-map-3026.rs +++ b/tests/ui/borrowck/borrow-box-in-map-3026.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/3026 + //@ run-pass use std::collections::HashMap; diff --git a/tests/ui/match/match-nested-enum-box-3121.rs b/tests/ui/match/match-nested-enum-box-3121.rs index aa150f11cf40..f2ab4bf08075 100644 --- a/tests/ui/match/match-nested-enum-box-3121.rs +++ b/tests/ui/match/match-nested-enum-box-3121.rs @@ -1,21 +1,34 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/3121 + //@ run-pass #![allow(dead_code)] #![allow(non_camel_case_types)] #[derive(Copy, Clone)] -enum side { mayo, catsup, vinegar } +enum side { + mayo, + catsup, + vinegar, +} #[derive(Copy, Clone)] -enum order { hamburger, fries(side), shake } +enum order { + hamburger, + fries(side), + shake, +} #[derive(Copy, Clone)] -enum meal { to_go(order), for_here(order) } +enum meal { + to_go(order), + for_here(order), +} fn foo(m: Box, cond: bool) { match *m { - meal::to_go(_) => { } - meal::for_here(_) if cond => {} - meal::for_here(order::hamburger) => {} - meal::for_here(order::fries(_s)) => {} - meal::for_here(order::shake) => {} + meal::to_go(_) => {} + meal::for_here(_) if cond => {} + meal::for_here(order::hamburger) => {} + meal::for_here(order::fries(_s)) => {} + meal::for_here(order::shake) => {} } } diff --git a/tests/ui/panics/vec-extend-after-panic-3029.rs b/tests/ui/panics/vec-extend-after-panic-3029.rs index 22d0906ccf70..3ae708d91e19 100644 --- a/tests/ui/panics/vec-extend-after-panic-3029.rs +++ b/tests/ui/panics/vec-extend-after-panic-3029.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/3029 + //@ run-fail //@ error-pattern:so long //@ needs-subprocess diff --git a/tests/ui/resolve/enum-variant-import-2904.rs b/tests/ui/resolve/enum-variant-import-2904.rs index 1ae3a8ad656e..3272ee5fb500 100644 --- a/tests/ui/resolve/enum-variant-import-2904.rs +++ b/tests/ui/resolve/enum-variant-import-2904.rs @@ -1,60 +1,80 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/2904 + //@ build-pass #![allow(unused_must_use)] #![allow(dead_code)] #![allow(unused_mut)] -#![allow(non_camel_case_types)] // Map representation +use Square::{Bot, ClosedLift, Earth, Empty, Lambda, OpenLift, Rock, Wall}; use std::fmt; use std::io::prelude::*; -use square::{bot, wall, rock, lambda, closed_lift, open_lift, earth, empty}; -enum square { - bot, - wall, - rock, - lambda, - closed_lift, - open_lift, - earth, - empty +enum Square { + Bot, + Wall, + Rock, + Lambda, + ClosedLift, + OpenLift, + Earth, + Empty, } -impl fmt::Debug for square { +impl fmt::Debug for Square { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", match *self { - bot => { "R".to_string() } - wall => { "#".to_string() } - rock => { "*".to_string() } - lambda => { "\\".to_string() } - closed_lift => { "L".to_string() } - open_lift => { "O".to_string() } - earth => { ".".to_string() } - empty => { " ".to_string() } - }) + write!( + f, + "{}", + match *self { + Bot => { + "R".to_string() + } + Wall => { + "#".to_string() + } + Rock => { + "*".to_string() + } + Lambda => { + "\\".to_string() + } + ClosedLift => { + "L".to_string() + } + OpenLift => { + "O".to_string() + } + Earth => { + ".".to_string() + } + Empty => { + " ".to_string() + } + } + ) } } -fn square_from_char(c: char) -> square { - match c { - 'R' => { bot } - '#' => { wall } - '*' => { rock } - '\\' => { lambda } - 'L' => { closed_lift } - 'O' => { open_lift } - '.' => { earth } - ' ' => { empty } - _ => { - println!("invalid square: {}", c); - panic!() - } +fn square_from_char(c: char) -> Square { + match c { + 'R' => Bot, + '#' => Wall, + '*' => Rock, + '\\' => Lambda, + 'L' => ClosedLift, + 'O' => OpenLift, + '.' => Earth, + ' ' => Empty, + _ => { + println!("invalid Square: {}", c); + panic!() + } } } -fn read_board_grid(mut input: rdr) - -> Vec> { +fn read_board_grid(mut input: Rdr) -> Vec> { let mut input: &mut dyn Read = &mut input; let mut grid = Vec::new(); let mut line = [0; 10]; @@ -65,14 +85,16 @@ fn read_board_grid(mut input: rdr) } grid.push(row); let width = grid[0].len(); - for row in &grid { assert_eq!(row.len(), width) } + for row in &grid { + assert_eq!(row.len(), width) + } grid } mod test { #[test] pub fn trivial_to_string() { - assert_eq!(lambda.to_string(), "\\") + assert_eq!(Lambda.to_string(), "\\") } } diff --git a/tests/ui/resolve/struct-function-same-name-2708.rs b/tests/ui/resolve/struct-function-same-name-2708.rs index 09d19f87aa64..729a5819ae4e 100644 --- a/tests/ui/resolve/struct-function-same-name-2708.rs +++ b/tests/ui/resolve/struct-function-same-name-2708.rs @@ -1,15 +1,13 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/2708 + //@ run-pass #![allow(dead_code)] #![allow(non_snake_case)] - - - struct Font { fontbuf: usize, cairo_font: usize, font_dtor: usize, - } impl Drop for Font { @@ -17,11 +15,7 @@ impl Drop for Font { } fn Font() -> Font { - Font { - fontbuf: 0, - cairo_font: 0, - font_dtor: 0 - } + Font { fontbuf: 0, cairo_font: 0, font_dtor: 0 } } pub fn main() { diff --git a/tests/ui/structs/struct-size-with-drop-2895.rs b/tests/ui/structs/struct-size-with-drop-2895.rs index 6301a8637534..9540d340ff68 100644 --- a/tests/ui/structs/struct-size-with-drop-2895.rs +++ b/tests/ui/structs/struct-size-with-drop-2895.rs @@ -1,10 +1,12 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/2895 + //@ run-pass #![allow(dead_code)] use std::mem; struct Cat { - x: isize + x: isize, } struct Kitty { diff --git a/tests/ui/traits/trait-object-method-call-2935.rs b/tests/ui/traits/trait-object-method-call-2935.rs index bcc25f6187b5..ea24aae89462 100644 --- a/tests/ui/traits/trait-object-method-call-2935.rs +++ b/tests/ui/traits/trait-object-method-call-2935.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/2935 + //@ run-pass #![allow(dead_code)] #![allow(non_camel_case_types)] @@ -11,14 +13,14 @@ trait it { } impl it for t { - fn f(&self) { } + fn f(&self) {} } pub fn main() { - // let x = ({a: 4} as it); - // let y = box ({a: 4}); - // let z = box ({a: 4} as it); - // let z = box ({a: true} as it); + // let x = ({a: 4} as it); + // let y = box ({a: 4}); + // let z = box ({a: 4} as it); + // let z = box ({a: true} as it); let z: Box<_> = Box::new(Box::new(true) as Box); // x.f(); // y.f(); diff --git a/tests/ui/traits/trait-object-type-alias-3052.rs b/tests/ui/traits/trait-object-type-alias-3052.rs index ab3519fe7147..e601c76713dc 100644 --- a/tests/ui/traits/trait-object-type-alias-3052.rs +++ b/tests/ui/traits/trait-object-type-alias-3052.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/3052 + //@ run-pass #![allow(dead_code)] @@ -8,5 +10,4 @@ fn f() -> Option { Some(mock_connection) } -pub fn main() { -} +pub fn main() {} From c77779e5294722c372ee834306118810e930f96e Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 3 Feb 2026 22:15:36 -0800 Subject: [PATCH 506/978] rustbook/README.md: add missing `)` To match the opening `(` before the reference to PR 127786 --- src/tools/rustbook/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rustbook/README.md b/src/tools/rustbook/README.md index d9570c23ead1..a9fd1b75b572 100644 --- a/src/tools/rustbook/README.md +++ b/src/tools/rustbook/README.md @@ -10,7 +10,7 @@ This is invoked automatically when building mdbook-style documentation, for exam ## Cargo workspace -This package defines a separate cargo workspace from the main Rust workspace for a few reasons (ref [#127786](https://github.com/rust-lang/rust/pull/127786): +This package defines a separate cargo workspace from the main Rust workspace for a few reasons (ref [#127786](https://github.com/rust-lang/rust/pull/127786)): - Avoids requiring checking out submodules for developers who are not working on the documentation. Otherwise, some submodules such as those that have custom preprocessors would be required for cargo to find the dependencies. - Avoids problems with updating dependencies. Unfortunately this workspace has a rather large set of dependencies, which can make coordinating updates difficult (see [#127890](https://github.com/rust-lang/rust/issues/127890)). From e7c142cc895f4a56e71d5e477bcb562b47cd1d16 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 3 Feb 2026 15:22:54 +0100 Subject: [PATCH 507/978] Convert to inline diagnostics in `rustc_interface` --- Cargo.lock | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_interface/Cargo.toml | 1 - compiler/rustc_interface/messages.ftl | 56 -------------------- compiler/rustc_interface/src/errors.rs | 62 ++++++++++++++--------- compiler/rustc_interface/src/interface.rs | 12 +---- compiler/rustc_interface/src/lib.rs | 2 - 7 files changed, 41 insertions(+), 94 deletions(-) delete mode 100644 compiler/rustc_interface/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 4cbc98beae11..1631d5362612 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4114,7 +4114,6 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", - "rustc_fluent_macro", "rustc_fs_util", "rustc_hir", "rustc_hir_analysis", diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 0ab71ad9981b..3059a4fefc61 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -124,7 +124,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_expand::DEFAULT_LOCALE_RESOURCE, rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE, rustc_hir_typeck::DEFAULT_LOCALE_RESOURCE, - rustc_interface::DEFAULT_LOCALE_RESOURCE, rustc_lint::DEFAULT_LOCALE_RESOURCE, rustc_metadata::DEFAULT_LOCALE_RESOURCE, rustc_middle::DEFAULT_LOCALE_RESOURCE, diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index d785030b5f2c..3a3b4d59db86 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -19,7 +19,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_hir = { path = "../rustc_hir" } rustc_hir_analysis = { path = "../rustc_hir_analysis" } diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl deleted file mode 100644 index d898e9bf7d1e..000000000000 --- a/compiler/rustc_interface/messages.ftl +++ /dev/null @@ -1,56 +0,0 @@ -interface_abi_required_feature = - target feature `{$feature}` must be {$enabled} to ensure that the ABI of the current target can be implemented correctly - .note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -interface_abi_required_feature_issue = for more information, see issue #116344 - -interface_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$crate_name}` != `{$attr_crate_name}` - -interface_crate_name_invalid = crate names cannot start with a `-`, but `{$crate_name}` has a leading hyphen - -interface_emoji_identifier = - identifiers cannot contain emoji: `{$ident}` - -interface_error_writing_dependencies = - error writing dependencies to `{$path}`: {$error} - -interface_failed_writing_file = - failed to write file {$path}: {$error}" - -interface_ferris_identifier = - Ferris cannot be used as an identifier - .suggestion = try using their name instead - -interface_generated_file_conflicts_with_directory = - the generated executable for the input file "{$input_path}" conflicts with the existing directory "{$dir_path}" - -interface_ignoring_extra_filename = ignoring -C extra-filename flag due to -o flag - -interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag - -interface_input_file_would_be_overwritten = - the input file "{$path}" would be overwritten by the generated executable - -interface_mixed_bin_crate = - cannot mix `bin` crate type with others - -interface_mixed_proc_macro_crate = - cannot mix `proc-macro` crate type with others - -interface_multiple_output_types_adaption = - due to multiple output types requested, the explicitly specified output file name will be adapted for each output type - -interface_multiple_output_types_to_stdout = can't use option `-o` or `--emit` to write multiple output types to stdout -interface_out_dir_error = - failed to find or create the directory specified by `--out-dir` - -interface_proc_macro_crate_panic_abort = - building proc macro crate with `panic=abort` or `panic=immediate-abort` may crash the compiler should the proc-macro panic - -interface_temps_dir_error = - failed to find or create the directory specified by `--temps-dir` - -interface_unsupported_crate_type_for_codegen_backend = - dropping unsupported crate type `{$crate_type}` for codegen backend `{$codegen_backend}` - -interface_unsupported_crate_type_for_target = - dropping unsupported crate type `{$crate_type}` for target `{$target_triple}` diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index aee8ec20e14d..7e4671889f57 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -7,7 +7,9 @@ use rustc_span::{Span, Symbol}; use rustc_target::spec::TargetTuple; #[derive(Diagnostic)] -#[diag(interface_crate_name_does_not_match)] +#[diag( + "`--crate-name` and `#[crate_name]` are required to match, but `{$crate_name}` != `{$attr_crate_name}`" +)] pub(crate) struct CrateNameDoesNotMatch { #[primary_span] pub(crate) span: Span, @@ -16,23 +18,27 @@ pub(crate) struct CrateNameDoesNotMatch { } #[derive(Diagnostic)] -#[diag(interface_crate_name_invalid)] +#[diag("crate names cannot start with a `-`, but `{$crate_name}` has a leading hyphen")] pub(crate) struct CrateNameInvalid<'a> { pub(crate) crate_name: &'a str, } #[derive(Diagnostic)] -#[diag(interface_ferris_identifier)] +#[diag("Ferris cannot be used as an identifier")] pub struct FerrisIdentifier { #[primary_span] pub spans: Vec, - #[suggestion(code = "{ferris_fix}", applicability = "maybe-incorrect")] + #[suggestion( + "try using their name instead", + code = "{ferris_fix}", + applicability = "maybe-incorrect" + )] pub first_span: Span, pub ferris_fix: &'static str, } #[derive(Diagnostic)] -#[diag(interface_emoji_identifier)] +#[diag("identifiers cannot contain emoji: `{$ident}`")] pub struct EmojiIdentifier { #[primary_span] pub spans: Vec, @@ -40,86 +46,96 @@ pub struct EmojiIdentifier { } #[derive(Diagnostic)] -#[diag(interface_mixed_bin_crate)] +#[diag("cannot mix `bin` crate type with others")] pub struct MixedBinCrate; #[derive(Diagnostic)] -#[diag(interface_mixed_proc_macro_crate)] +#[diag("cannot mix `proc-macro` crate type with others")] pub struct MixedProcMacroCrate; #[derive(Diagnostic)] -#[diag(interface_error_writing_dependencies)] +#[diag("error writing dependencies to `{$path}`: {$error}")] pub struct ErrorWritingDependencies<'a> { pub path: &'a Path, pub error: io::Error, } #[derive(Diagnostic)] -#[diag(interface_input_file_would_be_overwritten)] +#[diag("the input file \"{$path}\" would be overwritten by the generated executable")] pub struct InputFileWouldBeOverWritten<'a> { pub path: &'a Path, } #[derive(Diagnostic)] -#[diag(interface_generated_file_conflicts_with_directory)] +#[diag( + "the generated executable for the input file \"{$input_path}\" conflicts with the existing directory \"{$dir_path}\"" +)] pub struct GeneratedFileConflictsWithDirectory<'a> { pub input_path: &'a Path, pub dir_path: &'a Path, } #[derive(Diagnostic)] -#[diag(interface_temps_dir_error)] +#[diag("failed to find or create the directory specified by `--temps-dir`")] pub struct TempsDirError; #[derive(Diagnostic)] -#[diag(interface_out_dir_error)] +#[diag("failed to find or create the directory specified by `--out-dir`")] pub struct OutDirError; #[derive(Diagnostic)] -#[diag(interface_failed_writing_file)] +#[diag("failed to write file {$path}: {$error}\"")] pub struct FailedWritingFile<'a> { pub path: &'a Path, pub error: io::Error, } #[derive(Diagnostic)] -#[diag(interface_proc_macro_crate_panic_abort)] +#[diag( + "building proc macro crate with `panic=abort` or `panic=immediate-abort` may crash the compiler should the proc-macro panic" +)] pub struct ProcMacroCratePanicAbort; #[derive(Diagnostic)] -#[diag(interface_multiple_output_types_adaption)] +#[diag( + "due to multiple output types requested, the explicitly specified output file name will be adapted for each output type" +)] pub struct MultipleOutputTypesAdaption; #[derive(Diagnostic)] -#[diag(interface_ignoring_extra_filename)] +#[diag("ignoring -C extra-filename flag due to -o flag")] pub struct IgnoringExtraFilename; #[derive(Diagnostic)] -#[diag(interface_ignoring_out_dir)] +#[diag("ignoring --out-dir flag due to -o flag")] pub struct IgnoringOutDir; #[derive(Diagnostic)] -#[diag(interface_multiple_output_types_to_stdout)] +#[diag("can't use option `-o` or `--emit` to write multiple output types to stdout")] pub struct MultipleOutputTypesToStdout; #[derive(Diagnostic)] -#[diag(interface_abi_required_feature)] -#[note] -#[note(interface_abi_required_feature_issue)] +#[diag( + "target feature `{$feature}` must be {$enabled} to ensure that the ABI of the current target can be implemented correctly" +)] +#[note( + "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 #116344 ")] pub(crate) struct AbiRequiredTargetFeature<'a> { pub feature: &'a str, pub enabled: &'a str, } #[derive(Diagnostic)] -#[diag(interface_unsupported_crate_type_for_codegen_backend)] +#[diag("dropping unsupported crate type `{$crate_type}` for codegen backend `{$codegen_backend}`")] pub(crate) struct UnsupportedCrateTypeForCodegenBackend { pub(crate) crate_type: CrateType, pub(crate) codegen_backend: &'static str, } #[derive(Diagnostic)] -#[diag(interface_unsupported_crate_type_for_target)] +#[diag("dropping unsupported crate type `{$crate_type}` for target `{$target_triple}`")] pub(crate) struct UnsupportedCrateTypeForTarget<'a> { pub(crate) crate_type: CrateType, pub(crate) target_triple: &'a TargetTuple, diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index f76e8d4632fc..916618cb5049 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -55,11 +55,7 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec) -> Cfg { cfgs.into_iter() .map(|s| { let psess = ParseSess::emitter_with_note( - vec![ - crate::DEFAULT_LOCALE_RESOURCE, - rustc_parse::DEFAULT_LOCALE_RESOURCE, - rustc_session::DEFAULT_LOCALE_RESOURCE, - ], + vec![rustc_parse::DEFAULT_LOCALE_RESOURCE, rustc_session::DEFAULT_LOCALE_RESOURCE], format!("this occurred on the command line: `--cfg={s}`"), ); let filename = FileName::cfg_spec_source_code(&s); @@ -131,11 +127,7 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec) -> Ch for s in specs { let psess = ParseSess::emitter_with_note( - vec![ - crate::DEFAULT_LOCALE_RESOURCE, - rustc_parse::DEFAULT_LOCALE_RESOURCE, - rustc_session::DEFAULT_LOCALE_RESOURCE, - ], + vec![rustc_parse::DEFAULT_LOCALE_RESOURCE, rustc_session::DEFAULT_LOCALE_RESOURCE], format!("this occurred on the command line: `--check-cfg={s}`"), ); let filename = FileName::cfg_spec_source_code(&s); diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index ce2398fab919..b5e4a384861f 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -21,5 +21,3 @@ pub use queries::Linker; #[cfg(test)] mod tests; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } From ae21d43933419d80a2471afbd26d6e288e6666a7 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 3 Feb 2026 22:28:34 +0100 Subject: [PATCH 508/978] Convert to inline diagnostics in `rustc_privacy` --- Cargo.lock | 2 -- compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_privacy/Cargo.toml | 1 - compiler/rustc_privacy/messages.ftl | 39 --------------------- compiler/rustc_privacy/src/errors.rs | 50 ++++++++++++++++++--------- compiler/rustc_privacy/src/lib.rs | 2 -- 7 files changed, 33 insertions(+), 63 deletions(-) delete mode 100644 compiler/rustc_privacy/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 4cbc98beae11..e209821c5d70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3803,7 +3803,6 @@ dependencies = [ "rustc_parse", "rustc_passes", "rustc_pattern_analysis", - "rustc_privacy", "rustc_public", "rustc_resolve", "rustc_session", @@ -4487,7 +4486,6 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_macros", "rustc_middle", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index d184b6c8947c..ee6ffcca29ad 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -37,7 +37,6 @@ rustc_monomorphize = { path = "../rustc_monomorphize" } rustc_parse = { path = "../rustc_parse" } rustc_passes = { path = "../rustc_passes" } rustc_pattern_analysis = { path = "../rustc_pattern_analysis" } -rustc_privacy = { path = "../rustc_privacy" } rustc_public = { path = "../rustc_public", features = ["rustc_internal"] } rustc_resolve = { path = "../rustc_resolve" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 0ab71ad9981b..ffed24d72c41 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -134,7 +134,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_parse::DEFAULT_LOCALE_RESOURCE, rustc_passes::DEFAULT_LOCALE_RESOURCE, rustc_pattern_analysis::DEFAULT_LOCALE_RESOURCE, - rustc_privacy::DEFAULT_LOCALE_RESOURCE, rustc_resolve::DEFAULT_LOCALE_RESOURCE, rustc_session::DEFAULT_LOCALE_RESOURCE, rustc_trait_selection::DEFAULT_LOCALE_RESOURCE, diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index c8bfdb913041..ff59c19b6bb6 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -8,7 +8,6 @@ edition = "2024" rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_privacy/messages.ftl b/compiler/rustc_privacy/messages.ftl deleted file mode 100644 index 43c34a109d72..000000000000 --- a/compiler/rustc_privacy/messages.ftl +++ /dev/null @@ -1,39 +0,0 @@ -privacy_field_is_private = - {$len -> - [1] field - *[other] fields - } {$field_names} of {$variant_descr} `{$def_path_str}` {$len -> - [1] is - *[other] are - } private - .label = in this type -privacy_field_is_private_is_update_syntax_label = {$rest_len -> - [1] field - *[other] fields - } {$rest_field_names} {$rest_len -> - [1] is - *[other] are - } private -privacy_field_is_private_label = private field - -privacy_from_private_dep_in_public_interface = - {$kind} `{$descr}` from private dependency '{$krate}' in public interface - -privacy_in_public_interface = {$vis_descr} {$kind} `{$descr}` in public interface - .label = can't leak {$vis_descr} {$kind} - .visibility_label = `{$descr}` declared as {$vis_descr} - -privacy_item_is_private = {$kind} `{$descr}` is private - .label = private {$kind} - -privacy_private_interface_or_bounds_lint = {$ty_kind} `{$ty_descr}` is more private than the item `{$item_descr}` - .item_label = {$item_kind} `{$item_descr}` is reachable at visibility `{$item_vis_descr}` - .ty_note = but {$ty_kind} `{$ty_descr}` is only usable at visibility `{$ty_vis_descr}` - -privacy_report_effective_visibility = {$descr} - -privacy_unnameable_types_lint = {$kind} `{$descr}` is reachable but cannot be named - .label = reachable at visibility `{$reachable_vis}`, but can only be named at visibility `{$reexported_vis}` - -privacy_unnamed_item_is_private = {$kind} is private - .label = private {$kind} diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs index 4d1d58c08528..af4f0d61aa11 100644 --- a/compiler/rustc_privacy/src/errors.rs +++ b/compiler/rustc_privacy/src/errors.rs @@ -4,11 +4,17 @@ use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] -#[diag(privacy_field_is_private, code = E0451)] +#[diag("{$len -> + [1] field + *[other] fields +} {$field_names} of {$variant_descr} `{$def_path_str}` {$len -> + [1] is + *[other] are +} private", code = E0451)] pub(crate) struct FieldIsPrivate { #[primary_span] pub span: MultiSpan, - #[label] + #[label("in this type")] pub struct_span: Option, pub field_names: String, pub variant_descr: &'static str, @@ -20,14 +26,22 @@ pub(crate) struct FieldIsPrivate { #[derive(Subdiagnostic)] pub(crate) enum FieldIsPrivateLabel { - #[label(privacy_field_is_private_is_update_syntax_label)] + #[label( + "{$rest_len -> + [1] field + *[other] fields + } {$rest_field_names} {$rest_len -> + [1] is + *[other] are + } private" + )] IsUpdateSyntax { #[primary_span] span: Span, rest_field_names: String, rest_len: usize, }, - #[label(privacy_field_is_private_label)] + #[label("private field")] Other { #[primary_span] span: Span, @@ -35,17 +49,17 @@ pub(crate) enum FieldIsPrivateLabel { } #[derive(Diagnostic)] -#[diag(privacy_item_is_private)] +#[diag("{$kind} `{$descr}` is private")] pub(crate) struct ItemIsPrivate<'a> { #[primary_span] - #[label] + #[label("private {$kind}")] pub span: Span, pub kind: &'a str, pub descr: DiagArgFromDisplay<'a>, } #[derive(Diagnostic)] -#[diag(privacy_unnamed_item_is_private)] +#[diag("{$kind} is private")] pub(crate) struct UnnamedItemIsPrivate { #[primary_span] pub span: Span, @@ -53,20 +67,20 @@ pub(crate) struct UnnamedItemIsPrivate { } #[derive(Diagnostic)] -#[diag(privacy_in_public_interface, code = E0446)] +#[diag("{$vis_descr} {$kind} `{$descr}` in public interface", code = E0446)] pub(crate) struct InPublicInterface<'a> { #[primary_span] - #[label] + #[label("can't leak {$vis_descr} {$kind}")] pub span: Span, pub vis_descr: &'static str, pub kind: &'a str, pub descr: DiagArgFromDisplay<'a>, - #[label(privacy_visibility_label)] + #[label("`{$descr}` declared as {$vis_descr}")] pub vis_span: Span, } #[derive(Diagnostic)] -#[diag(privacy_report_effective_visibility)] +#[diag("{$descr}")] pub(crate) struct ReportEffectiveVisibility { #[primary_span] pub span: Span, @@ -74,7 +88,7 @@ pub(crate) struct ReportEffectiveVisibility { } #[derive(LintDiagnostic)] -#[diag(privacy_from_private_dep_in_public_interface)] +#[diag("{$kind} `{$descr}` from private dependency '{$krate}' in public interface")] pub(crate) struct FromPrivateDependencyInPublicInterface<'a> { pub kind: &'a str, pub descr: DiagArgFromDisplay<'a>, @@ -82,9 +96,11 @@ pub(crate) struct FromPrivateDependencyInPublicInterface<'a> { } #[derive(LintDiagnostic)] -#[diag(privacy_unnameable_types_lint)] +#[diag("{$kind} `{$descr}` is reachable but cannot be named")] pub(crate) struct UnnameableTypesLint<'a> { - #[label] + #[label( + "reachable at visibility `{$reachable_vis}`, but can only be named at visibility `{$reexported_vis}`" + )] pub span: Span, pub kind: &'a str, pub descr: DiagArgFromDisplay<'a>, @@ -96,14 +112,14 @@ pub(crate) struct UnnameableTypesLint<'a> { // They will replace private-in-public errors and compatibility lints in future. // See https://rust-lang.github.io/rfcs/2145-type-privacy.html for more details. #[derive(LintDiagnostic)] -#[diag(privacy_private_interface_or_bounds_lint)] +#[diag("{$ty_kind} `{$ty_descr}` is more private than the item `{$item_descr}`")] pub(crate) struct PrivateInterfacesOrBoundsLint<'a> { - #[label(privacy_item_label)] + #[label("{$item_kind} `{$item_descr}` is reachable at visibility `{$item_vis_descr}`")] pub item_span: Span, pub item_kind: &'a str, pub item_descr: DiagArgFromDisplay<'a>, pub item_vis_descr: &'a str, - #[note(privacy_ty_note)] + #[note("but {$ty_kind} `{$ty_descr}` is only usable at visibility `{$ty_vis_descr}`")] pub ty_span: Span, pub ty_kind: &'a str, pub ty_descr: DiagArgFromDisplay<'a>, diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 333677521023..4a88ea0cc445 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -39,8 +39,6 @@ use rustc_span::hygiene::Transparency; use rustc_span::{Ident, Span, Symbol, sym}; use tracing::debug; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - //////////////////////////////////////////////////////////////////////////////// // Generic infrastructure used to implement specific visitors below. //////////////////////////////////////////////////////////////////////////////// From f2fff8ee547b36dd96209a8d7d77635105a3352f Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Wed, 4 Feb 2026 07:02:48 +0000 Subject: [PATCH 509/978] Port reexport_test_harness_main. --- .../src/attributes/test_attrs.rs | 27 ++++ compiler/rustc_attr_parsing/src/context.rs | 1 + .../rustc_hir/src/attrs/data_structures.rs | 3 + .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 4 +- .../issue-43106-gating-of-builtin-attrs.rs | 12 +- ...issue-43106-gating-of-builtin-attrs.stderr | 141 ++++++++++-------- 7 files changed, 115 insertions(+), 74 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index ec7cdd3624dc..236d10d77b92 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -113,3 +113,30 @@ impl NoArgsAttributeParser for RustcVarianceOfOpaquesParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcVarianceOfOpaques; } + +pub(crate) struct ReexportTestHarnessMainParser; + +impl SingleAttributeParser for ReexportTestHarnessMainParser { + const PATH: &[Symbol] = &[sym::reexport_test_harness_main]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(nv) = args.name_value() else { + cx.expected_name_value( + args.span().unwrap_or(cx.inner_span), + Some(sym::reexport_test_harness_main), + ); + return None; + }; + + let Some(name) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + return None; + }; + + Some(AttributeKind::ReexportTestHarnessMain(name)) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index fa9f5b585926..63795886785b 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -188,6 +188,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 6138ffc8d954..1634c726e32a 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -990,6 +990,9 @@ pub enum AttributeKind { /// Represents [`#[recursion_limit]`](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute) RecursionLimit { attr_span: Span, limit_span: Span, limit: Limit }, + /// Represents `#[reexport_test_harness_main]` + ReexportTestHarnessMain(Symbol), + /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations). Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span }, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 7ec1920152a5..5162c6feec31 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -87,6 +87,7 @@ impl AttributeKind { ProcMacroDerive { .. } => No, ProfilerRuntime => No, RecursionLimit { .. } => No, + ReexportTestHarnessMain(..) => No, Repr { .. } => No, RustcAllocator => No, RustcAllocatorZeroed => No, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4784456a59d9..2dd87391ed9a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -284,6 +284,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::Pointee(..) | AttributeKind::ProfilerRuntime | AttributeKind::RecursionLimit { .. } + | AttributeKind::ReexportTestHarnessMain(..) // handled below this loop and elsewhere | AttributeKind::Repr { .. } | AttributeKind::RustcAllocator @@ -414,8 +415,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::feature | sym::register_tool | sym::rustc_no_implicit_bounds - | sym::test_runner - | sym::reexport_test_harness_main, + | sym::test_runner, .. ] => {} [name, rest@..] => { diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs index 9695a73c137f..83debd17777a 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs @@ -467,26 +467,26 @@ mod no_implicit_prelude { #[reexport_test_harness_main = "2900"] //~^ WARN crate-level attribute should be -//~| HELP add a `!` mod reexport_test_harness_main { +//~^ NOTE this attribute does not have an `!`, which means it is applied to this module mod inner { #![reexport_test_harness_main="2900"] } - //~^ WARN crate-level attribute should be + //~^ WARN the `#![reexport_test_harness_main]` attribute can only be used at the crate root #[reexport_test_harness_main = "2900"] fn f() { } //~^ WARN crate-level attribute should be - //~| HELP add a `!` + //~| NOTE this attribute does not have an `!`, which means it is applied to this function #[reexport_test_harness_main = "2900"] struct S; //~^ WARN crate-level attribute should be - //~| HELP add a `!` + //~| NOTE this attribute does not have an `!`, which means it is applied to this struct #[reexport_test_harness_main = "2900"] type T = S; //~^ WARN crate-level attribute should be - //~| HELP add a `!` + //~| NOTE this attribute does not have an `!`, which means it is applied to this type alias #[reexport_test_harness_main = "2900"] impl S { } //~^ WARN crate-level attribute should be - //~| HELP add a `!` + //~| NOTE this attribute does not have an `!`, which means it is applied to this implementation block } // Cannot feed "2700" to `#[macro_escape]` without signaling an error. diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index d69daf45b352..482980dde3bf 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -186,22 +186,6 @@ warning: unknown lint: `x5100` LL | #[deny(x5100)] impl S { } | ^^^^^ -warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:468:1 - | -LL | #[reexport_test_harness_main = "2900"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:36:9 - | -LL | #![warn(unused_attributes, unknown_lints)] - | ^^^^^^^^^^^^^^^^^ -help: add a `!` - | -LL | #![reexport_test_harness_main = "2900"] - | + - warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/issue-43106-gating-of-builtin-attrs.rs:710:1 | @@ -217,6 +201,11 @@ LL | | } | |_- not an `extern` block | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +note: the lint level is defined here + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:36:9 + | +LL | #![warn(unused_attributes, unknown_lints)] + | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute --> $DIR/issue-43106-gating-of-builtin-attrs.rs:860:1 @@ -245,56 +234,6 @@ LL | #![feature(rust1)] | = note: `#[warn(stable_features)]` on by default -warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:472:17 - | -LL | mod inner { #![reexport_test_harness_main="2900"] } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:475:5 - | -LL | #[reexport_test_harness_main = "2900"] fn f() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: add a `!` - | -LL | #![reexport_test_harness_main = "2900"] fn f() { } - | + - -warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:5 - | -LL | #[reexport_test_harness_main = "2900"] struct S; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: add a `!` - | -LL | #![reexport_test_harness_main = "2900"] struct S; - | + - -warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:5 - | -LL | #[reexport_test_harness_main = "2900"] type T = S; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: add a `!` - | -LL | #![reexport_test_harness_main = "2900"] type T = S; - | + - -warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:5 - | -LL | #[reexport_test_harness_main = "2900"] impl S { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: add a `!` - | -LL | #![reexport_test_harness_main = "2900"] impl S { } - | + - warning: attribute should be applied to an `extern` block with non-Rust ABI --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:17 | @@ -771,6 +710,76 @@ LL | #[no_implicit_prelude] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[no_implicit_prelude]` can be applied to crates and modules +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![reexport_test_harness_main]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:468:1 + | +LL | #[reexport_test_harness_main = "2900"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this module + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:1 + | +LL | / mod reexport_test_harness_main { +LL | | +LL | | mod inner { #![reexport_test_harness_main="2900"] } +... | +LL | | } + | |_^ + +warning: the `#![reexport_test_harness_main]` attribute can only be used at the crate root + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:472:17 + | +LL | mod inner { #![reexport_test_harness_main="2900"] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![reexport_test_harness_main]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:475:5 + | +LL | #[reexport_test_harness_main = "2900"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this function + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:475:44 + | +LL | #[reexport_test_harness_main = "2900"] fn f() { } + | ^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![reexport_test_harness_main]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:5 + | +LL | #[reexport_test_harness_main = "2900"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this struct + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:44 + | +LL | #[reexport_test_harness_main = "2900"] struct S; + | ^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![reexport_test_harness_main]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:5 + | +LL | #[reexport_test_harness_main = "2900"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this type alias + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:44 + | +LL | #[reexport_test_harness_main = "2900"] type T = S; + | ^^^^^^^^^^^ + +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![reexport_test_harness_main]` + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:5 + | +LL | #[reexport_test_harness_main = "2900"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this implementation block + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:44 + | +LL | #[reexport_test_harness_main = "2900"] impl S { } + | ^^^^^^^^^^ + warning: `#[macro_escape]` attribute cannot be used on functions --> $DIR/issue-43106-gating-of-builtin-attrs.rs:500:5 | From 7dbbab63e242e2e09902930b630cc0898bc55537 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 31 Jan 2026 23:27:51 +0100 Subject: [PATCH 510/978] Emit a future error warning for duplicate doc attribute --- .../rustc_attr_parsing/src/attributes/doc.rs | 13 ++++++++-- compiler/rustc_lint_defs/src/builtin.rs | 2 +- tests/rustdoc-ui/deprecated-attrs.rs | 4 ++- tests/rustdoc-ui/deprecated-attrs.stderr | 12 ++++++--- tests/rustdoc-ui/doc-cfg-2.rs | 1 + tests/rustdoc-ui/doc-cfg-2.stderr | 26 +++++++++++-------- tests/rustdoc-ui/doc-include-suggestion.rs | 4 ++- .../rustdoc-ui/doc-include-suggestion.stderr | 8 ++++-- tests/rustdoc-ui/doctest/doc-test-attr.rs | 1 + tests/rustdoc-ui/doctest/doc-test-attr.stderr | 12 ++++++--- tests/rustdoc-ui/lints/doc-attr-2.rs | 1 + tests/rustdoc-ui/lints/doc-attr-2.stderr | 14 ++++++---- tests/rustdoc-ui/lints/doc-spotlight.fixed | 1 + tests/rustdoc-ui/lints/doc-spotlight.rs | 1 + tests/rustdoc-ui/lints/doc-spotlight.stderr | 8 ++++-- tests/rustdoc-ui/lints/doc_cfg_hide.rs | 1 + tests/rustdoc-ui/lints/doc_cfg_hide.stderr | 12 ++++++--- tests/rustdoc-ui/lints/duplicated-attr.rs | 6 +++++ tests/rustdoc-ui/lints/duplicated-attr.stderr | 20 ++++++++++++++ .../lints/invalid-crate-level-lint.rs | 1 + .../lints/invalid-crate-level-lint.stderr | 12 ++++++--- tests/rustdoc-ui/lints/invalid-doc-attr.rs | 1 + .../rustdoc-ui/lints/invalid-doc-attr.stderr | 21 +++++++++------ tests/ui/attributes/doc-attr.rs | 1 + tests/ui/attributes/doc-attr.stderr | 20 ++++++++------ ...atures-note-version-and-pr-issue-141619.rs | 1 + ...es-note-version-and-pr-issue-141619.stderr | 10 ++++--- tests/ui/repr/invalid_repr_list_help.rs | 1 + tests/ui/repr/invalid_repr_list_help.stderr | 18 ++++++++----- 29 files changed, 166 insertions(+), 67 deletions(-) create mode 100644 tests/rustdoc-ui/lints/duplicated-attr.rs create mode 100644 tests/rustdoc-ui/lints/duplicated-attr.stderr diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index a287c0c5a930..8b1966a836f1 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -131,8 +131,17 @@ impl DocParser { return; } - if self.attribute.no_crate_inject.is_some() { - cx.duplicate_key(path.span(), sym::no_crate_inject); + if let Some(used_span) = self.attribute.no_crate_inject { + let unused_span = path.span(); + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::UnusedDuplicate { + this: unused_span, + other: used_span, + warning: true, + }, + unused_span, + ); return; } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index d1d5d0a56ead..f4e6e93356c7 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3458,7 +3458,7 @@ declare_lint! { /// but this lint was introduced to avoid breaking any existing /// crates which included them. pub INVALID_DOC_ATTRIBUTES, - Deny, + Warn, "detects invalid `#[doc(...)]` attributes", } diff --git a/tests/rustdoc-ui/deprecated-attrs.rs b/tests/rustdoc-ui/deprecated-attrs.rs index 26aaf0d46808..dcca3114fb7d 100644 --- a/tests/rustdoc-ui/deprecated-attrs.rs +++ b/tests/rustdoc-ui/deprecated-attrs.rs @@ -1,11 +1,13 @@ //@ compile-flags: --passes unknown-pass +#![deny(invalid_doc_attributes)] +//~^ NOTE + #![doc(no_default_passes)] //~^ ERROR unknown `doc` attribute `no_default_passes` //~| NOTE no longer functions //~| NOTE see issue #44136 //~| NOTE `doc(no_default_passes)` is now a no-op -//~| NOTE `#[deny(invalid_doc_attributes)]` on by default #![doc(passes = "collapse-docs unindent-comments")] //~^ ERROR unknown `doc` attribute `passes` //~| NOTE no longer functions diff --git a/tests/rustdoc-ui/deprecated-attrs.stderr b/tests/rustdoc-ui/deprecated-attrs.stderr index 6135b1496925..e32a1eb3370d 100644 --- a/tests/rustdoc-ui/deprecated-attrs.stderr +++ b/tests/rustdoc-ui/deprecated-attrs.stderr @@ -4,17 +4,21 @@ warning: the `passes` flag no longer functions = help: you may want to use --document-private-items error: unknown `doc` attribute `no_default_passes` - --> $DIR/deprecated-attrs.rs:3:8 + --> $DIR/deprecated-attrs.rs:6:8 | LL | #![doc(no_default_passes)] | ^^^^^^^^^^^^^^^^^ no longer functions | = note: `doc` attribute `no_default_passes` no longer functions; see issue #44136 = note: `doc(no_default_passes)` is now a no-op - = note: `#[deny(invalid_doc_attributes)]` on by default +note: the lint level is defined here + --> $DIR/deprecated-attrs.rs:3:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: unknown `doc` attribute `passes` - --> $DIR/deprecated-attrs.rs:9:8 + --> $DIR/deprecated-attrs.rs:11:8 | LL | #![doc(passes = "collapse-docs unindent-comments")] | ^^^^^^ no longer functions @@ -23,7 +27,7 @@ LL | #![doc(passes = "collapse-docs unindent-comments")] = note: `doc(passes)` is now a no-op error: unknown `doc` attribute `plugins` - --> $DIR/deprecated-attrs.rs:14:8 + --> $DIR/deprecated-attrs.rs:16:8 | LL | #![doc(plugins = "xxx")] | ^^^^^^^ no longer functions diff --git a/tests/rustdoc-ui/doc-cfg-2.rs b/tests/rustdoc-ui/doc-cfg-2.rs index 7a5d1f3e3dbb..f615e96bbc6b 100644 --- a/tests/rustdoc-ui/doc-cfg-2.rs +++ b/tests/rustdoc-ui/doc-cfg-2.rs @@ -1,3 +1,4 @@ +#![deny(invalid_doc_attributes)] #![feature(doc_cfg)] #[doc(cfg(foo), cfg(bar))] diff --git a/tests/rustdoc-ui/doc-cfg-2.stderr b/tests/rustdoc-ui/doc-cfg-2.stderr index 1272e569897b..a842cbc40288 100644 --- a/tests/rustdoc-ui/doc-cfg-2.stderr +++ b/tests/rustdoc-ui/doc-cfg-2.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `foo` - --> $DIR/doc-cfg-2.rs:3:11 + --> $DIR/doc-cfg-2.rs:4:11 | LL | #[doc(cfg(foo), cfg(bar))] | ^^^ @@ -10,7 +10,7 @@ LL | #[doc(cfg(foo), cfg(bar))] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `bar` - --> $DIR/doc-cfg-2.rs:3:21 + --> $DIR/doc-cfg-2.rs:4:21 | LL | #[doc(cfg(foo), cfg(bar))] | ^^^ @@ -19,45 +19,49 @@ LL | #[doc(cfg(foo), cfg(bar))] = note: see for more information about checking conditional configuration error: only `hide` or `show` are allowed in `#[doc(auto_cfg(...))]` - --> $DIR/doc-cfg-2.rs:6:16 + --> $DIR/doc-cfg-2.rs:7:16 | LL | #[doc(auto_cfg(42))] | ^^ | - = note: `#[deny(invalid_doc_attributes)]` on by default +note: the lint level is defined here + --> $DIR/doc-cfg-2.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or key/value items - --> $DIR/doc-cfg-2.rs:7:21 + --> $DIR/doc-cfg-2.rs:8:21 | LL | #[doc(auto_cfg(hide(true)))] | ^^^^ error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or key/value items - --> $DIR/doc-cfg-2.rs:8:21 + --> $DIR/doc-cfg-2.rs:9:21 | LL | #[doc(auto_cfg(hide(42)))] | ^^ error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or key/value items - --> $DIR/doc-cfg-2.rs:9:21 + --> $DIR/doc-cfg-2.rs:10:21 | LL | #[doc(auto_cfg(hide("a")))] | ^^^ error: expected boolean for `#[doc(auto_cfg = ...)]` - --> $DIR/doc-cfg-2.rs:10:18 + --> $DIR/doc-cfg-2.rs:11:18 | LL | #[doc(auto_cfg = 42)] | ^^ error: expected boolean for `#[doc(auto_cfg = ...)]` - --> $DIR/doc-cfg-2.rs:11:18 + --> $DIR/doc-cfg-2.rs:12:18 | LL | #[doc(auto_cfg = "a")] | ^^^ warning: unexpected `cfg` condition name: `feature` - --> $DIR/doc-cfg-2.rs:14:21 + --> $DIR/doc-cfg-2.rs:15:21 | LL | #[doc(auto_cfg(hide(feature = "windows")))] | ^^^^^^^^^^^^^^^^^^^ @@ -66,7 +70,7 @@ LL | #[doc(auto_cfg(hide(feature = "windows")))] = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `foo` - --> $DIR/doc-cfg-2.rs:16:21 + --> $DIR/doc-cfg-2.rs:17:21 | LL | #[doc(auto_cfg(hide(foo)))] | ^^^ diff --git a/tests/rustdoc-ui/doc-include-suggestion.rs b/tests/rustdoc-ui/doc-include-suggestion.rs index aff0a24ace86..1295805ae1a0 100644 --- a/tests/rustdoc-ui/doc-include-suggestion.rs +++ b/tests/rustdoc-ui/doc-include-suggestion.rs @@ -1,6 +1,8 @@ +#![deny(invalid_doc_attributes)] +//~^ NOTE + #[doc(include = "external-cross-doc.md")] //~^ ERROR unknown `doc` attribute `include` //~| HELP use `doc = include_str!` instead // FIXME(#85497): make this a deny instead so it's more clear what's happening -//~| NOTE on by default pub struct NeedMoreDocs; diff --git a/tests/rustdoc-ui/doc-include-suggestion.stderr b/tests/rustdoc-ui/doc-include-suggestion.stderr index ea5261e5bbd4..1587984b6e6e 100644 --- a/tests/rustdoc-ui/doc-include-suggestion.stderr +++ b/tests/rustdoc-ui/doc-include-suggestion.stderr @@ -1,10 +1,14 @@ error: unknown `doc` attribute `include` - --> $DIR/doc-include-suggestion.rs:1:7 + --> $DIR/doc-include-suggestion.rs:4:7 | LL | #[doc(include = "external-cross-doc.md")] | ^^^^^^^ help: use `doc = include_str!` instead: `#[doc = include_str!("external-cross-doc.md")]` | - = note: `#[deny(invalid_doc_attributes)]` on by default +note: the lint level is defined here + --> $DIR/doc-include-suggestion.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/doctest/doc-test-attr.rs b/tests/rustdoc-ui/doctest/doc-test-attr.rs index 8570252c4493..e664f75a9cf7 100644 --- a/tests/rustdoc-ui/doctest/doc-test-attr.rs +++ b/tests/rustdoc-ui/doctest/doc-test-attr.rs @@ -1,3 +1,4 @@ +#![deny(invalid_doc_attributes)] #![crate_type = "lib"] #![doc(test)] diff --git a/tests/rustdoc-ui/doctest/doc-test-attr.stderr b/tests/rustdoc-ui/doctest/doc-test-attr.stderr index cf7bce66ef40..98e7b315ea57 100644 --- a/tests/rustdoc-ui/doctest/doc-test-attr.stderr +++ b/tests/rustdoc-ui/doctest/doc-test-attr.stderr @@ -1,19 +1,23 @@ error: `#[doc(test(...)]` takes a list of attributes - --> $DIR/doc-test-attr.rs:3:8 + --> $DIR/doc-test-attr.rs:4:8 | LL | #![doc(test)] | ^^^^ | - = note: `#[deny(invalid_doc_attributes)]` on by default +note: the lint level is defined here + --> $DIR/doc-test-attr.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: `#[doc(test(...)]` takes a list of attributes - --> $DIR/doc-test-attr.rs:5:13 + --> $DIR/doc-test-attr.rs:6:13 | LL | #![doc(test = "hello")] | ^^^^^^^^^ error: unknown `doc(test)` attribute `a` - --> $DIR/doc-test-attr.rs:7:13 + --> $DIR/doc-test-attr.rs:8:13 | LL | #![doc(test(a))] | ^ diff --git a/tests/rustdoc-ui/lints/doc-attr-2.rs b/tests/rustdoc-ui/lints/doc-attr-2.rs index e5198e347523..9802fb5d95a5 100644 --- a/tests/rustdoc-ui/lints/doc-attr-2.rs +++ b/tests/rustdoc-ui/lints/doc-attr-2.rs @@ -1,3 +1,4 @@ +#![deny(invalid_doc_attributes)] #![doc(as_ptr)] //~^ ERROR unknown `doc` attribute `as_ptr` diff --git a/tests/rustdoc-ui/lints/doc-attr-2.stderr b/tests/rustdoc-ui/lints/doc-attr-2.stderr index c2bb45c5785e..f96eab1aba61 100644 --- a/tests/rustdoc-ui/lints/doc-attr-2.stderr +++ b/tests/rustdoc-ui/lints/doc-attr-2.stderr @@ -1,25 +1,29 @@ error: unknown `doc` attribute `as_ptr` - --> $DIR/doc-attr-2.rs:4:7 + --> $DIR/doc-attr-2.rs:5:7 | LL | #[doc(as_ptr)] | ^^^^^^ | - = note: `#[deny(invalid_doc_attributes)]` on by default +note: the lint level is defined here + --> $DIR/doc-attr-2.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: unknown `doc` attribute `foo::bar` - --> $DIR/doc-attr-2.rs:8:7 + --> $DIR/doc-attr-2.rs:9:7 | LL | #[doc(foo::bar, crate::bar::baz = "bye")] | ^^^^^^^^ error: unknown `doc` attribute `crate::bar::baz` - --> $DIR/doc-attr-2.rs:8:17 + --> $DIR/doc-attr-2.rs:9:17 | LL | #[doc(foo::bar, crate::bar::baz = "bye")] | ^^^^^^^^^^^^^^^ error: unknown `doc` attribute `as_ptr` - --> $DIR/doc-attr-2.rs:1:8 + --> $DIR/doc-attr-2.rs:2:8 | LL | #![doc(as_ptr)] | ^^^^^^ diff --git a/tests/rustdoc-ui/lints/doc-spotlight.fixed b/tests/rustdoc-ui/lints/doc-spotlight.fixed index 0f8f11a9430e..98b0fac87898 100644 --- a/tests/rustdoc-ui/lints/doc-spotlight.fixed +++ b/tests/rustdoc-ui/lints/doc-spotlight.fixed @@ -1,5 +1,6 @@ //@ run-rustfix #![feature(doc_notable_trait)] +#![deny(invalid_doc_attributes)] #[doc(notable_trait)] //~^ ERROR unknown `doc` attribute `spotlight` diff --git a/tests/rustdoc-ui/lints/doc-spotlight.rs b/tests/rustdoc-ui/lints/doc-spotlight.rs index c1f90dd442b2..a0d874bdcb21 100644 --- a/tests/rustdoc-ui/lints/doc-spotlight.rs +++ b/tests/rustdoc-ui/lints/doc-spotlight.rs @@ -1,5 +1,6 @@ //@ run-rustfix #![feature(doc_notable_trait)] +#![deny(invalid_doc_attributes)] #[doc(spotlight)] //~^ ERROR unknown `doc` attribute `spotlight` diff --git a/tests/rustdoc-ui/lints/doc-spotlight.stderr b/tests/rustdoc-ui/lints/doc-spotlight.stderr index 9682a3c0c8be..8c6f9738bdc0 100644 --- a/tests/rustdoc-ui/lints/doc-spotlight.stderr +++ b/tests/rustdoc-ui/lints/doc-spotlight.stderr @@ -1,12 +1,16 @@ error: unknown `doc` attribute `spotlight` - --> $DIR/doc-spotlight.rs:4:7 + --> $DIR/doc-spotlight.rs:5:7 | LL | #[doc(spotlight)] | ^^^^^^^^^ help: use `notable_trait` instead | = note: `doc(spotlight)` was renamed to `doc(notable_trait)` = note: `doc(spotlight)` is now a no-op - = note: `#[deny(invalid_doc_attributes)]` on by default +note: the lint level is defined here + --> $DIR/doc-spotlight.rs:3:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/lints/doc_cfg_hide.rs b/tests/rustdoc-ui/lints/doc_cfg_hide.rs index 397b21393e5c..6c190f9befac 100644 --- a/tests/rustdoc-ui/lints/doc_cfg_hide.rs +++ b/tests/rustdoc-ui/lints/doc_cfg_hide.rs @@ -1,3 +1,4 @@ +#![deny(invalid_doc_attributes)] #![feature(doc_cfg)] #![doc(auto_cfg(hide = "test"))] //~ ERROR #![doc(auto_cfg(hide))] //~ ERROR diff --git a/tests/rustdoc-ui/lints/doc_cfg_hide.stderr b/tests/rustdoc-ui/lints/doc_cfg_hide.stderr index acbe6ef69dd5..a5ec8fdf5d34 100644 --- a/tests/rustdoc-ui/lints/doc_cfg_hide.stderr +++ b/tests/rustdoc-ui/lints/doc_cfg_hide.stderr @@ -1,19 +1,23 @@ error: `#![doc(auto_cfg(hide(...)))]` expects a list of items - --> $DIR/doc_cfg_hide.rs:2:17 + --> $DIR/doc_cfg_hide.rs:3:17 | LL | #![doc(auto_cfg(hide = "test"))] | ^^^^^^^^^^^^^ | - = note: `#[deny(invalid_doc_attributes)]` on by default +note: the lint level is defined here + --> $DIR/doc_cfg_hide.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: `#![doc(auto_cfg(hide(...)))]` expects a list of items - --> $DIR/doc_cfg_hide.rs:3:17 + --> $DIR/doc_cfg_hide.rs:4:17 | LL | #![doc(auto_cfg(hide))] | ^^^^ error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or key/value items - --> $DIR/doc_cfg_hide.rs:4:22 + --> $DIR/doc_cfg_hide.rs:5:22 | LL | #![doc(auto_cfg(hide(not(windows))))] | ^^^^^^^^^^^^ diff --git a/tests/rustdoc-ui/lints/duplicated-attr.rs b/tests/rustdoc-ui/lints/duplicated-attr.rs new file mode 100644 index 000000000000..b89908d700f4 --- /dev/null +++ b/tests/rustdoc-ui/lints/duplicated-attr.rs @@ -0,0 +1,6 @@ +#![deny(invalid_doc_attributes)] +#![expect(unused_attributes)] +#![doc(test(no_crate_inject))] +#![doc(test(no_crate_inject))] +//~^ ERROR +//~| WARN diff --git a/tests/rustdoc-ui/lints/duplicated-attr.stderr b/tests/rustdoc-ui/lints/duplicated-attr.stderr new file mode 100644 index 000000000000..3682710bb54a --- /dev/null +++ b/tests/rustdoc-ui/lints/duplicated-attr.stderr @@ -0,0 +1,20 @@ +error: unused attribute + --> $DIR/duplicated-attr.rs:4:13 + | +LL | #![doc(test(no_crate_inject))] + | ^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/duplicated-attr.rs:3:13 + | +LL | #![doc(test(no_crate_inject))] + | ^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +note: the lint level is defined here + --> $DIR/duplicated-attr.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/rustdoc-ui/lints/invalid-crate-level-lint.rs b/tests/rustdoc-ui/lints/invalid-crate-level-lint.rs index 275e20e80a17..afb0a5987deb 100644 --- a/tests/rustdoc-ui/lints/invalid-crate-level-lint.rs +++ b/tests/rustdoc-ui/lints/invalid-crate-level-lint.rs @@ -1,3 +1,4 @@ +#![deny(invalid_doc_attributes)] #![crate_type = "lib"] #[doc(test(no_crate_inject))] diff --git a/tests/rustdoc-ui/lints/invalid-crate-level-lint.stderr b/tests/rustdoc-ui/lints/invalid-crate-level-lint.stderr index fdb95e7de41c..7569cf575e51 100644 --- a/tests/rustdoc-ui/lints/invalid-crate-level-lint.stderr +++ b/tests/rustdoc-ui/lints/invalid-crate-level-lint.stderr @@ -1,14 +1,18 @@ error: this attribute can only be applied at the crate level - --> $DIR/invalid-crate-level-lint.rs:3:12 + --> $DIR/invalid-crate-level-lint.rs:4:12 | LL | #[doc(test(no_crate_inject))] | ^^^^^^^^^^^^^^^ | = note: read for more information - = note: `#[deny(invalid_doc_attributes)]` on by default +note: the lint level is defined here + --> $DIR/invalid-crate-level-lint.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: this attribute can only be applied at the crate level - --> $DIR/invalid-crate-level-lint.rs:7:17 + --> $DIR/invalid-crate-level-lint.rs:8:17 | LL | #![doc(test(no_crate_inject))] | ^^^^^^^^^^^^^^^ @@ -16,7 +20,7 @@ LL | #![doc(test(no_crate_inject))] = note: read for more information error: this attribute can only be applied at the crate level - --> $DIR/invalid-crate-level-lint.rs:10:16 + --> $DIR/invalid-crate-level-lint.rs:11:16 | LL | #[doc(test(no_crate_inject))] | ^^^^^^^^^^^^^^^ diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.rs b/tests/rustdoc-ui/lints/invalid-doc-attr.rs index 169d092d7e17..60c215222d7f 100644 --- a/tests/rustdoc-ui/lints/invalid-doc-attr.rs +++ b/tests/rustdoc-ui/lints/invalid-doc-attr.rs @@ -1,3 +1,4 @@ +#![deny(invalid_doc_attributes)] #![crate_type = "lib"] #![feature(doc_masked)] diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr index e431b8df2263..2e9b9f0a8cfb 100644 --- a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr +++ b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr @@ -1,5 +1,5 @@ error: this attribute can only be applied to a `use` item - --> $DIR/invalid-doc-attr.rs:7:7 + --> $DIR/invalid-doc-attr.rs:8:7 | LL | #[doc(inline)] | ^^^^^^ only applicable on `use` items @@ -8,10 +8,14 @@ LL | pub fn foo() {} | ------------ not a `use` item | = note: read for more information - = note: `#[deny(invalid_doc_attributes)]` on by default +note: the lint level is defined here + --> $DIR/invalid-doc-attr.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: conflicting doc inlining attributes - --> $DIR/invalid-doc-attr.rs:17:7 + --> $DIR/invalid-doc-attr.rs:18:7 | LL | #[doc(inline)] | ^^^^^^ this attribute... @@ -21,7 +25,7 @@ LL | #[doc(no_inline)] = help: remove one of the conflicting attributes error: this attribute can only be applied to an `extern crate` item - --> $DIR/invalid-doc-attr.rs:23:7 + --> $DIR/invalid-doc-attr.rs:24:7 | LL | #[doc(masked)] | ^^^^^^ only applicable on `extern crate` items @@ -32,7 +36,7 @@ LL | pub struct Masked; = note: read for more information error: this attribute cannot be applied to an `extern crate self` item - --> $DIR/invalid-doc-attr.rs:27:7 + --> $DIR/invalid-doc-attr.rs:28:7 | LL | #[doc(masked)] | ^^^^^^ not applicable on `extern crate self` items @@ -41,9 +45,10 @@ LL | pub extern crate self as reexport; | --------------------------------- `extern crate self` defined here error: this attribute can only be applied to an `extern crate` item - --> $DIR/invalid-doc-attr.rs:4:8 + --> $DIR/invalid-doc-attr.rs:5:8 | -LL | / #![crate_type = "lib"] +LL | / #![deny(invalid_doc_attributes)] +LL | | #![crate_type = "lib"] LL | | #![feature(doc_masked)] LL | | LL | | #![doc(masked)] @@ -55,7 +60,7 @@ LL | | pub extern crate self as reexport; = note: read for more information error: this attribute can only be applied to a `use` item - --> $DIR/invalid-doc-attr.rs:12:11 + --> $DIR/invalid-doc-attr.rs:13:11 | LL | #[doc(inline)] | ^^^^^^ only applicable on `use` items diff --git a/tests/ui/attributes/doc-attr.rs b/tests/ui/attributes/doc-attr.rs index 8d733be93567..b45f211f6222 100644 --- a/tests/ui/attributes/doc-attr.rs +++ b/tests/ui/attributes/doc-attr.rs @@ -1,3 +1,4 @@ +#![deny(invalid_doc_attributes)] #![crate_type = "lib"] #![doc(as_ptr)] //~^ ERROR unknown `doc` attribute diff --git a/tests/ui/attributes/doc-attr.stderr b/tests/ui/attributes/doc-attr.stderr index dfc0e8ad5b6f..005810fa23fa 100644 --- a/tests/ui/attributes/doc-attr.stderr +++ b/tests/ui/attributes/doc-attr.stderr @@ -1,5 +1,5 @@ error[E0539]: malformed `doc` attribute input - --> $DIR/doc-attr.rs:9:1 + --> $DIR/doc-attr.rs:10:1 | LL | #[doc(123)] | ^^^^^^---^^ @@ -7,7 +7,7 @@ LL | #[doc(123)] | expected this to be of the form `... = "..."` error[E0539]: malformed `doc` attribute input - --> $DIR/doc-attr.rs:11:1 + --> $DIR/doc-attr.rs:12:1 | LL | #[doc("hello", "bar")] | ^^^^^^-------^^^^^^^^^ @@ -15,7 +15,7 @@ LL | #[doc("hello", "bar")] | expected this to be of the form `... = "..."` error[E0539]: malformed `doc` attribute input - --> $DIR/doc-attr.rs:11:1 + --> $DIR/doc-attr.rs:12:1 | LL | #[doc("hello", "bar")] | ^^^^^^^^^^^^^^^-----^^ @@ -23,27 +23,31 @@ LL | #[doc("hello", "bar")] | expected this to be of the form `... = "..."` error: unknown `doc` attribute `as_ptr` - --> $DIR/doc-attr.rs:5:7 + --> $DIR/doc-attr.rs:6:7 | LL | #[doc(as_ptr)] | ^^^^^^ | - = note: `#[deny(invalid_doc_attributes)]` on by default +note: the lint level is defined here + --> $DIR/doc-attr.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: unknown `doc` attribute `foo::bar` - --> $DIR/doc-attr.rs:14:7 + --> $DIR/doc-attr.rs:15:7 | LL | #[doc(foo::bar, crate::bar::baz = "bye")] | ^^^^^^^^ error: unknown `doc` attribute `crate::bar::baz` - --> $DIR/doc-attr.rs:14:17 + --> $DIR/doc-attr.rs:15:17 | LL | #[doc(foo::bar, crate::bar::baz = "bye")] | ^^^^^^^^^^^^^^^ error: unknown `doc` attribute `as_ptr` - --> $DIR/doc-attr.rs:2:8 + --> $DIR/doc-attr.rs:3:8 | LL | #![doc(as_ptr)] | ^^^^^^ diff --git a/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.rs b/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.rs index d8c5f48f9fd9..a7dde7c97f6a 100644 --- a/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.rs +++ b/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.rs @@ -1,3 +1,4 @@ +#![deny(invalid_doc_attributes)] #![feature(external_doc)] //~ ERROR feature has been removed #![doc(include("README.md"))] //~ ERROR unknown `doc` attribute `include` diff --git a/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.stderr b/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.stderr index d9556560b01c..a009898761df 100644 --- a/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.stderr +++ b/tests/ui/feature-gates/removed-features-note-version-and-pr-issue-141619.stderr @@ -1,5 +1,5 @@ error[E0557]: feature has been removed - --> $DIR/removed-features-note-version-and-pr-issue-141619.rs:1:12 + --> $DIR/removed-features-note-version-and-pr-issue-141619.rs:2:12 | LL | #![feature(external_doc)] | ^^^^^^^^^^^^ feature has been removed @@ -8,12 +8,16 @@ LL | #![feature(external_doc)] = note: use #[doc = include_str!("filename")] instead, which handles macro invocations error: unknown `doc` attribute `include` - --> $DIR/removed-features-note-version-and-pr-issue-141619.rs:2:8 + --> $DIR/removed-features-note-version-and-pr-issue-141619.rs:3:8 | LL | #![doc(include("README.md"))] | ^^^^^^^ | - = note: `#[deny(invalid_doc_attributes)]` on by default +note: the lint level is defined here + --> $DIR/removed-features-note-version-and-pr-issue-141619.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/repr/invalid_repr_list_help.rs b/tests/ui/repr/invalid_repr_list_help.rs index 77f2a68537b3..e8bf5fdcd3fd 100644 --- a/tests/ui/repr/invalid_repr_list_help.rs +++ b/tests/ui/repr/invalid_repr_list_help.rs @@ -1,3 +1,4 @@ +#![deny(invalid_doc_attributes)] #![crate_type = "lib"] #[repr(uwu)] //~ERROR: unrecognized representation hint diff --git a/tests/ui/repr/invalid_repr_list_help.stderr b/tests/ui/repr/invalid_repr_list_help.stderr index f9d1593275ee..322650814828 100644 --- a/tests/ui/repr/invalid_repr_list_help.stderr +++ b/tests/ui/repr/invalid_repr_list_help.stderr @@ -1,5 +1,5 @@ error[E0552]: unrecognized representation hint - --> $DIR/invalid_repr_list_help.rs:3:8 + --> $DIR/invalid_repr_list_help.rs:4:8 | LL | #[repr(uwu)] | ^^^ @@ -8,7 +8,7 @@ LL | #[repr(uwu)] = note: for more information, visit error[E0552]: unrecognized representation hint - --> $DIR/invalid_repr_list_help.rs:6:8 + --> $DIR/invalid_repr_list_help.rs:7:8 | LL | #[repr(uwu = "a")] | ^^^^^^^^^ @@ -17,7 +17,7 @@ LL | #[repr(uwu = "a")] = note: for more information, visit error[E0552]: unrecognized representation hint - --> $DIR/invalid_repr_list_help.rs:9:8 + --> $DIR/invalid_repr_list_help.rs:10:8 | LL | #[repr(uwu(4))] | ^^^^^^ @@ -26,7 +26,7 @@ LL | #[repr(uwu(4))] = note: for more information, visit error[E0552]: unrecognized representation hint - --> $DIR/invalid_repr_list_help.rs:14:8 + --> $DIR/invalid_repr_list_help.rs:15:8 | LL | #[repr(uwu, u8)] | ^^^ @@ -35,7 +35,7 @@ LL | #[repr(uwu, u8)] = note: for more information, visit error[E0552]: unrecognized representation hint - --> $DIR/invalid_repr_list_help.rs:19:8 + --> $DIR/invalid_repr_list_help.rs:20:8 | LL | #[repr(uwu)] | ^^^ @@ -44,12 +44,16 @@ LL | #[repr(uwu)] = note: for more information, visit error: unknown `doc` attribute `owo` - --> $DIR/invalid_repr_list_help.rs:20:7 + --> $DIR/invalid_repr_list_help.rs:21:7 | LL | #[doc(owo)] | ^^^ | - = note: `#[deny(invalid_doc_attributes)]` on by default +note: the lint level is defined here + --> $DIR/invalid_repr_list_help.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors From 6d713489d00a87a683f253a242d71e717c8fcf26 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 1 Feb 2026 00:58:51 +0100 Subject: [PATCH 511/978] Make more doc attribute parsing error into future warnings --- .../rustc_attr_parsing/src/attributes/doc.rs | 19 ++++++++-- compiler/rustc_lint/messages.ftl | 4 +++ compiler/rustc_lint/src/early/diagnostics.rs | 2 ++ compiler/rustc_lint/src/lints.rs | 5 +++ compiler/rustc_lint_defs/src/lib.rs | 1 + tests/rustdoc-ui/lints/doc-attr.rs | 4 +++ tests/rustdoc-ui/lints/doc-attr.stderr | 36 ++++++++++--------- tests/rustdoc-ui/lints/invalid-doc-attr-2.rs | 7 ++++ .../lints/invalid-doc-attr-2.stderr | 21 +++++++++++ 9 files changed, 80 insertions(+), 19 deletions(-) create mode 100644 tests/rustdoc-ui/lints/invalid-doc-attr-2.rs create mode 100644 tests/rustdoc-ui/lints/invalid-doc-attr-2.stderr diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 8b1966a836f1..1bf5352ee838 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -591,7 +591,7 @@ impl DocParser { let suggestions = cx.suggestions(); let span = cx.attr_span; cx.emit_lint( - rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT, + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, AttributeLintKind::IllFormedAttributeInput { suggestions, docs: None }, span, ); @@ -604,14 +604,27 @@ impl DocParser { self.parse_single_doc_attr_item(cx, mip); } MetaItemOrLitParser::Lit(lit) => { - cx.expected_name_value(lit.span, None); + // FIXME: Remove the lint and uncomment line after beta backport is + // done. + // cx.expected_name_value(lit.span, None); + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::MalformedDoc, + lit.span, + ); } } } } ArgParser::NameValue(nv) => { if nv.value_as_str().is_none() { - cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + // FIXME: Remove the lint and uncomment line after beta backport is done. + // cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::MalformedDoc, + nv.value_span, + ); } else { unreachable!( "Should have been handled at the same time as sugar-syntaxed doc comments" diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 867b937d4090..ebee380765c6 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -558,6 +558,10 @@ lint_macro_expr_fragment_specifier_2024_migration = lint_malformed_attribute = malformed lint attribute input +lint_malformed_doc = + malformed `doc` attribute input + .warn = {-lint_previously_accepted} + lint_map_unit_fn = `Iterator::map` call that discard the iterator's values .note = `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated .function_label = this function returns `()`, which is likely not what you wanted diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 377b3c439453..1360ba2d9c1c 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -428,5 +428,7 @@ pub fn decorate_attribute_lint( sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }), } .decorate_lint(diag), + + &AttributeLintKind::MalformedDoc => lints::MalformedDoc.decorate_lint(diag), } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a20d90e1227e..0b5197d7ebdf 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3185,6 +3185,11 @@ pub(crate) struct UnusedDuplicate { pub warning: bool, } +#[derive(LintDiagnostic)] +#[diag(lint_malformed_doc)] +#[warning] +pub(crate) struct MalformedDoc; + #[derive(LintDiagnostic)] #[diag(lint_unsafe_attr_outside_unsafe)] pub(crate) struct UnsafeAttrOutsideUnsafeLint { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 4c78287b7784..ea2e67b8869b 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -826,6 +826,7 @@ pub enum AttributeLintKind { span: Span, suggested: Option, }, + MalformedDoc, } pub type RegisteredTools = FxIndexSet; diff --git a/tests/rustdoc-ui/lints/doc-attr.rs b/tests/rustdoc-ui/lints/doc-attr.rs index b27faa81cb92..f04961aa930a 100644 --- a/tests/rustdoc-ui/lints/doc-attr.rs +++ b/tests/rustdoc-ui/lints/doc-attr.rs @@ -1,8 +1,12 @@ #![crate_type = "lib"] +#![deny(invalid_doc_attributes)] #[doc(123)] //~^ ERROR malformed `doc` attribute +//~| WARN #[doc("hello", "bar")] //~^ ERROR malformed `doc` attribute //~| ERROR malformed `doc` attribute +//~| WARN +//~| WARN fn bar() {} diff --git a/tests/rustdoc-ui/lints/doc-attr.stderr b/tests/rustdoc-ui/lints/doc-attr.stderr index 8f8c6000b364..5b6f48acb3be 100644 --- a/tests/rustdoc-ui/lints/doc-attr.stderr +++ b/tests/rustdoc-ui/lints/doc-attr.stderr @@ -1,27 +1,31 @@ -error[E0539]: malformed `doc` attribute input - --> $DIR/doc-attr.rs:3:1 +error: malformed `doc` attribute input + --> $DIR/doc-attr.rs:4:7 | LL | #[doc(123)] - | ^^^^^^---^^ - | | - | expected this to be of the form `... = "..."` + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +note: the lint level is defined here + --> $DIR/doc-attr.rs:2:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0539]: malformed `doc` attribute input - --> $DIR/doc-attr.rs:5:1 +error: malformed `doc` attribute input + --> $DIR/doc-attr.rs:7:7 | LL | #[doc("hello", "bar")] - | ^^^^^^-------^^^^^^^^^ - | | - | expected this to be of the form `... = "..."` + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error[E0539]: malformed `doc` attribute input - --> $DIR/doc-attr.rs:5:1 +error: malformed `doc` attribute input + --> $DIR/doc-attr.rs:7:16 | LL | #[doc("hello", "bar")] - | ^^^^^^^^^^^^^^^-----^^ - | | - | expected this to be of the form `... = "..."` + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0539`. diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr-2.rs b/tests/rustdoc-ui/lints/invalid-doc-attr-2.rs new file mode 100644 index 000000000000..de99d5a9e078 --- /dev/null +++ b/tests/rustdoc-ui/lints/invalid-doc-attr-2.rs @@ -0,0 +1,7 @@ +#![deny(invalid_doc_attributes)] + +#![doc("other attribute")] +//~^ ERROR +//~| WARN +#![doc] +//~^ ERROR diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr-2.stderr b/tests/rustdoc-ui/lints/invalid-doc-attr-2.stderr new file mode 100644 index 000000000000..bfd926a2a517 --- /dev/null +++ b/tests/rustdoc-ui/lints/invalid-doc-attr-2.stderr @@ -0,0 +1,21 @@ +error: malformed `doc` attribute input + --> $DIR/invalid-doc-attr-2.rs:3:8 + | +LL | #![doc("other attribute")] + | ^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +note: the lint level is defined here + --> $DIR/invalid-doc-attr-2.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: valid forms for the attribute are `#![doc = "string"]`, `#![doc(alias)]`, `#![doc(attribute)]`, `#![doc(auto_cfg)]`, `#![doc(cfg)]`, `#![doc(fake_variadic)]`, `#![doc(hidden)]`, `#![doc(html_favicon_url)]`, `#![doc(html_logo_url)]`, `#![doc(html_no_source)]`, `#![doc(html_playground_url)]`, `#![doc(html_root_url)]`, `#![doc(include)]`, `#![doc(inline)]`, `#![doc(issue_tracker_base_url)]`, `#![doc(keyword)]`, `#![doc(masked)]`, `#![doc(no_default_passes)]`, `#![doc(no_inline)]`, `#![doc(notable_trait)]`, `#![doc(passes)]`, `#![doc(plugins)]`, `#![doc(rust_logo)]`, `#![doc(search_unbox)]`, `#![doc(spotlight)]`, and `#![doc(test)]` + --> $DIR/invalid-doc-attr-2.rs:6:1 + | +LL | #![doc] + | ^^^^^^^ + +error: aborting due to 2 previous errors + From c910511cab40e005fffbd5c31939f89448d030a8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 1 Feb 2026 14:59:29 +0100 Subject: [PATCH 512/978] Move remaining doc attribute parsing errors to warnings --- .../rustc_attr_parsing/src/attributes/doc.rs | 98 +++++++--- compiler/rustc_lint/messages.ftl | 8 + compiler/rustc_lint/src/early/diagnostics.rs | 4 + compiler/rustc_lint/src/lints.rs | 10 + compiler/rustc_lint_defs/src/lib.rs | 2 + tests/rustdoc-ui/bad-render-options.rs | 37 ++-- tests/rustdoc-ui/bad-render-options.stderr | 97 +++++----- tests/rustdoc-ui/doc-cfg.rs | 7 +- tests/rustdoc-ui/doc-cfg.stderr | 21 +-- tests/rustdoc-ui/lints/doc-attr.rs | 6 +- tests/rustdoc-ui/lints/doc-attr.stderr | 6 +- .../lints/invalid-doc-attr-2.stderr | 2 +- tests/rustdoc-ui/lints/invalid-doc-attr-3.rs | 22 +++ .../lints/invalid-doc-attr-3.stderr | 55 ++++++ tests/ui/attributes/doc-attr.rs | 9 +- tests/ui/attributes/doc-attr.stderr | 53 +++--- tests/ui/attributes/doc-test-literal.rs | 5 +- tests/ui/attributes/doc-test-literal.stderr | 16 +- tests/ui/attributes/malformed-attrs.rs | 7 +- tests/ui/attributes/malformed-attrs.stderr | 172 ++++++++---------- tests/ui/malformed/malformed-regressions.rs | 3 +- .../ui/malformed/malformed-regressions.stderr | 36 ++-- tests/ui/malformed/malformed-special-attrs.rs | 2 + .../malformed/malformed-special-attrs.stderr | 8 +- 24 files changed, 404 insertions(+), 282 deletions(-) create mode 100644 tests/rustdoc-ui/lints/invalid-doc-attr-3.rs create mode 100644 tests/rustdoc-ui/lints/invalid-doc-attr-3.stderr diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 1bf5352ee838..f8968639f98c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -70,6 +70,42 @@ fn check_attr_crate_level(cx: &mut AcceptContext<'_, '_, S>, span: Spa true } +// FIXME: To be removed once merged and replace with `cx.expected_name_value(span, _name)`. +fn expected_name_value( + cx: &mut AcceptContext<'_, '_, S>, + span: Span, + _name: Option, +) { + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::ExpectedNameValue, + span, + ); +} + +// FIXME: remove this method once merged and use `cx.expected_no_args(span)` instead. +fn expected_no_args(cx: &mut AcceptContext<'_, '_, S>, span: Span) { + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::ExpectedNoArgs, + span, + ); +} + +// FIXME: remove this method once merged and use `cx.expected_no_args(span)` instead. +// cx.expected_string_literal(span, _actual_literal); +fn expected_string_literal( + cx: &mut AcceptContext<'_, '_, S>, + span: Span, + _actual_literal: Option<&MetaItemLit>, +) { + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::MalformedDoc, + span, + ); +} + fn parse_keyword_and_attribute( cx: &mut AcceptContext<'_, '_, S>, path: &OwnedPathParser, @@ -78,12 +114,12 @@ fn parse_keyword_and_attribute( attr_name: Symbol, ) { let Some(nv) = args.name_value() else { - cx.expected_name_value(args.span().unwrap_or(path.span()), path.word_sym()); + expected_name_value(cx, args.span().unwrap_or(path.span()), path.word_sym()); return; }; let Some(value) = nv.value_as_str() else { - cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + expected_string_literal(cx, nv.value_span, Some(nv.value_as_lit())); return; }; @@ -127,7 +163,7 @@ impl DocParser { match path.word_sym() { Some(sym::no_crate_inject) => { if let Err(span) = args.no_args() { - cx.expected_no_args(span); + expected_no_args(cx, span); return; } @@ -153,7 +189,14 @@ impl DocParser { } Some(sym::attr) => { let Some(list) = args.list() else { - cx.expected_list(cx.attr_span, args); + // FIXME: remove this method once merged and uncomment the line below instead. + // cx.expected_list(cx.attr_span, args); + let span = cx.attr_span; + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::MalformedDoc, + span, + ); return; }; @@ -255,7 +298,7 @@ impl DocParser { inline: DocInline, ) { if let Err(span) = args.no_args() { - cx.expected_no_args(span); + expected_no_args(cx, span); return; } @@ -337,7 +380,14 @@ impl DocParser { match sub_item.args() { a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => { let Some(name) = sub_item.path().word_sym() else { - cx.expected_identifier(sub_item.path().span()); + // FIXME: remove this method once merged and uncomment the line + // below instead. + // cx.expected_identifier(sub_item.path().span()); + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::MalformedDoc, + sub_item.path().span(), + ); continue; }; if let Ok(CfgEntry::NameValue { name, value, .. }) = @@ -400,7 +450,7 @@ impl DocParser { macro_rules! no_args { ($ident: ident) => {{ if let Err(span) = args.no_args() { - cx.expected_no_args(span); + expected_no_args(cx, span); return; } @@ -419,7 +469,7 @@ impl DocParser { macro_rules! no_args_and_not_crate_level { ($ident: ident) => {{ if let Err(span) = args.no_args() { - cx.expected_no_args(span); + expected_no_args(cx, span); return; } let span = path.span(); @@ -432,7 +482,7 @@ impl DocParser { macro_rules! no_args_and_crate_level { ($ident: ident) => {{ if let Err(span) = args.no_args() { - cx.expected_no_args(span); + expected_no_args(cx, span); return; } let span = path.span(); @@ -445,12 +495,12 @@ impl DocParser { macro_rules! string_arg_and_crate_level { ($ident: ident) => {{ let Some(nv) = args.name_value() else { - cx.expected_name_value(args.span().unwrap_or(path.span()), path.word_sym()); + expected_name_value(cx, args.span().unwrap_or(path.span()), path.word_sym()); return; }; let Some(s) = nv.value_as_str() else { - cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + expected_string_literal(cx, nv.value_span, Some(nv.value_as_lit())); return; }; @@ -521,7 +571,14 @@ impl DocParser { self.parse_single_test_doc_attr_item(cx, mip); } MetaItemOrLitParser::Lit(lit) => { - cx.unexpected_literal(lit.span); + // FIXME: remove this method once merged and uncomment the line + // below instead. + // cx.unexpected_literal(lit.span); + cx.emit_lint( + rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, + AttributeLintKind::MalformedDoc, + lit.span, + ); } } } @@ -604,27 +661,14 @@ impl DocParser { self.parse_single_doc_attr_item(cx, mip); } MetaItemOrLitParser::Lit(lit) => { - // FIXME: Remove the lint and uncomment line after beta backport is - // done. - // cx.expected_name_value(lit.span, None); - cx.emit_lint( - rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, - AttributeLintKind::MalformedDoc, - lit.span, - ); + expected_name_value(cx, lit.span, None); } } } } ArgParser::NameValue(nv) => { if nv.value_as_str().is_none() { - // FIXME: Remove the lint and uncomment line after beta backport is done. - // cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); - cx.emit_lint( - rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, - AttributeLintKind::MalformedDoc, - nv.value_span, - ); + expected_string_literal(cx, nv.value_span, Some(nv.value_as_lit())); } else { unreachable!( "Should have been handled at the same time as sugar-syntaxed doc comments" diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index ebee380765c6..2f5b7ed26952 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -326,6 +326,14 @@ lint_expectation = this lint expectation is unfulfilled .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message .rationale = {$rationale} +lint_expected_name_value = + expected this to be of the form `... = "..."` + .warn = {-lint_previously_accepted} + +lint_expected_no_args = + didn't expect any arguments here + .warn = {-lint_previously_accepted} + lint_for_loops_over_fallibles = for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement .suggestion = consider using `if let` to clear intent diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 1360ba2d9c1c..c0ab0d1f0040 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -430,5 +430,9 @@ pub fn decorate_attribute_lint( .decorate_lint(diag), &AttributeLintKind::MalformedDoc => lints::MalformedDoc.decorate_lint(diag), + + &AttributeLintKind::ExpectedNoArgs => lints::ExpectedNoArgs.decorate_lint(diag), + + &AttributeLintKind::ExpectedNameValue => lints::ExpectedNameValue.decorate_lint(diag), } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 0b5197d7ebdf..1a87cc013e79 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3190,6 +3190,16 @@ pub(crate) struct UnusedDuplicate { #[warning] pub(crate) struct MalformedDoc; +#[derive(LintDiagnostic)] +#[diag(lint_expected_no_args)] +#[warning] +pub(crate) struct ExpectedNoArgs; + +#[derive(LintDiagnostic)] +#[diag(lint_expected_name_value)] +#[warning] +pub(crate) struct ExpectedNameValue; + #[derive(LintDiagnostic)] #[diag(lint_unsafe_attr_outside_unsafe)] pub(crate) struct UnsafeAttrOutsideUnsafeLint { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index ea2e67b8869b..b3e5b93cf2fc 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -827,6 +827,8 @@ pub enum AttributeLintKind { suggested: Option, }, MalformedDoc, + ExpectedNoArgs, + ExpectedNameValue, } pub type RegisteredTools = FxIndexSet; diff --git a/tests/rustdoc-ui/bad-render-options.rs b/tests/rustdoc-ui/bad-render-options.rs index 0522f68cb6c2..c85a818511d7 100644 --- a/tests/rustdoc-ui/bad-render-options.rs +++ b/tests/rustdoc-ui/bad-render-options.rs @@ -1,29 +1,30 @@ // regression test for https://github.com/rust-lang/rust/issues/149187 +#![deny(invalid_doc_attributes)] #![doc(html_favicon_url)] -//~^ ERROR: malformed `doc` attribute -//~| NOTE expected this to be of the form `html_favicon_url = "..."` +//~^ ERROR +//~| WARN #![doc(html_logo_url)] -//~^ ERROR: malformed `doc` attribute -//~| NOTE expected this to be of the form `html_logo_url = "..."` +//~^ ERROR +//~| WARN #![doc(html_playground_url)] -//~^ ERROR: malformed `doc` attribute -//~| NOTE expected this to be of the form `html_playground_url = "..."` +//~^ ERROR +//~| WARN #![doc(issue_tracker_base_url)] -//~^ ERROR: malformed `doc` attribute -//~| NOTE expected this to be of the form `issue_tracker_base_url = "..."` +//~^ ERROR +//~| WARN #![doc(html_favicon_url = 1)] -//~^ ERROR malformed `doc` attribute -//~| NOTE expected a string literal +//~^ ERROR +//~| WARN #![doc(html_logo_url = 2)] -//~^ ERROR malformed `doc` attribute -//~| NOTE expected a string literal +//~^ ERROR +//~| WARN #![doc(html_playground_url = 3)] -//~^ ERROR malformed `doc` attribute -//~| NOTE expected a string literal +//~^ ERROR +//~| WARN #![doc(issue_tracker_base_url = 4)] -//~^ ERROR malformed `doc` attribute -//~| NOTE expected a string literal +//~^ ERROR +//~| WARN #![doc(html_no_source = "asdf")] -//~^ ERROR malformed `doc` attribute -//~| NOTE didn't expect any arguments here +//~^ ERROR +//~| WARN diff --git a/tests/rustdoc-ui/bad-render-options.stderr b/tests/rustdoc-ui/bad-render-options.stderr index 28d4533a6edb..dac6bc231c37 100644 --- a/tests/rustdoc-ui/bad-render-options.stderr +++ b/tests/rustdoc-ui/bad-render-options.stderr @@ -1,76 +1,79 @@ -error[E0539]: malformed `doc` attribute input - --> $DIR/bad-render-options.rs:3:1 +error: expected this to be of the form `... = "..."` + --> $DIR/bad-render-options.rs:4:8 | LL | #![doc(html_favicon_url)] - | ^^^^^^^----------------^^ - | | - | expected this to be of the form `html_favicon_url = "..."` + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +note: the lint level is defined here + --> $DIR/bad-render-options.rs:2:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0539]: malformed `doc` attribute input - --> $DIR/bad-render-options.rs:6:1 +error: expected this to be of the form `... = "..."` + --> $DIR/bad-render-options.rs:7:8 | LL | #![doc(html_logo_url)] - | ^^^^^^^-------------^^ - | | - | expected this to be of the form `html_logo_url = "..."` + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error[E0539]: malformed `doc` attribute input - --> $DIR/bad-render-options.rs:9:1 +error: expected this to be of the form `... = "..."` + --> $DIR/bad-render-options.rs:10:8 | LL | #![doc(html_playground_url)] - | ^^^^^^^-------------------^^ - | | - | expected this to be of the form `html_playground_url = "..."` + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error[E0539]: malformed `doc` attribute input - --> $DIR/bad-render-options.rs:12:1 +error: expected this to be of the form `... = "..."` + --> $DIR/bad-render-options.rs:13:8 | LL | #![doc(issue_tracker_base_url)] - | ^^^^^^^----------------------^^ - | | - | expected this to be of the form `issue_tracker_base_url = "..."` + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error[E0539]: malformed `doc` attribute input - --> $DIR/bad-render-options.rs:15:1 +error: malformed `doc` attribute input + --> $DIR/bad-render-options.rs:16:27 | LL | #![doc(html_favicon_url = 1)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ - | | - | expected a string literal here + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error[E0539]: malformed `doc` attribute input - --> $DIR/bad-render-options.rs:18:1 +error: malformed `doc` attribute input + --> $DIR/bad-render-options.rs:19:24 | LL | #![doc(html_logo_url = 2)] - | ^^^^^^^^^^^^^^^^^^^^^^^-^^ - | | - | expected a string literal here + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error[E0539]: malformed `doc` attribute input - --> $DIR/bad-render-options.rs:21:1 +error: malformed `doc` attribute input + --> $DIR/bad-render-options.rs:22:30 | LL | #![doc(html_playground_url = 3)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ - | | - | expected a string literal here + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error[E0539]: malformed `doc` attribute input - --> $DIR/bad-render-options.rs:24:1 +error: malformed `doc` attribute input + --> $DIR/bad-render-options.rs:25:33 | LL | #![doc(issue_tracker_base_url = 4)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ - | | - | expected a string literal here + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error[E0565]: malformed `doc` attribute input - --> $DIR/bad-render-options.rs:27:1 +error: didn't expect any arguments here + --> $DIR/bad-render-options.rs:28:23 | LL | #![doc(html_no_source = "asdf")] - | ^^^^^^^^^^^^^^^^^^^^^^--------^^ - | | - | didn't expect any arguments here + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: aborting due to 9 previous errors -Some errors have detailed explanations: E0539, E0565. -For more information about an error, try `rustc --explain E0539`. diff --git a/tests/rustdoc-ui/doc-cfg.rs b/tests/rustdoc-ui/doc-cfg.rs index f30d80aa9cda..abaea9719280 100644 --- a/tests/rustdoc-ui/doc-cfg.rs +++ b/tests/rustdoc-ui/doc-cfg.rs @@ -1,9 +1,10 @@ +#![deny(invalid_doc_attributes)] #![feature(doc_cfg)] #[doc(cfg(), cfg(foo, bar))] -//~^ ERROR malformed `doc` attribute input -//~| ERROR malformed `doc` attribute input +//~^ ERROR +//~| ERROR #[doc(cfg())] //~ ERROR #[doc(cfg(foo, bar))] //~ ERROR -#[doc(auto_cfg(hide(foo::bar)))] //~ ERROR +#[doc(auto_cfg(hide(foo::bar)))] pub fn foo() {} diff --git a/tests/rustdoc-ui/doc-cfg.stderr b/tests/rustdoc-ui/doc-cfg.stderr index ce16ec31d875..fa25a441e9b7 100644 --- a/tests/rustdoc-ui/doc-cfg.stderr +++ b/tests/rustdoc-ui/doc-cfg.stderr @@ -1,5 +1,5 @@ error[E0805]: malformed `doc` attribute input - --> $DIR/doc-cfg.rs:3:1 + --> $DIR/doc-cfg.rs:4:1 | LL | #[doc(cfg(), cfg(foo, bar))] | ^^^^^^^^^--^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[doc(cfg(), cfg(foo, bar))] | expected a single argument here error[E0805]: malformed `doc` attribute input - --> $DIR/doc-cfg.rs:3:1 + --> $DIR/doc-cfg.rs:4:1 | LL | #[doc(cfg(), cfg(foo, bar))] | ^^^^^^^^^^^^^^^^----------^^ @@ -15,7 +15,7 @@ LL | #[doc(cfg(), cfg(foo, bar))] | expected a single argument here error[E0805]: malformed `doc` attribute input - --> $DIR/doc-cfg.rs:6:1 + --> $DIR/doc-cfg.rs:7:1 | LL | #[doc(cfg())] | ^^^^^^^^^--^^ @@ -23,22 +23,13 @@ LL | #[doc(cfg())] | expected a single argument here error[E0805]: malformed `doc` attribute input - --> $DIR/doc-cfg.rs:7:1 + --> $DIR/doc-cfg.rs:8:1 | LL | #[doc(cfg(foo, bar))] | ^^^^^^^^^----------^^ | | | expected a single argument here -error[E0539]: malformed `doc` attribute input - --> $DIR/doc-cfg.rs:8:1 - | -LL | #[doc(auto_cfg(hide(foo::bar)))] - | ^^^^^^^^^^^^^^^^^^^^--------^^^^ - | | - | expected a valid identifier here +error: aborting due to 4 previous errors -error: aborting due to 5 previous errors - -Some errors have detailed explanations: E0539, E0805. -For more information about an error, try `rustc --explain E0539`. +For more information about this error, try `rustc --explain E0805`. diff --git a/tests/rustdoc-ui/lints/doc-attr.rs b/tests/rustdoc-ui/lints/doc-attr.rs index f04961aa930a..46d56e7f5962 100644 --- a/tests/rustdoc-ui/lints/doc-attr.rs +++ b/tests/rustdoc-ui/lints/doc-attr.rs @@ -2,11 +2,11 @@ #![deny(invalid_doc_attributes)] #[doc(123)] -//~^ ERROR malformed `doc` attribute +//~^ ERROR //~| WARN #[doc("hello", "bar")] -//~^ ERROR malformed `doc` attribute -//~| ERROR malformed `doc` attribute +//~^ ERROR +//~| ERROR //~| WARN //~| WARN fn bar() {} diff --git a/tests/rustdoc-ui/lints/doc-attr.stderr b/tests/rustdoc-ui/lints/doc-attr.stderr index 5b6f48acb3be..263b068e092d 100644 --- a/tests/rustdoc-ui/lints/doc-attr.stderr +++ b/tests/rustdoc-ui/lints/doc-attr.stderr @@ -1,4 +1,4 @@ -error: malformed `doc` attribute input +error: expected this to be of the form `... = "..."` --> $DIR/doc-attr.rs:4:7 | LL | #[doc(123)] @@ -11,7 +11,7 @@ note: the lint level is defined here LL | #![deny(invalid_doc_attributes)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: malformed `doc` attribute input +error: expected this to be of the form `... = "..."` --> $DIR/doc-attr.rs:7:7 | LL | #[doc("hello", "bar")] @@ -19,7 +19,7 @@ LL | #[doc("hello", "bar")] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error: malformed `doc` attribute input +error: expected this to be of the form `... = "..."` --> $DIR/doc-attr.rs:7:16 | LL | #[doc("hello", "bar")] diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr-2.stderr b/tests/rustdoc-ui/lints/invalid-doc-attr-2.stderr index bfd926a2a517..2457352bb342 100644 --- a/tests/rustdoc-ui/lints/invalid-doc-attr-2.stderr +++ b/tests/rustdoc-ui/lints/invalid-doc-attr-2.stderr @@ -1,4 +1,4 @@ -error: malformed `doc` attribute input +error: expected this to be of the form `... = "..."` --> $DIR/invalid-doc-attr-2.rs:3:8 | LL | #![doc("other attribute")] diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr-3.rs b/tests/rustdoc-ui/lints/invalid-doc-attr-3.rs new file mode 100644 index 000000000000..1d2e4445140a --- /dev/null +++ b/tests/rustdoc-ui/lints/invalid-doc-attr-3.rs @@ -0,0 +1,22 @@ +#![deny(invalid_doc_attributes)] + +#![doc(test(no_crate_inject = 1))] +//~^ ERROR +//~| WARN +#![doc(test(attr = 1))] +//~^ ERROR +//~| WARN + +#[doc(hidden = true)] +//~^ ERROR +//~| WARN +#[doc(hidden("or you will be fired"))] +//~^ ERROR +//~| WARN +#[doc(hidden = "handled transparently by codegen")] +//~^ ERROR +//~| WARN +#[doc = 1] +//~^ ERROR +//~| WARN +pub struct X; diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr-3.stderr b/tests/rustdoc-ui/lints/invalid-doc-attr-3.stderr new file mode 100644 index 000000000000..9cec930174ce --- /dev/null +++ b/tests/rustdoc-ui/lints/invalid-doc-attr-3.stderr @@ -0,0 +1,55 @@ +error: didn't expect any arguments here + --> $DIR/invalid-doc-attr-3.rs:10:14 + | +LL | #[doc(hidden = true)] + | ^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +note: the lint level is defined here + --> $DIR/invalid-doc-attr-3.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: didn't expect any arguments here + --> $DIR/invalid-doc-attr-3.rs:13:13 + | +LL | #[doc(hidden("or you will be fired"))] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: didn't expect any arguments here + --> $DIR/invalid-doc-attr-3.rs:16:14 + | +LL | #[doc(hidden = "handled transparently by codegen")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: malformed `doc` attribute input + --> $DIR/invalid-doc-attr-3.rs:19:9 + | +LL | #[doc = 1] + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: didn't expect any arguments here + --> $DIR/invalid-doc-attr-3.rs:3:29 + | +LL | #![doc(test(no_crate_inject = 1))] + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: malformed `doc` attribute input + --> $DIR/invalid-doc-attr-3.rs:6:1 + | +LL | #![doc(test(attr = 1))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: aborting due to 6 previous errors + diff --git a/tests/ui/attributes/doc-attr.rs b/tests/ui/attributes/doc-attr.rs index b45f211f6222..8c81bc18d6ae 100644 --- a/tests/ui/attributes/doc-attr.rs +++ b/tests/ui/attributes/doc-attr.rs @@ -8,10 +8,13 @@ pub fn foo() {} #[doc(123)] -//~^ ERROR malformed `doc` attribute +//~^ ERROR +//~| WARN #[doc("hello", "bar")] -//~^ ERROR malformed `doc` attribute -//~| ERROR malformed `doc` attribute +//~^ ERROR +//~| ERROR +//~| WARN +//~| WARN #[doc(foo::bar, crate::bar::baz = "bye")] //~^ ERROR unknown `doc` attribute //~| ERROR unknown `doc` attribute diff --git a/tests/ui/attributes/doc-attr.stderr b/tests/ui/attributes/doc-attr.stderr index 005810fa23fa..79d9fb5bea7e 100644 --- a/tests/ui/attributes/doc-attr.stderr +++ b/tests/ui/attributes/doc-attr.stderr @@ -1,27 +1,3 @@ -error[E0539]: malformed `doc` attribute input - --> $DIR/doc-attr.rs:10:1 - | -LL | #[doc(123)] - | ^^^^^^---^^ - | | - | expected this to be of the form `... = "..."` - -error[E0539]: malformed `doc` attribute input - --> $DIR/doc-attr.rs:12:1 - | -LL | #[doc("hello", "bar")] - | ^^^^^^-------^^^^^^^^^ - | | - | expected this to be of the form `... = "..."` - -error[E0539]: malformed `doc` attribute input - --> $DIR/doc-attr.rs:12:1 - | -LL | #[doc("hello", "bar")] - | ^^^^^^^^^^^^^^^-----^^ - | | - | expected this to be of the form `... = "..."` - error: unknown `doc` attribute `as_ptr` --> $DIR/doc-attr.rs:6:7 | @@ -34,14 +10,38 @@ note: the lint level is defined here LL | #![deny(invalid_doc_attributes)] | ^^^^^^^^^^^^^^^^^^^^^^ +error: expected this to be of the form `... = "..."` + --> $DIR/doc-attr.rs:10:7 + | +LL | #[doc(123)] + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: expected this to be of the form `... = "..."` + --> $DIR/doc-attr.rs:13:7 + | +LL | #[doc("hello", "bar")] + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: expected this to be of the form `... = "..."` + --> $DIR/doc-attr.rs:13:16 + | +LL | #[doc("hello", "bar")] + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + error: unknown `doc` attribute `foo::bar` - --> $DIR/doc-attr.rs:15:7 + --> $DIR/doc-attr.rs:18:7 | LL | #[doc(foo::bar, crate::bar::baz = "bye")] | ^^^^^^^^ error: unknown `doc` attribute `crate::bar::baz` - --> $DIR/doc-attr.rs:15:17 + --> $DIR/doc-attr.rs:18:17 | LL | #[doc(foo::bar, crate::bar::baz = "bye")] | ^^^^^^^^^^^^^^^ @@ -54,4 +54,3 @@ LL | #![doc(as_ptr)] error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/attributes/doc-test-literal.rs b/tests/ui/attributes/doc-test-literal.rs index f9776e9924bd..ceb8967ea229 100644 --- a/tests/ui/attributes/doc-test-literal.rs +++ b/tests/ui/attributes/doc-test-literal.rs @@ -1,4 +1,7 @@ +#![deny(invalid_doc_attributes)] + #![doc(test(""))] -//~^ ERROR malformed `doc` attribute input +//~^ ERROR +//~| WARN fn main() {} diff --git a/tests/ui/attributes/doc-test-literal.stderr b/tests/ui/attributes/doc-test-literal.stderr index 2d70d5d206f0..c26aa94ec1af 100644 --- a/tests/ui/attributes/doc-test-literal.stderr +++ b/tests/ui/attributes/doc-test-literal.stderr @@ -1,11 +1,15 @@ -error[E0565]: malformed `doc` attribute input - --> $DIR/doc-test-literal.rs:1:1 +error: malformed `doc` attribute input + --> $DIR/doc-test-literal.rs:3:13 | LL | #![doc(test(""))] - | ^^^^^^^^^^^^--^^^ - | | - | didn't expect a literal here + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +note: the lint level is defined here + --> $DIR/doc-test-literal.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs index b0d8fd774f74..6dc3086b63e1 100644 --- a/tests/ui/attributes/malformed-attrs.rs +++ b/tests/ui/attributes/malformed-attrs.rs @@ -1,5 +1,6 @@ // This file contains a bunch of malformed attributes. // We enable a bunch of features to not get feature-gate errs in this test. +#![deny(invalid_doc_attributes)] #![feature(rustc_attrs)] #![feature(rustc_allow_const_fn_unstable)] #![feature(allow_internal_unstable)] @@ -39,8 +40,7 @@ #[deprecated = 5] //~^ ERROR malformed #[doc] -//~^ ERROR valid forms for the attribute are -//~| WARN this was previously accepted by the compiler +//~^ ERROR #[rustc_macro_transparency] //~^ ERROR malformed //~| ERROR attribute cannot be used on @@ -75,8 +75,7 @@ //~^ ERROR malformed //~| WARN crate-level attribute should be an inner attribute #[doc] -//~^ ERROR valid forms for the attribute are -//~| WARN this was previously accepted by the compiler +//~^ ERROR #[target_feature] //~^ ERROR malformed #[export_stable = 1] diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index f817a0b0d91b..22e222efa435 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -1,5 +1,5 @@ error[E0539]: malformed `cfg` attribute input - --> $DIR/malformed-attrs.rs:108:1 + --> $DIR/malformed-attrs.rs:107:1 | LL | #[cfg] | ^^^^^^ @@ -10,7 +10,7 @@ LL | #[cfg] = note: for more information, visit error[E0539]: malformed `cfg_attr` attribute input - --> $DIR/malformed-attrs.rs:110:1 + --> $DIR/malformed-attrs.rs:109:1 | LL | #[cfg_attr] | ^^^^^^^^^^^ @@ -21,13 +21,13 @@ LL | #[cfg_attr] = note: for more information, visit error[E0463]: can't find crate for `wloop` - --> $DIR/malformed-attrs.rs:218:1 + --> $DIR/malformed-attrs.rs:217:1 | LL | extern crate wloop; | ^^^^^^^^^^^^^^^^^^^ can't find crate error: malformed `allow` attribute input - --> $DIR/malformed-attrs.rs:184:1 + --> $DIR/malformed-attrs.rs:183:1 | LL | #[allow] | ^^^^^^^^ @@ -43,7 +43,7 @@ LL | #[allow(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `expect` attribute input - --> $DIR/malformed-attrs.rs:186:1 + --> $DIR/malformed-attrs.rs:185:1 | LL | #[expect] | ^^^^^^^^^ @@ -59,7 +59,7 @@ LL | #[expect(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `warn` attribute input - --> $DIR/malformed-attrs.rs:188:1 + --> $DIR/malformed-attrs.rs:187:1 | LL | #[warn] | ^^^^^^^ @@ -75,7 +75,7 @@ LL | #[warn(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `deny` attribute input - --> $DIR/malformed-attrs.rs:190:1 + --> $DIR/malformed-attrs.rs:189:1 | LL | #[deny] | ^^^^^^^ @@ -91,7 +91,7 @@ LL | #[deny(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `forbid` attribute input - --> $DIR/malformed-attrs.rs:192:1 + --> $DIR/malformed-attrs.rs:191:1 | LL | #[forbid] | ^^^^^^^^^ @@ -107,25 +107,25 @@ LL | #[forbid(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:105:1 + --> $DIR/malformed-attrs.rs:104:1 | LL | #[proc_macro = 18] | ^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:122:1 + --> $DIR/malformed-attrs.rs:121:1 | LL | #[proc_macro_attribute = 19] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:129:1 + --> $DIR/malformed-attrs.rs:128:1 | LL | #[proc_macro_derive] | ^^^^^^^^^^^^^^^^^^^^ error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint - --> $DIR/malformed-attrs.rs:223:1 + --> $DIR/malformed-attrs.rs:222:1 | LL | #[allow_internal_unsafe = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -134,7 +134,7 @@ LL | #[allow_internal_unsafe = 1] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0539]: malformed `windows_subsystem` attribute input - --> $DIR/malformed-attrs.rs:26:1 + --> $DIR/malformed-attrs.rs:27:1 | LL | #![windows_subsystem] | ^^^-----------------^ @@ -150,25 +150,25 @@ LL | #![windows_subsystem = "windows"] | +++++++++++ error[E0539]: malformed `export_name` attribute input - --> $DIR/malformed-attrs.rs:29:1 + --> $DIR/malformed-attrs.rs:30:1 | LL | #[unsafe(export_name)] | ^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[export_name = "name"]` error: `rustc_allow_const_fn_unstable` expects a list of feature names - --> $DIR/malformed-attrs.rs:31:1 + --> $DIR/malformed-attrs.rs:32:1 | LL | #[rustc_allow_const_fn_unstable] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `allow_internal_unstable` expects a list of feature names - --> $DIR/malformed-attrs.rs:34:1 + --> $DIR/malformed-attrs.rs:35:1 | LL | #[allow_internal_unstable] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0539]: malformed `rustc_confusables` attribute input - --> $DIR/malformed-attrs.rs:36:1 + --> $DIR/malformed-attrs.rs:37:1 | LL | #[rustc_confusables] | ^^^^^^^^^^^^^^^^^^^^ @@ -177,7 +177,7 @@ LL | #[rustc_confusables] | help: must be of the form: `#[rustc_confusables("name1", "name2", ...)]` error: `#[rustc_confusables]` attribute cannot be used on functions - --> $DIR/malformed-attrs.rs:36:1 + --> $DIR/malformed-attrs.rs:37:1 | LL | #[rustc_confusables] | ^^^^^^^^^^^^^^^^^^^^ @@ -185,7 +185,7 @@ LL | #[rustc_confusables] = help: `#[rustc_confusables]` can only be applied to inherent methods error[E0539]: malformed `deprecated` attribute input - --> $DIR/malformed-attrs.rs:39:1 + --> $DIR/malformed-attrs.rs:40:1 | LL | #[deprecated = 5] | ^^^^^^^^^^^^^^^-^ @@ -349,7 +349,7 @@ LL | #[crate_name] | ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]` error[E0539]: malformed `target_feature` attribute input - --> $DIR/malformed-attrs.rs:80:1 + --> $DIR/malformed-attrs.rs:79:1 | LL | #[target_feature] | ^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | #[target_feature] | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]` error[E0565]: malformed `export_stable` attribute input - --> $DIR/malformed-attrs.rs:82:1 + --> $DIR/malformed-attrs.rs:81:1 | LL | #[export_stable = 1] | ^^^^^^^^^^^^^^^^---^ @@ -367,7 +367,7 @@ LL | #[export_stable = 1] | help: must be of the form: `#[export_stable]` error[E0539]: malformed `link` attribute input - --> $DIR/malformed-attrs.rs:84:1 + --> $DIR/malformed-attrs.rs:83:1 | LL | #[link] | ^^^^^^^ expected this to be a list @@ -375,7 +375,7 @@ LL | #[link] = note: for more information, visit error[E0539]: malformed `link_name` attribute input - --> $DIR/malformed-attrs.rs:88:1 + --> $DIR/malformed-attrs.rs:87:1 | LL | #[link_name] | ^^^^^^^^^^^^ help: must be of the form: `#[link_name = "name"]` @@ -383,7 +383,7 @@ LL | #[link_name] = note: for more information, visit error[E0539]: malformed `link_section` attribute input - --> $DIR/malformed-attrs.rs:92:1 + --> $DIR/malformed-attrs.rs:91:1 | LL | #[link_section] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[link_section = "name"]` @@ -391,7 +391,7 @@ LL | #[link_section] = note: for more information, visit error[E0539]: malformed `coverage` attribute input - --> $DIR/malformed-attrs.rs:94:1 + --> $DIR/malformed-attrs.rs:93:1 | LL | #[coverage] | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -404,13 +404,13 @@ LL | #[coverage(on)] | ++++ error[E0539]: malformed `sanitize` attribute input - --> $DIR/malformed-attrs.rs:96:1 + --> $DIR/malformed-attrs.rs:95:1 | LL | #[sanitize] | ^^^^^^^^^^^ expected this to be a list error[E0565]: malformed `no_implicit_prelude` attribute input - --> $DIR/malformed-attrs.rs:101:1 + --> $DIR/malformed-attrs.rs:100:1 | LL | #[no_implicit_prelude = 23] | ^^^^^^^^^^^^^^^^^^^^^^----^ @@ -419,7 +419,7 @@ LL | #[no_implicit_prelude = 23] | help: must be of the form: `#[no_implicit_prelude]` error[E0565]: malformed `proc_macro` attribute input - --> $DIR/malformed-attrs.rs:105:1 + --> $DIR/malformed-attrs.rs:104:1 | LL | #[proc_macro = 18] | ^^^^^^^^^^^^^----^ @@ -428,7 +428,7 @@ LL | #[proc_macro = 18] | help: must be of the form: `#[proc_macro]` error[E0539]: malformed `instruction_set` attribute input - --> $DIR/malformed-attrs.rs:112:1 + --> $DIR/malformed-attrs.rs:111:1 | LL | #[instruction_set] | ^^^^^^^^^^^^^^^^^^ @@ -439,7 +439,7 @@ LL | #[instruction_set] = note: for more information, visit error[E0539]: malformed `patchable_function_entry` attribute input - --> $DIR/malformed-attrs.rs:114:1 + --> $DIR/malformed-attrs.rs:113:1 | LL | #[patchable_function_entry] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -448,7 +448,7 @@ LL | #[patchable_function_entry] | help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` error[E0565]: malformed `coroutine` attribute input - --> $DIR/malformed-attrs.rs:117:5 + --> $DIR/malformed-attrs.rs:116:5 | LL | #[coroutine = 63] || {} | ^^^^^^^^^^^^----^ @@ -457,7 +457,7 @@ LL | #[coroutine = 63] || {} | help: must be of the form: `#[coroutine]` error[E0565]: malformed `proc_macro_attribute` attribute input - --> $DIR/malformed-attrs.rs:122:1 + --> $DIR/malformed-attrs.rs:121:1 | LL | #[proc_macro_attribute = 19] | ^^^^^^^^^^^^^^^^^^^^^^^----^ @@ -466,7 +466,7 @@ LL | #[proc_macro_attribute = 19] | help: must be of the form: `#[proc_macro_attribute]` error[E0539]: malformed `must_use` attribute input - --> $DIR/malformed-attrs.rs:125:1 + --> $DIR/malformed-attrs.rs:124:1 | LL | #[must_use = 1] | ^^^^^^^^^^^^^-^ @@ -484,7 +484,7 @@ LL + #[must_use] | error[E0539]: malformed `proc_macro_derive` attribute input - --> $DIR/malformed-attrs.rs:129:1 + --> $DIR/malformed-attrs.rs:128:1 | LL | #[proc_macro_derive] | ^^^^^^^^^^^^^^^^^^^^ expected this to be a list @@ -498,7 +498,7 @@ LL | #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] | ++++++++++++++++++++++++++++++++++++++++++ error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input - --> $DIR/malformed-attrs.rs:134:1 + --> $DIR/malformed-attrs.rs:133:1 | LL | #[rustc_layout_scalar_valid_range_start] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -507,7 +507,7 @@ LL | #[rustc_layout_scalar_valid_range_start] | help: must be of the form: `#[rustc_layout_scalar_valid_range_start(start)]` error[E0539]: malformed `rustc_layout_scalar_valid_range_end` attribute input - --> $DIR/malformed-attrs.rs:136:1 + --> $DIR/malformed-attrs.rs:135:1 | LL | #[rustc_layout_scalar_valid_range_end] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -516,7 +516,7 @@ LL | #[rustc_layout_scalar_valid_range_end] | help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]` error[E0539]: malformed `must_not_suspend` attribute input - --> $DIR/malformed-attrs.rs:138:1 + --> $DIR/malformed-attrs.rs:137:1 | LL | #[must_not_suspend()] | ^^^^^^^^^^^^^^^^^^--^ @@ -532,7 +532,7 @@ LL + #[must_not_suspend] | error[E0539]: malformed `cfi_encoding` attribute input - --> $DIR/malformed-attrs.rs:140:1 + --> $DIR/malformed-attrs.rs:139:1 | LL | #[cfi_encoding = ""] | ^^^^^^^^^^^^^^^^^--^ @@ -541,7 +541,7 @@ LL | #[cfi_encoding = ""] | help: must be of the form: `#[cfi_encoding = "encoding"]` error[E0565]: malformed `marker` attribute input - --> $DIR/malformed-attrs.rs:161:1 + --> $DIR/malformed-attrs.rs:160:1 | LL | #[marker = 3] | ^^^^^^^^^---^ @@ -550,7 +550,7 @@ LL | #[marker = 3] | help: must be of the form: `#[marker]` error[E0565]: malformed `fundamental` attribute input - --> $DIR/malformed-attrs.rs:163:1 + --> $DIR/malformed-attrs.rs:162:1 | LL | #[fundamental()] | ^^^^^^^^^^^^^--^ @@ -559,7 +559,7 @@ LL | #[fundamental()] | help: must be of the form: `#[fundamental]` error[E0565]: malformed `ffi_pure` attribute input - --> $DIR/malformed-attrs.rs:171:5 + --> $DIR/malformed-attrs.rs:170:5 | LL | #[unsafe(ffi_pure = 1)] | ^^^^^^^^^^^^^^^^^^---^^ @@ -568,7 +568,7 @@ LL | #[unsafe(ffi_pure = 1)] | help: must be of the form: `#[ffi_pure]` error[E0539]: malformed `link_ordinal` attribute input - --> $DIR/malformed-attrs.rs:173:5 + --> $DIR/malformed-attrs.rs:172:5 | LL | #[link_ordinal] | ^^^^^^^^^^^^^^^ @@ -579,7 +579,7 @@ LL | #[link_ordinal] = note: for more information, visit error[E0565]: malformed `ffi_const` attribute input - --> $DIR/malformed-attrs.rs:177:5 + --> $DIR/malformed-attrs.rs:176:5 | LL | #[unsafe(ffi_const = 1)] | ^^^^^^^^^^^^^^^^^^^---^^ @@ -588,13 +588,13 @@ LL | #[unsafe(ffi_const = 1)] | help: must be of the form: `#[ffi_const]` error[E0539]: malformed `linkage` attribute input - --> $DIR/malformed-attrs.rs:179:5 + --> $DIR/malformed-attrs.rs:178:5 | LL | #[linkage] | ^^^^^^^^^^ expected this to be of the form `linkage = "..."` error[E0539]: malformed `debugger_visualizer` attribute input - --> $DIR/malformed-attrs.rs:194:1 + --> $DIR/malformed-attrs.rs:193:1 | LL | #[debugger_visualizer] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -605,7 +605,7 @@ LL | #[debugger_visualizer] = note: for more information, visit error[E0565]: malformed `automatically_derived` attribute input - --> $DIR/malformed-attrs.rs:196:1 + --> $DIR/malformed-attrs.rs:195:1 | LL | #[automatically_derived = 18] | ^^^^^^^^^^^^^^^^^^^^^^^^----^ @@ -614,7 +614,7 @@ LL | #[automatically_derived = 18] | help: must be of the form: `#[automatically_derived]` error[E0565]: malformed `non_exhaustive` attribute input - --> $DIR/malformed-attrs.rs:204:1 + --> $DIR/malformed-attrs.rs:203:1 | LL | #[non_exhaustive = 1] | ^^^^^^^^^^^^^^^^^---^ @@ -623,7 +623,7 @@ LL | #[non_exhaustive = 1] | help: must be of the form: `#[non_exhaustive]` error[E0565]: malformed `thread_local` attribute input - --> $DIR/malformed-attrs.rs:210:1 + --> $DIR/malformed-attrs.rs:209:1 | LL | #[thread_local()] | ^^^^^^^^^^^^^^--^ @@ -632,7 +632,7 @@ LL | #[thread_local()] | help: must be of the form: `#[thread_local]` error[E0565]: malformed `no_link` attribute input - --> $DIR/malformed-attrs.rs:214:1 + --> $DIR/malformed-attrs.rs:213:1 | LL | #[no_link()] | ^^^^^^^^^--^ @@ -641,7 +641,7 @@ LL | #[no_link()] | help: must be of the form: `#[no_link]` error[E0539]: malformed `macro_use` attribute input - --> $DIR/malformed-attrs.rs:216:1 + --> $DIR/malformed-attrs.rs:215:1 | LL | #[macro_use = 1] | ^^^^^^^^^^^^---^ @@ -659,7 +659,7 @@ LL + #[macro_use] | error[E0539]: malformed `macro_export` attribute input - --> $DIR/malformed-attrs.rs:221:1 + --> $DIR/malformed-attrs.rs:220:1 | LL | #[macro_export = 18] | ^^^^^^^^^^^^^^^----^ @@ -676,7 +676,7 @@ LL + #[macro_export] | error[E0565]: malformed `allow_internal_unsafe` attribute input - --> $DIR/malformed-attrs.rs:223:1 + --> $DIR/malformed-attrs.rs:222:1 | LL | #[allow_internal_unsafe = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^---^ @@ -685,7 +685,7 @@ LL | #[allow_internal_unsafe = 1] | help: must be of the form: `#[allow_internal_unsafe]` error[E0565]: malformed `type_const` attribute input - --> $DIR/malformed-attrs.rs:149:5 + --> $DIR/malformed-attrs.rs:148:5 | LL | #[type_const = 1] | ^^^^^^^^^^^^^---^ @@ -694,7 +694,7 @@ LL | #[type_const = 1] | help: must be of the form: `#[type_const]` error: attribute should be applied to `const fn` - --> $DIR/malformed-attrs.rs:31:1 + --> $DIR/malformed-attrs.rs:32:1 | LL | #[rustc_allow_const_fn_unstable] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -706,7 +706,7 @@ LL | | } | |_- not a `const fn` warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/malformed-attrs.rs:84:1 + --> $DIR/malformed-attrs.rs:83:1 | LL | #[link] | ^^^^^^^ @@ -733,7 +733,7 @@ LL | #[repr] | ^^^^^^^ warning: missing options for `on_unimplemented` attribute - --> $DIR/malformed-attrs.rs:144:1 + --> $DIR/malformed-attrs.rs:143:1 | LL | #[diagnostic::on_unimplemented] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -742,7 +742,7 @@ LL | #[diagnostic::on_unimplemented] = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default warning: malformed `on_unimplemented` attribute - --> $DIR/malformed-attrs.rs:146:1 + --> $DIR/malformed-attrs.rs:145:1 | LL | #[diagnostic::on_unimplemented = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -750,14 +750,16 @@ LL | #[diagnostic::on_unimplemented = 1] = help: only `message`, `note` and `label` are allowed as options error: valid forms for the attribute are `#[doc = "string"]`, `#[doc(alias)]`, `#[doc(attribute)]`, `#[doc(auto_cfg)]`, `#[doc(cfg)]`, `#[doc(fake_variadic)]`, `#[doc(hidden)]`, `#[doc(html_favicon_url)]`, `#[doc(html_logo_url)]`, `#[doc(html_no_source)]`, `#[doc(html_playground_url)]`, `#[doc(html_root_url)]`, `#[doc(include)]`, `#[doc(inline)]`, `#[doc(issue_tracker_base_url)]`, `#[doc(keyword)]`, `#[doc(masked)]`, `#[doc(no_default_passes)]`, `#[doc(no_inline)]`, `#[doc(notable_trait)]`, `#[doc(passes)]`, `#[doc(plugins)]`, `#[doc(rust_logo)]`, `#[doc(search_unbox)]`, `#[doc(spotlight)]`, and `#[doc(test)]` - --> $DIR/malformed-attrs.rs:41:1 + --> $DIR/malformed-attrs.rs:42:1 | LL | #[doc] | ^^^^^^ | - = 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 #57571 - = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default +note: the lint level is defined here + --> $DIR/malformed-attrs.rs:3:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` --> $DIR/malformed-attrs.rs:52:1 @@ -767,6 +769,7 @@ LL | #[inline = 5] | = 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 #57571 + = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]` --> $DIR/malformed-attrs.rs:74:1 @@ -775,7 +778,7 @@ LL | #[crate_name] | ^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this function - --> $DIR/malformed-attrs.rs:116:1 + --> $DIR/malformed-attrs.rs:115:1 | LL | / fn test() { LL | | #[coroutine = 63] || {} @@ -788,12 +791,9 @@ error: valid forms for the attribute are `#[doc = "string"]`, `#[doc(alias)]`, ` | LL | #[doc] | ^^^^^^ - | - = 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 #57571 warning: `#[link_name]` attribute cannot be used on functions - --> $DIR/malformed-attrs.rs:88:1 + --> $DIR/malformed-attrs.rs:87:1 | LL | #[link_name] | ^^^^^^^^^^^^ @@ -802,7 +802,7 @@ LL | #[link_name] = help: `#[link_name]` can be applied to foreign functions and foreign statics error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:98:1 + --> $DIR/malformed-attrs.rs:97:1 | LL | #[ignore()] | ^^^^^^^^^^^ @@ -811,7 +811,7 @@ LL | #[ignore()] = note: for more information, see issue #57571 warning: `#[no_implicit_prelude]` attribute cannot be used on functions - --> $DIR/malformed-attrs.rs:101:1 + --> $DIR/malformed-attrs.rs:100:1 | LL | #[no_implicit_prelude = 23] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -820,13 +820,13 @@ LL | #[no_implicit_prelude = 23] = help: `#[no_implicit_prelude]` can be applied to crates and modules warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/malformed-attrs.rs:155:1 + --> $DIR/malformed-attrs.rs:154:1 | LL | #[diagnostic::do_not_recommend()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` attribute cannot be used on modules - --> $DIR/malformed-attrs.rs:196:1 + --> $DIR/malformed-attrs.rs:195:1 | LL | #[automatically_derived = 18] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -835,7 +835,7 @@ LL | #[automatically_derived = 18] = help: `#[automatically_derived]` can only be applied to trait impl blocks error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:230:1 + --> $DIR/malformed-attrs.rs:229:1 | LL | #[ignore = 1] | ^^^^^^^^^^^^^ @@ -844,7 +844,7 @@ LL | #[ignore = 1] = note: for more information, see issue #57571 error[E0308]: mismatched types - --> $DIR/malformed-attrs.rs:117:23 + --> $DIR/malformed-attrs.rs:116:23 | LL | fn test() { | - help: a return type might be missing here: `-> _` @@ -852,24 +852,13 @@ LL | #[coroutine = 63] || {} | ^^^^^ expected `()`, found coroutine | = note: expected unit type `()` - found coroutine `{coroutine@$DIR/malformed-attrs.rs:117:23: 117:25}` + found coroutine `{coroutine@$DIR/malformed-attrs.rs:116:23: 116:25}` error: aborting due to 76 previous errors; 8 warnings emitted Some errors have detailed explanations: E0308, E0463, E0539, E0565, E0658, E0805. For more information about an error, try `rustc --explain E0308`. Future incompatibility report: Future breakage diagnostic: -error: valid forms for the attribute are `#[doc = "string"]`, `#[doc(alias)]`, `#[doc(attribute)]`, `#[doc(auto_cfg)]`, `#[doc(cfg)]`, `#[doc(fake_variadic)]`, `#[doc(hidden)]`, `#[doc(html_favicon_url)]`, `#[doc(html_logo_url)]`, `#[doc(html_no_source)]`, `#[doc(html_playground_url)]`, `#[doc(html_root_url)]`, `#[doc(include)]`, `#[doc(inline)]`, `#[doc(issue_tracker_base_url)]`, `#[doc(keyword)]`, `#[doc(masked)]`, `#[doc(no_default_passes)]`, `#[doc(no_inline)]`, `#[doc(notable_trait)]`, `#[doc(passes)]`, `#[doc(plugins)]`, `#[doc(rust_logo)]`, `#[doc(search_unbox)]`, `#[doc(spotlight)]`, and `#[doc(test)]` - --> $DIR/malformed-attrs.rs:41:1 - | -LL | #[doc] - | ^^^^^^ - | - = 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 #57571 - = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default - -Future breakage diagnostic: error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` --> $DIR/malformed-attrs.rs:52:1 | @@ -880,20 +869,9 @@ LL | #[inline = 5] = note: for more information, see issue #57571 = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default -Future breakage diagnostic: -error: valid forms for the attribute are `#[doc = "string"]`, `#[doc(alias)]`, `#[doc(attribute)]`, `#[doc(auto_cfg)]`, `#[doc(cfg)]`, `#[doc(fake_variadic)]`, `#[doc(hidden)]`, `#[doc(html_favicon_url)]`, `#[doc(html_logo_url)]`, `#[doc(html_no_source)]`, `#[doc(html_playground_url)]`, `#[doc(html_root_url)]`, `#[doc(include)]`, `#[doc(inline)]`, `#[doc(issue_tracker_base_url)]`, `#[doc(keyword)]`, `#[doc(masked)]`, `#[doc(no_default_passes)]`, `#[doc(no_inline)]`, `#[doc(notable_trait)]`, `#[doc(passes)]`, `#[doc(plugins)]`, `#[doc(rust_logo)]`, `#[doc(search_unbox)]`, `#[doc(spotlight)]`, and `#[doc(test)]` - --> $DIR/malformed-attrs.rs:77:1 - | -LL | #[doc] - | ^^^^^^ - | - = 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 #57571 - = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default - Future breakage diagnostic: error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:98:1 + --> $DIR/malformed-attrs.rs:97:1 | LL | #[ignore()] | ^^^^^^^^^^^ @@ -904,7 +882,7 @@ LL | #[ignore()] Future breakage diagnostic: error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:230:1 + --> $DIR/malformed-attrs.rs:229:1 | LL | #[ignore = 1] | ^^^^^^^^^^^^^ diff --git a/tests/ui/malformed/malformed-regressions.rs b/tests/ui/malformed/malformed-regressions.rs index c0f8c0d15bb8..63b918520ec0 100644 --- a/tests/ui/malformed/malformed-regressions.rs +++ b/tests/ui/malformed/malformed-regressions.rs @@ -1,5 +1,6 @@ +#![deny(invalid_doc_attributes)] + #[doc] //~ ERROR valid forms for the attribute are -//~^ WARN this was previously accepted #[ignore()] //~ ERROR valid forms for the attribute are //~^ WARN this was previously accepted #[inline = ""] //~ ERROR valid forms for the attribute are diff --git a/tests/ui/malformed/malformed-regressions.stderr b/tests/ui/malformed/malformed-regressions.stderr index 2bf6ff3a9e7a..283834a48552 100644 --- a/tests/ui/malformed/malformed-regressions.stderr +++ b/tests/ui/malformed/malformed-regressions.stderr @@ -1,5 +1,5 @@ error[E0539]: malformed `link` attribute input - --> $DIR/malformed-regressions.rs:7:1 + --> $DIR/malformed-regressions.rs:8:1 | LL | #[link] | ^^^^^^^ expected this to be a list @@ -7,7 +7,7 @@ LL | #[link] = note: for more information, visit error[E0539]: malformed `link` attribute input - --> $DIR/malformed-regressions.rs:10:1 + --> $DIR/malformed-regressions.rs:11:1 | LL | #[link = ""] | ^^^^^^^----^ @@ -17,7 +17,7 @@ LL | #[link = ""] = note: for more information, visit warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/malformed-regressions.rs:7:1 + --> $DIR/malformed-regressions.rs:8:1 | LL | #[link] | ^^^^^^^ @@ -29,26 +29,29 @@ LL | fn main() {} = note: requested on the command line with `-W unused-attributes` error: valid forms for the attribute are `#[doc = "string"]`, `#[doc(alias)]`, `#[doc(attribute)]`, `#[doc(auto_cfg)]`, `#[doc(cfg)]`, `#[doc(fake_variadic)]`, `#[doc(hidden)]`, `#[doc(html_favicon_url)]`, `#[doc(html_logo_url)]`, `#[doc(html_no_source)]`, `#[doc(html_playground_url)]`, `#[doc(html_root_url)]`, `#[doc(include)]`, `#[doc(inline)]`, `#[doc(issue_tracker_base_url)]`, `#[doc(keyword)]`, `#[doc(masked)]`, `#[doc(no_default_passes)]`, `#[doc(no_inline)]`, `#[doc(notable_trait)]`, `#[doc(passes)]`, `#[doc(plugins)]`, `#[doc(rust_logo)]`, `#[doc(search_unbox)]`, `#[doc(spotlight)]`, and `#[doc(test)]` - --> $DIR/malformed-regressions.rs:1:1 + --> $DIR/malformed-regressions.rs:3:1 | LL | #[doc] | ^^^^^^ | - = 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 #57571 - = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default +note: the lint level is defined here + --> $DIR/malformed-regressions.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-regressions.rs:3:1 + --> $DIR/malformed-regressions.rs:4:1 | LL | #[ignore()] | ^^^^^^^^^^^ | = 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 #57571 + = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` - --> $DIR/malformed-regressions.rs:5:1 + --> $DIR/malformed-regressions.rs:6:1 | LL | #[inline = ""] | ^^^^^^^^^^^^^^ @@ -60,19 +63,8 @@ error: aborting due to 5 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0539`. Future incompatibility report: Future breakage diagnostic: -error: valid forms for the attribute are `#[doc = "string"]`, `#[doc(alias)]`, `#[doc(attribute)]`, `#[doc(auto_cfg)]`, `#[doc(cfg)]`, `#[doc(fake_variadic)]`, `#[doc(hidden)]`, `#[doc(html_favicon_url)]`, `#[doc(html_logo_url)]`, `#[doc(html_no_source)]`, `#[doc(html_playground_url)]`, `#[doc(html_root_url)]`, `#[doc(include)]`, `#[doc(inline)]`, `#[doc(issue_tracker_base_url)]`, `#[doc(keyword)]`, `#[doc(masked)]`, `#[doc(no_default_passes)]`, `#[doc(no_inline)]`, `#[doc(notable_trait)]`, `#[doc(passes)]`, `#[doc(plugins)]`, `#[doc(rust_logo)]`, `#[doc(search_unbox)]`, `#[doc(spotlight)]`, and `#[doc(test)]` - --> $DIR/malformed-regressions.rs:1:1 - | -LL | #[doc] - | ^^^^^^ - | - = 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 #57571 - = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default - -Future breakage diagnostic: error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-regressions.rs:3:1 + --> $DIR/malformed-regressions.rs:4:1 | LL | #[ignore()] | ^^^^^^^^^^^ @@ -83,7 +75,7 @@ LL | #[ignore()] Future breakage diagnostic: error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` - --> $DIR/malformed-regressions.rs:5:1 + --> $DIR/malformed-regressions.rs:6:1 | LL | #[inline = ""] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/malformed/malformed-special-attrs.rs b/tests/ui/malformed/malformed-special-attrs.rs index 05b7ebe46666..f0e66ef0f835 100644 --- a/tests/ui/malformed/malformed-special-attrs.rs +++ b/tests/ui/malformed/malformed-special-attrs.rs @@ -1,3 +1,5 @@ +#![deny(invalid_doc_attributes)] + #[cfg_attr] //~ ERROR malformed `cfg_attr` attribute struct S1; diff --git a/tests/ui/malformed/malformed-special-attrs.stderr b/tests/ui/malformed/malformed-special-attrs.stderr index 91e5939eb1f9..a2501d2aa398 100644 --- a/tests/ui/malformed/malformed-special-attrs.stderr +++ b/tests/ui/malformed/malformed-special-attrs.stderr @@ -1,5 +1,5 @@ error[E0539]: malformed `cfg_attr` attribute input - --> $DIR/malformed-special-attrs.rs:1:1 + --> $DIR/malformed-special-attrs.rs:3:1 | LL | #[cfg_attr] | ^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | #[cfg_attr] = note: for more information, visit error[E0539]: malformed `cfg_attr` attribute input - --> $DIR/malformed-special-attrs.rs:4:1 + --> $DIR/malformed-special-attrs.rs:6:1 | LL | #[cfg_attr = ""] | ^^^^^^^^^^^^^^^^ @@ -21,13 +21,13 @@ LL | #[cfg_attr = ""] = note: for more information, visit error: malformed `derive` attribute input - --> $DIR/malformed-special-attrs.rs:7:1 + --> $DIR/malformed-special-attrs.rs:9:1 | LL | #[derive] | ^^^^^^^^^ help: must be of the form: `#[derive(Trait1, Trait2, ...)]` error: malformed `derive` attribute input - --> $DIR/malformed-special-attrs.rs:10:1 + --> $DIR/malformed-special-attrs.rs:12:1 | LL | #[derive = ""] | ^^^^^^^^^^^^^^ help: must be of the form: `#[derive(Trait1, Trait2, ...)]` From b902f89f92429eef8cff9aa8431a99624a71e2b7 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 4 Feb 2026 21:19:38 +1100 Subject: [PATCH 513/978] Remove panicking default impl of `DepNodeKey::to_fingerprint` There don't appear to be any trait impls relying on this default body. --- compiler/rustc_query_system/src/dep_graph/dep_node.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index e18483d0b435..5df50b2864b2 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -173,12 +173,7 @@ pub trait DepNodeKey: fmt::Debug + Sized { /// This method turns a query key into an opaque `Fingerprint` to be used /// in `DepNode`. - /// - /// Not all `DepNodeKey` impls support being turned into a `Fingerprint` - /// (they don't need to if the corresponding `DepNode` is anonymous). - fn to_fingerprint(&self, _: Tcx) -> Fingerprint { - panic!("Not implemented. Accidentally called on anonymous node?") - } + fn to_fingerprint(&self, _: Tcx) -> Fingerprint; fn to_debug_str(&self, tcx: Tcx) -> String; From 0f9b0d38410c1d17e6c8f3186595110a79702eb6 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 3 Feb 2026 21:50:59 +0100 Subject: [PATCH 514/978] Convert to inline diagnostics in `rustc_session` --- Cargo.lock | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_interface/src/interface.rs | 4 +- compiler/rustc_session/Cargo.toml | 1 - compiler/rustc_session/messages.ftl | 149 ----------------- compiler/rustc_session/src/errors.rs | 187 ++++++++++++---------- compiler/rustc_session/src/lib.rs | 2 - 7 files changed, 106 insertions(+), 239 deletions(-) delete mode 100644 compiler/rustc_session/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 1631d5362612..49563a61d2dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4641,7 +4641,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_fs_util", "rustc_hashes", "rustc_hir", diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 3059a4fefc61..268040d3cb7d 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -135,7 +135,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_pattern_analysis::DEFAULT_LOCALE_RESOURCE, rustc_privacy::DEFAULT_LOCALE_RESOURCE, rustc_resolve::DEFAULT_LOCALE_RESOURCE, - rustc_session::DEFAULT_LOCALE_RESOURCE, rustc_trait_selection::DEFAULT_LOCALE_RESOURCE, rustc_ty_utils::DEFAULT_LOCALE_RESOURCE, // tidy-alphabetical-end diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 916618cb5049..bb22bd20ac2a 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -55,7 +55,7 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec) -> Cfg { cfgs.into_iter() .map(|s| { let psess = ParseSess::emitter_with_note( - vec![rustc_parse::DEFAULT_LOCALE_RESOURCE, rustc_session::DEFAULT_LOCALE_RESOURCE], + vec![rustc_parse::DEFAULT_LOCALE_RESOURCE], format!("this occurred on the command line: `--cfg={s}`"), ); let filename = FileName::cfg_spec_source_code(&s); @@ -127,7 +127,7 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec) -> Ch for s in specs { let psess = ParseSess::emitter_with_note( - vec![rustc_parse::DEFAULT_LOCALE_RESOURCE, rustc_session::DEFAULT_LOCALE_RESOURCE], + vec![rustc_parse::DEFAULT_LOCALE_RESOURCE], format!("this occurred on the command line: `--check-cfg={s}`"), ); let filename = FileName::cfg_spec_source_code(&s); diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index aebac3880d2f..d66e04f58106 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -12,7 +12,6 @@ rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl deleted file mode 100644 index 5c851cb90a66..000000000000 --- a/compiler/rustc_session/messages.ftl +++ /dev/null @@ -1,149 +0,0 @@ -session_apple_deployment_target_invalid = - failed to parse deployment target specified in {$env_var}: {$error} - -session_apple_deployment_target_too_low = - deployment target in {$env_var} was set to {$version}, but the minimum supported by `rustc` is {$os_min} - -session_binary_float_literal_not_supported = binary float literal is not supported -session_branch_protection_requires_aarch64 = `-Zbranch-protection` is only supported on aarch64 - -session_cannot_enable_crt_static_linux = sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static` - -session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}` - -session_cli_feature_diagnostic_help = - add `-Zcrate-attr="feature({$feature})"` to the command-line options to enable - -session_crate_name_empty = crate name must not be empty - -session_embed_source_insufficient_dwarf_version = `-Zembed-source=y` requires at least `-Z dwarf-version=5` but DWARF version is {$dwarf_version} - -session_embed_source_requires_debug_info = `-Zembed-source=y` requires debug information to be enabled - -session_expr_parentheses_needed = parentheses are required to parse this as an expression - -session_failed_to_create_profiler = failed to create profiler: {$err} - -session_feature_diagnostic_for_issue = - see issue #{$n} for more information - -session_feature_diagnostic_help = - add `#![feature({$feature})]` to the crate attributes to enable - -session_feature_diagnostic_suggestion = - add `#![feature({$feature})]` to the crate attributes to enable - -session_feature_suggest_upgrade_compiler = - this compiler was built on {$date}; consider upgrading it if it is out of date - -session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions - -session_file_write_fail = failed to write `{$path}` due to error `{$err}` - -session_function_return_requires_x86_or_x86_64 = `-Zfunction-return` (except `keep`) is only supported on x86 and x86_64 - -session_function_return_thunk_extern_requires_non_large_code_model = `-Zfunction-return=thunk-extern` is only supported on non-large code models - -session_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported - -session_incompatible_linker_flavor = linker flavor `{$flavor}` is incompatible with the current target - .note = compatible flavors are: {$compatible_list} - -session_indirect_branch_cs_prefix_requires_x86_or_x86_64 = `-Zindirect-branch-cs-prefix` is only supported on x86 and x86_64 - -session_instrumentation_not_supported = {$us} instrumentation is not supported for this target - -session_int_literal_too_large = integer literal is too large - .note = value exceeds limit of `{$limit}` - -session_invalid_character_in_crate_name = invalid character {$character} in crate name: `{$crate_name}` - -session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal - .label = invalid suffix `{$suffix}` - .help = valid suffixes are `f32` and `f64` - -session_invalid_float_literal_width = invalid width `{$width}` for float literal - .help = valid widths are 32 and 64 - -session_invalid_int_literal_width = invalid width `{$width}` for integer literal - .help = valid widths are 8, 16, 32, 64 and 128 - -session_invalid_literal_suffix = suffixes on {$kind} literals are invalid - .label = invalid suffix `{$suffix}` - -session_invalid_num_literal_base_prefix = invalid base prefix for number literal - .note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase - .suggestion = try making the prefix lowercase - -session_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal - .label = invalid suffix `{$suffix}` - .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) - -session_linker_plugin_lto_windows_not_supported = linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets - -session_must_be_name_of_associated_function = must be a name of an associated function - -session_not_circumvent_feature = `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine - -session_not_supported = not supported - -session_octal_float_literal_not_supported = octal float literal is not supported - -session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C profile-sample-use` does not exist - -session_profile_use_file_does_not_exist = file `{$path}` passed to `-C profile-use` does not exist - -session_sanitizer_cfi_canonical_jump_tables_requires_cfi = `-Zsanitizer-cfi-canonical-jump-tables` requires `-Zsanitizer=cfi` - -session_sanitizer_cfi_generalize_pointers_requires_cfi = `-Zsanitizer-cfi-generalize-pointers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi` - -session_sanitizer_cfi_normalize_integers_requires_cfi = `-Zsanitizer-cfi-normalize-integers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi` - -session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto` or `-Clinker-plugin-lto` - -session_sanitizer_cfi_requires_single_codegen_unit = `-Zsanitizer=cfi` with `-Clto` requires `-Ccodegen-units=1` - -session_sanitizer_kcfi_arity_requires_kcfi = `-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi` - -session_sanitizer_kcfi_requires_panic_abort = `-Z sanitizer=kcfi` requires `-C panic=abort` - -session_sanitizer_not_supported = {$us} sanitizer is not supported for this target - -session_sanitizers_not_supported = {$us} sanitizers are not supported for this target - -session_skipping_const_checks = skipping const checks - -session_soft_float_deprecated = - `-Csoft-float` is unsound and deprecated; use a corresponding *eabi target instead - .note = it will be removed or ignored in a future version of Rust -session_soft_float_deprecated_issue = see issue #129893 for more information - -session_soft_float_ignored = - `-Csoft-float` is ignored on this target; it only has an effect on *eabihf targets - .note = this may become a hard error in a future version of Rust - -session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform - -session_split_lto_unit_requires_lto = `-Zsplit-lto-unit` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto` - -session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no` - -session_target_small_data_threshold_not_supported = `-Z small-data-threshold` is not supported for target {$target_triple} and will be ignored - -session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored - -session_unexpected_builtin_cfg = unexpected `--cfg {$cfg}` flag - .controlled_by = config `{$cfg_name}` is only supposed to be controlled by `{$controlled_by}` - .incoherent = manually setting a built-in cfg can and does create incoherent behaviors - -session_unleashed_feature_help_named = skipping check for `{$gate}` feature -session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate - -session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto` - -session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is not supported -session_unsupported_dwarf_version_help = supported DWARF versions are 2, 3, 4 and 5 - -session_unsupported_reg_struct_return_arch = `-Zreg-struct-return` is only supported on x86 -session_unsupported_regparm = `-Zregparm={$regparm}` is unsupported (valid values 0-3) -session_unsupported_regparm_arch = `-Zregparm=N` is only supported on x86 diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 54e792fd7b59..0c6a33f22808 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -15,9 +15,11 @@ use crate::parse::ParseSess; #[derive(Diagnostic)] pub(crate) enum AppleDeploymentTarget { - #[diag(session_apple_deployment_target_invalid)] + #[diag("failed to parse deployment target specified in {$env_var}: {$error}")] Invalid { env_var: &'static str, error: ParseIntError }, - #[diag(session_apple_deployment_target_too_low)] + #[diag( + "deployment target in {$env_var} was set to {$version}, but the minimum supported by `rustc` is {$os_min}" + )] TooLow { env_var: &'static str, version: String, os_min: String }, } @@ -34,13 +36,13 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for FeatureGateError { } #[derive(Subdiagnostic)] -#[note(session_feature_diagnostic_for_issue)] +#[note("see issue #{$n} for more information")] pub(crate) struct FeatureDiagnosticForIssue { pub(crate) n: NonZero, } #[derive(Subdiagnostic)] -#[note(session_feature_suggest_upgrade_compiler)] +#[note("this compiler was built on {$date}; consider upgrading it if it is out of date")] pub(crate) struct SuggestUpgradeCompiler { date: &'static str, } @@ -58,14 +60,14 @@ impl SuggestUpgradeCompiler { } #[derive(Subdiagnostic)] -#[help(session_feature_diagnostic_help)] +#[help("add `#![feature({$feature})]` to the crate attributes to enable")] pub(crate) struct FeatureDiagnosticHelp { pub(crate) feature: Symbol, } #[derive(Subdiagnostic)] #[suggestion( - session_feature_diagnostic_suggestion, + "add `#![feature({$feature})]` to the crate attributes to enable", applicability = "maybe-incorrect", code = "#![feature({feature})]\n" )] @@ -76,169 +78,181 @@ pub struct FeatureDiagnosticSuggestion { } #[derive(Subdiagnostic)] -#[help(session_cli_feature_diagnostic_help)] +#[help("add `-Zcrate-attr=\"feature({$feature})\"` to the command-line options to enable")] pub(crate) struct CliFeatureDiagnosticHelp { pub(crate) feature: Symbol, } #[derive(Diagnostic)] -#[diag(session_must_be_name_of_associated_function)] +#[diag("must be a name of an associated function")] pub struct MustBeNameOfAssociatedFunction { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(session_not_circumvent_feature)] +#[diag( + "`-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine" +)] pub(crate) struct NotCircumventFeature; #[derive(Diagnostic)] -#[diag(session_linker_plugin_lto_windows_not_supported)] +#[diag( + "linker plugin based LTO is not supported together with `-C prefer-dynamic` when targeting Windows-like targets" +)] pub(crate) struct LinkerPluginToWindowsNotSupported; #[derive(Diagnostic)] -#[diag(session_profile_use_file_does_not_exist)] +#[diag("file `{$path}` passed to `-C profile-use` does not exist")] pub(crate) struct ProfileUseFileDoesNotExist<'a> { pub(crate) path: &'a std::path::Path, } #[derive(Diagnostic)] -#[diag(session_profile_sample_use_file_does_not_exist)] +#[diag("file `{$path}` passed to `-C profile-sample-use` does not exist")] pub(crate) struct ProfileSampleUseFileDoesNotExist<'a> { pub(crate) path: &'a std::path::Path, } #[derive(Diagnostic)] -#[diag(session_target_requires_unwind_tables)] +#[diag("target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`")] pub(crate) struct TargetRequiresUnwindTables; #[derive(Diagnostic)] -#[diag(session_instrumentation_not_supported)] +#[diag("{$us} instrumentation is not supported for this target")] pub(crate) struct InstrumentationNotSupported { pub(crate) us: String, } #[derive(Diagnostic)] -#[diag(session_sanitizer_not_supported)] +#[diag("{$us} sanitizer is not supported for this target")] pub(crate) struct SanitizerNotSupported { pub(crate) us: String, } #[derive(Diagnostic)] -#[diag(session_sanitizers_not_supported)] +#[diag("{$us} sanitizers are not supported for this target")] pub(crate) struct SanitizersNotSupported { pub(crate) us: String, } #[derive(Diagnostic)] -#[diag(session_cannot_mix_and_match_sanitizers)] +#[diag("`-Zsanitizer={$first}` is incompatible with `-Zsanitizer={$second}`")] pub(crate) struct CannotMixAndMatchSanitizers { pub(crate) first: String, pub(crate) second: String, } #[derive(Diagnostic)] -#[diag(session_cannot_enable_crt_static_linux)] +#[diag( + "sanitizer is incompatible with statically linked libc, disable it using `-C target-feature=-crt-static`" +)] pub(crate) struct CannotEnableCrtStaticLinux; #[derive(Diagnostic)] -#[diag(session_sanitizer_cfi_requires_lto)] +#[diag("`-Zsanitizer=cfi` requires `-Clto` or `-Clinker-plugin-lto`")] pub(crate) struct SanitizerCfiRequiresLto; #[derive(Diagnostic)] -#[diag(session_sanitizer_cfi_requires_single_codegen_unit)] +#[diag("`-Zsanitizer=cfi` with `-Clto` requires `-Ccodegen-units=1`")] pub(crate) struct SanitizerCfiRequiresSingleCodegenUnit; #[derive(Diagnostic)] -#[diag(session_sanitizer_cfi_canonical_jump_tables_requires_cfi)] +#[diag("`-Zsanitizer-cfi-canonical-jump-tables` requires `-Zsanitizer=cfi`")] pub(crate) struct SanitizerCfiCanonicalJumpTablesRequiresCfi; #[derive(Diagnostic)] -#[diag(session_sanitizer_cfi_generalize_pointers_requires_cfi)] +#[diag("`-Zsanitizer-cfi-generalize-pointers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`")] pub(crate) struct SanitizerCfiGeneralizePointersRequiresCfi; #[derive(Diagnostic)] -#[diag(session_sanitizer_cfi_normalize_integers_requires_cfi)] +#[diag("`-Zsanitizer-cfi-normalize-integers` requires `-Zsanitizer=cfi` or `-Zsanitizer=kcfi`")] pub(crate) struct SanitizerCfiNormalizeIntegersRequiresCfi; #[derive(Diagnostic)] -#[diag(session_sanitizer_kcfi_arity_requires_kcfi)] +#[diag("`-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi`")] pub(crate) struct SanitizerKcfiArityRequiresKcfi; #[derive(Diagnostic)] -#[diag(session_sanitizer_kcfi_requires_panic_abort)] +#[diag("`-Z sanitizer=kcfi` requires `-C panic=abort`")] pub(crate) struct SanitizerKcfiRequiresPanicAbort; #[derive(Diagnostic)] -#[diag(session_split_lto_unit_requires_lto)] +#[diag("`-Zsplit-lto-unit` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto`")] pub(crate) struct SplitLtoUnitRequiresLto; #[derive(Diagnostic)] -#[diag(session_unstable_virtual_function_elimination)] +#[diag("`-Zvirtual-function-elimination` requires `-Clto`")] pub(crate) struct UnstableVirtualFunctionElimination; #[derive(Diagnostic)] -#[diag(session_unsupported_dwarf_version)] -#[help(session_unsupported_dwarf_version_help)] +#[diag("requested DWARF version {$dwarf_version} is not supported")] +#[help("supported DWARF versions are 2, 3, 4 and 5")] pub(crate) struct UnsupportedDwarfVersion { pub(crate) dwarf_version: u32, } #[derive(Diagnostic)] -#[diag(session_embed_source_insufficient_dwarf_version)] +#[diag( + "`-Zembed-source=y` requires at least `-Z dwarf-version=5` but DWARF version is {$dwarf_version}" +)] pub(crate) struct EmbedSourceInsufficientDwarfVersion { pub(crate) dwarf_version: u32, } #[derive(Diagnostic)] -#[diag(session_embed_source_requires_debug_info)] +#[diag("`-Zembed-source=y` requires debug information to be enabled")] pub(crate) struct EmbedSourceRequiresDebugInfo; #[derive(Diagnostic)] -#[diag(session_target_stack_protector_not_supported)] +#[diag( + "`-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored" +)] pub(crate) struct StackProtectorNotSupportedForTarget<'a> { pub(crate) stack_protector: StackProtector, pub(crate) target_triple: &'a TargetTuple, } #[derive(Diagnostic)] -#[diag(session_target_small_data_threshold_not_supported)] +#[diag( + "`-Z small-data-threshold` is not supported for target {$target_triple} and will be ignored" +)] pub(crate) struct SmallDataThresholdNotSupportedForTarget<'a> { pub(crate) target_triple: &'a TargetTuple, } #[derive(Diagnostic)] -#[diag(session_branch_protection_requires_aarch64)] +#[diag("`-Zbranch-protection` is only supported on aarch64")] pub(crate) struct BranchProtectionRequiresAArch64; #[derive(Diagnostic)] -#[diag(session_split_debuginfo_unstable_platform)] +#[diag("`-Csplit-debuginfo={$debuginfo}` is unstable on this platform")] pub(crate) struct SplitDebugInfoUnstablePlatform { pub(crate) debuginfo: SplitDebuginfo, } #[derive(Diagnostic)] -#[diag(session_file_is_not_writeable)] +#[diag("output file {$file} is not writeable -- check its permissions")] pub(crate) struct FileIsNotWriteable<'a> { pub(crate) file: &'a std::path::Path, } #[derive(Diagnostic)] -#[diag(session_file_write_fail)] +#[diag("failed to write `{$path}` due to error `{$err}`")] pub(crate) struct FileWriteFail<'a> { pub(crate) path: &'a std::path::Path, pub(crate) err: String, } #[derive(Diagnostic)] -#[diag(session_crate_name_empty)] +#[diag("crate name must not be empty")] pub(crate) struct CrateNameEmpty { #[primary_span] pub(crate) span: Option, } #[derive(Diagnostic)] -#[diag(session_invalid_character_in_crate_name)] +#[diag("invalid character {$character} in crate name: `{$crate_name}`")] pub(crate) struct InvalidCharacterInCrateName { #[primary_span] pub(crate) span: Option, @@ -247,7 +261,10 @@ pub(crate) struct InvalidCharacterInCrateName { } #[derive(Subdiagnostic)] -#[multipart_suggestion(session_expr_parentheses_needed, applicability = "machine-applicable")] +#[multipart_suggestion( + "parentheses are required to parse this as an expression", + applicability = "machine-applicable" +)] pub struct ExprParenthesesNeeded { #[suggestion_part(code = "(")] left: Span, @@ -262,7 +279,7 @@ impl ExprParenthesesNeeded { } #[derive(Diagnostic)] -#[diag(session_skipping_const_checks)] +#[diag("skipping const checks")] pub(crate) struct SkippingConstChecks { #[subdiagnostic] pub(crate) unleashed_features: Vec, @@ -270,13 +287,13 @@ pub(crate) struct SkippingConstChecks { #[derive(Subdiagnostic)] pub(crate) enum UnleashedFeatureHelp { - #[help(session_unleashed_feature_help_named)] + #[help("skipping check for `{$gate}` feature")] Named { #[primary_span] span: Span, gate: Symbol, }, - #[help(session_unleashed_feature_help_unnamed)] + #[help("skipping check that does not even have a feature gate")] Unnamed { #[primary_span] span: Span, @@ -284,10 +301,10 @@ pub(crate) enum UnleashedFeatureHelp { } #[derive(Diagnostic)] -#[diag(session_invalid_literal_suffix)] +#[diag("suffixes on {$kind} literals are invalid")] struct InvalidLiteralSuffix<'a> { #[primary_span] - #[label] + #[label("invalid suffix `{$suffix}`")] span: Span, // FIXME(#100717) kind: &'a str, @@ -295,8 +312,8 @@ struct InvalidLiteralSuffix<'a> { } #[derive(Diagnostic)] -#[diag(session_invalid_int_literal_width)] -#[help] +#[diag("invalid width `{$width}` for integer literal")] +#[help("valid widths are 8, 16, 32, 64 and 128")] struct InvalidIntLiteralWidth { #[primary_span] span: Span, @@ -304,28 +321,32 @@ struct InvalidIntLiteralWidth { } #[derive(Diagnostic)] -#[diag(session_invalid_num_literal_base_prefix)] -#[note] +#[diag("invalid base prefix for number literal")] +#[note("base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase")] struct InvalidNumLiteralBasePrefix { #[primary_span] - #[suggestion(applicability = "maybe-incorrect", code = "{fixed}")] + #[suggestion( + "try making the prefix lowercase", + applicability = "maybe-incorrect", + code = "{fixed}" + )] span: Span, fixed: String, } #[derive(Diagnostic)] -#[diag(session_invalid_num_literal_suffix)] -#[help] +#[diag("invalid suffix `{$suffix}` for number literal")] +#[help("the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)")] struct InvalidNumLiteralSuffix { #[primary_span] - #[label] + #[label("invalid suffix `{$suffix}`")] span: Span, suffix: String, } #[derive(Diagnostic)] -#[diag(session_invalid_float_literal_width)] -#[help] +#[diag("invalid width `{$width}` for float literal")] +#[help("valid widths are 32 and 64")] struct InvalidFloatLiteralWidth { #[primary_span] span: Span, @@ -333,18 +354,18 @@ struct InvalidFloatLiteralWidth { } #[derive(Diagnostic)] -#[diag(session_invalid_float_literal_suffix)] -#[help] +#[diag("invalid suffix `{$suffix}` for float literal")] +#[help("valid suffixes are `f32` and `f64`")] struct InvalidFloatLiteralSuffix { #[primary_span] - #[label] + #[label("invalid suffix `{$suffix}`")] span: Span, suffix: String, } #[derive(Diagnostic)] -#[diag(session_int_literal_too_large)] -#[note] +#[diag("integer literal is too large")] +#[note("value exceeds limit of `{$limit}`")] struct IntLiteralTooLarge { #[primary_span] span: Span, @@ -352,26 +373,26 @@ struct IntLiteralTooLarge { } #[derive(Diagnostic)] -#[diag(session_hexadecimal_float_literal_not_supported)] +#[diag("hexadecimal float literal is not supported")] struct HexadecimalFloatLiteralNotSupported { #[primary_span] - #[label(session_not_supported)] + #[label("not supported")] span: Span, } #[derive(Diagnostic)] -#[diag(session_octal_float_literal_not_supported)] +#[diag("octal float literal is not supported")] struct OctalFloatLiteralNotSupported { #[primary_span] - #[label(session_not_supported)] + #[label("not supported")] span: Span, } #[derive(Diagnostic)] -#[diag(session_binary_float_literal_not_supported)] +#[diag("binary float literal is not supported")] struct BinaryFloatLiteralNotSupported { #[primary_span] - #[label(session_not_supported)] + #[label("not supported")] span: Span, } @@ -457,60 +478,60 @@ pub fn create_lit_error(psess: &ParseSess, err: LitError, lit: token::Lit, span: } #[derive(Diagnostic)] -#[diag(session_incompatible_linker_flavor)] -#[note] +#[diag("linker flavor `{$flavor}` is incompatible with the current target")] +#[note("compatible flavors are: {$compatible_list}")] pub(crate) struct IncompatibleLinkerFlavor { pub(crate) flavor: &'static str, pub(crate) compatible_list: String, } #[derive(Diagnostic)] -#[diag(session_function_return_requires_x86_or_x86_64)] +#[diag("`-Zfunction-return` (except `keep`) is only supported on x86 and x86_64")] pub(crate) struct FunctionReturnRequiresX86OrX8664; #[derive(Diagnostic)] -#[diag(session_function_return_thunk_extern_requires_non_large_code_model)] +#[diag("`-Zfunction-return=thunk-extern` is only supported on non-large code models")] pub(crate) struct FunctionReturnThunkExternRequiresNonLargeCodeModel; #[derive(Diagnostic)] -#[diag(session_indirect_branch_cs_prefix_requires_x86_or_x86_64)] +#[diag("`-Zindirect-branch-cs-prefix` is only supported on x86 and x86_64")] pub(crate) struct IndirectBranchCsPrefixRequiresX86OrX8664; #[derive(Diagnostic)] -#[diag(session_unsupported_regparm)] +#[diag("`-Zregparm={$regparm}` is unsupported (valid values 0-3)")] pub(crate) struct UnsupportedRegparm { pub(crate) regparm: u32, } #[derive(Diagnostic)] -#[diag(session_unsupported_regparm_arch)] +#[diag("`-Zregparm=N` is only supported on x86")] pub(crate) struct UnsupportedRegparmArch; #[derive(Diagnostic)] -#[diag(session_unsupported_reg_struct_return_arch)] +#[diag("`-Zreg-struct-return` is only supported on x86")] pub(crate) struct UnsupportedRegStructReturnArch; #[derive(Diagnostic)] -#[diag(session_failed_to_create_profiler)] +#[diag("failed to create profiler: {$err}")] pub(crate) struct FailedToCreateProfiler { pub(crate) err: String, } #[derive(Diagnostic)] -#[diag(session_soft_float_ignored)] -#[note] +#[diag("`-Csoft-float` is ignored on this target; it only has an effect on *eabihf targets")] +#[note("this may become a hard error in a future version of Rust")] pub(crate) struct SoftFloatIgnored; #[derive(Diagnostic)] -#[diag(session_soft_float_deprecated)] -#[note] -#[note(session_soft_float_deprecated_issue)] +#[diag("`-Csoft-float` is unsound and deprecated; use a corresponding *eabi target instead")] +#[note("it will be removed or ignored in a future version of Rust")] +#[note("see issue #129893 for more information")] pub(crate) struct SoftFloatDeprecated; #[derive(LintDiagnostic)] -#[diag(session_unexpected_builtin_cfg)] -#[note(session_controlled_by)] -#[note(session_incoherent)] +#[diag("unexpected `--cfg {$cfg}` flag")] +#[note("config `{$cfg_name}` is only supposed to be controlled by `{$controlled_by}`")] +#[note("manually setting a built-in cfg can and does create incoherent behaviors")] pub(crate) struct UnexpectedBuiltinCfg { pub(crate) cfg: String, pub(crate) cfg_name: Symbol, diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 90108e911044..98731a235d41 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -32,8 +32,6 @@ pub mod output; pub use getopts; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro /// instead of implementing everything in `rustc_middle`. From 2c89741a353fd5945288601e00ef769b3e62cf71 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 31 Jan 2026 21:30:53 +1100 Subject: [PATCH 515/978] Overhaul `tests/run-make/short-ice` to make it easier to read --- src/tools/run-make-support/src/lib.rs | 1 + tests/run-make/short-ice/rmake.rs | 61 ++++++++++++++++----------- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index b19d73b78a94..52cc7ae9d379 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -47,6 +47,7 @@ pub use crate::assertion_helpers::{ assert_contains, assert_contains_regex, assert_count_is, assert_dirs_are_equal, assert_equals, assert_not_contains, assert_not_contains_regex, }; +pub use crate::command::CompletedProcess; // `diff` is implemented in terms of the [similar] library. // // [similar]: https://github.com/mitsuhiko/similar diff --git a/tests/run-make/short-ice/rmake.rs b/tests/run-make/short-ice/rmake.rs index dbe0f692aefb..4fc183a8c74e 100644 --- a/tests/run-make/short-ice/rmake.rs +++ b/tests/run-make/short-ice/rmake.rs @@ -12,40 +12,53 @@ // - FIXME(#143198): On `x86_64-pc-windows-msvc`: full backtrace sometimes do not contain matching // count of short backtrace markers (e.g. 5x end marker, but 3x start marker). -use run_make_support::rustc; +use run_make_support::CompletedProcess; fn main() { - let rust_test_1 = - rustc().set_backtrace_level("1").input("src/lib.rs").arg("-Ztreat-err-as-bug=1").run_fail(); - let rust_test_2 = rustc() - .set_backtrace_level("full") - .input("src/lib.rs") - .arg("-Ztreat-err-as-bug=1") - .run_fail(); + // Run the same command twice with `RUST_BACKTRACE=1` and `RUST_BACKTRACE=full`. + let configure_rustc = || { + let mut rustc = run_make_support::rustc(); + rustc.input("src/lib.rs").arg("-Ztreat-err-as-bug=1"); + rustc + }; + let rustc_bt_short = configure_rustc().set_backtrace_level("1").run_fail(); + let rustc_bt_full = configure_rustc().set_backtrace_level("full").run_fail(); - let mut rust_test_log_1 = rust_test_1.stderr_utf8(); - rust_test_log_1.push_str(&rust_test_1.stdout_utf8()); - let rust_test_log_1 = rust_test_log_1.as_str(); + // Combine stderr and stdout for subsequent checks. + let concat_stderr_stdout = + |proc: &CompletedProcess| format!("{}\n{}", proc.stderr_utf8(), proc.stdout_utf8()); + let output_bt_short = &concat_stderr_stdout(&rustc_bt_short); + let output_bt_full = &concat_stderr_stdout(&rustc_bt_full); - let mut rust_test_log_2 = rust_test_2.stderr_utf8(); - rust_test_log_2.push_str(&rust_test_2.stdout_utf8()); - let rust_test_log_2 = rust_test_log_2.as_str(); + // Count how many lines of output mention symbols or paths in + // `rustc_query_system` or `rustc_query_impl`, which are the kinds of + // stack frames we want to be omitting in short backtraces. + let rustc_query_count_short = count_lines_with(output_bt_short, "rustc_query_"); + let rustc_query_count_full = count_lines_with(output_bt_full, "rustc_query_"); - let rustc_query_count_full = count_lines_with(rust_test_log_2, "rustc_query_"); + // Dump both outputs in full to make debugging easier, especially on CI. + // Use `--no-capture --force-rerun` to view output even when the test is passing. + println!("=== BEGIN SHORT BACKTRACE ===\n{output_bt_short}\n=== END SHORT BACKTRACE === "); + println!("=== BEGIN FULL BACKTRACE ===\n{output_bt_full}\n=== END FULL BACKTRACE === "); assert!( - rust_test_log_1.lines().count() < rust_test_log_2.lines().count(), - "Short backtrace should be shorter than full backtrace.\nShort backtrace:\n\ - {rust_test_log_1}\nFull backtrace:\n{rust_test_log_2}" + output_bt_short.lines().count() < output_bt_full.lines().count(), + "Short backtrace should be shorter than full backtrace" ); + + let n_begin = count_lines_with(output_bt_full, "__rust_begin_short_backtrace"); + let n_end = count_lines_with(output_bt_full, "__rust_end_short_backtrace"); + assert!(n_begin + n_end > 0, "Full backtrace should contain short-backtrace markers"); assert_eq!( - count_lines_with(rust_test_log_2, "__rust_begin_short_backtrace"), - count_lines_with(rust_test_log_2, "__rust_end_short_backtrace"), - "Full backtrace should contain the short backtrace markers.\nFull backtrace:\n\ - {rust_test_log_2}" + n_begin, n_end, + "Full backtrace should contain equal numbers of begin and end markers" + ); + + assert!( + rustc_query_count_short + 5 < rustc_query_count_full, + "Short backtrace should have omitted more query plumbing lines \ + (actual: {rustc_query_count_short} vs {rustc_query_count_full})" ); - assert!(count_lines_with(rust_test_log_1, "rustc_query_") + 5 < rustc_query_count_full); - assert!(rustc_query_count_full > 5); } fn count_lines_with(s: &str, search: &str) -> usize { From eaff0cbdb6b2a616bd41a88f0cbf29b29d030ca4 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 27 Jan 2026 23:09:37 +1100 Subject: [PATCH 516/978] Use fewer intermediate functions for short backtraces in queries If we make sure that `compute_fn` in the query's vtable is actually named `__rust_begin_short_backtrace`, we can avoid the need for some additional intermediate functions and stack frames. This is similar to how the `get_query_incr` and `get_query_non_incr` functions are actually named `__rust_end_short_backtrace`. --- compiler/rustc_middle/src/query/plumbing.rs | 2 +- compiler/rustc_query_impl/src/lib.rs | 4 +- compiler/rustc_query_impl/src/plumbing.rs | 55 ++++++++++----------- 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 0b7dc3092719..b8f1fe9ec20b 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -45,7 +45,7 @@ pub struct QueryVTable<'tcx, C: QueryCache> { pub query_cache: usize, pub will_cache_on_disk_for_key_fn: Option>, pub execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value, - pub compute: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value, + pub compute_fn: fn(tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value, pub try_load_from_disk_fn: Option>, pub is_loadable_from_disk_fn: Option>, pub hash_result: HashResult, diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index baa37111c807..f0e0ce09db8e 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -29,7 +29,7 @@ use rustc_query_system::query::{ }; use rustc_span::{ErrorGuaranteed, Span}; -use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green}; +use crate::plumbing::{encode_all_query_results, try_mark_green}; use crate::profiling_support::QueryKeyStringCache; #[macro_use] @@ -123,7 +123,7 @@ where #[inline(always)] fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value { - (self.vtable.compute)(qcx.tcx, key) + (self.vtable.compute_fn)(qcx.tcx, key) } #[inline(always)] diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index b074a9ca11b0..a28bbeccc078 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -566,18 +566,6 @@ macro_rules! expand_if_cached { }; } -/// Don't show the backtrace for query system by default -/// use `RUST_BACKTRACE=full` to show all the backtraces -#[inline(never)] -pub(crate) fn __rust_begin_short_backtrace(f: F) -> T -where - F: FnOnce() -> T, -{ - let result = f(); - std::hint::black_box(()); - result -} - // NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros // invoked by `rustc_with_all_queries`. macro_rules! define_queries { @@ -636,6 +624,32 @@ macro_rules! define_queries { } } + /// Defines a `compute` function for this query, to be used as a + /// function pointer in the query's vtable. + mod compute_fn { + use super::*; + use ::rustc_middle::queries::$name::{Key, Value, provided_to_erased}; + + /// This function would be named `compute`, but we also want it + /// to mark the boundaries of an omitted region in backtraces. + #[inline(never)] + pub(crate) fn __rust_begin_short_backtrace<'tcx>( + tcx: TyCtxt<'tcx>, + key: Key<'tcx>, + ) -> Erased> { + #[cfg(debug_assertions)] + let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); + + // Call the actual provider function for this query. + let provided_value = call_provider!([$($modifiers)*][tcx, $name, key]); + rustc_middle::ty::print::with_reduced_queries!({ + tracing::trace!(?provided_value); + }); + + provided_to_erased(tcx, provided_value) + } + } + pub(crate) fn make_query_vtable<'tcx>() -> QueryVTable<'tcx, queries::$name::Storage<'tcx>> { @@ -652,22 +666,7 @@ macro_rules! define_queries { None }), execute_query: |tcx, key| erase::erase_val(tcx.$name(key)), - compute: |tcx, key| { - #[cfg(debug_assertions)] - let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); - __rust_begin_short_backtrace(|| - queries::$name::provided_to_erased( - tcx, - { - let ret = call_provider!([$($modifiers)*][tcx, $name, key]); - rustc_middle::ty::print::with_reduced_queries!({ - tracing::trace!(?ret); - }); - ret - } - ) - ) - }, + compute_fn: self::compute_fn::__rust_begin_short_backtrace, try_load_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] { Some(|tcx, key, prev_index, index| { // Check the `cache_on_disk_if` condition for this key. From baca8648563b4b71113c051a2d5e3636c11f5c87 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 4 Feb 2026 13:13:44 +0100 Subject: [PATCH 517/978] Set hidden visibility for compiler-builtins statics too. --- compiler/rustc_codegen_llvm/src/mono_item.rs | 26 +++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 838db689e729..1a8fbf67f0bc 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -41,7 +41,8 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { }); llvm::set_linkage(g, base::linkage_to_llvm(linkage)); - llvm::set_visibility(g, base::visibility_to_llvm(visibility)); + self.set_visibility(g, linkage, visibility); + self.assume_dso_local(g, false); let attrs = self.tcx.codegen_instance_attrs(instance.def); @@ -69,16 +70,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { { llvm::SetUniqueComdat(self.llmod, lldecl); } - - // If we're compiling the compiler-builtins crate, e.g., the equivalent of - // compiler-rt, then we want to implicitly compile everything with hidden - // visibility as we're going to link this object all over the place but - // don't want the symbols to get exported. - if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) { - llvm::set_visibility(lldecl, llvm::Visibility::Hidden); - } else { - llvm::set_visibility(lldecl, base::visibility_to_llvm(visibility)); - } + self.set_visibility(lldecl, linkage, visibility); debug!("predefine_fn: instance = {:?}", instance); @@ -122,6 +114,18 @@ impl CodegenCx<'_, '_> { assume } + fn set_visibility(&self, lldecl: &llvm::Value, linkage: Linkage, visibility: Visibility) { + // If we're compiling the compiler-builtins crate, i.e., the equivalent of + // compiler-rt, then we want to implicitly compile everything with hidden + // visibility as we're going to link this object all over the place but + // don't want the symbols to get exported. + if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) { + llvm::set_visibility(lldecl, llvm::Visibility::Hidden); + } else { + llvm::set_visibility(lldecl, base::visibility_to_llvm(visibility)); + } + } + fn should_assume_dso_local(&self, llval: &llvm::Value, is_declaration: bool) -> bool { let linkage = llvm::get_linkage(llval); let visibility = llvm::get_visibility(llval); From d2a0557afb3f7826266e24ab4b539e8efcb5d92f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:35:28 +0000 Subject: [PATCH 518/978] Convert to inline diagnostics in all codegen backends --- Cargo.lock | 1 - compiler/rustc_codegen_cranelift/src/lib.rs | 5 - compiler/rustc_codegen_gcc/messages.ftl | 8 -- compiler/rustc_codegen_gcc/src/errors.rs | 8 +- compiler/rustc_codegen_gcc/src/lib.rs | 7 - compiler/rustc_codegen_llvm/Cargo.toml | 1 - compiler/rustc_codegen_llvm/messages.ftl | 75 ----------- compiler/rustc_codegen_llvm/src/errors.rs | 124 +++++++++++------- compiler/rustc_codegen_llvm/src/lib.rs | 6 - .../rustc_codegen_ssa/src/traits/backend.rs | 4 - compiler/rustc_interface/src/interface.rs | 5 +- compiler/rustc_interface/src/util.rs | 4 - .../codegen-backend/auxiliary/the_backend.rs | 4 - 13 files changed, 79 insertions(+), 173 deletions(-) delete mode 100644 compiler/rustc_codegen_gcc/messages.ftl delete mode 100644 compiler/rustc_codegen_llvm/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 4cbc98beae11..d61826dd96f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3635,7 +3635,6 @@ dependencies = [ "rustc_codegen_ssa", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_fs_util", "rustc_hashes", "rustc_hir", diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 7361a6af4178..a49dc9be3458 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -125,11 +125,6 @@ pub struct CraneliftCodegenBackend { } impl CodegenBackend for CraneliftCodegenBackend { - fn locale_resource(&self) -> &'static str { - // FIXME(rust-lang/rust#100717) - cranelift codegen backend is not yet translated - "" - } - fn name(&self) -> &'static str { "cranelift" } diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl deleted file mode 100644 index b9b77b7d18c6..000000000000 --- a/compiler/rustc_codegen_gcc/messages.ftl +++ /dev/null @@ -1,8 +0,0 @@ -codegen_gcc_unwinding_inline_asm = - GCC backend does not support unwinding from inline asm - -codegen_gcc_copy_bitcode = failed to copy bitcode to object file: {$err} - -codegen_gcc_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$gcc_err}) - -codegen_gcc_explicit_tail_calls_unsupported = explicit tail calls with the 'become' keyword are not implemented in the GCC backend diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index b252c39c0c05..f5815e723392 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -2,24 +2,24 @@ use rustc_macros::Diagnostic; use rustc_span::Span; #[derive(Diagnostic)] -#[diag(codegen_gcc_unwinding_inline_asm)] +#[diag("GCC backend does not support unwinding from inline asm")] pub(crate) struct UnwindingInlineAsm { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(codegen_gcc_copy_bitcode)] +#[diag("failed to copy bitcode to object file: {$err}")] pub(crate) struct CopyBitcode { pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_gcc_lto_bitcode_from_rlib)] +#[diag("failed to get bitcode from object file for LTO ({$gcc_err})")] pub(crate) struct LtoBitcodeFromRlib { pub gcc_err: String, } #[derive(Diagnostic)] -#[diag(codegen_gcc_explicit_tail_calls_unsupported)] +#[diag("explicit tail calls with the 'become' keyword are not implemented in the GCC backend")] pub(crate) struct ExplicitTailCallsUnsupported; diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 00bea0222622..cc88fd02435e 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -27,7 +27,6 @@ extern crate rustc_ast; extern crate rustc_codegen_ssa; extern crate rustc_data_structures; extern crate rustc_errors; -extern crate rustc_fluent_macro; extern crate rustc_fs_util; extern crate rustc_hir; extern crate rustc_index; @@ -105,8 +104,6 @@ use tempfile::TempDir; use crate::back::lto::ModuleBuffer; use crate::gcc_util::{target_cpu, to_gcc_features}; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub struct PrintOnPanic String>(pub F); impl String> Drop for PrintOnPanic { @@ -197,10 +194,6 @@ fn load_libgccjit_if_needed(libgccjit_target_lib_file: &Path) { } impl CodegenBackend for GccCodegenBackend { - fn locale_resource(&self) -> &'static str { - crate::DEFAULT_LOCALE_RESOURCE - } - fn name(&self) -> &'static str { "gcc" } diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 9741436aacb7..90c87494c3c5 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -23,7 +23,6 @@ rustc_ast = { path = "../rustc_ast" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl deleted file mode 100644 index 85cb7499cca4..000000000000 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ /dev/null @@ -1,75 +0,0 @@ -codegen_llvm_autodiff_component_missing = autodiff backend not found in the sysroot: {$err} - .note = it will be distributed via rustup in the future - -codegen_llvm_autodiff_component_unavailable = failed to load our autodiff backend: {$err} - -codegen_llvm_autodiff_without_enable = using the autodiff feature requires -Z autodiff=Enable -codegen_llvm_autodiff_without_lto = using the autodiff feature requires setting `lto="fat"` in your Cargo.toml - -codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err} - -codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture - -codegen_llvm_from_llvm_diag = {$message} - -codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message} - -codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}" -codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err} - -codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$err}) - -codegen_llvm_mismatch_data_layout = - data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}` - -codegen_llvm_offload_bundleimages_failed = call to BundleImages failed, `host.out` was not created -codegen_llvm_offload_embed_failed = call to EmbedBufferInModule failed, `host.o` was not created -codegen_llvm_offload_no_abs_path = using the `-Z offload=Host=/absolute/path/to/host.out` flag requires an absolute path -codegen_llvm_offload_no_host_out = using the `-Z offload=Host=/absolute/path/to/host.out` flag must point to a `host.out` file -codegen_llvm_offload_nonexisting = the given path/file to `host.out` does not exist. Did you forget to run the device compilation first? -codegen_llvm_offload_without_enable = using the offload feature requires -Z offload= -codegen_llvm_offload_without_fat_lto = using the offload feature requires -C lto=fat - -codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module -codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err} - -codegen_llvm_parse_target_machine_config = - failed to parse target machine config to target machine: {$error} - -codegen_llvm_prepare_autodiff = failed to prepare autodiff: src: {$src}, target: {$target}, {$error} -codegen_llvm_prepare_autodiff_with_llvm_err = failed to prepare autodiff: {$llvm_err}, src: {$src}, target: {$target}, {$error} -codegen_llvm_prepare_thin_lto_context = failed to prepare thin LTO context -codegen_llvm_prepare_thin_lto_context_with_llvm_err = failed to prepare thin LTO context: {$llvm_err} - -codegen_llvm_prepare_thin_lto_module = failed to prepare thin LTO module -codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO module: {$llvm_err} - -codegen_llvm_run_passes = failed to run LLVM passes -codegen_llvm_run_passes_with_llvm_err = failed to run LLVM passes: {$llvm_err} - -codegen_llvm_sanitizer_kcfi_arity_requires_llvm_21_0_0 = `-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later. - -codegen_llvm_sanitizer_memtag_requires_mte = - `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte` - -codegen_llvm_serialize_module = failed to serialize module {$name} -codegen_llvm_serialize_module_with_llvm_err = failed to serialize module {$name}: {$llvm_err} - -codegen_llvm_symbol_already_defined = - symbol `{$symbol_name}` is already defined - -codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple} -codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err} - -codegen_llvm_unknown_debuginfo_compression = unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo - -codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err} - -codegen_llvm_write_ir = failed to write LLVM IR to {$path} -codegen_llvm_write_ir_with_llvm_err = failed to write LLVM IR to {$path}: {$llvm_err} - -codegen_llvm_write_output = could not write output to {$path} -codegen_llvm_write_output_with_llvm_err = could not write output to {$path}: {$llvm_err} - -codegen_llvm_write_thinlto_key = error while writing ThinLTO key data: {$err} -codegen_llvm_write_thinlto_key_with_llvm_err = error while writing ThinLTO key data: {$err}: {$llvm_err} diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index bd42cf556966..23fa05f3d02f 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -2,14 +2,12 @@ use std::ffi::CString; use std::path::Path; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level}; +use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, inline_fluent}; use rustc_macros::Diagnostic; use rustc_span::Span; -use crate::fluent_generated as fluent; - #[derive(Diagnostic)] -#[diag(codegen_llvm_symbol_already_defined)] +#[diag("symbol `{$symbol_name}` is already defined")] pub(crate) struct SymbolAlreadyDefined<'a> { #[primary_span] pub span: Span, @@ -17,7 +15,7 @@ pub(crate) struct SymbolAlreadyDefined<'a> { } #[derive(Diagnostic)] -#[diag(codegen_llvm_sanitizer_memtag_requires_mte)] +#[diag("`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`")] pub(crate) struct SanitizerMemtagRequiresMte; pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>); @@ -27,89 +25,97 @@ impl Diagnostic<'_, G> for ParseTargetMachineConfig<'_> { let diag: Diag<'_, G> = self.0.into_diag(dcx, level); let (message, _) = diag.messages.first().expect("`LlvmError` with no message"); let message = dcx.eagerly_translate_to_string(message.clone(), diag.args.iter()); - Diag::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config) - .with_arg("error", message) + Diag::new( + dcx, + level, + inline_fluent!("failed to parse target machine config to target machine: {$error}"), + ) + .with_arg("error", message) } } #[derive(Diagnostic)] -#[diag(codegen_llvm_autodiff_component_unavailable)] +#[diag("failed to load our autodiff backend: {$err}")] pub(crate) struct AutoDiffComponentUnavailable { pub err: String, } #[derive(Diagnostic)] -#[diag(codegen_llvm_autodiff_component_missing)] -#[note] +#[diag("autodiff backend not found in the sysroot: {$err}")] +#[note("it will be distributed via rustup in the future")] pub(crate) struct AutoDiffComponentMissing { pub err: String, } #[derive(Diagnostic)] -#[diag(codegen_llvm_autodiff_without_lto)] +#[diag("using the autodiff feature requires setting `lto=\"fat\"` in your Cargo.toml")] pub(crate) struct AutoDiffWithoutLto; #[derive(Diagnostic)] -#[diag(codegen_llvm_autodiff_without_enable)] +#[diag("using the autodiff feature requires -Z autodiff=Enable")] pub(crate) struct AutoDiffWithoutEnable; #[derive(Diagnostic)] -#[diag(codegen_llvm_offload_without_enable)] +#[diag("using the offload feature requires -Z offload=")] pub(crate) struct OffloadWithoutEnable; #[derive(Diagnostic)] -#[diag(codegen_llvm_offload_without_fat_lto)] +#[diag("using the offload feature requires -C lto=fat")] pub(crate) struct OffloadWithoutFatLTO; #[derive(Diagnostic)] -#[diag(codegen_llvm_offload_no_abs_path)] +#[diag("using the `-Z offload=Host=/absolute/path/to/host.out` flag requires an absolute path")] pub(crate) struct OffloadWithoutAbsPath; #[derive(Diagnostic)] -#[diag(codegen_llvm_offload_no_host_out)] +#[diag( + "using the `-Z offload=Host=/absolute/path/to/host.out` flag must point to a `host.out` file" +)] pub(crate) struct OffloadWrongFileName; #[derive(Diagnostic)] -#[diag(codegen_llvm_offload_nonexisting)] +#[diag( + "the given path/file to `host.out` does not exist. Did you forget to run the device compilation first?" +)] pub(crate) struct OffloadNonexistingPath; #[derive(Diagnostic)] -#[diag(codegen_llvm_offload_bundleimages_failed)] +#[diag("call to BundleImages failed, `host.out` was not created")] pub(crate) struct OffloadBundleImagesFailed; #[derive(Diagnostic)] -#[diag(codegen_llvm_offload_embed_failed)] +#[diag("call to EmbedBufferInModule failed, `host.o` was not created")] pub(crate) struct OffloadEmbedFailed; #[derive(Diagnostic)] -#[diag(codegen_llvm_lto_bitcode_from_rlib)] +#[diag("failed to get bitcode from object file for LTO ({$err})")] pub(crate) struct LtoBitcodeFromRlib { pub err: String, } #[derive(Diagnostic)] pub enum LlvmError<'a> { - #[diag(codegen_llvm_write_output)] + #[diag("could not write output to {$path}")] WriteOutput { path: &'a Path }, - #[diag(codegen_llvm_target_machine)] + #[diag("could not create LLVM TargetMachine for triple: {$triple}")] CreateTargetMachine { triple: SmallCStr }, - #[diag(codegen_llvm_run_passes)] + #[diag("failed to run LLVM passes")] RunLlvmPasses, - #[diag(codegen_llvm_serialize_module)] + #[diag("failed to serialize module {$name}")] SerializeModule { name: &'a str }, - #[diag(codegen_llvm_write_ir)] + #[diag("failed to write LLVM IR to {$path}")] WriteIr { path: &'a Path }, - #[diag(codegen_llvm_prepare_thin_lto_context)] + #[diag("failed to prepare thin LTO context")] PrepareThinLtoContext, - #[diag(codegen_llvm_load_bitcode)] + #[diag("failed to load bitcode of module \"{$name}\"")] LoadBitcode { name: CString }, - #[diag(codegen_llvm_write_thinlto_key)] + #[diag("error while writing ThinLTO key data: {$err}")] WriteThinLtoKey { err: std::io::Error }, - #[diag(codegen_llvm_prepare_thin_lto_module)] + #[diag("failed to prepare thin LTO module")] PrepareThinLtoModule, - #[diag(codegen_llvm_parse_bitcode)] + #[diag("failed to parse bitcode for LTO module")] ParseBitcode, - #[diag(codegen_llvm_prepare_autodiff)] + #[diag("failed to prepare autodiff: src: {$src}, target: {$target}, {$error}")] PrepareAutoDiff { src: String, target: String, error: String }, } @@ -119,17 +125,31 @@ impl Diagnostic<'_, G> for WithLlvmError<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { use LlvmError::*; let msg_with_llvm_err = match &self.0 { - WriteOutput { .. } => fluent::codegen_llvm_write_output_with_llvm_err, - CreateTargetMachine { .. } => fluent::codegen_llvm_target_machine_with_llvm_err, - RunLlvmPasses => fluent::codegen_llvm_run_passes_with_llvm_err, - SerializeModule { .. } => fluent::codegen_llvm_serialize_module_with_llvm_err, - WriteIr { .. } => fluent::codegen_llvm_write_ir_with_llvm_err, - PrepareThinLtoContext => fluent::codegen_llvm_prepare_thin_lto_context_with_llvm_err, - LoadBitcode { .. } => fluent::codegen_llvm_load_bitcode_with_llvm_err, - WriteThinLtoKey { .. } => fluent::codegen_llvm_write_thinlto_key_with_llvm_err, - PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err, - ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err, - PrepareAutoDiff { .. } => fluent::codegen_llvm_prepare_autodiff_with_llvm_err, + WriteOutput { .. } => inline_fluent!("could not write output to {$path}: {$llvm_err}"), + CreateTargetMachine { .. } => inline_fluent!( + "could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}" + ), + RunLlvmPasses => inline_fluent!("failed to run LLVM passes: {$llvm_err}"), + SerializeModule { .. } => { + inline_fluent!("failed to serialize module {$name}: {$llvm_err}") + } + WriteIr { .. } => inline_fluent!("failed to write LLVM IR to {$path}: {$llvm_err}"), + PrepareThinLtoContext => { + inline_fluent!("failed to prepare thin LTO context: {$llvm_err}") + } + LoadBitcode { .. } => { + inline_fluent!("failed to load bitcode of module \"{$name}\": {$llvm_err}") + } + WriteThinLtoKey { .. } => { + inline_fluent!("error while writing ThinLTO key data: {$err}: {$llvm_err}") + } + PrepareThinLtoModule => { + inline_fluent!("failed to prepare thin LTO module: {$llvm_err}") + } + ParseBitcode => inline_fluent!("failed to parse bitcode for LTO module: {$llvm_err}"), + PrepareAutoDiff { .. } => inline_fluent!( + "failed to prepare autodiff: {$llvm_err}, src: {$src}, target: {$target}, {$error}" + ), }; self.0 .into_diag(dcx, level) @@ -139,7 +159,7 @@ impl Diagnostic<'_, G> for WithLlvmError<'_> { } #[derive(Diagnostic)] -#[diag(codegen_llvm_from_llvm_optimization_diag)] +#[diag("{$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}")] pub(crate) struct FromLlvmOptimizationDiag<'a> { pub filename: &'a str, pub line: std::ffi::c_uint, @@ -150,32 +170,36 @@ pub(crate) struct FromLlvmOptimizationDiag<'a> { } #[derive(Diagnostic)] -#[diag(codegen_llvm_from_llvm_diag)] +#[diag("{$message}")] pub(crate) struct FromLlvmDiag { pub message: String, } #[derive(Diagnostic)] -#[diag(codegen_llvm_write_bytecode)] +#[diag("failed to write bytecode to {$path}: {$err}")] pub(crate) struct WriteBytecode<'a> { pub path: &'a Path, pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_llvm_copy_bitcode)] +#[diag("failed to copy bitcode to object file: {$err}")] pub(crate) struct CopyBitcode { pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_llvm_unknown_debuginfo_compression)] +#[diag( + "unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo" +)] pub(crate) struct UnknownCompression { pub algorithm: &'static str, } #[derive(Diagnostic)] -#[diag(codegen_llvm_mismatch_data_layout)] +#[diag( + "data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}`" +)] pub(crate) struct MismatchedDataLayout<'a> { pub rustc_target: &'a str, pub rustc_layout: &'a str, @@ -184,11 +208,11 @@ pub(crate) struct MismatchedDataLayout<'a> { } #[derive(Diagnostic)] -#[diag(codegen_llvm_fixed_x18_invalid_arch)] +#[diag("the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture")] pub(crate) struct FixedX18InvalidArch<'a> { pub arch: &'a str, } #[derive(Diagnostic)] -#[diag(codegen_llvm_sanitizer_kcfi_arity_requires_llvm_21_0_0)] +#[diag("`-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later.")] pub(crate) struct SanitizerKcfiArityRequiresLLVM2100; diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 5879132eb9fb..8bcf99cbb316 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -74,8 +74,6 @@ mod typetree; mod va_arg; mod value; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub(crate) use macros::TryFromU32; #[derive(Clone)] @@ -241,10 +239,6 @@ impl LlvmCodegenBackend { } impl CodegenBackend for LlvmCodegenBackend { - fn locale_resource(&self) -> &'static str { - crate::DEFAULT_LOCALE_RESOURCE - } - fn name(&self) -> &'static str { "llvm" } diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 625551d17d9d..ebedcc4b756d 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -37,10 +37,6 @@ pub trait BackendTypes { } pub trait CodegenBackend { - /// Locale resources for diagnostic messages - a string the content of the Fluent resource. - /// Called before `init` so that all other functions are able to emit translatable diagnostics. - fn locale_resource(&self) -> &'static str; - fn name(&self) -> &'static str; fn init(&self, _sess: &Session) {} diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index f76e8d4632fc..9165842dbdd0 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -463,9 +463,6 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se Err(e) => early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")), }; - let mut locale_resources = config.locale_resources; - locale_resources.push(codegen_backend.locale_resource()); - let mut sess = rustc_session::build_session( config.opts, CompilerIO { @@ -476,7 +473,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se }, bundle, config.registry, - locale_resources, + config.locale_resources, config.lint_caps, target, util::rustc_version_str().unwrap_or("unknown"), diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 25f59f0e89df..458e7ad32143 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -361,10 +361,6 @@ pub struct DummyCodegenBackend { } impl CodegenBackend for DummyCodegenBackend { - fn locale_resource(&self) -> &'static str { - "" - } - fn name(&self) -> &'static str { "dummy" } diff --git a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs index 48f328f4fad3..c15c2dea4c19 100644 --- a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs +++ b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs @@ -29,10 +29,6 @@ use rustc_session::config::OutputFilenames; struct TheBackend; impl CodegenBackend for TheBackend { - fn locale_resource(&self) -> &'static str { - "" - } - fn name(&self) -> &'static str { "the-backend" } From e4e725aec63cc773acf74b27e91dfc0630a8724f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:35:28 +0000 Subject: [PATCH 519/978] Convert to inline diagnostics in all codegen backends --- messages.ftl | 8 -------- src/errors.rs | 8 ++++---- src/lib.rs | 7 ------- 3 files changed, 4 insertions(+), 19 deletions(-) delete mode 100644 messages.ftl diff --git a/messages.ftl b/messages.ftl deleted file mode 100644 index b9b77b7d18c6..000000000000 --- a/messages.ftl +++ /dev/null @@ -1,8 +0,0 @@ -codegen_gcc_unwinding_inline_asm = - GCC backend does not support unwinding from inline asm - -codegen_gcc_copy_bitcode = failed to copy bitcode to object file: {$err} - -codegen_gcc_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$gcc_err}) - -codegen_gcc_explicit_tail_calls_unsupported = explicit tail calls with the 'become' keyword are not implemented in the GCC backend diff --git a/src/errors.rs b/src/errors.rs index b252c39c0c05..f5815e723392 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -2,24 +2,24 @@ use rustc_macros::Diagnostic; use rustc_span::Span; #[derive(Diagnostic)] -#[diag(codegen_gcc_unwinding_inline_asm)] +#[diag("GCC backend does not support unwinding from inline asm")] pub(crate) struct UnwindingInlineAsm { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(codegen_gcc_copy_bitcode)] +#[diag("failed to copy bitcode to object file: {$err}")] pub(crate) struct CopyBitcode { pub err: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_gcc_lto_bitcode_from_rlib)] +#[diag("failed to get bitcode from object file for LTO ({$gcc_err})")] pub(crate) struct LtoBitcodeFromRlib { pub gcc_err: String, } #[derive(Diagnostic)] -#[diag(codegen_gcc_explicit_tail_calls_unsupported)] +#[diag("explicit tail calls with the 'become' keyword are not implemented in the GCC backend")] pub(crate) struct ExplicitTailCallsUnsupported; diff --git a/src/lib.rs b/src/lib.rs index 00bea0222622..cc88fd02435e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,6 @@ extern crate rustc_ast; extern crate rustc_codegen_ssa; extern crate rustc_data_structures; extern crate rustc_errors; -extern crate rustc_fluent_macro; extern crate rustc_fs_util; extern crate rustc_hir; extern crate rustc_index; @@ -105,8 +104,6 @@ use tempfile::TempDir; use crate::back::lto::ModuleBuffer; use crate::gcc_util::{target_cpu, to_gcc_features}; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub struct PrintOnPanic String>(pub F); impl String> Drop for PrintOnPanic { @@ -197,10 +194,6 @@ fn load_libgccjit_if_needed(libgccjit_target_lib_file: &Path) { } impl CodegenBackend for GccCodegenBackend { - fn locale_resource(&self) -> &'static str { - crate::DEFAULT_LOCALE_RESOURCE - } - fn name(&self) -> &'static str { "gcc" } From 732406017c2b3d8aecb77e12fc7c51d71bd9e4c3 Mon Sep 17 00:00:00 2001 From: dianqk Date: Sat, 18 Oct 2025 21:42:08 +0800 Subject: [PATCH 520/978] Add miscompiled test cases for GVN --- .../gvn_copy_aggregate.deref_nonssa.GVN.diff | 50 ++++++++++++ ...gvn_copy_aggregate.deref_nonssa_2.GVN.diff | 77 +++++++++++++++++++ tests/mir-opt/gvn_copy_aggregate.rs | 25 ++++++ .../gvn_overlapping.copy_overlapping.GVN.diff | 19 +++++ tests/mir-opt/gvn_overlapping.rs | 17 ++++ 5 files changed, 188 insertions(+) create mode 100644 tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff create mode 100644 tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff create mode 100644 tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff diff --git a/tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff new file mode 100644 index 000000000000..d17213993282 --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff @@ -0,0 +1,50 @@ +- // MIR for `deref_nonssa` before GVN ++ // MIR for `deref_nonssa` after GVN + + fn deref_nonssa() -> Single { + let mut _0: Single; + let mut _1: Single; + let mut _4: Single; + let mut _5: u8; + scope 1 { + debug a => _1; + let _2: &Single; + scope 2 { + debug b => _2; + let _3: u8; + scope 3 { + debug c => _3; + } + } + } + + bb0: { + StorageLive(_1); +- _1 = Single(const 0_u8); +- StorageLive(_2); ++ _1 = const Single(0_u8); ++ nop; + _2 = &_1; +- StorageLive(_3); ++ nop; + _3 = copy ((*_2).0: u8); + StorageLive(_4); +- _4 = Single(const 1_u8); +- _1 = move _4; ++ _4 = const Single(1_u8); ++ _1 = const Single(1_u8); + StorageDead(_4); + StorageLive(_5); + _5 = copy _3; +- _0 = Single(move _5); ++ _0 = copy (*_2); + StorageDead(_5); +- StorageDead(_3); +- StorageDead(_2); ++ nop; ++ nop; + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff new file mode 100644 index 000000000000..64d137bfc26b --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff @@ -0,0 +1,77 @@ +- // MIR for `deref_nonssa_2` before GVN ++ // MIR for `deref_nonssa_2` after GVN + + fn deref_nonssa_2() -> Single { + let mut _0: Single; + let mut _1: Single; + let mut _3: &Single; + let _4: &Single; + let mut _7: Single; + let mut _9: u8; + scope 1 { + debug a => _1; + let _2: SingleRef<'_>; + scope 2 { + debug r => _2; + let _5: &Single; + scope 3 { + debug b => _5; + let _6: u8; + scope 4 { + debug c => _6; + let _8: Single; + scope 5 { + debug d => _8; + } + } + } + } + } + + bb0: { + StorageLive(_1); +- _1 = Single(const 0_u8); ++ _1 = const Single(0_u8); + StorageLive(_2); +- StorageLive(_3); +- StorageLive(_4); ++ nop; ++ nop; + _4 = &_1; + _3 = &(*_4); +- _2 = SingleRef::<'_>(move _3); +- StorageDead(_3); +- StorageDead(_4); ++ _2 = SingleRef::<'_>(copy _3); ++ nop; ++ nop; + StorageLive(_5); +- _5 = copy (_2.0: &Single); +- StorageLive(_6); +- _6 = copy ((*_5).0: u8); ++ _5 = copy _3; ++ nop; ++ _6 = copy ((*_4).0: u8); + StorageLive(_7); +- _7 = Single(const 1_u8); +- _1 = move _7; ++ _7 = const Single(1_u8); ++ _1 = const Single(1_u8); + StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + _9 = copy _6; +- _8 = Single(move _9); ++ _8 = copy (*_4); + StorageDead(_9); + _0 = move _8; + StorageDead(_8); +- StorageDead(_6); ++ nop; + StorageDead(_5); + StorageDead(_2); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.rs b/tests/mir-opt/gvn_copy_aggregate.rs index c9473025a15f..af1839fd3efc 100644 --- a/tests/mir-opt/gvn_copy_aggregate.rs +++ b/tests/mir-opt/gvn_copy_aggregate.rs @@ -259,3 +259,28 @@ fn remove_storage_dead_from_index(f: fn() -> usize, v: [SameType; 5]) -> SameTyp } } } + +pub struct Single(u8); + +// EMIT_MIR gvn_copy_aggregate.deref_nonssa.GVN.diff +fn deref_nonssa() -> Single { + let mut a = Single(0); + let b = &a; + let c = (*b).0; + a = Single(1); + // GVN shouldn't replace `Single(c)` with `*b`. + Single(c) +} + +pub struct SingleRef<'a>(&'a Single); + +// EMIT_MIR gvn_copy_aggregate.deref_nonssa_2.GVN.diff +pub fn deref_nonssa_2() -> Single { + let mut a = Single(0); + let r = SingleRef(&a); + let b = r.0; + let c = (*b).0; + a = Single(1); + let d = Single(c); + d +} diff --git a/tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff b/tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff new file mode 100644 index 000000000000..f13c92e4fd01 --- /dev/null +++ b/tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff @@ -0,0 +1,19 @@ +- // MIR for `copy_overlapping` before GVN ++ // MIR for `copy_overlapping` after GVN + + fn copy_overlapping() -> () { + let mut _0: (); + let mut _1: Adt; + let mut _2: u32; + let mut _3: &Adt; + + bb0: { + ((_1 as variant#1).0: u32) = const 0_u32; + _3 = &_1; + _2 = copy (((*_3) as variant#1).0: u32); +- _1 = Adt::Some(copy _2); ++ _1 = copy (*_3); + return; + } + } + diff --git a/tests/mir-opt/gvn_overlapping.rs b/tests/mir-opt/gvn_overlapping.rs index f148a8435612..a41f8ad5fd60 100644 --- a/tests/mir-opt/gvn_overlapping.rs +++ b/tests/mir-opt/gvn_overlapping.rs @@ -64,6 +64,23 @@ fn fields(_1: (Adt, Adt)) { } } +// EMIT_MIR gvn_overlapping.copy_overlapping.GVN.diff +#[custom_mir(dialect = "runtime")] +fn copy_overlapping() { + mir! { + let _1; + let _2; + let _3; + { + place!(Field(Variant(_1, 1), 0)) = 0u32; + _3 = &_1; + _2 = Field(Variant(*_3, 1), 0); + _1 = Adt::Some(_2); + Return() + } + } +} + fn main() { overlapping(Adt::Some(0)); } From 9f9c4c8b0b7d787fc0ee05d3f25144c8c4ef7283 Mon Sep 17 00:00:00 2001 From: dianqk Date: Tue, 21 Oct 2025 20:06:44 +0800 Subject: [PATCH 521/978] GVN: Remove invalidate_derefs --- compiler/rustc_middle/src/mir/terminator.rs | 22 ------------ compiler/rustc_mir_transform/src/gvn.rs | 38 +-------------------- 2 files changed, 1 insertion(+), 59 deletions(-) diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index cd447d4ed992..cd9db451ac53 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -695,28 +695,6 @@ impl<'tcx> TerminatorKind<'tcx> { _ => None, } } - - /// Returns true if the terminator can write to memory. - pub fn can_write_to_memory(&self) -> bool { - match self { - TerminatorKind::Goto { .. } - | TerminatorKind::SwitchInt { .. } - | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate(_) - | TerminatorKind::Return - | TerminatorKind::Assert { .. } - | TerminatorKind::CoroutineDrop - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::Unreachable => false, - TerminatorKind::Call { .. } - | TerminatorKind::Drop { .. } - | TerminatorKind::TailCall { .. } - // Yield writes to the resume_arg place. - | TerminatorKind::Yield { .. } - | TerminatorKind::InlineAsm { .. } => true, - } - } } #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index db38c271aaf9..bd6bfe2ef791 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -129,7 +129,6 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { let ssa = SsaLocals::new(tcx, body, typing_env); // Clone dominators because we need them while mutating the body. let dominators = body.basic_blocks.dominators().clone(); - let maybe_loop_headers = loops::maybe_loop_headers(body); let arena = DroplessArena::default(); let mut state = @@ -142,11 +141,6 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec(); for bb in reverse_postorder { - // N.B. With loops, reverse postorder cannot produce a valid topological order. - // A statement or terminator from inside the loop, that is not processed yet, may have performed an indirect write. - if maybe_loop_headers.contains(bb) { - state.invalidate_derefs(); - } let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb]; state.visit_basic_block_data(bb, data); } @@ -350,12 +344,6 @@ impl<'a, 'tcx> ValueSet<'a, 'tcx> { fn ty(&self, index: VnIndex) -> Ty<'tcx> { self.types[index] } - - /// Replace the value associated with `index` with an opaque value. - #[inline] - fn forget(&mut self, index: VnIndex) { - self.values[index] = Value::Opaque(VnOpaque); - } } struct VnState<'body, 'a, 'tcx> { @@ -374,8 +362,6 @@ struct VnState<'body, 'a, 'tcx> { /// - `Some(None)` are values for which computation has failed; /// - `Some(Some(op))` are successful computations. evaluated: IndexVec>>>, - /// Cache the deref values. - derefs: Vec, ssa: &'body SsaLocals, dominators: Dominators, reused_locals: DenseBitSet, @@ -408,7 +394,6 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { rev_locals: IndexVec::with_capacity(num_values), values: ValueSet::new(num_values), evaluated: IndexVec::with_capacity(num_values), - derefs: Vec::new(), ssa, dominators, reused_locals: DenseBitSet::new_empty(local_decls.len()), @@ -542,15 +527,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { } fn insert_deref(&mut self, ty: Ty<'tcx>, value: VnIndex) -> VnIndex { - let value = self.insert(ty, Value::Projection(value, ProjectionElem::Deref)); - self.derefs.push(value); - value - } - - fn invalidate_derefs(&mut self) { - for deref in std::mem::take(&mut self.derefs) { - self.values.forget(deref); - } + self.insert(ty, Value::Projection(value, ProjectionElem::Deref)) } #[instrument(level = "trace", skip(self), ret)] @@ -1916,10 +1893,6 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> { fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { self.simplify_place_projection(place, location); - if context.is_mutating_use() && place.is_indirect() { - // Non-local mutation maybe invalidate deref. - self.invalidate_derefs(); - } self.super_place(place, context, location); } @@ -1949,11 +1922,6 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> { } } - if lhs.is_indirect() { - // Non-local mutation maybe invalidate deref. - self.invalidate_derefs(); - } - if let Some(local) = lhs.as_local() && self.ssa.is_ssa(local) && let rvalue_ty = rvalue.ty(self.local_decls, self.tcx) @@ -1976,10 +1944,6 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> { self.assign(local, opaque); } } - // Terminators that can write to memory may invalidate (nested) derefs. - if terminator.kind.can_write_to_memory() { - self.invalidate_derefs(); - } self.super_terminator(terminator, location); } } From bc2bf6b544be9e4140bf77db4491ecfc9487764e Mon Sep 17 00:00:00 2001 From: dianqk Date: Mon, 29 Dec 2025 21:30:37 +0800 Subject: [PATCH 522/978] GVN: Do not introduce new dereferences if they borrow from non-SSA locals --- compiler/rustc_mir_transform/src/gvn.rs | 50 +++++++++----- ...ng_operand.test.GVN.32bit.panic-abort.diff | 9 +-- ...g_operand.test.GVN.32bit.panic-unwind.diff | 9 +-- ...ng_operand.test.GVN.64bit.panic-abort.diff | 9 +-- ...g_operand.test.GVN.64bit.panic-unwind.diff | 9 +-- .../gvn.dereferences.GVN.panic-abort.diff | 30 ++++++--- .../gvn.dereferences.GVN.panic-unwind.diff | 30 ++++++--- .../gvn.fn_pointers.GVN.panic-abort.diff | 18 ++--- .../gvn.fn_pointers.GVN.panic-unwind.diff | 18 ++--- tests/mir-opt/gvn.rs | 67 +++++++++++-------- ...xpression_elimination.GVN.panic-abort.diff | 50 +++++++++----- ...pression_elimination.GVN.panic-unwind.diff | 50 +++++++++----- .../gvn_copy_aggregate.all_copy_2.GVN.diff | 2 +- .../gvn_copy_aggregate.all_copy_mut.GVN.diff | 61 +++++++++++++++++ .../gvn_copy_aggregate.deref_nonssa.GVN.diff | 8 +-- ...gvn_copy_aggregate.deref_nonssa_2.GVN.diff | 23 ++----- tests/mir-opt/gvn_copy_aggregate.rs | 25 +++++-- .../mir-opt/gvn_loop.loop_deref_mut.GVN.diff | 24 ++----- tests/mir-opt/gvn_loop.rs | 2 +- .../gvn_overlapping.copy_overlapping.GVN.diff | 3 +- .../gvn_overlapping.overlapping.GVN.diff | 4 +- tests/mir-opt/gvn_overlapping.rs | 29 ++++---- ...gvn_overlapping.stable_projection.GVN.diff | 12 ++-- .../pre-codegen/deref_nested_borrows.rs | 3 - ...ef_nested_borrows.src.GVN.panic-abort.diff | 8 ++- ...f_nested_borrows.src.GVN.panic-unwind.diff | 8 ++- ...rrows.src.PreCodegen.after.panic-abort.mir | 8 +-- ...rows.src.PreCodegen.after.panic-unwind.mir | 8 +-- 28 files changed, 339 insertions(+), 238 deletions(-) create mode 100644 tests/mir-opt/gvn_copy_aggregate.all_copy_mut.GVN.diff diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index bd6bfe2ef791..3466248b2bf7 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -135,7 +135,7 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls, &arena); for local in body.args_iter().filter(|&local| ssa.is_ssa(local)) { - let opaque = state.new_opaque(body.local_decls[local].ty); + let opaque = state.new_argument(body.local_decls[local].ty); state.assign(local, opaque); } @@ -198,8 +198,9 @@ enum AddressBase { enum Value<'a, 'tcx> { // Root values. /// Used to represent values we know nothing about. - /// The `usize` is a counter incremented by `new_opaque`. Opaque(VnOpaque), + /// The value is a argument. + Argument(VnOpaque), /// Evaluated or unevaluated constant value. Constant { value: Const<'tcx>, @@ -284,7 +285,7 @@ impl<'a, 'tcx> ValueSet<'a, 'tcx> { let value = value(VnOpaque); debug_assert!(match value { - Value::Opaque(_) | Value::Address { .. } => true, + Value::Opaque(_) | Value::Argument(_) | Value::Address { .. } => true, Value::Constant { disambiguator, .. } => disambiguator.is_some(), _ => false, }); @@ -440,6 +441,13 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { index } + #[instrument(level = "trace", skip(self), ret)] + fn new_argument(&mut self, ty: Ty<'tcx>) -> VnIndex { + let index = self.insert_unique(ty, Value::Argument); + self.evaluated[index] = Some(None); + index + } + /// Create a new `Value::Address` distinct from all the others. #[instrument(level = "trace", skip(self), ret)] fn new_pointer(&mut self, place: Place<'tcx>, kind: AddressKind) -> Option { @@ -457,8 +465,11 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { // Skip the initial `Deref`. projection.next(); AddressBase::Deref(base) - } else { + } else if self.ssa.is_ssa(place.local) { + // Only propagate the pointer of the SSA local. AddressBase::Local(place.local) + } else { + return None; }; // Do not try evaluating inside `Index`, this has been done by `simplify_place_projection`. let projection = @@ -526,10 +537,6 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { self.insert(ty, Value::Aggregate(VariantIdx::ZERO, self.arena.alloc_slice(values))) } - fn insert_deref(&mut self, ty: Ty<'tcx>, value: VnIndex) -> VnIndex { - self.insert(ty, Value::Projection(value, ProjectionElem::Deref)) - } - #[instrument(level = "trace", skip(self), ret)] fn eval_to_const_inner(&mut self, value: VnIndex) -> Option> { use Value::*; @@ -543,7 +550,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { let op = match self.get(value) { _ if ty.is_zst() => ImmTy::uninit(ty).into(), - Opaque(_) => return None, + Opaque(_) | Argument(_) => return None, // Keep runtime check constants as symbolic. RuntimeChecks(..) => return None, @@ -795,7 +802,9 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { // An immutable borrow `_x` always points to the same value for the // lifetime of the borrow, so we can merge all instances of `*_x`. - return Some((projection_ty, self.insert_deref(projection_ty.ty, value))); + let deref = self + .insert(projection_ty.ty, Value::Projection(value, ProjectionElem::Deref)); + return Some((projection_ty, deref)); } else { return None; } @@ -1014,7 +1023,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { let op = self.simplify_operand(op, location)?; Value::Repeat(op, amount) } - Rvalue::Aggregate(..) => return self.simplify_aggregate(lhs, rvalue, location), + Rvalue::Aggregate(..) => return self.simplify_aggregate(rvalue, location), Rvalue::Ref(_, borrow_kind, ref mut place) => { self.simplify_place_projection(place, location); return self.new_pointer(*place, AddressKind::Ref(borrow_kind)); @@ -1125,7 +1134,6 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { fn simplify_aggregate( &mut self, - lhs: &Place<'tcx>, rvalue: &mut Rvalue<'tcx>, location: Location, ) -> Option { @@ -1208,12 +1216,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { } if let Some(value) = self.simplify_aggregate_to_copy(ty, variant_index, &fields) { - // Allow introducing places with non-constant offsets, as those are still better than - // reconstructing an aggregate. But avoid creating `*a = copy (*b)`, as they might be - // aliases resulting in overlapping assignments. - let allow_complex_projection = - lhs.projection[..].iter().all(PlaceElem::is_stable_offset); - if let Some(place) = self.try_as_place(value, location, allow_complex_projection) { + if let Some(place) = self.try_as_place(value, location, true) { self.reused_locals.insert(place.local); *rvalue = Rvalue::Use(Operand::Copy(place)); } @@ -1867,6 +1870,17 @@ impl<'tcx> VnState<'_, '_, 'tcx> { && (allow_complex_projection || proj.is_stable_offset()) && let Some(proj) = self.try_as_place_elem(self.ty(index), proj, loc) { + if proj == PlaceElem::Deref { + // We can introduce a new dereference if the source value cannot be changed in the body. + // Dereferencing an immutable argument always gives the same value in the body. + match self.get(pointer) { + Value::Argument(_) + if let Some(Mutability::Not) = self.ty(pointer).ref_mutability() => {} + _ => { + return None; + } + } + } projection.push(proj); index = pointer; } else { diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff index cde4d281f687..f3ccc66cdc95 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff @@ -75,8 +75,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = (); @@ -144,12 +143,10 @@ StorageDead(_4); _2 = &_3; _1 = &(*_2); -- StorageDead(_2); + StorageDead(_2); - StorageLive(_5); -- _10 = copy (*_1); + nop; -+ nop; -+ _10 = copy (*_2); + _10 = copy (*_1); _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); _5 = &raw const (*_11); - StorageLive(_6); diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff index 82a14a8b6ec9..9a354fc005ed 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff @@ -37,8 +37,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = (); @@ -51,12 +50,10 @@ StorageDead(_4); _2 = &_3; _1 = &(*_2); -- StorageDead(_2); + StorageDead(_2); - StorageLive(_5); -- _10 = copy (*_1); + nop; -+ nop; -+ _10 = copy (*_2); + _10 = copy (*_1); _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); _5 = &raw const (*_11); - StorageLive(_6); diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff index ea5622eb9a2f..f8d781bb706f 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff @@ -75,8 +75,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = (); @@ -144,12 +143,10 @@ StorageDead(_4); _2 = &_3; _1 = &(*_2); -- StorageDead(_2); + StorageDead(_2); - StorageLive(_5); -- _10 = copy (*_1); + nop; -+ nop; -+ _10 = copy (*_2); + _10 = copy (*_1); _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); _5 = &raw const (*_11); - StorageLive(_6); diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff index 82a14a8b6ec9..9a354fc005ed 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff @@ -37,8 +37,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = (); @@ -51,12 +50,10 @@ StorageDead(_4); _2 = &_3; _1 = &(*_2); -- StorageDead(_2); + StorageDead(_2); - StorageLive(_5); -- _10 = copy (*_1); + nop; -+ nop; -+ _10 = copy (*_2); + _10 = copy (*_1); _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); _5 = &raw const (*_11); - StorageLive(_6); diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff index ecd7bdc433cd..a763614dc644 100644 --- a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff @@ -107,18 +107,23 @@ StorageLive(_18); _18 = &(*_1); StorageLive(_19); - StorageLive(_20); +- StorageLive(_20); ++ nop; _20 = copy (*_18); - _19 = opaque::(move _20) -> [return: bb7, unwind unreachable]; +- _19 = opaque::(move _20) -> [return: bb7, unwind unreachable]; ++ _19 = opaque::(copy _20) -> [return: bb7, unwind unreachable]; } bb7: { - StorageDead(_20); +- StorageDead(_20); ++ nop; StorageDead(_19); StorageLive(_21); StorageLive(_22); - _22 = copy (*_18); - _21 = opaque::(move _22) -> [return: bb8, unwind unreachable]; +- _22 = copy (*_18); +- _21 = opaque::(move _22) -> [return: bb8, unwind unreachable]; ++ _22 = copy _20; ++ _21 = opaque::(copy _20) -> [return: bb8, unwind unreachable]; } bb8: { @@ -152,18 +157,23 @@ StorageDead(_28); StorageDead(_27); StorageLive(_29); - StorageLive(_30); +- StorageLive(_30); ++ nop; _30 = copy ((*_3).0: u32); - _29 = opaque::(move _30) -> [return: bb12, unwind unreachable]; +- _29 = opaque::(move _30) -> [return: bb12, unwind unreachable]; ++ _29 = opaque::(copy _30) -> [return: bb12, unwind unreachable]; } bb12: { - StorageDead(_30); +- StorageDead(_30); ++ nop; StorageDead(_29); StorageLive(_31); StorageLive(_32); - _32 = copy ((*_3).0: u32); - _31 = opaque::(move _32) -> [return: bb13, unwind unreachable]; +- _32 = copy ((*_3).0: u32); +- _31 = opaque::(move _32) -> [return: bb13, unwind unreachable]; ++ _32 = copy _30; ++ _31 = opaque::(copy _30) -> [return: bb13, unwind unreachable]; } bb13: { diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff index bbca6bc3c754..ca6fda483642 100644 --- a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff @@ -107,18 +107,23 @@ StorageLive(_18); _18 = &(*_1); StorageLive(_19); - StorageLive(_20); +- StorageLive(_20); ++ nop; _20 = copy (*_18); - _19 = opaque::(move _20) -> [return: bb7, unwind continue]; +- _19 = opaque::(move _20) -> [return: bb7, unwind continue]; ++ _19 = opaque::(copy _20) -> [return: bb7, unwind continue]; } bb7: { - StorageDead(_20); +- StorageDead(_20); ++ nop; StorageDead(_19); StorageLive(_21); StorageLive(_22); - _22 = copy (*_18); - _21 = opaque::(move _22) -> [return: bb8, unwind continue]; +- _22 = copy (*_18); +- _21 = opaque::(move _22) -> [return: bb8, unwind continue]; ++ _22 = copy _20; ++ _21 = opaque::(copy _20) -> [return: bb8, unwind continue]; } bb8: { @@ -152,18 +157,23 @@ StorageDead(_28); StorageDead(_27); StorageLive(_29); - StorageLive(_30); +- StorageLive(_30); ++ nop; _30 = copy ((*_3).0: u32); - _29 = opaque::(move _30) -> [return: bb12, unwind continue]; +- _29 = opaque::(move _30) -> [return: bb12, unwind continue]; ++ _29 = opaque::(copy _30) -> [return: bb12, unwind continue]; } bb12: { - StorageDead(_30); +- StorageDead(_30); ++ nop; StorageDead(_29); StorageLive(_31); StorageLive(_32); - _32 = copy ((*_3).0: u32); - _31 = opaque::(move _32) -> [return: bb13, unwind continue]; +- _32 = copy ((*_3).0: u32); +- _31 = opaque::(move _32) -> [return: bb13, unwind continue]; ++ _32 = copy _30; ++ _31 = opaque::(copy _30) -> [return: bb13, unwind continue]; } bb13: { diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff index a29d3331f380..96920af4dddc 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:618:19: 618:21}; + let mut _9: {closure@$DIR/gvn.rs:629:19: 629:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:618:19: 618:21}; + let mut _13: {closure@$DIR/gvn.rs:629:19: 629:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:618:19: 618:21}; + let _7: {closure@$DIR/gvn.rs:629:19: 629:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:618:19: 618:21}; +- _7 = {closure@$DIR/gvn.rs:629:19: 629:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21}; + nop; StorageLive(_9); - _9 = copy _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = copy _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff index b716fcd4e74b..d32a82322203 100644 --- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff @@ -8,10 +8,10 @@ let mut _3: fn(u8) -> u8; let _5: (); let mut _6: fn(u8) -> u8; - let mut _9: {closure@$DIR/gvn.rs:618:19: 618:21}; + let mut _9: {closure@$DIR/gvn.rs:629:19: 629:21}; let _10: (); let mut _11: fn(); - let mut _13: {closure@$DIR/gvn.rs:618:19: 618:21}; + let mut _13: {closure@$DIR/gvn.rs:629:19: 629:21}; let _14: (); let mut _15: fn(); scope 1 { @@ -19,7 +19,7 @@ let _4: fn(u8) -> u8; scope 2 { debug g => _4; - let _7: {closure@$DIR/gvn.rs:618:19: 618:21}; + let _7: {closure@$DIR/gvn.rs:629:19: 629:21}; scope 3 { debug closure => _7; let _8: fn(); @@ -62,16 +62,16 @@ StorageDead(_6); StorageDead(_5); - StorageLive(_7); -- _7 = {closure@$DIR/gvn.rs:618:19: 618:21}; +- _7 = {closure@$DIR/gvn.rs:629:19: 629:21}; - StorageLive(_8); + nop; -+ _7 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; ++ _7 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21}; + nop; StorageLive(_9); - _9 = copy _7; - _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _9 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; -+ _8 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _9 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21}; ++ _8 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_9); StorageLive(_10); StorageLive(_11); @@ -88,8 +88,8 @@ StorageLive(_13); - _13 = copy _7; - _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); -+ _13 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21}; -+ _12 = const ZeroSized: {closure@$DIR/gvn.rs:618:19: 618:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); ++ _13 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21}; ++ _12 = const ZeroSized: {closure@$DIR/gvn.rs:629:19: 629:21} as fn() (PointerCoercion(ClosureFnPointer(Safe), AsCast)); StorageDead(_13); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 837e8ac4d9e3..ad2826c3cb04 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -100,14 +100,14 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) { opaque((x * y) - y); opaque((x * y) - y); - // We cannot substitute through an immutable reference. + // We can substitute through an immutable reference. // CHECK: [[ref:_.*]] = &_3; // CHECK: [[deref:_.*]] = copy (*[[ref]]); - // CHECK: [[addref:_.*]] = Add(move [[deref]], copy _1); - // CHECK: opaque::(move [[addref]]) - // CHECK: [[deref2:_.*]] = copy (*[[ref]]); - // CHECK: [[addref2:_.*]] = Add(move [[deref2]], copy _1); - // CHECK: opaque::(move [[addref2]]) + // CHECK: [[addref:_.*]] = Add(copy [[deref]], copy _1); + // CHECK: opaque::(copy [[addref]]) + // CHECK: [[deref2:_.*]] = copy [[deref]]; + // CHECK: [[addref2:_.*]] = copy [[addref]]; + // CHECK: opaque::(copy [[addref]]) let a = &z; opaque(*a + x); opaque(*a + x); @@ -140,15 +140,14 @@ fn subexpression_elimination(x: u64, y: u64, mut z: u64) { opaque(*d + x); } - // We still cannot substitute again, and never with the earlier computations. // Important: `e` is not `a`! // CHECK: [[ref2:_.*]] = &_3; // CHECK: [[deref2:_.*]] = copy (*[[ref2]]); - // CHECK: [[addref2:_.*]] = Add(move [[deref2]], copy _1); - // CHECK: opaque::(move [[addref2]]) - // CHECK: [[deref3:_.*]] = copy (*[[ref2]]); - // CHECK: [[addref3:_.*]] = Add(move [[deref3]], copy _1); - // CHECK: opaque::(move [[addref3]]) + // CHECK: [[addref2:_.*]] = Add(copy [[deref2]], copy _1); + // CHECK: opaque::(copy [[addref2]]) + // CHECK: [[deref3:_.*]] = copy [[deref2]]; + // CHECK: [[addref3:_.*]] = copy [[addref2]]; + // CHECK: opaque::(copy [[addref2]]) let e = &z; opaque(*e + x); opaque(*e + x); @@ -452,20 +451,21 @@ fn references(mut x: impl Sized) { // CHECK: opaque::<*mut impl Sized>(move [[ref8]]) opaque(&raw mut x); + // FIXME: ReferencePropagation transform this pattern. let r = &mut x; let s = S(r).0; // Obfuscate `r`. Following lines should still reborrow `r`. // CHECK: [[ref9:_.*]] = &mut _1; - // CHECK: [[ref10:_.*]] = &(*[[ref9]]); - // CHECK: opaque::<&impl Sized>(move [[ref10]]) + // COM: CHECK: [[ref10:_.*]] = &(*[[ref9]]); + // COM: CHECK: opaque::<&impl Sized>(move [[ref10]]) opaque(&*s); - // CHECK: [[ref11:_.*]] = &mut (*[[ref9]]); - // CHECK: opaque::<&mut impl Sized>(move [[ref11]]) + // COM: CHECK: [[ref11:_.*]] = &mut (*[[ref9]]); + // COM: CHECK: opaque::<&mut impl Sized>(move [[ref11]]) opaque(&mut *s); - // CHECK: [[ref12:_.*]] = &raw const (*[[ref9]]); - // CHECK: opaque::<*const impl Sized>(move [[ref12]]) + // COM: CHECK: [[ref12:_.*]] = &raw const (*[[ref9]]); + // COM: CHECK: opaque::<*const impl Sized>(move [[ref12]]) opaque(&raw const *s); - // CHECK: [[ref12:_.*]] = &raw mut (*[[ref9]]); - // CHECK: opaque::<*mut impl Sized>(move [[ref12]]) + // COM: CHECK: [[ref12:_.*]] = &raw mut (*[[ref9]]); + // COM: CHECK: opaque::<*mut impl Sized>(move [[ref12]]) opaque(&raw mut *s); } @@ -473,17 +473,21 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S) { // CHECK-LABEL: fn dereferences( // Do not reuse dereferences of `&mut`. + // CHECK: bb0: // CHECK: [[st1:_.*]] = copy (*_1); // CHECK: opaque::(move [[st1]]) + // CHECK: bb1: // CHECK: [[st2:_.*]] = copy (*_1); // CHECK: opaque::(move [[st2]]) opaque(*t); opaque(*t); // Do not reuse dereferences of `*const`. + // CHECK: bb2: // CHECK: [[raw:_.*]] = &raw const (*_1); // CHECK: [[st3:_.*]] = copy (*[[raw]]); // CHECK: opaque::(move [[st3]]) + // CHECK: bb3: // CHECK: [[st4:_.*]] = copy (*[[raw]]); // CHECK: opaque::(move [[st4]]) let z = &raw const *t; @@ -491,42 +495,49 @@ fn dereferences(t: &mut u32, u: &impl Copy, s: &S) { unsafe { opaque(*z) }; // Do not reuse dereferences of `*mut`. + // CHECK: bb4: // CHECK: [[ptr:_.*]] = &raw mut (*_1); // CHECK: [[st5:_.*]] = copy (*[[ptr]]); // CHECK: opaque::(move [[st5]]) + // CHECK: bb5: // CHECK: [[st6:_.*]] = copy (*[[ptr]]); // CHECK: opaque::(move [[st6]]) let z = &raw mut *t; unsafe { opaque(*z) }; unsafe { opaque(*z) }; - // Do not reuse dereferences of `&Freeze`. + // CHECK: bb6: // CHECK: [[ref:_.*]] = &(*_1); // CHECK: [[st7:_.*]] = copy (*[[ref]]); - // CHECK: opaque::(move [[st7]]) - // CHECK: [[st8:_.*]] = copy (*[[ref]]); - // CHECK: opaque::(move [[st8]]) + // CHECK: opaque::(copy [[st7]]) + // CHECK: bb7: + // CHECK: [[st8:_.*]] = copy [[st7]]; + // CHECK: opaque::(copy [[st7]]) let z = &*t; opaque(*z); opaque(*z); // Not in reborrows either. + // CHECK: bb8: // CHECK: [[reborrow:_.*]] = &(*[[ref]]); // CHECK: opaque::<&u32>(move [[reborrow]]) opaque(&*z); // `*u` is not Freeze, so we cannot reuse. + // CHECK: bb9: // CHECK: [[st8:_.*]] = copy (*_2); // CHECK: opaque::(move [[st8]]) + // CHECK: bb10: // CHECK: [[st9:_.*]] = copy (*_2); // CHECK: opaque::(move [[st9]]) opaque(*u); opaque(*u); - // `*s` is not Copy, but `(*s).0` is, but we still cannot reuse. + // CHECK: bb11: // CHECK: [[st10:_.*]] = copy ((*_3).0: u32); - // CHECK: opaque::(move [[st10]]) - // CHECK: [[st11:_.*]] = copy ((*_3).0: u32); - // CHECK: opaque::(move [[st11]]) + // CHECK: opaque::(copy [[st10]]) + // CHECK: bb12: + // CHECK: [[st11:_.*]] = copy [[st10]]; + // CHECK: opaque::(copy [[st10]]) opaque(s.0); opaque(s.0); } diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff index e872e011542b..7a479bc55da7 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff @@ -758,32 +758,39 @@ StorageLive(_126); _126 = &_3; StorageLive(_127); - StorageLive(_128); - StorageLive(_129); +- StorageLive(_128); +- StorageLive(_129); ++ nop; ++ nop; _129 = copy (*_126); StorageLive(_130); _130 = copy _1; - _128 = Add(move _129, move _130); -+ _128 = Add(move _129, copy _1); ++ _128 = Add(copy _129, copy _1); StorageDead(_130); - StorageDead(_129); - _127 = opaque::(move _128) -> [return: bb35, unwind unreachable]; +- StorageDead(_129); +- _127 = opaque::(move _128) -> [return: bb35, unwind unreachable]; ++ nop; ++ _127 = opaque::(copy _128) -> [return: bb35, unwind unreachable]; } bb35: { - StorageDead(_128); +- StorageDead(_128); ++ nop; StorageDead(_127); StorageLive(_131); StorageLive(_132); StorageLive(_133); - _133 = copy (*_126); +- _133 = copy (*_126); ++ _133 = copy _129; StorageLive(_134); _134 = copy _1; - _132 = Add(move _133, move _134); -+ _132 = Add(move _133, copy _1); ++ _132 = copy _128; StorageDead(_134); StorageDead(_133); - _131 = opaque::(move _132) -> [return: bb36, unwind unreachable]; +- _131 = opaque::(move _132) -> [return: bb36, unwind unreachable]; ++ _131 = opaque::(copy _128) -> [return: bb36, unwind unreachable]; } bb36: { @@ -899,32 +906,39 @@ StorageLive(_163); _163 = &_3; StorageLive(_164); - StorageLive(_165); - StorageLive(_166); +- StorageLive(_165); +- StorageLive(_166); ++ nop; ++ nop; _166 = copy (*_163); StorageLive(_167); _167 = copy _1; - _165 = Add(move _166, move _167); -+ _165 = Add(move _166, copy _1); ++ _165 = Add(copy _166, copy _1); StorageDead(_167); - StorageDead(_166); - _164 = opaque::(move _165) -> [return: bb43, unwind unreachable]; +- StorageDead(_166); +- _164 = opaque::(move _165) -> [return: bb43, unwind unreachable]; ++ nop; ++ _164 = opaque::(copy _165) -> [return: bb43, unwind unreachable]; } bb43: { - StorageDead(_165); +- StorageDead(_165); ++ nop; StorageDead(_164); StorageLive(_168); StorageLive(_169); StorageLive(_170); - _170 = copy (*_163); +- _170 = copy (*_163); ++ _170 = copy _166; StorageLive(_171); _171 = copy _1; - _169 = Add(move _170, move _171); -+ _169 = Add(move _170, copy _1); ++ _169 = copy _165; StorageDead(_171); StorageDead(_170); - _168 = opaque::(move _169) -> [return: bb44, unwind unreachable]; +- _168 = opaque::(move _169) -> [return: bb44, unwind unreachable]; ++ _168 = opaque::(copy _165) -> [return: bb44, unwind unreachable]; } bb44: { diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff index 3996dab27a34..3ca5238663c2 100644 --- a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff @@ -758,32 +758,39 @@ StorageLive(_126); _126 = &_3; StorageLive(_127); - StorageLive(_128); - StorageLive(_129); +- StorageLive(_128); +- StorageLive(_129); ++ nop; ++ nop; _129 = copy (*_126); StorageLive(_130); _130 = copy _1; - _128 = Add(move _129, move _130); -+ _128 = Add(move _129, copy _1); ++ _128 = Add(copy _129, copy _1); StorageDead(_130); - StorageDead(_129); - _127 = opaque::(move _128) -> [return: bb35, unwind continue]; +- StorageDead(_129); +- _127 = opaque::(move _128) -> [return: bb35, unwind continue]; ++ nop; ++ _127 = opaque::(copy _128) -> [return: bb35, unwind continue]; } bb35: { - StorageDead(_128); +- StorageDead(_128); ++ nop; StorageDead(_127); StorageLive(_131); StorageLive(_132); StorageLive(_133); - _133 = copy (*_126); +- _133 = copy (*_126); ++ _133 = copy _129; StorageLive(_134); _134 = copy _1; - _132 = Add(move _133, move _134); -+ _132 = Add(move _133, copy _1); ++ _132 = copy _128; StorageDead(_134); StorageDead(_133); - _131 = opaque::(move _132) -> [return: bb36, unwind continue]; +- _131 = opaque::(move _132) -> [return: bb36, unwind continue]; ++ _131 = opaque::(copy _128) -> [return: bb36, unwind continue]; } bb36: { @@ -899,32 +906,39 @@ StorageLive(_163); _163 = &_3; StorageLive(_164); - StorageLive(_165); - StorageLive(_166); +- StorageLive(_165); +- StorageLive(_166); ++ nop; ++ nop; _166 = copy (*_163); StorageLive(_167); _167 = copy _1; - _165 = Add(move _166, move _167); -+ _165 = Add(move _166, copy _1); ++ _165 = Add(copy _166, copy _1); StorageDead(_167); - StorageDead(_166); - _164 = opaque::(move _165) -> [return: bb43, unwind continue]; +- StorageDead(_166); +- _164 = opaque::(move _165) -> [return: bb43, unwind continue]; ++ nop; ++ _164 = opaque::(copy _165) -> [return: bb43, unwind continue]; } bb43: { - StorageDead(_165); +- StorageDead(_165); ++ nop; StorageDead(_164); StorageLive(_168); StorageLive(_169); StorageLive(_170); - _170 = copy (*_163); +- _170 = copy (*_163); ++ _170 = copy _166; StorageLive(_171); _171 = copy _1; - _169 = Add(move _170, move _171); -+ _169 = Add(move _170, copy _1); ++ _169 = copy _165; StorageDead(_171); StorageDead(_170); - _168 = opaque::(move _169) -> [return: bb44, unwind continue]; +- _168 = opaque::(move _169) -> [return: bb44, unwind continue]; ++ _168 = opaque::(copy _165) -> [return: bb44, unwind continue]; } bb44: { diff --git a/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff index eed8cb7d62e7..a44968a43e5d 100644 --- a/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff +++ b/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff @@ -47,7 +47,7 @@ StorageLive(_7); _7 = copy _4; - _0 = AllCopy { a: move _5, b: move _6, c: move _7 }; -+ _0 = copy (*_8); ++ _0 = AllCopy { a: copy _2, b: copy _3, c: copy _4 }; StorageDead(_7); StorageDead(_6); StorageDead(_5); diff --git a/tests/mir-opt/gvn_copy_aggregate.all_copy_mut.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.all_copy_mut.GVN.diff new file mode 100644 index 000000000000..92c9db1b3d79 --- /dev/null +++ b/tests/mir-opt/gvn_copy_aggregate.all_copy_mut.GVN.diff @@ -0,0 +1,61 @@ +- // MIR for `all_copy_mut` before GVN ++ // MIR for `all_copy_mut` after GVN + + fn all_copy_mut(_1: &mut AllCopy) -> AllCopy { + debug mut_v => _1; + let mut _0: AllCopy; + let _2: &AllCopy; + let mut _6: i32; + let mut _7: u64; + let mut _8: [i8; 3]; + scope 1 { + debug v => _2; + let _3: i32; + scope 2 { + debug a => _3; + let _4: u64; + scope 3 { + debug b => _4; + let _5: [i8; 3]; + scope 4 { + debug c => _5; + } + } + } + } + + bb0: { + StorageLive(_2); + _2 = &(*_1); +- StorageLive(_3); ++ nop; + _3 = copy ((*_2).0: i32); +- StorageLive(_4); ++ nop; + _4 = copy ((*_2).1: u64); +- StorageLive(_5); ++ nop; + _5 = copy ((*_2).2: [i8; 3]); + ((*_1).0: i32) = const 0_i32; + StorageLive(_6); + _6 = copy _3; + StorageLive(_7); + _7 = copy _4; + StorageLive(_8); + _8 = copy _5; +- _0 = AllCopy { a: move _6, b: move _7, c: move _8 }; ++ _0 = AllCopy { a: copy _3, b: copy _4, c: copy _5 }; + StorageDead(_8); + StorageDead(_7); + StorageDead(_6); +- StorageDead(_5); +- StorageDead(_4); +- StorageDead(_3); ++ nop; ++ nop; ++ nop; + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff index d17213993282..d9707e40c0bd 100644 --- a/tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff +++ b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa.GVN.diff @@ -21,9 +21,8 @@ bb0: { StorageLive(_1); - _1 = Single(const 0_u8); -- StorageLive(_2); + _1 = const Single(0_u8); -+ nop; + StorageLive(_2); _2 = &_1; - StorageLive(_3); + nop; @@ -37,12 +36,11 @@ StorageLive(_5); _5 = copy _3; - _0 = Single(move _5); -+ _0 = copy (*_2); ++ _0 = Single(copy _3); StorageDead(_5); - StorageDead(_3); -- StorageDead(_2); -+ nop; + nop; + StorageDead(_2); StorageDead(_1); return; } diff --git a/tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff index 64d137bfc26b..0dea89020e85 100644 --- a/tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff +++ b/tests/mir-opt/gvn_copy_aggregate.deref_nonssa_2.GVN.diff @@ -7,7 +7,7 @@ let mut _3: &Single; let _4: &Single; let mut _7: Single; - let mut _9: u8; + let mut _8: u8; scope 1 { debug a => _1; let _2: SingleRef<'_>; @@ -19,10 +19,6 @@ let _6: u8; scope 4 { debug c => _6; - let _8: Single; - scope 5 { - debug d => _8; - } } } } @@ -34,24 +30,22 @@ + _1 = const Single(0_u8); StorageLive(_2); - StorageLive(_3); -- StorageLive(_4); -+ nop; + nop; + StorageLive(_4); _4 = &_1; _3 = &(*_4); - _2 = SingleRef::<'_>(move _3); - StorageDead(_3); -- StorageDead(_4); + _2 = SingleRef::<'_>(copy _3); + nop; -+ nop; + StorageDead(_4); StorageLive(_5); - _5 = copy (_2.0: &Single); - StorageLive(_6); - _6 = copy ((*_5).0: u8); + _5 = copy _3; + nop; -+ _6 = copy ((*_4).0: u8); ++ _6 = copy ((*_3).0: u8); StorageLive(_7); - _7 = Single(const 1_u8); - _1 = move _7; @@ -59,12 +53,9 @@ + _1 = const Single(1_u8); StorageDead(_7); StorageLive(_8); - StorageLive(_9); - _9 = copy _6; -- _8 = Single(move _9); -+ _8 = copy (*_4); - StorageDead(_9); - _0 = move _8; + _8 = copy _6; +- _0 = Single(move _8); ++ _0 = Single(copy _6); StorageDead(_8); - StorageDead(_6); + nop; diff --git a/tests/mir-opt/gvn_copy_aggregate.rs b/tests/mir-opt/gvn_copy_aggregate.rs index af1839fd3efc..c96138824154 100644 --- a/tests/mir-opt/gvn_copy_aggregate.rs +++ b/tests/mir-opt/gvn_copy_aggregate.rs @@ -24,13 +24,25 @@ fn all_copy(v: &AllCopy) -> AllCopy { AllCopy { a, b, c } } +// EMIT_MIR gvn_copy_aggregate.all_copy_mut.GVN.diff +fn all_copy_mut(mut_v: &mut AllCopy) -> AllCopy { + // CHECK-LABEL: fn all_copy_mut( + // CHECK: = AllCopy { {{.*}} }; + // CHECK-NOT: _0 = copy ({{.*}}); + let v = &*mut_v; + let a = v.a; + let b = v.b; + let c = v.c; + mut_v.a = 0; + AllCopy { a, b, c } +} + +// Nested references may be modified. // EMIT_MIR gvn_copy_aggregate.all_copy_2.GVN.diff fn all_copy_2(v: &&AllCopy) -> AllCopy { // CHECK-LABEL: fn all_copy_2( // CHECK: bb0: { - // CHECK-NOT: = AllCopy { {{.*}} }; - // CHECK: [[V1:_.*]] = copy (*_1); - // CHECK: _0 = copy (*[[V1]]); + // CHECK: _0 = AllCopy { {{.*}} }; let a = v.a; let b = v.b; let c = v.c; @@ -264,6 +276,8 @@ pub struct Single(u8); // EMIT_MIR gvn_copy_aggregate.deref_nonssa.GVN.diff fn deref_nonssa() -> Single { + // CHECK-LABEL: fn deref_nonssa( + // CHECK: _0 = Single(copy {{.*}}); let mut a = Single(0); let b = &a; let c = (*b).0; @@ -276,11 +290,12 @@ pub struct SingleRef<'a>(&'a Single); // EMIT_MIR gvn_copy_aggregate.deref_nonssa_2.GVN.diff pub fn deref_nonssa_2() -> Single { + // CHECK-LABEL: fn deref_nonssa_2( + // CHECK: _0 = Single(copy {{.*}}); let mut a = Single(0); let r = SingleRef(&a); let b = r.0; let c = (*b).0; a = Single(1); - let d = Single(c); - d + Single(c) } diff --git a/tests/mir-opt/gvn_loop.loop_deref_mut.GVN.diff b/tests/mir-opt/gvn_loop.loop_deref_mut.GVN.diff index e5d719cf3ca9..589cfd2a3cf1 100644 --- a/tests/mir-opt/gvn_loop.loop_deref_mut.GVN.diff +++ b/tests/mir-opt/gvn_loop.loop_deref_mut.GVN.diff @@ -17,7 +17,7 @@ let mut _15: !; let mut _16: Value; scope 1 { - debug val_alias => _2; + debug val_alias => _3; let mut _5: bool; scope 2 { debug stop => _5; @@ -33,23 +33,16 @@ } bb0: { - StorageLive(_2); -- StorageLive(_3); -+ nop; StorageLive(_4); _4 = &(*_1); - _3 = get::(move _4) -> [return: bb1, unwind unreachable]; + _3 = get::(copy _4) -> [return: bb1, unwind unreachable]; } bb1: { - _2 = &(*_3); StorageDead(_4); -- StorageDead(_3); -+ nop; StorageLive(_5); _5 = const false; -- _8 = discriminant((*_2)); -+ _8 = discriminant((*_3)); + _8 = discriminant((*_3)); switchInt(move _8) -> [0: bb3, otherwise: bb2]; } @@ -59,10 +52,8 @@ bb3: { - StorageLive(_7); -- _7 = copy (((*_2) as V0).0: i32); + nop; -+ _7 = copy (((*_3) as V0).0: i32); - StorageLive(_9); + _7 = copy (((*_3) as V0).0: i32); goto -> bb4; } @@ -73,7 +64,6 @@ - _11 = Value::V0(move _12); + _11 = Value::V0(copy _7); StorageDead(_12); - StorageLive(_13); StorageLive(_14); _14 = copy _5; switchInt(move _14) -> [0: bb6, otherwise: bb5]; @@ -82,20 +72,15 @@ bb5: { _0 = move _11; StorageDead(_14); - StorageDead(_13); StorageDead(_11); - StorageDead(_9); - StorageDead(_7); + nop; StorageDead(_5); - StorageDead(_2); return; } bb6: { - _13 = const (); StorageDead(_14); - StorageDead(_13); _5 = const true; StorageLive(_16); - _16 = Value::V1; @@ -103,7 +88,6 @@ + _16 = const Value::V1; + (*_1) = const Value::V1; StorageDead(_16); - _10 = const (); StorageDead(_11); goto -> bb4; } diff --git a/tests/mir-opt/gvn_loop.rs b/tests/mir-opt/gvn_loop.rs index ce23f7930f1b..d51baf46302f 100644 --- a/tests/mir-opt/gvn_loop.rs +++ b/tests/mir-opt/gvn_loop.rs @@ -1,5 +1,5 @@ //@ test-mir-pass: GVN -//@ compile-flags: -Zdump-mir-exclude-alloc-bytes +//@ compile-flags: -Zdump-mir-exclude-alloc-bytes -Zmir-enable-passes=+ReferencePropagation #![crate_type = "lib"] #![feature(core_intrinsics, rustc_attrs)] diff --git a/tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff b/tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff index f13c92e4fd01..7b7537bc9b40 100644 --- a/tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff +++ b/tests/mir-opt/gvn_overlapping.copy_overlapping.GVN.diff @@ -11,8 +11,7 @@ ((_1 as variant#1).0: u32) = const 0_u32; _3 = &_1; _2 = copy (((*_3) as variant#1).0: u32); -- _1 = Adt::Some(copy _2); -+ _1 = copy (*_3); + _1 = Adt::Some(copy _2); return; } } diff --git a/tests/mir-opt/gvn_overlapping.overlapping.GVN.diff b/tests/mir-opt/gvn_overlapping.overlapping.GVN.diff index fcabcdbcfef2..efebdf53c292 100644 --- a/tests/mir-opt/gvn_overlapping.overlapping.GVN.diff +++ b/tests/mir-opt/gvn_overlapping.overlapping.GVN.diff @@ -3,12 +3,12 @@ fn overlapping(_1: Adt) -> () { let mut _0: (); - let mut _2: *mut Adt; + let mut _2: &mut Adt; let mut _3: u32; let mut _4: &Adt; bb0: { - _2 = &raw mut _1; + _2 = &mut _1; _4 = &(*_2); _3 = copy (((*_4) as variant#1).0: u32); (*_2) = Adt::Some(copy _3); diff --git a/tests/mir-opt/gvn_overlapping.rs b/tests/mir-opt/gvn_overlapping.rs index a41f8ad5fd60..bd93787cb483 100644 --- a/tests/mir-opt/gvn_overlapping.rs +++ b/tests/mir-opt/gvn_overlapping.rs @@ -7,19 +7,19 @@ use std::intrinsics::mir::*; // EMIT_MIR gvn_overlapping.overlapping.GVN.diff /// Check that we do not create overlapping assignments. #[custom_mir(dialect = "runtime")] -fn overlapping(_17: Adt) { +fn overlapping(_1: Adt) { // CHECK-LABEL: fn overlapping( - // CHECK: let mut [[PTR:.*]]: *mut Adt; + // CHECK: let mut [[PTR:.*]]: &mut Adt; // CHECK: (*[[PTR]]) = Adt::Some(copy {{.*}}); mir! { - let _33: *mut Adt; - let _48: u32; - let _73: &Adt; + let _2: &mut Adt; + let _3: u32; + let _4: &Adt; { - _33 = core::ptr::addr_of_mut!(_17); - _73 = &(*_33); - _48 = Field(Variant((*_73), 1), 0); - (*_33) = Adt::Some(_48); + _2 = &mut _1; + _4 = &(*_2); + _3 = Field(Variant((*_4), 1), 0); + (*_2) = Adt::Some(_3); Return() } } @@ -30,18 +30,19 @@ fn overlapping(_17: Adt) { #[custom_mir(dialect = "runtime")] fn stable_projection(_1: (Adt,)) { // CHECK-LABEL: fn stable_projection( - // CHECK: let mut _2: *mut Adt; + // CHECK: let mut _2: &Adt; // CHECK: let mut _4: &Adt; - // CHECK: (_1.0: Adt) = copy (*_4); + // CHECK: (_5.0: Adt) = copy (_1.0: Adt); mir! { - let _2: *mut Adt; + let _2: &Adt; let _3: u32; let _4: &Adt; + let _5: (Adt,); { - _2 = core::ptr::addr_of_mut!(_1.0); + _2 = &_1.0; _4 = &(*_2); _3 = Field(Variant((*_4), 1), 0); - _1.0 = Adt::Some(_3); + _5.0 = Adt::Some(_3); Return() } } diff --git a/tests/mir-opt/gvn_overlapping.stable_projection.GVN.diff b/tests/mir-opt/gvn_overlapping.stable_projection.GVN.diff index 088354565911..b5353b7abde7 100644 --- a/tests/mir-opt/gvn_overlapping.stable_projection.GVN.diff +++ b/tests/mir-opt/gvn_overlapping.stable_projection.GVN.diff @@ -3,16 +3,18 @@ fn stable_projection(_1: (Adt,)) -> () { let mut _0: (); - let mut _2: *mut Adt; + let mut _2: &Adt; let mut _3: u32; let mut _4: &Adt; + let mut _5: (Adt,); bb0: { - _2 = &raw mut (_1.0: Adt); + _2 = &(_1.0: Adt); _4 = &(*_2); - _3 = copy (((*_4) as variant#1).0: u32); -- (_1.0: Adt) = Adt::Some(copy _3); -+ (_1.0: Adt) = copy (*_4); +- _3 = copy (((*_4) as variant#1).0: u32); +- (_5.0: Adt) = Adt::Some(copy _3); ++ _3 = copy (((_1.0: Adt) as variant#1).0: u32); ++ (_5.0: Adt) = copy (_1.0: Adt); return; } } diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.rs b/tests/mir-opt/pre-codegen/deref_nested_borrows.rs index 738cd981ae67..ab700a642900 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.rs +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.rs @@ -2,9 +2,6 @@ fn src(x: &&u8) -> bool { // CHECK-LABEL: fn src( - // CHECK-NOT: _0 = const true; - // CHECK: _0 = Eq({{.*}}, {{.*}}); - // CHECK-NOT: _0 = const true; let y = **x; unsafe { unknown() }; **x == y diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff index 269af438e37e..a68ff13f26a6 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff @@ -24,12 +24,14 @@ bb1: { StorageLive(_4); - _7 = copy (*_1); - _4 = copy (*_7); +- _7 = copy (*_1); +- _4 = copy (*_7); ++ _7 = copy _6; ++ _4 = copy _2; StorageLive(_5); _5 = copy _2; - _0 = Eq(move _4, move _5); -+ _0 = Eq(move _4, copy _2); ++ _0 = const true; StorageDead(_5); StorageDead(_4); - StorageDead(_2); diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff index 9ce17342a445..fe64d8f97d20 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff @@ -24,12 +24,14 @@ bb1: { StorageLive(_4); - _7 = copy (*_1); - _4 = copy (*_7); +- _7 = copy (*_1); +- _4 = copy (*_7); ++ _7 = copy _6; ++ _4 = copy _2; StorageLive(_5); _5 = copy _2; - _0 = Eq(move _4, move _5); -+ _0 = Eq(move _4, copy _2); ++ _0 = const true; StorageDead(_5); StorageDead(_4); - StorageDead(_2); diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-abort.mir index 23b1c3f3f43a..13f2eb9874b4 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-abort.mir @@ -6,8 +6,6 @@ fn src(_1: &&u8) -> bool { let mut _2: &u8; let _3: u8; let _4: (); - let mut _5: &u8; - let mut _6: u8; scope 1 { debug y => _3; } @@ -19,11 +17,7 @@ fn src(_1: &&u8) -> bool { } bb1: { - StorageLive(_6); - _5 = copy (*_1); - _6 = copy (*_5); - _0 = Eq(move _6, copy _3); - StorageDead(_6); + _0 = const true; return; } } diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir index 4c01e9464bf4..7fab6e5511fd 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir @@ -6,8 +6,6 @@ fn src(_1: &&u8) -> bool { let mut _2: &u8; let _3: u8; let _4: (); - let mut _5: &u8; - let mut _6: u8; scope 1 { debug y => _3; } @@ -19,11 +17,7 @@ fn src(_1: &&u8) -> bool { } bb1: { - StorageLive(_6); - _5 = copy (*_1); - _6 = copy (*_5); - _0 = Eq(move _6, copy _3); - StorageDead(_6); + _0 = const true; return; } } From 9c029d2102b76ea1bab41062a26d144e342a4713 Mon Sep 17 00:00:00 2001 From: dianqk Date: Mon, 26 Jan 2026 20:49:16 +0800 Subject: [PATCH 523/978] GVN: Do not unify dereferences if they are references --- compiler/rustc_mir_transform/src/gvn.rs | 12 ++ ....dereference_reborrow.GVN.panic-abort.diff | 37 +++++ ...dereference_reborrow.GVN.panic-unwind.diff | 37 +++++ .../gvn.field_borrow.GVN.panic-abort.diff | 30 ++++ .../gvn.field_borrow.GVN.panic-unwind.diff | 30 ++++ .../gvn.field_borrow_2.GVN.panic-abort.diff | 51 ++++++ .../gvn.field_borrow_2.GVN.panic-unwind.diff | 51 ++++++ tests/mir-opt/gvn.rs | 50 ++++++ .../gvn_copy_aggregate.all_copy_2.GVN.diff | 14 +- .../pre-codegen/deref_nested_borrows.rs | 11 ++ ...ef_nested_borrows.src.GVN.panic-abort.diff | 8 +- ...f_nested_borrows.src.GVN.panic-unwind.diff | 8 +- ...rrows.src.PreCodegen.after.panic-abort.mir | 8 +- ...rows.src.PreCodegen.after.panic-unwind.mir | 8 +- ...variant_a-{closure#0}.PreCodegen.after.mir | 152 +++++++++--------- ...variant_b-{closure#0}.PreCodegen.after.mir | 54 ++++--- 16 files changed, 443 insertions(+), 118 deletions(-) create mode 100644 tests/mir-opt/gvn.dereference_reborrow.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.dereference_reborrow.GVN.panic-unwind.diff create mode 100644 tests/mir-opt/gvn.field_borrow.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.field_borrow.GVN.panic-unwind.diff create mode 100644 tests/mir-opt/gvn.field_borrow_2.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn.field_borrow_2.GVN.panic-unwind.diff diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 3466248b2bf7..6507a5194add 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -799,6 +799,18 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { { return Some((projection_ty, value)); } + // DO NOT reason the pointer value. + // We cannot unify two pointers that dereference same local, because they may + // have different lifetimes. + // ``` + // let b: &T = *a; + // ... `a` is allowed to be modified. `c` and `b` have different borrowing lifetime. + // Unifying them will extend the lifetime of `b`. + // let c: &T = *a; + // ``` + if projection_ty.ty.is_ref() { + return None; + } // An immutable borrow `_x` always points to the same value for the // lifetime of the borrow, so we can merge all instances of `*_x`. diff --git a/tests/mir-opt/gvn.dereference_reborrow.GVN.panic-abort.diff b/tests/mir-opt/gvn.dereference_reborrow.GVN.panic-abort.diff new file mode 100644 index 000000000000..1b2e6c681b92 --- /dev/null +++ b/tests/mir-opt/gvn.dereference_reborrow.GVN.panic-abort.diff @@ -0,0 +1,37 @@ +- // MIR for `dereference_reborrow` before GVN ++ // MIR for `dereference_reborrow` after GVN + + fn dereference_reborrow(_1: &mut u8) -> () { + debug mut_a => _1; + let mut _0: (); + let _2: &u8; + scope 1 { + debug a => _2; + let _3: u8; + scope 2 { + debug b => _3; + let _4: u8; + scope 3 { + debug c => _4; + } + } + } + + bb0: { + StorageLive(_2); + _2 = &(*_1); +- StorageLive(_3); ++ nop; + _3 = copy (*_2); + StorageLive(_4); +- _4 = copy (*_2); ++ _4 = copy _3; + _0 = const (); + StorageDead(_4); +- StorageDead(_3); ++ nop; + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/gvn.dereference_reborrow.GVN.panic-unwind.diff b/tests/mir-opt/gvn.dereference_reborrow.GVN.panic-unwind.diff new file mode 100644 index 000000000000..1b2e6c681b92 --- /dev/null +++ b/tests/mir-opt/gvn.dereference_reborrow.GVN.panic-unwind.diff @@ -0,0 +1,37 @@ +- // MIR for `dereference_reborrow` before GVN ++ // MIR for `dereference_reborrow` after GVN + + fn dereference_reborrow(_1: &mut u8) -> () { + debug mut_a => _1; + let mut _0: (); + let _2: &u8; + scope 1 { + debug a => _2; + let _3: u8; + scope 2 { + debug b => _3; + let _4: u8; + scope 3 { + debug c => _4; + } + } + } + + bb0: { + StorageLive(_2); + _2 = &(*_1); +- StorageLive(_3); ++ nop; + _3 = copy (*_2); + StorageLive(_4); +- _4 = copy (*_2); ++ _4 = copy _3; + _0 = const (); + StorageDead(_4); +- StorageDead(_3); ++ nop; + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/gvn.field_borrow.GVN.panic-abort.diff b/tests/mir-opt/gvn.field_borrow.GVN.panic-abort.diff new file mode 100644 index 000000000000..5839ff581129 --- /dev/null +++ b/tests/mir-opt/gvn.field_borrow.GVN.panic-abort.diff @@ -0,0 +1,30 @@ +- // MIR for `field_borrow` before GVN ++ // MIR for `field_borrow` after GVN + + fn field_borrow(_1: &FieldBorrow<'_>) -> () { + debug a => _1; + let mut _0: (); + let _2: &u8; + scope 1 { + debug b => _2; + let _3: &u8; + scope 2 { + debug c => _3; + } + } + + bb0: { +- StorageLive(_2); ++ nop; + _2 = copy ((*_1).0: &u8); + StorageLive(_3); +- _3 = copy ((*_1).0: &u8); ++ _3 = copy _2; + _0 = const (); + StorageDead(_3); +- StorageDead(_2); ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn.field_borrow.GVN.panic-unwind.diff b/tests/mir-opt/gvn.field_borrow.GVN.panic-unwind.diff new file mode 100644 index 000000000000..5839ff581129 --- /dev/null +++ b/tests/mir-opt/gvn.field_borrow.GVN.panic-unwind.diff @@ -0,0 +1,30 @@ +- // MIR for `field_borrow` before GVN ++ // MIR for `field_borrow` after GVN + + fn field_borrow(_1: &FieldBorrow<'_>) -> () { + debug a => _1; + let mut _0: (); + let _2: &u8; + scope 1 { + debug b => _2; + let _3: &u8; + scope 2 { + debug c => _3; + } + } + + bb0: { +- StorageLive(_2); ++ nop; + _2 = copy ((*_1).0: &u8); + StorageLive(_3); +- _3 = copy ((*_1).0: &u8); ++ _3 = copy _2; + _0 = const (); + StorageDead(_3); +- StorageDead(_2); ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn.field_borrow_2.GVN.panic-abort.diff b/tests/mir-opt/gvn.field_borrow_2.GVN.panic-abort.diff new file mode 100644 index 000000000000..819211c41f90 --- /dev/null +++ b/tests/mir-opt/gvn.field_borrow_2.GVN.panic-abort.diff @@ -0,0 +1,51 @@ +- // MIR for `field_borrow_2` before GVN ++ // MIR for `field_borrow_2` after GVN + + fn field_borrow_2(_1: &&FieldBorrow<'_>) -> () { + debug a => _1; + let mut _0: (); + let _2: &FieldBorrow<'_>; + scope 1 { + debug b => _2; + let _3: &u8; + scope 2 { + debug c => _3; + let _4: &FieldBorrow<'_>; + scope 3 { + debug d => _4; + let _5: &u8; + scope 4 { + debug e => _5; + let _6: &u8; + scope 5 { + debug f => _6; + } + } + } + } + } + + bb0: { + StorageLive(_2); + _2 = copy (*_1); + StorageLive(_3); + _3 = copy ((*_2).0: &u8); + StorageLive(_4); + _4 = copy (*_1); +- StorageLive(_5); ++ nop; + _5 = copy ((*_4).0: &u8); + StorageLive(_6); +- _6 = copy ((*_4).0: &u8); ++ _6 = copy _5; + _0 = const (); + StorageDead(_6); +- StorageDead(_5); ++ nop; + StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/gvn.field_borrow_2.GVN.panic-unwind.diff b/tests/mir-opt/gvn.field_borrow_2.GVN.panic-unwind.diff new file mode 100644 index 000000000000..819211c41f90 --- /dev/null +++ b/tests/mir-opt/gvn.field_borrow_2.GVN.panic-unwind.diff @@ -0,0 +1,51 @@ +- // MIR for `field_borrow_2` before GVN ++ // MIR for `field_borrow_2` after GVN + + fn field_borrow_2(_1: &&FieldBorrow<'_>) -> () { + debug a => _1; + let mut _0: (); + let _2: &FieldBorrow<'_>; + scope 1 { + debug b => _2; + let _3: &u8; + scope 2 { + debug c => _3; + let _4: &FieldBorrow<'_>; + scope 3 { + debug d => _4; + let _5: &u8; + scope 4 { + debug e => _5; + let _6: &u8; + scope 5 { + debug f => _6; + } + } + } + } + } + + bb0: { + StorageLive(_2); + _2 = copy (*_1); + StorageLive(_3); + _3 = copy ((*_2).0: &u8); + StorageLive(_4); + _4 = copy (*_1); +- StorageLive(_5); ++ nop; + _5 = copy ((*_4).0: &u8); + StorageLive(_6); +- _6 = copy ((*_4).0: &u8); ++ _6 = copy _5; + _0 = const (); + StorageDead(_6); +- StorageDead(_5); ++ nop; + StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index ad2826c3cb04..07309c1569cd 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -1100,6 +1100,53 @@ fn dereference_indexing(array: [u8; 2], index: usize) { opaque(*a); } +// EMIT_MIR gvn.dereference_reborrow.GVN.diff +fn dereference_reborrow(mut_a: &mut u8) { + // CHECK-LABEL: fn dereference_reborrow( + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + // CHECK: debug c => [[c:_.*]]; + // CHECK: [[a]] = &(*_1); + // CHECK: [[b]] = copy (*[[a]]); + // CHECK: [[c]] = copy [[b]]; + let a = &*mut_a; + let b = *a; + let c = *a; +} + +struct FieldBorrow<'a>(&'a u8); + +// EMIT_MIR gvn.field_borrow.GVN.diff +fn field_borrow(a: &FieldBorrow<'_>) { + // CHECK-LABEL: fn field_borrow( + // CHECK: debug b => [[b:_.*]]; + // CHECK: debug c => [[c:_.*]]; + // CHECK: [[b]] = copy ((*_1).0: &u8); + // CHECK: [[c]] = copy [[b]]; + let b = a.0; + let c = a.0; +} + +// EMIT_MIR gvn.field_borrow_2.GVN.diff +fn field_borrow_2(a: &&FieldBorrow<'_>) { + // CHECK-LABEL: fn field_borrow_2( + // CHECK: debug b => [[b:_.*]]; + // CHECK: debug c => [[c:_.*]]; + // CHECK: debug d => [[d:_.*]]; + // CHECK: debug e => [[e:_.*]]; + // CHECK: debug f => [[f:_.*]]; + // CHECK: [[b]] = copy (*_1); + // CHECK: [[c]] = copy ((*[[b]]).0: &u8); + // CHECK: [[d]] = copy (*_1); + // CHECK: [[e]] = copy ((*[[d]]).0: &u8); + // CHECK: [[f]] = copy [[e]]; + let b = *a; + let c = b.0; + let d = *a; + let e = d.0; + let f = d.0; +} + // CHECK-LABEL: fn main( fn main() { subexpression_elimination(2, 4, 5); @@ -1129,6 +1176,9 @@ fn main() { meta_of_ref_to_slice(&42); slice_from_raw_parts_as_ptr(&123, 456); dereference_indexing([129, 14], 5); + dereference_reborrow(&mut 5); + field_borrow(&FieldBorrow(&0)); + field_borrow(&&FieldBorrow(&0)); } #[inline(never)] diff --git a/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff index a44968a43e5d..2eeeff56cc77 100644 --- a/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff +++ b/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff @@ -29,17 +29,13 @@ _8 = copy (*_1); _2 = copy ((*_8).0: i32); - StorageLive(_3); -- _9 = copy (*_1); -- _3 = copy ((*_9).1: u64); ++ nop; + _9 = copy (*_1); + _3 = copy ((*_9).1: u64); - StorageLive(_4); -- _10 = copy (*_1); -- _4 = copy ((*_10).2: [i8; 3]); + nop; -+ _9 = copy _8; -+ _3 = copy ((*_8).1: u64); -+ nop; -+ _10 = copy _8; -+ _4 = copy ((*_8).2: [i8; 3]); + _10 = copy (*_1); + _4 = copy ((*_10).2: [i8; 3]); StorageLive(_5); _5 = copy _2; StorageLive(_6); diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.rs b/tests/mir-opt/pre-codegen/deref_nested_borrows.rs index ab700a642900..23ad0189a66d 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.rs +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.rs @@ -2,6 +2,17 @@ fn src(x: &&u8) -> bool { // CHECK-LABEL: fn src( + // CHECK: debug y => [[Y:_.*]]; + // CHECK: bb0: + // CHECK: [[BORROW_u8:_.*]] = copy (*_1); + // CHECK: [[Y]] = copy (*[[BORROW_u8]]); + // CHECK: bb1: + // BORROW_u8 outside its lifetime in bb1. + // CHECK-NOT: copy (*[[BORROW_u8]]); + // CHECK: copy (*_1); + // CHECK-NOT: _0 = const true; + // CHECK: _0 = Eq({{.*}}, {{.*}}); + // CHECK-NOT: _0 = const true; let y = **x; unsafe { unknown() }; **x == y diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff index a68ff13f26a6..269af438e37e 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-abort.diff @@ -24,14 +24,12 @@ bb1: { StorageLive(_4); -- _7 = copy (*_1); -- _4 = copy (*_7); -+ _7 = copy _6; -+ _4 = copy _2; + _7 = copy (*_1); + _4 = copy (*_7); StorageLive(_5); _5 = copy _2; - _0 = Eq(move _4, move _5); -+ _0 = const true; ++ _0 = Eq(move _4, copy _2); StorageDead(_5); StorageDead(_4); - StorageDead(_2); diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff index fe64d8f97d20..9ce17342a445 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff @@ -24,14 +24,12 @@ bb1: { StorageLive(_4); -- _7 = copy (*_1); -- _4 = copy (*_7); -+ _7 = copy _6; -+ _4 = copy _2; + _7 = copy (*_1); + _4 = copy (*_7); StorageLive(_5); _5 = copy _2; - _0 = Eq(move _4, move _5); -+ _0 = const true; ++ _0 = Eq(move _4, copy _2); StorageDead(_5); StorageDead(_4); - StorageDead(_2); diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-abort.mir index 13f2eb9874b4..23b1c3f3f43a 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-abort.mir @@ -6,6 +6,8 @@ fn src(_1: &&u8) -> bool { let mut _2: &u8; let _3: u8; let _4: (); + let mut _5: &u8; + let mut _6: u8; scope 1 { debug y => _3; } @@ -17,7 +19,11 @@ fn src(_1: &&u8) -> bool { } bb1: { - _0 = const true; + StorageLive(_6); + _5 = copy (*_1); + _6 = copy (*_5); + _0 = Eq(move _6, copy _3); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir index 7fab6e5511fd..4c01e9464bf4 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir @@ -6,6 +6,8 @@ fn src(_1: &&u8) -> bool { let mut _2: &u8; let _3: u8; let _4: (); + let mut _5: &u8; + let mut _6: u8; scope 1 { debug y => _3; } @@ -17,7 +19,11 @@ fn src(_1: &&u8) -> bool { } bb1: { - _0 = const true; + StorageLive(_6); + _5 = copy (*_1); + _6 = copy (*_5); + _0 = Eq(move _6, copy _3); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index 2cab88182962..afac0d23115e 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -3,101 +3,107 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2: &&(usize, usize, usize, usize)) -> bool { let mut _0: bool; let mut _3: &(usize, usize, usize, usize); - let mut _6: bool; + let mut _4: &(usize, usize, usize, usize); + let mut _5: &(usize, usize, usize, usize); + let mut _6: &(usize, usize, usize, usize); let mut _9: bool; - let mut _10: bool; - let _13: &usize; - let _14: &usize; - let _15: &usize; + let mut _12: bool; + let mut _13: bool; let _16: &usize; - let mut _17: &&usize; - let mut _18: &&usize; - let mut _19: &&usize; + let _17: &usize; + let _18: &usize; + let _19: &usize; let mut _20: &&usize; let mut _21: &&usize; let mut _22: &&usize; let mut _23: &&usize; let mut _24: &&usize; + let mut _25: &&usize; + let mut _26: &&usize; + let mut _27: &&usize; scope 1 { - debug a => _13; - debug b => _14; - debug c => _15; - debug d => _16; + debug a => _16; + debug b => _17; + debug c => _18; + debug d => _19; scope 2 (inlined std::cmp::impls::::le) { - debug self => _17; - debug other => _18; + debug self => _20; + debug other => _21; scope 3 (inlined std::cmp::impls::::le) { - debug self => _13; - debug other => _15; - let mut _4: usize; - let mut _5: usize; - } - } - scope 4 (inlined std::cmp::impls::::le) { - debug self => _19; - debug other => _20; - scope 5 (inlined std::cmp::impls::::le) { debug self => _16; - debug other => _14; + debug other => _18; let mut _7: usize; let mut _8: usize; } } + scope 4 (inlined std::cmp::impls::::le) { + debug self => _22; + debug other => _23; + scope 5 (inlined std::cmp::impls::::le) { + debug self => _19; + debug other => _17; + let mut _10: usize; + let mut _11: usize; + } + } scope 6 (inlined std::cmp::impls::::le) { - debug self => _21; - debug other => _22; + debug self => _24; + debug other => _25; scope 7 (inlined std::cmp::impls::::le) { - debug self => _15; - debug other => _13; + debug self => _18; + debug other => _16; } } scope 8 (inlined std::cmp::impls::::le) { - debug self => _23; - debug other => _24; + debug self => _26; + debug other => _27; scope 9 (inlined std::cmp::impls::::le) { - debug self => _14; - debug other => _16; - let mut _11: usize; - let mut _12: usize; + debug self => _17; + debug other => _19; + let mut _14: usize; + let mut _15: usize; } } } bb0: { _3 = copy (*_2); - // DBG: _13 = &((*_3).0: usize); - // DBG: _14 = &((*_3).1: usize); - // DBG: _15 = &((*_3).2: usize); - // DBG: _16 = &((*_3).3: usize); - StorageLive(_6); - // DBG: _17 = &_13; - // DBG: _18 = &?; - _4 = copy ((*_3).0: usize); - _5 = copy ((*_3).2: usize); - _6 = Le(copy _4, copy _5); - switchInt(move _6) -> [0: bb2, otherwise: bb1]; + // DBG: _16 = &((*_3).0: usize); + _4 = copy (*_2); + // DBG: _17 = &((*_4).1: usize); + _5 = copy (*_2); + // DBG: _18 = &((*_5).2: usize); + _6 = copy (*_2); + // DBG: _19 = &((*_6).3: usize); + StorageLive(_9); + // DBG: _20 = &_16; + // DBG: _21 = &?; + _7 = copy ((*_3).0: usize); + _8 = copy ((*_5).2: usize); + _9 = Le(copy _7, copy _8); + switchInt(move _9) -> [0: bb2, otherwise: bb1]; } bb1: { - StorageLive(_9); - // DBG: _19 = &_16; - // DBG: _20 = &?; - StorageLive(_7); - _7 = copy ((*_3).3: usize); - StorageLive(_8); - _8 = copy ((*_3).1: usize); - _9 = Le(move _7, move _8); - StorageDead(_8); - StorageDead(_7); - switchInt(move _9) -> [0: bb2, otherwise: bb6]; + StorageLive(_12); + // DBG: _22 = &_19; + // DBG: _23 = &?; + StorageLive(_10); + _10 = copy ((*_6).3: usize); + StorageLive(_11); + _11 = copy ((*_4).1: usize); + _12 = Le(move _10, move _11); + StorageDead(_11); + StorageDead(_10); + switchInt(move _12) -> [0: bb2, otherwise: bb6]; } bb2: { - StorageLive(_10); - // DBG: _21 = &_15; - // DBG: _22 = &?; - _10 = Le(copy _5, copy _4); - switchInt(move _10) -> [0: bb3, otherwise: bb4]; + StorageLive(_13); + // DBG: _24 = &_18; + // DBG: _25 = &?; + _13 = Le(copy _8, copy _7); + switchInt(move _13) -> [0: bb3, otherwise: bb4]; } bb3: { @@ -106,20 +112,20 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 } bb4: { - // DBG: _23 = &_14; - // DBG: _24 = &?; - StorageLive(_11); - _11 = copy ((*_3).1: usize); - StorageLive(_12); - _12 = copy ((*_3).3: usize); - _0 = Le(move _11, move _12); - StorageDead(_12); - StorageDead(_11); + // DBG: _26 = &_17; + // DBG: _27 = &?; + StorageLive(_14); + _14 = copy ((*_4).1: usize); + StorageLive(_15); + _15 = copy ((*_6).3: usize); + _0 = Le(move _14, move _15); + StorageDead(_15); + StorageDead(_14); goto -> bb5; } bb5: { - StorageDead(_10); + StorageDead(_13); goto -> bb7; } @@ -129,8 +135,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 } bb7: { + StorageDead(_12); StorageDead(_9); - StorageDead(_6); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir index bc7a31d52199..f93f7264dec2 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir @@ -4,40 +4,46 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, let mut _0: bool; let mut _3: &(usize, usize, usize, usize); let _4: usize; - let _5: usize; + let mut _5: &(usize, usize, usize, usize); let _6: usize; - let _7: usize; - let mut _8: bool; - let mut _9: bool; - let mut _10: bool; + let mut _7: &(usize, usize, usize, usize); + let _8: usize; + let mut _9: &(usize, usize, usize, usize); + let _10: usize; + let mut _11: bool; + let mut _12: bool; + let mut _13: bool; scope 1 { debug a => _4; - debug b => _5; - debug c => _6; - debug d => _7; + debug b => _6; + debug c => _8; + debug d => _10; } bb0: { _3 = copy (*_2); _4 = copy ((*_3).0: usize); - _5 = copy ((*_3).1: usize); - _6 = copy ((*_3).2: usize); - _7 = copy ((*_3).3: usize); - StorageLive(_8); - _8 = Le(copy _4, copy _6); - switchInt(move _8) -> [0: bb2, otherwise: bb1]; + _5 = copy (*_2); + _6 = copy ((*_5).1: usize); + _7 = copy (*_2); + _8 = copy ((*_7).2: usize); + _9 = copy (*_2); + _10 = copy ((*_9).3: usize); + StorageLive(_11); + _11 = Le(copy _4, copy _8); + switchInt(move _11) -> [0: bb2, otherwise: bb1]; } bb1: { - StorageLive(_9); - _9 = Le(copy _7, copy _5); - switchInt(move _9) -> [0: bb2, otherwise: bb6]; + StorageLive(_12); + _12 = Le(copy _10, copy _6); + switchInt(move _12) -> [0: bb2, otherwise: bb6]; } bb2: { - StorageLive(_10); - _10 = Le(copy _6, copy _4); - switchInt(move _10) -> [0: bb3, otherwise: bb4]; + StorageLive(_13); + _13 = Le(copy _8, copy _4); + switchInt(move _13) -> [0: bb3, otherwise: bb4]; } bb3: { @@ -46,12 +52,12 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, } bb4: { - _0 = Le(copy _5, copy _7); + _0 = Le(copy _6, copy _10); goto -> bb5; } bb5: { - StorageDead(_10); + StorageDead(_13); goto -> bb7; } @@ -61,8 +67,8 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, } bb7: { - StorageDead(_9); - StorageDead(_8); + StorageDead(_12); + StorageDead(_11); return; } } From 212c8c3811ad37c5554f69790a1d468affc7b6c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelo=20Dom=C3=ADnguez?= Date: Mon, 2 Feb 2026 23:58:36 +0100 Subject: [PATCH 524/978] Remove dummy loads --- .../src/builder/gpu_offload.rs | 26 +++++-------------- tests/codegen-llvm/gpu_offload/gpu_host.rs | 4 +-- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs index 402861eda870..16ab18a568e8 100644 --- a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs +++ b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs @@ -347,7 +347,6 @@ pub(crate) struct OffloadKernelGlobals<'ll> { pub offload_sizes: &'ll llvm::Value, pub memtransfer_types: &'ll llvm::Value, pub region_id: &'ll llvm::Value, - pub offload_entry: &'ll llvm::Value, } fn gen_tgt_data_mappers<'ll>( @@ -468,8 +467,12 @@ pub(crate) fn gen_define_handling<'ll>( let c_section_name = CString::new("llvm_offload_entries").unwrap(); llvm::set_section(offload_entry, &c_section_name); - let result = - OffloadKernelGlobals { offload_sizes, memtransfer_types, region_id, offload_entry }; + cx.add_compiler_used_global(offload_entry); + + let result = OffloadKernelGlobals { offload_sizes, memtransfer_types, region_id }; + + // FIXME(Sa4dUs): use this global for constant offload sizes + cx.add_compiler_used_global(result.offload_sizes); cx.offload_kernel_cache.borrow_mut().insert(symbol, result); @@ -532,8 +535,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( offload_dims: &OffloadKernelDims<'ll>, ) { let cx = builder.cx; - let OffloadKernelGlobals { offload_sizes, offload_entry, memtransfer_types, region_id } = - offload_data; + let OffloadKernelGlobals { memtransfer_types, region_id, .. } = offload_data; let OffloadKernelDims { num_workgroups, threads_per_block, workgroup_dims, thread_dims } = offload_dims; @@ -548,20 +550,6 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( let num_args = types.len() as u64; let bb = builder.llbb(); - // FIXME(Sa4dUs): dummy loads are a temp workaround, we should find a proper way to prevent these - // variables from being optimized away - for val in [offload_sizes, offload_entry] { - unsafe { - let dummy = llvm::LLVMBuildLoad2( - &builder.llbuilder, - llvm::LLVMTypeOf(val), - val, - b"dummy\0".as_ptr() as *const _, - ); - llvm::LLVMSetVolatile(dummy, llvm::TRUE); - } - } - // Step 0) unsafe { llvm::LLVMRustPositionBuilderPastAllocas(&builder.llbuilder, builder.llfn()); diff --git a/tests/codegen-llvm/gpu_offload/gpu_host.rs b/tests/codegen-llvm/gpu_offload/gpu_host.rs index d0bc34ec66b2..e12d7c792ae7 100644 --- a/tests/codegen-llvm/gpu_offload/gpu_host.rs +++ b/tests/codegen-llvm/gpu_offload/gpu_host.rs @@ -55,9 +55,7 @@ pub fn _kernel_1(x: &mut [f32; 256]) { // CHECK-NEXT: %.offload_ptrs = alloca [1 x ptr], align 8 // CHECK-NEXT: %.offload_sizes = alloca [1 x i64], align 8 // CHECK-NEXT: %kernel_args = alloca %struct.__tgt_kernel_arguments, align 8 -// CHECK: %dummy = load volatile ptr, ptr @.offload_sizes.[[K]], align 8 -// CHECK-NEXT: %dummy1 = load volatile ptr, ptr @.offloading.entry.[[K]], align 8 -// CHECK-NEXT: call void @__tgt_init_all_rtls() +// CHECK: call void @__tgt_init_all_rtls() // CHECK-NEXT: store ptr %x, ptr %.offload_baseptrs, align 8 // CHECK-NEXT: store ptr %x, ptr %.offload_ptrs, align 8 // CHECK-NEXT: store i64 1024, ptr %.offload_sizes, align 8 From 9dab26a9ab2b31088eebabd167ae27c43938c7b7 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 4 Feb 2026 16:16:16 +0100 Subject: [PATCH 525/978] Convert to inline diagnostics in `rustc_expand` --- Cargo.lock | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_expand/Cargo.toml | 1 - compiler/rustc_expand/messages.ftl | 207 -------------- compiler/rustc_expand/src/config.rs | 7 +- compiler/rustc_expand/src/errors.rs | 267 +++++++++++-------- compiler/rustc_expand/src/expand.rs | 5 +- compiler/rustc_expand/src/lib.rs | 2 - compiler/rustc_expand/src/mbe/diagnostics.rs | 8 +- 9 files changed, 171 insertions(+), 328 deletions(-) delete mode 100644 compiler/rustc_expand/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 1631d5362612..171080f65797 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3879,7 +3879,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_hir", "rustc_lexer", "rustc_lint_defs", diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 3059a4fefc61..744fa69025aa 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -121,7 +121,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_codegen_ssa::DEFAULT_LOCALE_RESOURCE, rustc_const_eval::DEFAULT_LOCALE_RESOURCE, rustc_errors::DEFAULT_LOCALE_RESOURCE, - rustc_expand::DEFAULT_LOCALE_RESOURCE, rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE, rustc_hir_typeck::DEFAULT_LOCALE_RESOURCE, rustc_lint::DEFAULT_LOCALE_RESOURCE, diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml index a18506c42afc..12b0c384a8ae 100644 --- a/compiler/rustc_expand/Cargo.toml +++ b/compiler/rustc_expand/Cargo.toml @@ -16,7 +16,6 @@ rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_lexer = { path = "../rustc_lexer" } rustc_lint_defs = { path = "../rustc_lint_defs" } diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl deleted file mode 100644 index 851d78e0b105..000000000000 --- a/compiler/rustc_expand/messages.ftl +++ /dev/null @@ -1,207 +0,0 @@ -expand_attributes_on_expressions_experimental = - attributes on expressions are experimental - .help_outer_doc = `///` is used for outer documentation comments; for a plain comment, use `//` - .help_inner_doc = `//!` is used for inner documentation comments; for a plain comment, use `//` by removing the `!` or inserting a space in between them: `// !` - -expand_cfg_attr_no_attributes = `#[cfg_attr]` does not expand to any attributes - -expand_count_repetition_misplaced = - `count` can not be placed inside the innermost repetition - -expand_crate_name_in_cfg_attr = - `crate_name` within an `#![cfg_attr]` attribute is forbidden - -expand_crate_type_in_cfg_attr = - `crate_type` within an `#![cfg_attr]` attribute is forbidden - -expand_custom_attribute_panicked = - custom attribute panicked - .help = message: {$message} - -expand_duplicate_matcher_binding = duplicate matcher binding - .label = duplicate binding - .label2 = previous binding - -expand_empty_delegation_mac = - empty {$kind} delegation is not supported - -expand_expected_paren_or_brace = - expected `(` or `{"{"}`, found `{$token}` - -expand_explain_doc_comment_inner = - inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match - -expand_explain_doc_comment_outer = - outer doc comments expand to `#[doc = "..."]`, which is what this macro attempted to match - -expand_expr_repeat_no_syntax_vars = - attempted to repeat an expression containing no syntax variables matched as repeating at this depth - -expand_feature_not_allowed = - the feature `{$name}` is not in the list of allowed features - -expand_feature_removed = - feature has been removed - .label = feature has been removed - .note = removed in {$removed_rustc_version}{$pull_note} - .reason = {$reason} - -expand_file_modules_in_proc_macro_input_are_unstable = - file modules in proc macro input are unstable - -expand_glob_delegation_outside_impls = - glob delegation is only supported in impls - -expand_glob_delegation_traitless_qpath = - qualified path without a trait in glob delegation - -expand_incomplete_parse = - macro expansion ignores {$descr} and any tokens following - .label = caused by the macro expansion here - .note = the usage of `{$macro_path}!` is likely invalid in {$kind_name} context - .suggestion_add_semi = you might be missing a semicolon here - -expand_invalid_cfg_expected_syntax = expected syntax is - -expand_invalid_cfg_multiple_predicates = multiple `cfg` predicates are specified -expand_invalid_cfg_no_parens = `cfg` is not followed by parentheses -expand_invalid_cfg_no_predicate = `cfg` predicate is not specified -expand_invalid_cfg_predicate_literal = `cfg` predicate key cannot be a literal - -expand_invalid_fragment_specifier = - invalid fragment specifier `{$fragment}` - .help = {$help} - -expand_macro_args_bad_delim = `{$rule_kw}` rule argument matchers require parentheses -expand_macro_args_bad_delim_sugg = the delimiters should be `(` and `)` - -expand_macro_body_stability = - macros cannot have body stability attributes - .label = invalid body stability attribute - .label2 = body stability attribute affects this macro - -expand_macro_call_unused_doc_comment = unused doc comment - .label = rustdoc does not generate documentation for macro invocations - .help = to document an item produced by a macro, the macro must produce the documentation as part of its expansion - -expand_macro_const_stability = - macros cannot have const stability attributes - .label = invalid const stability attribute - .label2 = const stability attribute affects this macro - -expand_macro_expands_to_match_arm = macros cannot expand to match arms - -expand_malformed_feature_attribute = - malformed `feature` attribute input - .expected = expected just one word - -expand_meta_var_dif_seq_matchers = {$msg} - -expand_metavar_still_repeating = variable `{$ident}` is still repeating at this depth - .label = expected repetition - -expand_metavariable_wrong_operator = meta-variable repeats with different Kleene operator - .binder_label = expected repetition - .occurrence_label = conflicting repetition - -expand_missing_fragment_specifier = missing fragment specifier - .note = fragment specifiers must be provided - .suggestion_add_fragspec = try adding a specifier here - .valid = {$valid} - -expand_module_circular = - circular modules: {$modules} - -expand_module_file_not_found = - file not found for module `{$name}` - .help = to create the module `{$name}`, create file "{$default_path}" or "{$secondary_path}" - .note = if there is a `mod {$name}` elsewhere in the crate already, import it with `use crate::...` instead - -expand_module_in_block = - cannot declare a file module inside a block unless it has a path attribute - .help = maybe `use` the module `{$name}` instead of redeclaring it - .note = file modules are usually placed outside of blocks, at the top level of the file - -expand_module_multiple_candidates = - file for module `{$name}` found at both "{$default_path}" and "{$secondary_path}" - .help = delete or rename one of them to remove the ambiguity - -expand_must_repeat_once = - this must repeat at least once - -expand_mve_extra_tokens = - unexpected trailing tokens - .label = for this metavariable expression - .range = the `{$name}` metavariable expression takes between {$min_or_exact_args} and {$max_args} arguments - .exact = the `{$name}` metavariable expression takes {$min_or_exact_args -> - [zero] no arguments - [one] a single argument - *[other] {$min_or_exact_args} arguments - } - .suggestion = try removing {$extra_count -> - [one] this token - *[other] these tokens - } - -expand_mve_missing_paren = - expected `(` - .label = for this this metavariable expression - .unexpected = unexpected token - .note = metavariable expressions use function-like parentheses syntax - .suggestion = try adding parentheses - -expand_mve_unrecognized_expr = - unrecognized metavariable expression - .label = not a valid metavariable expression - .note = valid metavariable expressions are {$valid_expr_list} - -expand_mve_unrecognized_var = - variable `{$key}` is not recognized in meta-variable expression - -expand_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro - .suggestion = use pat_param to preserve semantics - -expand_proc_macro_back_compat = using an old version of `{$crate_name}` - .note = older versions of the `{$crate_name}` crate no longer compile; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives - -expand_proc_macro_derive_panicked = - proc-macro derive panicked - .help = message: {$message} - -expand_proc_macro_derive_tokens = - proc-macro derive produced unparsable tokens - -expand_proc_macro_panicked = - proc macro panicked - .help = message: {$message} - -expand_recursion_limit_reached = - recursion limit reached while expanding `{$descr}` - .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`) - -expand_remove_expr_not_supported = - removing an expression is not supported in this position - -expand_remove_node_not_supported = - removing {$descr} is not supported in this position - -expand_resolve_relative_path = - cannot resolve relative path in non-file source `{$path}` - -expand_trace_macro = trace_macro - -expand_trailing_semi_macro = trailing semicolon in macro used in expression position - .note1 = macro invocations at the end of a block are treated as expressions - .note2 = to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}` - -expand_unknown_macro_variable = unknown macro variable `{$name}` - -expand_unsupported_key_value = - key-value macro attributes are not supported - -expand_unused_builtin_attribute = unused attribute `{$attr_name}` - .note = the built-in attribute `{$attr_name}` will be ignored, since it's applied to the macro invocation `{$macro_name}` - .suggestion = remove the attribute - -expand_wrong_fragment_kind = - non-{$kind} macro in {$kind} position: {$name} diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 1e1f98aef1b1..c9d0319a97c5 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -15,6 +15,7 @@ use rustc_attr_parsing::{ AttributeParser, CFG_TEMPLATE, EvalConfigResult, ShouldEmit, eval_config_entry, parse_cfg, }; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; +use rustc_errors::inline_fluent; use rustc_feature::{ ACCEPTED_LANG_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, REMOVED_LANG_FEATURES, UNSTABLE_LANG_FEATURES, @@ -432,14 +433,14 @@ impl<'a> StripUnconfigured<'a> { &self.sess, sym::stmt_expr_attributes, attr.span, - crate::fluent_generated::expand_attributes_on_expressions_experimental, + inline_fluent!("attributes on expressions are experimental"), ); if attr.is_doc_comment() { err.help(if attr.style == AttrStyle::Outer { - crate::fluent_generated::expand_help_outer_doc + inline_fluent!("`///` is used for outer documentation comments; for a plain comment, use `//`") } else { - crate::fluent_generated::expand_help_inner_doc + inline_fluent!("`//!` is used for inner documentation comments; for a plain comment, use `//` by removing the `!` or inserting a space in between them: `// !`") }); } diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 9f9764e060d1..e64bfc136d16 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -7,32 +7,34 @@ use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol}; #[derive(LintDiagnostic)] -#[diag(expand_cfg_attr_no_attributes)] +#[diag("`#[cfg_attr]` does not expand to any attributes")] pub(crate) struct CfgAttrNoAttributes; #[derive(Diagnostic)] -#[diag(expand_expr_repeat_no_syntax_vars)] +#[diag( + "attempted to repeat an expression containing no syntax variables matched as repeating at this depth" +)] pub(crate) struct NoSyntaxVarsExprRepeat { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_must_repeat_once)] +#[diag("this must repeat at least once")] pub(crate) struct MustRepeatOnce { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_count_repetition_misplaced)] +#[diag("`count` can not be placed inside the innermost repetition")] pub(crate) struct CountRepetitionMisplaced { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_metavar_still_repeating)] +#[diag("variable `{$ident}` is still repeating at this depth")] pub(crate) struct MacroVarStillRepeating { #[primary_span] pub span: Span, @@ -40,24 +42,24 @@ pub(crate) struct MacroVarStillRepeating { } #[derive(LintDiagnostic)] -#[diag(expand_metavar_still_repeating)] +#[diag("variable `{$ident}` is still repeating at this depth")] pub(crate) struct MetaVarStillRepeatingLint { - #[label] + #[label("expected repetition")] pub label: Span, pub ident: MacroRulesNormalizedIdent, } #[derive(LintDiagnostic)] -#[diag(expand_metavariable_wrong_operator)] +#[diag("meta-variable repeats with different Kleene operator")] pub(crate) struct MetaVariableWrongOperator { - #[label(expand_binder_label)] + #[label("expected repetition")] pub binder: Span, - #[label(expand_occurrence_label)] + #[label("conflicting repetition")] pub occurrence: Span, } #[derive(Diagnostic)] -#[diag(expand_meta_var_dif_seq_matchers)] +#[diag("{$msg}")] pub(crate) struct MetaVarsDifSeqMatchers { #[primary_span] pub span: Span, @@ -65,13 +67,13 @@ pub(crate) struct MetaVarsDifSeqMatchers { } #[derive(LintDiagnostic)] -#[diag(expand_unknown_macro_variable)] +#[diag("unknown macro variable `{$name}`")] pub(crate) struct UnknownMacroVariable { pub name: MacroRulesNormalizedIdent, } #[derive(Diagnostic)] -#[diag(expand_resolve_relative_path)] +#[diag("cannot resolve relative path in non-file source `{$path}`")] pub(crate) struct ResolveRelativePath { #[primary_span] pub span: Span, @@ -79,31 +81,31 @@ pub(crate) struct ResolveRelativePath { } #[derive(Diagnostic)] -#[diag(expand_macro_const_stability)] +#[diag("macros cannot have const stability attributes")] pub(crate) struct MacroConstStability { #[primary_span] - #[label] + #[label("invalid const stability attribute")] pub span: Span, - #[label(expand_label2)] + #[label("const stability attribute affects this macro")] pub head_span: Span, } #[derive(Diagnostic)] -#[diag(expand_macro_body_stability)] +#[diag("macros cannot have body stability attributes")] pub(crate) struct MacroBodyStability { #[primary_span] - #[label] + #[label("invalid body stability attribute")] pub span: Span, - #[label(expand_label2)] + #[label("body stability attribute affects this macro")] pub head_span: Span, } #[derive(Diagnostic)] -#[diag(expand_feature_removed, code = E0557)] -#[note] +#[diag("feature has been removed", code = E0557)] +#[note("removed in {$removed_rustc_version}{$pull_note}")] pub(crate) struct FeatureRemoved<'a> { #[primary_span] - #[label] + #[label("feature has been removed")] pub span: Span, #[subdiagnostic] pub reason: Option>, @@ -112,13 +114,13 @@ pub(crate) struct FeatureRemoved<'a> { } #[derive(Subdiagnostic)] -#[note(expand_reason)] +#[note("{$reason}")] pub(crate) struct FeatureRemovedReason<'a> { pub reason: &'a str, } #[derive(Diagnostic)] -#[diag(expand_feature_not_allowed, code = E0725)] +#[diag("the feature `{$name}` is not in the list of allowed features", code = E0725)] pub(crate) struct FeatureNotAllowed { #[primary_span] pub span: Span, @@ -126,8 +128,10 @@ pub(crate) struct FeatureNotAllowed { } #[derive(Diagnostic)] -#[diag(expand_recursion_limit_reached)] -#[help] +#[diag("recursion limit reached while expanding `{$descr}`")] +#[help( + "consider increasing the recursion limit by adding a `#![recursion_limit = \"{$suggested_limit}\"]` attribute to your crate (`{$crate_name}`)" +)] pub(crate) struct RecursionLimitReached { #[primary_span] pub span: Span, @@ -137,7 +141,7 @@ pub(crate) struct RecursionLimitReached { } #[derive(Diagnostic)] -#[diag(expand_malformed_feature_attribute, code = E0556)] +#[diag("malformed `feature` attribute input", code = E0556)] pub(crate) struct MalformedFeatureAttribute { #[primary_span] pub span: Span, @@ -147,12 +151,16 @@ pub(crate) struct MalformedFeatureAttribute { #[derive(Subdiagnostic)] pub(crate) enum MalformedFeatureAttributeHelp { - #[label(expand_expected)] + #[label("expected just one word")] Label { #[primary_span] span: Span, }, - #[suggestion(expand_expected, code = "{suggestion}", applicability = "maybe-incorrect")] + #[suggestion( + "expected just one word", + code = "{suggestion}", + applicability = "maybe-incorrect" + )] Suggestion { #[primary_span] span: Span, @@ -161,7 +169,7 @@ pub(crate) enum MalformedFeatureAttributeHelp { } #[derive(Diagnostic)] -#[diag(expand_remove_expr_not_supported)] +#[diag("removing an expression is not supported in this position")] pub(crate) struct RemoveExprNotSupported { #[primary_span] pub span: Span, @@ -169,32 +177,32 @@ pub(crate) struct RemoveExprNotSupported { #[derive(Diagnostic)] pub(crate) enum InvalidCfg { - #[diag(expand_invalid_cfg_no_parens)] + #[diag("`cfg` is not followed by parentheses")] NotFollowedByParens { #[primary_span] #[suggestion( - expand_invalid_cfg_expected_syntax, + "expected syntax is", code = "cfg(/* predicate */)", applicability = "has-placeholders" )] span: Span, }, - #[diag(expand_invalid_cfg_no_predicate)] + #[diag("`cfg` predicate is not specified")] NoPredicate { #[primary_span] #[suggestion( - expand_invalid_cfg_expected_syntax, + "expected syntax is", code = "cfg(/* predicate */)", applicability = "has-placeholders" )] span: Span, }, - #[diag(expand_invalid_cfg_multiple_predicates)] + #[diag("multiple `cfg` predicates are specified")] MultiplePredicates { #[primary_span] span: Span, }, - #[diag(expand_invalid_cfg_predicate_literal)] + #[diag("`cfg` predicate key cannot be a literal")] PredicateLiteral { #[primary_span] span: Span, @@ -202,7 +210,7 @@ pub(crate) enum InvalidCfg { } #[derive(Diagnostic)] -#[diag(expand_wrong_fragment_kind)] +#[diag("non-{$kind} macro in {$kind} position: {$name}")] pub(crate) struct WrongFragmentKind<'a> { #[primary_span] pub span: Span, @@ -211,28 +219,28 @@ pub(crate) struct WrongFragmentKind<'a> { } #[derive(Diagnostic)] -#[diag(expand_unsupported_key_value)] +#[diag("key-value macro attributes are not supported")] pub(crate) struct UnsupportedKeyValue { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_incomplete_parse)] -#[note] +#[diag("macro expansion ignores {$descr} and any tokens following")] +#[note("the usage of `{$macro_path}!` is likely invalid in {$kind_name} context")] pub(crate) struct IncompleteParse<'a> { #[primary_span] pub span: Span, pub descr: String, - #[label] + #[label("caused by the macro expansion here")] pub label_span: Span, pub macro_path: &'a ast::Path, pub kind_name: &'a str, - #[note(expand_macro_expands_to_match_arm)] + #[note("macros cannot expand to match arms")] pub expands_to_match_arm: bool, #[suggestion( - expand_suggestion_add_semi, + "you might be missing a semicolon here", style = "verbose", code = ";", applicability = "maybe-incorrect" @@ -241,7 +249,7 @@ pub(crate) struct IncompleteParse<'a> { } #[derive(Diagnostic)] -#[diag(expand_remove_node_not_supported)] +#[diag("removing {$descr} is not supported in this position")] pub(crate) struct RemoveNodeNotSupported { #[primary_span] pub span: Span, @@ -249,7 +257,7 @@ pub(crate) struct RemoveNodeNotSupported { } #[derive(Diagnostic)] -#[diag(expand_module_circular)] +#[diag("circular modules: {$modules}")] pub(crate) struct ModuleCircular { #[primary_span] pub span: Span, @@ -257,8 +265,8 @@ pub(crate) struct ModuleCircular { } #[derive(Diagnostic)] -#[diag(expand_module_in_block)] -#[note] +#[diag("cannot declare a file module inside a block unless it has a path attribute")] +#[note("file modules are usually placed outside of blocks, at the top level of the file")] pub(crate) struct ModuleInBlock { #[primary_span] pub span: Span, @@ -267,7 +275,7 @@ pub(crate) struct ModuleInBlock { } #[derive(Subdiagnostic)] -#[help(expand_help)] +#[help("maybe `use` the module `{$name}` instead of redeclaring it")] pub(crate) struct ModuleInBlockName { #[primary_span] pub span: Span, @@ -275,9 +283,11 @@ pub(crate) struct ModuleInBlockName { } #[derive(Diagnostic)] -#[diag(expand_module_file_not_found, code = E0583)] -#[help] -#[note] +#[diag("file not found for module `{$name}`", code = E0583)] +#[help("to create the module `{$name}`, create file \"{$default_path}\" or \"{$secondary_path}\"")] +#[note( + "if there is a `mod {$name}` elsewhere in the crate already, import it with `use crate::...` instead" +)] pub(crate) struct ModuleFileNotFound { #[primary_span] pub span: Span, @@ -287,8 +297,8 @@ pub(crate) struct ModuleFileNotFound { } #[derive(Diagnostic)] -#[diag(expand_module_multiple_candidates, code = E0761)] -#[help] +#[diag("file for module `{$name}` found at both \"{$default_path}\" and \"{$secondary_path}\"", code = E0761)] +#[help("delete or rename one of them to remove the ambiguity")] pub(crate) struct ModuleMultipleCandidates { #[primary_span] pub span: Span, @@ -298,14 +308,14 @@ pub(crate) struct ModuleMultipleCandidates { } #[derive(Diagnostic)] -#[diag(expand_trace_macro)] +#[diag("trace_macro")] pub(crate) struct TraceMacro { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_proc_macro_panicked)] +#[diag("proc macro panicked")] pub(crate) struct ProcMacroPanicked { #[primary_span] pub span: Span, @@ -314,13 +324,13 @@ pub(crate) struct ProcMacroPanicked { } #[derive(Subdiagnostic)] -#[help(expand_help)] +#[help("message: {$message}")] pub(crate) struct ProcMacroPanickedHelp { pub message: String, } #[derive(Diagnostic)] -#[diag(expand_proc_macro_derive_panicked)] +#[diag("proc-macro derive panicked")] pub(crate) struct ProcMacroDerivePanicked { #[primary_span] pub span: Span, @@ -329,13 +339,13 @@ pub(crate) struct ProcMacroDerivePanicked { } #[derive(Subdiagnostic)] -#[help(expand_help)] +#[help("message: {$message}")] pub(crate) struct ProcMacroDerivePanickedHelp { pub message: String, } #[derive(Diagnostic)] -#[diag(expand_custom_attribute_panicked)] +#[diag("custom attribute panicked")] pub(crate) struct CustomAttributePanicked { #[primary_span] pub span: Span, @@ -344,46 +354,46 @@ pub(crate) struct CustomAttributePanicked { } #[derive(Subdiagnostic)] -#[help(expand_help)] +#[help("message: {$message}")] pub(crate) struct CustomAttributePanickedHelp { pub message: String, } #[derive(Diagnostic)] -#[diag(expand_proc_macro_derive_tokens)] +#[diag("proc-macro derive produced unparsable tokens")] pub(crate) struct ProcMacroDeriveTokens { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_duplicate_matcher_binding)] +#[diag("duplicate matcher binding")] pub(crate) struct DuplicateMatcherBinding { #[primary_span] - #[label] + #[label("duplicate binding")] pub span: Span, - #[label(expand_label2)] + #[label("previous binding")] pub prev: Span, } #[derive(LintDiagnostic)] -#[diag(expand_duplicate_matcher_binding)] +#[diag("duplicate matcher binding")] pub(crate) struct DuplicateMatcherBindingLint { - #[label] + #[label("duplicate binding")] pub span: Span, - #[label(expand_label2)] + #[label("previous binding")] pub prev: Span, } #[derive(Diagnostic)] -#[diag(expand_missing_fragment_specifier)] -#[note] -#[help(expand_valid)] +#[diag("missing fragment specifier")] +#[note("fragment specifiers must be provided")] +#[help("{$valid}")] pub(crate) struct MissingFragmentSpecifier { #[primary_span] pub span: Span, #[suggestion( - expand_suggestion_add_fragspec, + "try adding a specifier here", style = "verbose", code = ":spec", applicability = "maybe-incorrect" @@ -393,8 +403,8 @@ pub(crate) struct MissingFragmentSpecifier { } #[derive(Diagnostic)] -#[diag(expand_invalid_fragment_specifier)] -#[help] +#[diag("invalid fragment specifier `{$fragment}`")] +#[help("{$help}")] pub(crate) struct InvalidFragmentSpecifier { #[primary_span] pub span: Span, @@ -403,7 +413,7 @@ pub(crate) struct InvalidFragmentSpecifier { } #[derive(Diagnostic)] -#[diag(expand_expected_paren_or_brace)] +#[diag("expected `(` or `{\"{\"}`, found `{$token}`")] pub(crate) struct ExpectedParenOrBrace<'a> { #[primary_span] pub span: Span, @@ -411,7 +421,7 @@ pub(crate) struct ExpectedParenOrBrace<'a> { } #[derive(Diagnostic)] -#[diag(expand_empty_delegation_mac)] +#[diag("empty {$kind} delegation is not supported")] pub(crate) struct EmptyDelegationMac { #[primary_span] pub span: Span, @@ -419,28 +429,28 @@ pub(crate) struct EmptyDelegationMac { } #[derive(Diagnostic)] -#[diag(expand_glob_delegation_outside_impls)] +#[diag("glob delegation is only supported in impls")] pub(crate) struct GlobDelegationOutsideImpls { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_crate_name_in_cfg_attr)] +#[diag("`crate_name` within an `#![cfg_attr]` attribute is forbidden")] pub(crate) struct CrateNameInCfgAttr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_crate_type_in_cfg_attr)] +#[diag("`crate_type` within an `#![cfg_attr]` attribute is forbidden")] pub(crate) struct CrateTypeInCfgAttr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(expand_glob_delegation_traitless_qpath)] +#[diag("qualified path without a trait in glob delegation")] pub(crate) struct GlobDelegationTraitlessQpath { #[primary_span] pub span: Span, @@ -449,8 +459,10 @@ pub(crate) struct GlobDelegationTraitlessQpath { // This used to be the `proc_macro_back_compat` lint (#83125). It was later // turned into a hard error. #[derive(Diagnostic)] -#[diag(expand_proc_macro_back_compat)] -#[note] +#[diag("using an old version of `{$crate_name}`")] +#[note( + "older versions of the `{$crate_name}` crate no longer compile; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives" +)] pub(crate) struct ProcMacroBackCompat { pub crate_name: String, pub fixed_version: String, @@ -461,20 +473,35 @@ mod metavar_exprs { use super::*; #[derive(Diagnostic, Default)] - #[diag(expand_mve_extra_tokens)] + #[diag("unexpected trailing tokens")] pub(crate) struct MveExtraTokens { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion( + "try removing {$extra_count -> + [one] this token + *[other] these tokens + }", + code = "", + applicability = "machine-applicable" + )] pub span: Span, - #[label] + #[label("for this metavariable expression")] pub ident_span: Span, pub extra_count: usize, // The rest is only used for specific diagnostics and can be default if neither // `note` is `Some`. - #[note(expand_exact)] + #[note( + "the `{$name}` metavariable expression takes {$min_or_exact_args -> + [zero] no arguments + [one] a single argument + *[other] {$min_or_exact_args} arguments + }" + )] pub exact_args_note: Option<()>, - #[note(expand_range)] + #[note( + "the `{$name}` metavariable expression takes between {$min_or_exact_args} and {$max_args} arguments" + )] pub range_args_note: Option<()>, pub min_or_exact_args: usize, pub max_args: usize, @@ -482,30 +509,34 @@ mod metavar_exprs { } #[derive(Diagnostic)] - #[note] - #[diag(expand_mve_missing_paren)] + #[note("metavariable expressions use function-like parentheses syntax")] + #[diag("expected `(`")] pub(crate) struct MveMissingParen { #[primary_span] - #[label] + #[label("for this this metavariable expression")] pub ident_span: Span, - #[label(expand_unexpected)] + #[label("unexpected token")] pub unexpected_span: Option, - #[suggestion(code = "( /* ... */ )", applicability = "has-placeholders")] + #[suggestion( + "try adding parentheses", + code = "( /* ... */ )", + applicability = "has-placeholders" + )] pub insert_span: Option, } #[derive(Diagnostic)] - #[note] - #[diag(expand_mve_unrecognized_expr)] + #[note("valid metavariable expressions are {$valid_expr_list}")] + #[diag("unrecognized metavariable expression")] pub(crate) struct MveUnrecognizedExpr { #[primary_span] - #[label] + #[label("not a valid metavariable expression")] pub span: Span, pub valid_expr_list: &'static str, } #[derive(Diagnostic)] - #[diag(expand_mve_unrecognized_var)] + #[diag("variable `{$key}` is not recognized in meta-variable expression")] pub(crate) struct MveUnrecognizedVar { #[primary_span] pub span: Span, @@ -514,7 +545,7 @@ mod metavar_exprs { } #[derive(Diagnostic)] -#[diag(expand_macro_args_bad_delim)] +#[diag("`{$rule_kw}` rule argument matchers require parentheses")] pub(crate) struct MacroArgsBadDelim { #[primary_span] pub span: Span, @@ -524,7 +555,10 @@ pub(crate) struct MacroArgsBadDelim { } #[derive(Subdiagnostic)] -#[multipart_suggestion(expand_macro_args_bad_delim_sugg, applicability = "machine-applicable")] +#[multipart_suggestion( + "the delimiters should be `(` and `)`", + applicability = "machine-applicable" +)] pub(crate) struct MacroArgsBadDelimSugg { #[suggestion_part(code = "(")] pub open: Span, @@ -533,37 +567,54 @@ pub(crate) struct MacroArgsBadDelimSugg { } #[derive(LintDiagnostic)] -#[diag(expand_macro_call_unused_doc_comment)] -#[help] +#[diag("unused doc comment")] +#[help( + "to document an item produced by a macro, the macro must produce the documentation as part of its expansion" +)] pub(crate) struct MacroCallUnusedDocComment { - #[label] + #[label("rustdoc does not generate documentation for macro invocations")] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(expand_or_patterns_back_compat)] +#[diag( + "the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro" +)] pub(crate) struct OrPatternsBackCompat { - #[suggestion(code = "{suggestion}", applicability = "machine-applicable")] + #[suggestion( + "use pat_param to preserve semantics", + code = "{suggestion}", + applicability = "machine-applicable" + )] pub span: Span, pub suggestion: String, } #[derive(LintDiagnostic)] -#[diag(expand_trailing_semi_macro)] +#[diag("trailing semicolon in macro used in expression position")] pub(crate) struct TrailingMacro { - #[note(expand_note1)] - #[note(expand_note2)] + #[note("macro invocations at the end of a block are treated as expressions")] + #[note( + "to ignore the value produced by the macro, add a semicolon after the invocation of `{$name}`" + )] pub is_trailing: bool, pub name: Ident, } #[derive(LintDiagnostic)] -#[diag(expand_unused_builtin_attribute)] +#[diag("unused attribute `{$attr_name}`")] pub(crate) struct UnusedBuiltinAttribute { - #[note] + #[note( + "the built-in attribute `{$attr_name}` will be ignored, since it's applied to the macro invocation `{$macro_name}`" + )] pub invoc_span: Span, pub attr_name: Symbol, pub macro_name: String, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove the attribute", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub attr_span: Span, } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 449dc95ea372..da678ff70346 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -19,7 +19,7 @@ use rustc_attr_parsing::{ }; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::PResult; +use rustc_errors::{PResult, inline_fluent}; use rustc_feature::Features; use rustc_hir::Target; use rustc_hir::def::MacroKinds; @@ -42,7 +42,6 @@ use crate::errors::{ RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue, WrongFragmentKind, }; -use crate::fluent_generated; use crate::mbe::diagnostics::annotate_err_with_kind; use crate::module::{ DirOwnership, ParsedExternalMod, mod_dir_path, mod_file_path_from_attr, parse_external_mod, @@ -1052,7 +1051,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.sess, sym::proc_macro_hygiene, item.span, - fluent_generated::expand_file_modules_in_proc_macro_input_are_unstable, + inline_fluent!("file modules in proc macro input are unstable"), ) .emit(); } diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 89540a9a5c5b..96f17418b8d2 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -26,5 +26,3 @@ pub mod proc_macro; pub fn provide(providers: &mut rustc_middle::query::Providers) { providers.derive_macro_expansion = proc_macro::provide_derive_macro_expansion; } - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index f5edaf50edd5..df6903dc4937 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -302,12 +302,16 @@ pub(crate) fn annotate_err_with_kind(err: &mut Diag<'_>, kind: AstFragmentKind, #[derive(Subdiagnostic)] enum ExplainDocComment { - #[label(expand_explain_doc_comment_inner)] + #[label( + "inner doc comments expand to `#![doc = \"...\"]`, which is what this macro attempted to match" + )] Inner { #[primary_span] span: Span, }, - #[label(expand_explain_doc_comment_outer)] + #[label( + "outer doc comments expand to `#[doc = \"...\"]`, which is what this macro attempted to match" + )] Outer { #[primary_span] span: Span, From 8d09ba7ae54d4431d10eb09eae4153208fd3d3a7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 Feb 2026 14:37:15 +0100 Subject: [PATCH 526/978] Convert to inline diagnostics in `rustc_ast_lowering` --- Cargo.lock | 2 - compiler/rustc_ast_lowering/Cargo.toml | 1 - compiler/rustc_ast_lowering/messages.ftl | 191 ------------------ compiler/rustc_ast_lowering/src/asm.rs | 12 +- compiler/rustc_ast_lowering/src/errors.rs | 226 +++++++++++++--------- compiler/rustc_ast_lowering/src/expr.rs | 7 +- compiler/rustc_ast_lowering/src/lib.rs | 2 - compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - 9 files changed, 141 insertions(+), 302 deletions(-) delete mode 100644 compiler/rustc_ast_lowering/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 1631d5362612..e9cdc493451d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3490,7 +3490,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", @@ -3775,7 +3774,6 @@ dependencies = [ "libc", "rustc_abi", "rustc_ast", - "rustc_ast_lowering", "rustc_ast_passes", "rustc_ast_pretty", "rustc_borrowck", diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 6ac258155fe9..c00bac5d3c5a 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -15,7 +15,6 @@ rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl deleted file mode 100644 index 0cd5c4f303de..000000000000 --- a/compiler/rustc_ast_lowering/messages.ftl +++ /dev/null @@ -1,191 +0,0 @@ -ast_lowering_abi_specified_multiple_times = - `{$prev_name}` ABI specified multiple times - .label = previously specified here - .note = these ABIs are equivalent on the current target - -ast_lowering_arbitrary_expression_in_pattern = - arbitrary expressions aren't allowed in patterns - .pattern_from_macro_note = the `expr` fragment specifier forces the metavariable's content to be an expression - .const_block_in_pattern_help = use a named `const`-item or an `if`-guard (`x if x == const {"{ ... }"}`) instead - -ast_lowering_argument = argument - -ast_lowering_assoc_ty_binding_in_dyn = - associated type bounds are not allowed in `dyn` types - .suggestion = use `impl Trait` to introduce a type instead - -ast_lowering_assoc_ty_parentheses = - parenthesized generic arguments cannot be used in associated type constraints - -ast_lowering_async_bound_not_on_trait = - `async` bound modifier only allowed on trait, not `{$descr}` - -ast_lowering_async_bound_only_for_fn_traits = - `async` bound modifier only allowed on `Fn`/`FnMut`/`FnOnce` traits - -ast_lowering_async_coroutines_not_supported = - `async` coroutines are not yet supported - -ast_lowering_att_syntax_only_x86 = - the `att_syntax` option is only supported on x86 - -ast_lowering_await_only_in_async_fn_and_blocks = - `await` is only allowed inside `async` functions and blocks - .label = only allowed inside `async` functions and blocks - -ast_lowering_bad_return_type_notation_inputs = - argument types not allowed with return type notation - .suggestion = remove the input types - -ast_lowering_bad_return_type_notation_needs_dots = return type notation arguments must be elided with `..` - .suggestion = use the correct syntax by adding `..` to the arguments - -ast_lowering_bad_return_type_notation_output = - return type not allowed with return type notation -ast_lowering_bad_return_type_notation_output_suggestion = use the right argument notation and remove the return type - -ast_lowering_bad_return_type_notation_position = return type notation not allowed in this position yet - -ast_lowering_clobber_abi_not_supported = - `clobber_abi` is not supported on this target - -ast_lowering_closure_cannot_be_static = closures cannot be static - -ast_lowering_coroutine_too_many_parameters = - too many parameters for a coroutine (expected 0 or 1 parameters) - -ast_lowering_default_field_in_tuple = default fields are not supported in tuple structs - .label = default fields are only supported on structs - -ast_lowering_delegation_cycle_in_signature_resolution = encountered a cycle during delegation signature resolution -ast_lowering_delegation_unresolved_callee = failed to resolve delegation callee -ast_lowering_does_not_support_modifiers = - the `{$class_name}` register class does not support template modifiers - -ast_lowering_extra_double_dot = - `..` can only be used once per {$ctx} pattern - .label = can only be used once per {$ctx} pattern - -ast_lowering_functional_record_update_destructuring_assignment = - functional record updates are not allowed in destructuring assignments - .suggestion = consider removing the trailing pattern - -ast_lowering_generic_param_default_in_binder = - defaults for generic parameters are not allowed in `for<...>` binders - -ast_lowering_generic_type_with_parentheses = - parenthesized type parameters may only be used with a `Fn` trait - .label = only `Fn` traits may use parentheses - -ast_lowering_inclusive_range_with_no_end = inclusive range with no end - -ast_lowering_inline_asm_unsupported_target = - inline assembly is unsupported on this target - -ast_lowering_invalid_abi = - invalid ABI: found `{$abi}` - .label = invalid ABI - .note = invoke `{$command}` for a full list of supported calling conventions - -ast_lowering_invalid_abi_clobber_abi = - invalid ABI for `clobber_abi` - .note = the following ABIs are supported on this target: {$supported_abis} - -ast_lowering_invalid_abi_suggestion = there's a similarly named valid ABI `{$suggestion}` - -ast_lowering_invalid_asm_template_modifier_const = - asm template modifiers are not allowed for `const` arguments - -ast_lowering_invalid_asm_template_modifier_label = - asm template modifiers are not allowed for `label` arguments - -ast_lowering_invalid_asm_template_modifier_reg_class = - invalid asm template modifier for this register class - -ast_lowering_invalid_asm_template_modifier_sym = - asm template modifiers are not allowed for `sym` arguments - -ast_lowering_invalid_legacy_const_generic_arg = - invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items - -ast_lowering_invalid_legacy_const_generic_arg_suggestion = - try using a const generic argument instead - -ast_lowering_invalid_register = - invalid register `{$reg}`: {$error} - -ast_lowering_invalid_register_class = - invalid register class `{$reg_class}`: unknown register class - .note = the following register classes are supported on this target: {$supported_register_classes} - -ast_lowering_match_arm_with_no_body = - `match` arm with no body - .suggestion = add a body after the pattern - -ast_lowering_misplaced_double_dot = - `..` patterns are not allowed here - .note = only allowed in tuple, tuple struct, and slice patterns - -ast_lowering_misplaced_impl_trait = - `impl Trait` is not allowed in {$position} - .note = `impl Trait` is only allowed in arguments and return types of functions and methods - -ast_lowering_never_pattern_with_body = - a never pattern is always unreachable - .label = this will never be executed - .suggestion = remove this expression - -ast_lowering_never_pattern_with_guard = - a guard on a never pattern will never be run - .suggestion = remove this guard - -ast_lowering_no_precise_captures_on_apit = `use<...>` precise capturing syntax not allowed in argument-position `impl Trait` - -ast_lowering_previously_used_here = previously used here - -ast_lowering_register1 = register `{$reg1_name}` - -ast_lowering_register2 = register `{$reg2_name}` - -ast_lowering_register_class_only_clobber = - register class `{$reg_class_name}` can only be used as a clobber, not as an input or output -ast_lowering_register_class_only_clobber_stable = - register class `{$reg_class_name}` can only be used as a clobber in stable - -ast_lowering_register_conflict = - register `{$reg1_name}` conflicts with register `{$reg2_name}` - .help = use `lateout` instead of `out` to avoid conflict - -ast_lowering_remove_parentheses = remove these parentheses - -ast_lowering_sub_tuple_binding = - `{$ident_name} @` is not allowed in a {$ctx} - .label = this is only allowed in slice patterns - .help = remove this and bind each tuple field independently - -ast_lowering_sub_tuple_binding_suggestion = if you don't need to use the contents of {$ident}, discard the tuple's remaining fields - -ast_lowering_support_modifiers = - the `{$class_name}` register class supports the following template modifiers: {$modifiers} - -ast_lowering_template_modifier = template modifier - -ast_lowering_this_not_async = this is not `async` - -ast_lowering_underscore_expr_lhs_assign = - in expressions, `_` can only be used on the left-hand side of an assignment - .label = `_` not allowed here - -ast_lowering_union_default_field_values = unions cannot have default field values - -ast_lowering_unstable_inline_assembly = inline assembly is not stable yet on this architecture -ast_lowering_unstable_inline_assembly_label_operand_with_outputs = - using both label and output operands for inline assembly is unstable -ast_lowering_unstable_may_unwind = the `may_unwind` option is unstable - -ast_lowering_use_angle_brackets = use angle brackets instead - -ast_lowering_yield = yield syntax is experimental -ast_lowering_yield_in_closure = - `yield` can only be used in `#[coroutine]` closures, or `gen` blocks - .suggestion = use `#[coroutine]` to make this closure a coroutine diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 36fcd4b924c8..fc1f198e8b2a 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -3,6 +3,7 @@ use std::fmt::Write; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; +use rustc_errors::inline_fluent; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_session::parse::feature_err; @@ -19,8 +20,7 @@ use super::errors::{ RegisterConflict, }; use crate::{ - AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, ParamMode, - ResolverAstLoweringExt, fluent_generated as fluent, + AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, ParamMode, ResolverAstLoweringExt, }; impl<'a, 'hir> LoweringContext<'a, 'hir> { @@ -67,7 +67,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &self.tcx.sess, sym::asm_experimental_arch, sp, - fluent::ast_lowering_unstable_inline_assembly, + inline_fluent!("inline assembly is not stable yet on this architecture"), ) .emit(); } @@ -84,7 +84,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &self.tcx.sess, sym::asm_unwind, sp, - fluent::ast_lowering_unstable_may_unwind, + inline_fluent!("the `may_unwind` option is unstable"), ) .emit(); } @@ -499,7 +499,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { sess, sym::asm_goto_with_outputs, *op_sp, - fluent::ast_lowering_unstable_inline_assembly_label_operand_with_outputs, + inline_fluent!( + "using both label and output operands for inline assembly is unstable" + ), ) .emit(); } diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 88e69e67d8a5..1eb72727df66 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -4,17 +4,17 @@ use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; #[derive(Diagnostic)] -#[diag(ast_lowering_generic_type_with_parentheses, code = E0214)] +#[diag("parenthesized type parameters may only be used with a `Fn` trait", code = E0214)] pub(crate) struct GenericTypeWithParentheses { #[primary_span] - #[label] + #[label("only `Fn` traits may use parentheses")] pub span: Span, #[subdiagnostic] pub sub: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion(ast_lowering_use_angle_brackets, applicability = "maybe-incorrect")] +#[multipart_suggestion("use angle brackets instead", applicability = "maybe-incorrect")] pub(crate) struct UseAngleBrackets { #[suggestion_part(code = "<")] pub open_param: Span, @@ -23,11 +23,11 @@ pub(crate) struct UseAngleBrackets { } #[derive(Diagnostic)] -#[diag(ast_lowering_invalid_abi, code = E0703)] -#[note] +#[diag("invalid ABI: found `{$abi}`", code = E0703)] +#[note("invoke `{$command}` for a full list of supported calling conventions")] pub(crate) struct InvalidAbi { #[primary_span] - #[label] + #[label("invalid ABI")] pub span: Span, pub abi: Symbol, pub command: String, @@ -36,16 +36,16 @@ pub(crate) struct InvalidAbi { } #[derive(Diagnostic)] -#[diag(ast_lowering_default_field_in_tuple)] +#[diag("default fields are not supported in tuple structs")] pub(crate) struct TupleStructWithDefault { #[primary_span] - #[label] + #[label("default fields are only supported on structs")] pub span: Span, } #[derive(Subdiagnostic)] #[suggestion( - ast_lowering_invalid_abi_suggestion, + "there's a similarly named valid ABI `{$suggestion}`", code = "\"{suggestion}\"", applicability = "maybe-incorrect", style = "verbose" @@ -57,7 +57,7 @@ pub(crate) struct InvalidAbiSuggestion { } #[derive(Diagnostic)] -#[diag(ast_lowering_assoc_ty_parentheses)] +#[diag("parenthesized generic arguments cannot be used in associated type constraints")] pub(crate) struct AssocTyParentheses { #[primary_span] pub span: Span, @@ -67,12 +67,12 @@ pub(crate) struct AssocTyParentheses { #[derive(Subdiagnostic)] pub(crate) enum AssocTyParenthesesSub { - #[multipart_suggestion(ast_lowering_remove_parentheses)] + #[multipart_suggestion("remove these parentheses")] Empty { #[suggestion_part(code = "")] parentheses_span: Span, }, - #[multipart_suggestion(ast_lowering_use_angle_brackets)] + #[multipart_suggestion("use angle brackets instead")] NotEmpty { #[suggestion_part(code = "<")] open_param: Span, @@ -82,8 +82,8 @@ pub(crate) enum AssocTyParenthesesSub { } #[derive(Diagnostic)] -#[diag(ast_lowering_misplaced_impl_trait, code = E0562)] -#[note] +#[diag("`impl Trait` is not allowed in {$position}", code = E0562)] +#[note("`impl Trait` is only allowed in arguments and return types of functions and methods")] pub(crate) struct MisplacedImplTrait<'a> { #[primary_span] pub span: Span, @@ -91,97 +91,106 @@ pub(crate) struct MisplacedImplTrait<'a> { } #[derive(Diagnostic)] -#[diag(ast_lowering_assoc_ty_binding_in_dyn)] +#[diag("associated type bounds are not allowed in `dyn` types")] pub(crate) struct MisplacedAssocTyBinding { #[primary_span] pub span: Span, - #[suggestion(code = " = impl", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "use `impl Trait` to introduce a type instead", + code = " = impl", + applicability = "maybe-incorrect", + style = "verbose" + )] pub suggestion: Option, } #[derive(Diagnostic)] -#[diag(ast_lowering_underscore_expr_lhs_assign)] +#[diag("in expressions, `_` can only be used on the left-hand side of an assignment")] pub(crate) struct UnderscoreExprLhsAssign { #[primary_span] - #[label] + #[label("`_` not allowed here")] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = E0728)] +#[diag("`await` is only allowed inside `async` functions and blocks", code = E0728)] pub(crate) struct AwaitOnlyInAsyncFnAndBlocks { #[primary_span] - #[label] + #[label("only allowed inside `async` functions and blocks")] pub await_kw_span: Span, - #[label(ast_lowering_this_not_async)] + #[label("this is not `async`")] pub item_span: Option, } #[derive(Diagnostic)] -#[diag(ast_lowering_coroutine_too_many_parameters, code = E0628)] +#[diag("too many parameters for a coroutine (expected 0 or 1 parameters)", code = E0628)] pub(crate) struct CoroutineTooManyParameters { #[primary_span] pub fn_decl_span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_closure_cannot_be_static, code = E0697)] +#[diag("closures cannot be static", code = E0697)] pub(crate) struct ClosureCannotBeStatic { #[primary_span] pub fn_decl_span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_functional_record_update_destructuring_assignment)] +#[diag("functional record updates are not allowed in destructuring assignments")] pub(crate) struct FunctionalRecordUpdateDestructuringAssignment { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion( + "consider removing the trailing pattern", + code = "", + applicability = "machine-applicable" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_async_coroutines_not_supported, code = E0727)] +#[diag("`async` coroutines are not yet supported", code = E0727)] pub(crate) struct AsyncCoroutinesNotSupported { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_inline_asm_unsupported_target, code = E0472)] +#[diag("inline assembly is unsupported on this target", code = E0472)] pub(crate) struct InlineAsmUnsupportedTarget { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_att_syntax_only_x86)] +#[diag("the `att_syntax` option is only supported on x86")] pub(crate) struct AttSyntaxOnlyX86 { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_abi_specified_multiple_times)] +#[diag("`{$prev_name}` ABI specified multiple times")] pub(crate) struct AbiSpecifiedMultipleTimes { #[primary_span] pub abi_span: Span, pub prev_name: Symbol, - #[label] + #[label("previously specified here")] pub prev_span: Span, - #[note] + #[note("these ABIs are equivalent on the current target")] pub equivalent: bool, } #[derive(Diagnostic)] -#[diag(ast_lowering_clobber_abi_not_supported)] +#[diag("`clobber_abi` is not supported on this target")] pub(crate) struct ClobberAbiNotSupported { #[primary_span] pub abi_span: Span, } #[derive(Diagnostic)] -#[note] -#[diag(ast_lowering_invalid_abi_clobber_abi)] +#[note("the following ABIs are supported on this target: {$supported_abis}")] +#[diag("invalid ABI for `clobber_abi`")] pub(crate) struct InvalidAbiClobberAbi { #[primary_span] pub abi_span: Span, @@ -189,7 +198,7 @@ pub(crate) struct InvalidAbiClobberAbi { } #[derive(Diagnostic)] -#[diag(ast_lowering_invalid_register)] +#[diag("invalid register `{$reg}`: {$error}")] pub(crate) struct InvalidRegister<'a> { #[primary_span] pub op_span: Span, @@ -198,8 +207,10 @@ pub(crate) struct InvalidRegister<'a> { } #[derive(Diagnostic)] -#[note] -#[diag(ast_lowering_invalid_register_class)] +#[note( + "the following register classes are supported on this target: {$supported_register_classes}" +)] +#[diag("invalid register class `{$reg_class}`: unknown register class")] pub(crate) struct InvalidRegisterClass { #[primary_span] pub op_span: Span, @@ -208,12 +219,12 @@ pub(crate) struct InvalidRegisterClass { } #[derive(Diagnostic)] -#[diag(ast_lowering_invalid_asm_template_modifier_reg_class)] +#[diag("invalid asm template modifier for this register class")] pub(crate) struct InvalidAsmTemplateModifierRegClass { #[primary_span] - #[label(ast_lowering_template_modifier)] + #[label("template modifier")] pub placeholder_span: Span, - #[label(ast_lowering_argument)] + #[label("argument")] pub op_span: Span, #[subdiagnostic] pub sub: InvalidAsmTemplateModifierRegClassSub, @@ -221,44 +232,48 @@ pub(crate) struct InvalidAsmTemplateModifierRegClass { #[derive(Subdiagnostic)] pub(crate) enum InvalidAsmTemplateModifierRegClassSub { - #[note(ast_lowering_support_modifiers)] + #[note( + "the `{$class_name}` register class supports the following template modifiers: {$modifiers}" + )] SupportModifier { class_name: Symbol, modifiers: String }, - #[note(ast_lowering_does_not_support_modifiers)] + #[note("the `{$class_name}` register class does not support template modifiers")] DoesNotSupportModifier { class_name: Symbol }, } #[derive(Diagnostic)] -#[diag(ast_lowering_invalid_asm_template_modifier_const)] +#[diag("asm template modifiers are not allowed for `const` arguments")] pub(crate) struct InvalidAsmTemplateModifierConst { #[primary_span] - #[label(ast_lowering_template_modifier)] + #[label("template modifier")] pub placeholder_span: Span, - #[label(ast_lowering_argument)] + #[label("argument")] pub op_span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_invalid_asm_template_modifier_sym)] +#[diag("asm template modifiers are not allowed for `sym` arguments")] pub(crate) struct InvalidAsmTemplateModifierSym { #[primary_span] - #[label(ast_lowering_template_modifier)] + #[label("template modifier")] pub placeholder_span: Span, - #[label(ast_lowering_argument)] + #[label("argument")] pub op_span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_invalid_asm_template_modifier_label)] +#[diag("asm template modifiers are not allowed for `label` arguments")] pub(crate) struct InvalidAsmTemplateModifierLabel { #[primary_span] - #[label(ast_lowering_template_modifier)] + #[label("template modifier")] pub placeholder_span: Span, - #[label(ast_lowering_argument)] + #[label("argument")] pub op_span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_register_class_only_clobber)] +#[diag( + "register class `{$reg_class_name}` can only be used as a clobber, not as an input or output" +)] pub(crate) struct RegisterClassOnlyClobber { #[primary_span] pub op_span: Span, @@ -266,7 +281,7 @@ pub(crate) struct RegisterClassOnlyClobber { } #[derive(Diagnostic)] -#[diag(ast_lowering_register_class_only_clobber_stable)] +#[diag("register class `{$reg_class_name}` can only be used as a clobber in stable")] pub(crate) struct RegisterClassOnlyClobberStable { #[primary_span] pub op_span: Span, @@ -274,27 +289,27 @@ pub(crate) struct RegisterClassOnlyClobberStable { } #[derive(Diagnostic)] -#[diag(ast_lowering_register_conflict)] +#[diag("register `{$reg1_name}` conflicts with register `{$reg2_name}`")] pub(crate) struct RegisterConflict<'a> { #[primary_span] - #[label(ast_lowering_register1)] + #[label("register `{$reg1_name}`")] pub op_span1: Span, - #[label(ast_lowering_register2)] + #[label("register `{$reg2_name}`")] pub op_span2: Span, pub reg1_name: &'a str, pub reg2_name: &'a str, - #[help] + #[help("use `lateout` instead of `out` to avoid conflict")] pub in_out: Option, } #[derive(Diagnostic)] -#[help] -#[diag(ast_lowering_sub_tuple_binding)] +#[help("remove this and bind each tuple field independently")] +#[diag("`{$ident_name} @` is not allowed in a {$ctx}")] pub(crate) struct SubTupleBinding<'a> { #[primary_span] - #[label] + #[label("this is only allowed in slice patterns")] #[suggestion( - ast_lowering_sub_tuple_binding_suggestion, + "if you don't need to use the contents of {$ident}, discard the tuple's remaining fields", style = "verbose", code = "..", applicability = "maybe-incorrect" @@ -306,63 +321,67 @@ pub(crate) struct SubTupleBinding<'a> { } #[derive(Diagnostic)] -#[diag(ast_lowering_extra_double_dot)] +#[diag("`..` can only be used once per {$ctx} pattern")] pub(crate) struct ExtraDoubleDot<'a> { #[primary_span] - #[label] + #[label("can only be used once per {$ctx} pattern")] pub span: Span, - #[label(ast_lowering_previously_used_here)] + #[label("previously used here")] pub prev_span: Span, pub ctx: &'a str, } #[derive(Diagnostic)] -#[note] -#[diag(ast_lowering_misplaced_double_dot)] +#[note("only allowed in tuple, tuple struct, and slice patterns")] +#[diag("`..` patterns are not allowed here")] pub(crate) struct MisplacedDoubleDot { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_match_arm_with_no_body)] +#[diag("`match` arm with no body")] pub(crate) struct MatchArmWithNoBody { #[primary_span] pub span: Span, - #[suggestion(code = " => todo!(),", applicability = "has-placeholders")] + #[suggestion( + "add a body after the pattern", + code = " => todo!(),", + applicability = "has-placeholders" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_never_pattern_with_body)] +#[diag("a never pattern is always unreachable")] pub(crate) struct NeverPatternWithBody { #[primary_span] - #[label] - #[suggestion(code = "", applicability = "maybe-incorrect")] + #[label("this will never be executed")] + #[suggestion("remove this expression", code = "", applicability = "maybe-incorrect")] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_never_pattern_with_guard)] +#[diag("a guard on a never pattern will never be run")] pub(crate) struct NeverPatternWithGuard { #[primary_span] - #[suggestion(code = "", applicability = "maybe-incorrect")] + #[suggestion("remove this guard", code = "", applicability = "maybe-incorrect")] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_arbitrary_expression_in_pattern)] +#[diag("arbitrary expressions aren't allowed in patterns")] pub(crate) struct ArbitraryExpressionInPattern { #[primary_span] pub span: Span, - #[note(ast_lowering_pattern_from_macro_note)] + #[note("the `expr` fragment specifier forces the metavariable's content to be an expression")] pub pattern_from_macro_note: bool, - #[help(ast_lowering_const_block_in_pattern_help)] + #[help("use a named `const`-item or an `if`-guard (`x if x == const {\"{ ... }\"}`) instead")] pub const_block_in_pattern_help: bool, } #[derive(Diagnostic)] -#[diag(ast_lowering_inclusive_range_with_no_end)] +#[diag("inclusive range with no end")] pub(crate) struct InclusiveRangeWithNoEnd { #[primary_span] pub span: Span, @@ -370,7 +389,7 @@ pub(crate) struct InclusiveRangeWithNoEnd { #[derive(Subdiagnostic)] #[multipart_suggestion( - ast_lowering_bad_return_type_notation_output_suggestion, + "use the right argument notation and remove the return type", applicability = "machine-applicable", style = "verbose" )] @@ -384,26 +403,36 @@ pub(crate) struct RTNSuggestion { #[derive(Diagnostic)] pub(crate) enum BadReturnTypeNotation { - #[diag(ast_lowering_bad_return_type_notation_inputs)] + #[diag("argument types not allowed with return type notation")] Inputs { #[primary_span] - #[suggestion(code = "(..)", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove the input types", + code = "(..)", + applicability = "machine-applicable", + style = "verbose" + )] span: Span, }, - #[diag(ast_lowering_bad_return_type_notation_output)] + #[diag("return type not allowed with return type notation")] Output { #[primary_span] span: Span, #[subdiagnostic] suggestion: RTNSuggestion, }, - #[diag(ast_lowering_bad_return_type_notation_needs_dots)] + #[diag("return type notation arguments must be elided with `..`")] NeedsDots { #[primary_span] - #[suggestion(code = "(..)", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "use the correct syntax by adding `..` to the arguments", + code = "(..)", + applicability = "machine-applicable", + style = "verbose" + )] span: Span, }, - #[diag(ast_lowering_bad_return_type_notation_position)] + #[diag("return type notation not allowed in this position yet")] Position { #[primary_span] span: Span, @@ -411,14 +440,14 @@ pub(crate) enum BadReturnTypeNotation { } #[derive(Diagnostic)] -#[diag(ast_lowering_generic_param_default_in_binder)] +#[diag("defaults for generic parameters are not allowed in `for<...>` binders")] pub(crate) struct GenericParamDefaultInBinder { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_async_bound_not_on_trait)] +#[diag("`async` bound modifier only allowed on trait, not `{$descr}`")] pub(crate) struct AsyncBoundNotOnTrait { #[primary_span] pub span: Span, @@ -426,30 +455,37 @@ pub(crate) struct AsyncBoundNotOnTrait { } #[derive(Diagnostic)] -#[diag(ast_lowering_async_bound_only_for_fn_traits)] +#[diag("`async` bound modifier only allowed on `Fn`/`FnMut`/`FnOnce` traits")] pub(crate) struct AsyncBoundOnlyForFnTraits { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_no_precise_captures_on_apit)] +#[diag("`use<...>` precise capturing syntax not allowed in argument-position `impl Trait`")] pub(crate) struct NoPreciseCapturesOnApit { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_yield_in_closure)] +#[diag("`yield` can only be used in `#[coroutine]` closures, or `gen` blocks")] pub(crate) struct YieldInClosure { #[primary_span] pub span: Span, - #[suggestion(code = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "use `#[coroutine]` to make this closure a coroutine", + code = "#[coroutine] ", + applicability = "maybe-incorrect", + style = "verbose" + )] pub suggestion: Option, } #[derive(Diagnostic)] -#[diag(ast_lowering_invalid_legacy_const_generic_arg)] +#[diag( + "invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items" +)] pub(crate) struct InvalidLegacyConstGenericArg { #[primary_span] pub span: Span, @@ -459,7 +495,7 @@ pub(crate) struct InvalidLegacyConstGenericArg { #[derive(Subdiagnostic)] #[multipart_suggestion( - ast_lowering_invalid_legacy_const_generic_arg_suggestion, + "try using a const generic argument instead", applicability = "maybe-incorrect" )] pub(crate) struct UseConstGenericArg { @@ -472,21 +508,21 @@ pub(crate) struct UseConstGenericArg { } #[derive(Diagnostic)] -#[diag(ast_lowering_union_default_field_values)] +#[diag("unions cannot have default field values")] pub(crate) struct UnionWithDefault { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_delegation_unresolved_callee)] +#[diag("failed to resolve delegation callee")] pub(crate) struct UnresolvedDelegationCallee { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_lowering_delegation_cycle_in_signature_resolution)] +#[diag("encountered a cycle during delegation signature resolution")] pub(crate) struct CycleInDelegationSignatureResolution { #[primary_span] pub span: Span, diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 9fbfeb7a11e6..051bebfbec00 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -5,6 +5,7 @@ use std::sync::Arc; use rustc_ast::*; use rustc_ast_pretty::pprust::expr_to_string; use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_errors::inline_fluent; use rustc_hir as hir; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; @@ -28,9 +29,7 @@ use super::{ GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt, }; use crate::errors::{InvalidLegacyConstGenericArg, UseConstGenericArg, YieldInClosure}; -use crate::{ - AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition, TryBlockScope, fluent_generated, -}; +use crate::{AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition, TryBlockScope}; struct WillCreateDefIdsVisitor {} @@ -1703,7 +1702,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &self.tcx.sess, sym::yield_expr, span, - fluent_generated::ast_lowering_yield, + inline_fluent!("yield syntax is experimental"), ) .emit(); } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8c6ee9d6bc63..e4f431fd2431 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -88,8 +88,6 @@ mod pat; mod path; pub mod stability; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - struct LoweringContext<'a, 'hir> { tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering, diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index d184b6c8947c..f2b972da9789 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -9,7 +9,6 @@ anstyle = "1.0.13" jiff = { version = "0.2.5", default-features = false, features = ["std"] } rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } -rustc_ast_lowering = { path = "../rustc_ast_lowering" } rustc_ast_passes = { path = "../rustc_ast_passes" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_borrowck = { path = "../rustc_borrowck" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 3059a4fefc61..a37f0f92697b 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -114,7 +114,6 @@ pub fn default_translator() -> Translator { pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ // tidy-alphabetical-start - rustc_ast_lowering::DEFAULT_LOCALE_RESOURCE, rustc_ast_passes::DEFAULT_LOCALE_RESOURCE, rustc_borrowck::DEFAULT_LOCALE_RESOURCE, rustc_builtin_macros::DEFAULT_LOCALE_RESOURCE, From caaca04e681adac08929fbae6a98893f80b2e0f2 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 4 Feb 2026 09:29:07 -0600 Subject: [PATCH 527/978] bootstrap: exclude hexagon-unknown-qurt from llvm-libunwind default Hexagon Linux targets (hexagon-unknown-linux-musl) use in-tree llvm-libunwind for stack unwinding. However, hexagon-unknown-qurt uses libc_eh from the Hexagon SDK instead. --- src/bootstrap/src/core/config/config.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 07405a0309fe..61eef3c01592 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1859,11 +1859,17 @@ impl Config { .get(&target) .and_then(|t| t.llvm_libunwind) .or(self.llvm_libunwind_default) - .unwrap_or(if target.contains("fuchsia") || target.contains("hexagon") { - LlvmLibunwind::InTree - } else { - LlvmLibunwind::No - }) + .unwrap_or( + if target.contains("fuchsia") + || (target.contains("hexagon") && !target.contains("qurt")) + { + // Fuchsia and Hexagon Linux use in-tree llvm-libunwind. + // Hexagon QuRT uses libc_eh from the Hexagon SDK instead. + LlvmLibunwind::InTree + } else { + LlvmLibunwind::No + }, + ) } pub fn split_debuginfo(&self, target: TargetSelection) -> SplitDebuginfo { From 78b55fc337e0ff9eb5f83aef0031abee0c8996b3 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Wed, 4 Feb 2026 23:29:18 +0800 Subject: [PATCH 528/978] Fix incorrect RSS on systems with non-4K page size `get_resident_set_size` computed RSS by multiplying the number of pages from `/proc/self/statm` with a hard-coded 4096-byte page size. This produces incorrect results on systems where the runtime page size is not 4 KiB. Use `sysconf(_SC_PAGESIZE)` to determine the actual page size at runtime so the RSS reported in `-Z time-passes` output is accurate across platforms. --- compiler/rustc_data_structures/src/profiling.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 4a9551a60cf9..b04caa69adfb 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -995,12 +995,14 @@ cfg_select! { } unix => { pub fn get_resident_set_size() -> Option { + use libc::{sysconf, _SC_PAGESIZE}; let field = 1; let contents = fs::read("/proc/self/statm").ok()?; let contents = String::from_utf8(contents).ok()?; let s = contents.split_whitespace().nth(field)?; let npages = s.parse::().ok()?; - Some(npages * 4096) + // SAFETY: `sysconf(_SC_PAGESIZE)` has no side effects and is safe to call. + Some(npages * unsafe { sysconf(_SC_PAGESIZE) } as usize) } } _ => { From 34c6ae0d488f34be9f9d3576a8dae675d5e30d17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 4 Feb 2026 16:41:21 +0100 Subject: [PATCH 529/978] Fix GitHub CI summary in CodeBuild --- src/ci/docker/run.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 691b8b8deb81..6c35105225c0 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -359,11 +359,11 @@ docker \ rust-ci \ "${command[@]}" -if isCI; then - cat $objdir/${SUMMARY_FILE} >> "${GITHUB_STEP_SUMMARY}" -fi - if [ -f /.dockerenv ]; then rm -rf $objdir docker cp checkout:/checkout/obj $objdir fi + +if isCI; then + cat $objdir/${SUMMARY_FILE} >> "${GITHUB_STEP_SUMMARY}" +fi From ef00ebfdec7d9d257ef19dc9d6d17bf64df0373d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 4 Feb 2026 11:17:25 +0000 Subject: [PATCH 530/978] Remove is_ctfe_mir_available query It isn't called anywhere anymore. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 4 ---- compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 1 - compiler/rustc_middle/src/queries.rs | 5 ----- compiler/rustc_mir_transform/src/lib.rs | 1 - 4 files changed, 11 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index c7423386a771..bd5b3893e4e8 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1298,10 +1298,6 @@ impl<'a> CrateMetadataRef<'a> { } } - fn is_ctfe_mir_available(self, tcx: TyCtxt<'_>, id: DefIndex) -> bool { - self.root.tables.mir_for_ctfe.get((self, tcx), id).is_some() - } - fn is_item_mir_available(self, tcx: TyCtxt<'_>, id: DefIndex) -> bool { self.root.tables.optimized_mir.get((self, tcx), id).is_some() } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index b1f3bafd92fb..c6c87534851c 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -324,7 +324,6 @@ provide! { tcx, def_id, other, cdata, inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } attrs_for_def => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(tcx, def_id.index)) } is_mir_available => { cdata.is_item_mir_available(tcx, def_id.index) } - is_ctfe_mir_available => { cdata.is_ctfe_mir_available(tcx, def_id.index) } cross_crate_inlinable => { table_direct } dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) } diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index ca8e5e90318d..de2298914438 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -1588,11 +1588,6 @@ rustc_queries! { separate_provide_extern } - query is_ctfe_mir_available(key: DefId) -> bool { - desc { |tcx| "checking if item has CTFE MIR available: `{}`", tcx.def_path_str(key) } - cache_on_disk_if { key.is_local() } - separate_provide_extern - } query is_mir_available(key: DefId) -> bool { desc { |tcx| "checking if item has MIR available: `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 0e6a1a414e45..96ec7f1e9bdc 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -231,7 +231,6 @@ pub fn provide(providers: &mut Providers) { optimized_mir, check_liveness: liveness::check_liveness, is_mir_available, - is_ctfe_mir_available: is_mir_available, mir_callgraph_cyclic: inline::cycle::mir_callgraph_cyclic, mir_inliner_callees: inline::cycle::mir_inliner_callees, promoted_mir, From 1e6f7845ed334829c8a0caed8640c9bfb708de22 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 4 Feb 2026 11:21:52 +0000 Subject: [PATCH 531/978] Avoid encoding optimized MIR for constructors We only use mir_for_ctfe for them anyway in instance_mir. This does prevent MIR inlining of constructor calls, but constructor calls that are inlinable during MIR optimizations are rare anyway given that MIR building already inlines all direct calls to constructors. --- compiler/rustc_metadata/src/rmeta/encoder.rs | 8 ++------ compiler/rustc_monomorphize/src/collector.rs | 4 +++- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 471c19ed4d4e..2905eb819b24 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1102,12 +1102,8 @@ fn should_encode_mir( def_id: LocalDefId, ) -> (bool, bool) { match tcx.def_kind(def_id) { - // Constructors - DefKind::Ctor(_, _) => { - let mir_opt_base = tcx.sess.opts.output_types.should_codegen() - || tcx.sess.opts.unstable_opts.always_encode_mir; - (true, mir_opt_base) - } + // instance_mir uses mir_for_ctfe rather than optimized_mir for constructors + DefKind::Ctor(_, _) => (true, false), // Constants DefKind::AnonConst | DefKind::InlineConst | DefKind::AssocConst | DefKind::Const => { (true, false) diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 81d46e3b5b0d..3362038ed091 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1084,7 +1084,9 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> return false; } - if !tcx.is_mir_available(def_id) { + // See comment in should_encode_mir in rustc_metadata for why we don't report + // an error for constructors. + if !tcx.is_mir_available(def_id) && !matches!(tcx.def_kind(def_id), DefKind::Ctor(..)) { tcx.dcx().emit_fatal(NoOptimizedMir { span: tcx.def_span(def_id), crate_name: tcx.crate_name(def_id.krate), From 05921d41e9ffeda1a5e3a2147818e4e5c9824279 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 4 Feb 2026 11:23:29 +0000 Subject: [PATCH 532/978] Only call generics_of query in should_encode_mir when necessary --- compiler/rustc_metadata/src/rmeta/encoder.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 2905eb819b24..30f8a753b9b7 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1113,11 +1113,10 @@ fn should_encode_mir( DefKind::SyntheticCoroutineBody => (false, true), // Full-fledged functions + closures DefKind::AssocFn | DefKind::Fn | DefKind::Closure => { - let generics = tcx.generics_of(def_id); let opt = tcx.sess.opts.unstable_opts.always_encode_mir || (tcx.sess.opts.output_types.should_codegen() && reachable_set.contains(&def_id) - && (generics.requires_monomorphization(tcx) + && (tcx.generics_of(def_id).requires_monomorphization(tcx) || tcx.cross_crate_inlinable(def_id))); // The function has a `const` modifier or is in a `const trait`. let is_const_fn = tcx.is_const_fn(def_id.to_def_id()); From 607ac4bb840bc4b533b0758755a41b22a17d36b9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 Feb 2026 17:09:57 +0100 Subject: [PATCH 533/978] Remove rustdoc GUI flaky test --- tests/rustdoc-gui/globals.goml | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 tests/rustdoc-gui/globals.goml diff --git a/tests/rustdoc-gui/globals.goml b/tests/rustdoc-gui/globals.goml deleted file mode 100644 index 7fd9c5bfb6f2..000000000000 --- a/tests/rustdoc-gui/globals.goml +++ /dev/null @@ -1,20 +0,0 @@ -// Make sure search stores its data in `window` -// It needs to use a global to avoid racing on search-index.js and search.js -// https://github.com/rust-lang/rust/pull/118961 -include: "utils.goml" - -// URL query -go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=sa" -wait-for: "#search-tabs" -wait-for-window-property-false: {"searchIndex": null} - -// Form input -go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" -call-function: ("perform-search", {"query": "Foo"}) -wait-for-window-property-false: {"searchIndex": null} - -// source sidebar -go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html" -click: "#sidebar-button" -wait-for: "#src-sidebar details" -assert-window-property: {"searchIndex": null} From d445a2aabb70d0c0280eaf2523c54dc1d51d5d0f Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 4 Feb 2026 17:23:35 +0100 Subject: [PATCH 534/978] Convert to inline diagnostics in `rustc_codegen_ssa` --- Cargo.lock | 1 - compiler/rustc_codegen_ssa/Cargo.toml | 1 - compiler/rustc_codegen_ssa/messages.ftl | 397 ----------------- compiler/rustc_codegen_ssa/src/back/apple.rs | 12 +- compiler/rustc_codegen_ssa/src/back/link.rs | 2 +- compiler/rustc_codegen_ssa/src/errors.rs | 443 ++++++++++--------- compiler/rustc_codegen_ssa/src/lib.rs | 2 - compiler/rustc_driver_impl/src/lib.rs | 1 - 8 files changed, 252 insertions(+), 607 deletions(-) delete mode 100644 compiler/rustc_codegen_ssa/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 1631d5362612..32fa08784bed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3673,7 +3673,6 @@ dependencies = [ "rustc_attr_parsing", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_fs_util", "rustc_hashes", "rustc_hir", diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 3d045a02fef1..864220635120 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -18,7 +18,6 @@ rustc_ast = { path = "../rustc_ast" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl deleted file mode 100644 index a49f411a7df6..000000000000 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ /dev/null @@ -1,397 +0,0 @@ -codegen_ssa_L4Bender_exporting_symbols_unimplemented = exporting symbols not implemented yet for L4Bender - -codegen_ssa_aarch64_softfloat_neon = enabling the `neon` target feature on the current target is unsound due to ABI issues - -codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error} - -codegen_ssa_aix_strip_not_used = using host's `strip` binary to cross-compile to AIX which is not guaranteed to work - -codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error} - -codegen_ssa_binary_output_to_tty = option `-o` or `--emit` is used to write binary output type `{$shorthand}` to stdout, but stdout is a tty - -codegen_ssa_bpf_staticlib_not_supported = linking static libraries is not supported for BPF - -codegen_ssa_cgu_not_recorded = - CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded - -codegen_ssa_check_installed_visual_studio = please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option. - -codegen_ssa_compiler_builtins_cannot_call = - `compiler_builtins` cannot call functions through upstream monomorphizations; encountered invalid call from `{$caller}` to `{$callee}` - -codegen_ssa_copy_path = could not copy {$from} to {$to}: {$error} - -codegen_ssa_copy_path_buf = unable to copy {$source_file} to {$output_path}: {$error} - -codegen_ssa_cpu_required = target requires explicitly specifying a cpu with `-C target-cpu` - -codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error} - -codegen_ssa_dlltool_fail_import_library = - dlltool could not create import library with {$dlltool_path} {$dlltool_args}: - {$stdout} - {$stderr} - -codegen_ssa_dynamic_linking_with_lto = - cannot prefer dynamic linking when performing LTO - .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO - -codegen_ssa_error_calling_dlltool = - error calling dlltool '{$dlltool_path}': {$error} - -codegen_ssa_error_creating_import_library = - error creating import library for {$lib_name}: {$error} - -codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$error} - -codegen_ssa_error_writing_def_file = - error writing .DEF file: {$error} - -codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified - -codegen_ssa_extract_bundled_libs_archive_member = failed to get data from archive member '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_convert_name = failed to convert name '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_mmap_file = failed to mmap file '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_open_file = failed to open file '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_parse_archive = failed to parse archive '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_read_entry = failed to read entry '{$rlib}': {$error} -codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$error} - -codegen_ssa_failed_to_get_layout = failed to get layout for {$ty}: {$err} - -codegen_ssa_failed_to_write = failed to write {$path}: {$error} - -codegen_ssa_feature_not_valid = the feature named `{$feature}` is not valid for this target - .label = `{$feature}` is not valid for this target - .help = consider removing the leading `+` in the feature name - -codegen_ssa_field_associated_value_expected = associated value expected for `{$name}` - -codegen_ssa_forbidden_ctarget_feature = - target feature `{$feature}` cannot be {$enabled} with `-Ctarget-feature`: {$reason} - .note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -codegen_ssa_forbidden_ctarget_feature_issue = for more information, see issue #116344 - -codegen_ssa_forbidden_target_feature_attr = - target feature `{$feature}` cannot be enabled with `#[target_feature]`: {$reason} - -codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extension} files were produced - -codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files were produced - -codegen_ssa_incorrect_cgu_reuse_type = - CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least -> - [one] {"at least "} - *[other] {""} - }`{$expected_reuse}` - -codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient. - -codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}` - -codegen_ssa_invalid_monomorphization_basic_integer_or_ptr_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer or pointer type, found `{$ty}` - -codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}` - -codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` - -codegen_ssa_invalid_monomorphization_cast_wide_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast wide pointer `{$ty}` - -codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}` - -codegen_ssa_invalid_monomorphization_expected_pointer = invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}` - -codegen_ssa_invalid_monomorphization_expected_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}` - -codegen_ssa_invalid_monomorphization_expected_usize = invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}` - -codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type - -codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}` - -codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type - -codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}` - -codegen_ssa_invalid_monomorphization_inserted_type = invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}` - -codegen_ssa_invalid_monomorphization_invalid_bitmask = invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` - -codegen_ssa_invalid_monomorphization_mask_wrong_element_type = invalid monomorphization of `{$name}` intrinsic: expected mask element type to be an integer, found `{$ty}` - -codegen_ssa_invalid_monomorphization_mismatched_lengths = invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}` - -codegen_ssa_invalid_monomorphization_non_scalable_type = invalid monomorphization of `{$name}` intrinsic: expected non-scalable type, found scalable type `{$ty}` -codegen_ssa_invalid_monomorphization_return_element = invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}` - -codegen_ssa_invalid_monomorphization_return_integer_type = invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}` - -codegen_ssa_invalid_monomorphization_return_length = invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len} - -codegen_ssa_invalid_monomorphization_return_length_input_type = invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len} - -codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` - -codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len} - -codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}` - -codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}` - -codegen_ssa_invalid_monomorphization_simd_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: SIMD index #{$arg_idx} is out of bounds (limit {$total_len}) - -codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}` - -codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}` - -codegen_ssa_invalid_monomorphization_simd_second = invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}` - -codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be a SIMD vector of `u32`, got `{$ty}` - -codegen_ssa_invalid_monomorphization_simd_third = invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}` - -codegen_ssa_invalid_monomorphization_third_argument_length = invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len} - -codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}` - -codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}` - -codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}` - -codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` - -codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}` - -codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64 - -codegen_ssa_lib_def_write_failure = failed to write lib.def file: {$error} - -codegen_ssa_link_exe_status_stack_buffer_overrun = 0xc0000409 is `STATUS_STACK_BUFFER_OVERRUN` - .abort_note = this may have been caused by a program abort and not a stack buffer overrun - .event_log_note = consider checking the Application Event Log for Windows Error Reporting events to see the fail fast error code - -codegen_ssa_link_exe_unexpected_error = `link.exe` returned an unexpected error - -codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker - -codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error} - -codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker - -codegen_ssa_linker_not_found = linker `{$linker_path}` not found - .note = {$error} - -codegen_ssa_linker_output = {$inner} - -codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker - -codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status} - -codegen_ssa_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs - -codegen_ssa_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto` - -codegen_ssa_lto_proc_macro = lto cannot be used for `proc-macro` crate type without `-Zdylib-lto` - -codegen_ssa_malformed_cgu_name = - found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case). - -codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload - -codegen_ssa_missing_features = add the missing features in a `target_feature` attribute - -codegen_ssa_missing_query_depgraph = - found CGU-reuse attribute but `-Zquery-dep-graph` was not specified - -codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but `link.exe` was not found - -codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions - -codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times - .help = did you use `#[no_mangle]` on `fn main`? Use `#![no_main]` to suppress the usual Rust-generated entry point - -codegen_ssa_no_field = no field `{$name}` - -codegen_ssa_no_module_named = - no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names} - -codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error} - -codegen_ssa_no_saved_object_file = cached cgu {$cgu_name} should have an object file, but doesn't - -codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status} - .note = {$output} - -codegen_ssa_read_file = failed to read file: {$message} - -codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer - -codegen_ssa_requires_rust_abi = `#[track_caller]` requires Rust ABI - -codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib at `{$path}`: {$error} - -codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`) - -codegen_ssa_rlib_missing_format = could not find formats for rlibs - -codegen_ssa_rlib_not_found = could not find rlib for: `{$crate_name}` - -codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, found rmeta (metadata) file - -codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected - -codegen_ssa_self_contained_linker_missing = the self-contained linker was requested, but it wasn't found in the target's sysroot, or in rustc's sysroot - -codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time - -codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libraries to link - -codegen_ssa_static_library_native_artifacts = link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms. - -codegen_ssa_static_library_native_artifacts_to_file = native artifacts to link against have been written to {$path}. The order and any duplication can be significant on some platforms. - -codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` failed: {$status} - .note = {$output} - -codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error} - -codegen_ssa_target_feature_disable_or_enable = - the target features {$features} must all be either enabled or disabled together - -codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method - .label = cannot be applied to safe trait method - .label_def = not an `unsafe` function - -codegen_ssa_thorin_decompress_data = failed to decompress compressed section - -codegen_ssa_thorin_duplicate_unit = duplicate split compilation unit ({$unit}) - -codegen_ssa_thorin_empty_unit = unit {$unit} in input DWARF object with no data - -codegen_ssa_thorin_gimli_read = {$error} -codegen_ssa_thorin_gimli_write = {$error} - -codegen_ssa_thorin_incompatible_index_version = incompatible `{$section}` index version: found version {$actual}, expected version {$format} - -codegen_ssa_thorin_invalid_input_kind = input is not an archive or elf object - -codegen_ssa_thorin_io = {$error} -codegen_ssa_thorin_missing_dwo_name = missing path attribute to DWARF object ({$id}) - -codegen_ssa_thorin_missing_referenced_unit = unit {$unit} referenced by executable was not found - -codegen_ssa_thorin_missing_required_section = input object missing required section `{$section}` - -codegen_ssa_thorin_mixed_input_encodings = input objects have mixed encodings - -codegen_ssa_thorin_multiple_debug_info_section = multiple `.debug_info.dwo` sections - -codegen_ssa_thorin_multiple_debug_types_section = multiple `.debug_types.dwo` sections in a package - -codegen_ssa_thorin_multiple_relocations = multiple relocations for section `{$section}` at offset {$offset} - -codegen_ssa_thorin_no_compilation_units = input object has no compilation units - -codegen_ssa_thorin_no_die = no top-level debugging information entry in compilation/type unit - -codegen_ssa_thorin_not_output_object_created = no output object was created from inputs - -codegen_ssa_thorin_not_split_unit = regular compilation unit in object (missing dwo identifier) - -codegen_ssa_thorin_object_read = {$error} -codegen_ssa_thorin_object_write = {$error} -codegen_ssa_thorin_offset_at_index = read offset at index {$index} of `.debug_str_offsets.dwo` section - -codegen_ssa_thorin_parse_archive_member = failed to parse archive member - -codegen_ssa_thorin_parse_index = failed to parse `{$section}` index section - -codegen_ssa_thorin_parse_input_archive_file = failed to parse input archive file - -codegen_ssa_thorin_parse_input_file_kind = failed to parse input file kind - -codegen_ssa_thorin_parse_input_object_file = failed to parse input object file - -codegen_ssa_thorin_parse_unit = failed to parse unit - -codegen_ssa_thorin_parse_unit_abbreviations = failed to parse unit abbreviations - -codegen_ssa_thorin_parse_unit_attribute = failed to parse unit attribute - -codegen_ssa_thorin_parse_unit_header = failed to parse unit header - -codegen_ssa_thorin_read_input_failure = failed to read input file - -codegen_ssa_thorin_relocation_with_invalid_symbol = relocation with invalid symbol for section `{$section}` at offset {$offset} - -codegen_ssa_thorin_row_not_in_index = row {$row} found in index's hash table not present in index - -codegen_ssa_thorin_section_not_in_row = section not found in unit's row in index - -codegen_ssa_thorin_section_without_name = section without name at offset {$offset} - -codegen_ssa_thorin_str_at_offset = read string at offset {$offset} of `.debug_str.dwo` section - -codegen_ssa_thorin_top_level_die_not_unit = top-level debugging information entry is not a compilation/type unit - -codegen_ssa_thorin_unit_not_in_index = unit {$unit} from input package is not in its index - -codegen_ssa_thorin_unsupported_relocation = unsupported relocation for section {$section} at offset {$offset} - -codegen_ssa_unable_to_exe_linker = could not exec the linker `{$linker_path}` - .note = {$error} - .command_note = {$command_formatted} - -codegen_ssa_unable_to_run = unable to run `{$util}`: {$error} - -codegen_ssa_unable_to_run_dsymutil = unable to run `dsymutil`: {$error} - -codegen_ssa_unable_to_write_debugger_visualizer = unable to write debugger visualizer file `{$path}`: {$error} - -codegen_ssa_unknown_archive_kind = - don't know how to build archive of type: {$kind} - -codegen_ssa_unknown_ctarget_feature = - 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 - -codegen_ssa_unknown_ctarget_feature_prefix = - unknown feature specified for `-Ctarget-feature`: `{$feature}` - .note = features must begin with a `+` to enable or `-` to disable it - -codegen_ssa_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified - -codegen_ssa_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_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target - -codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-link-lib) - -codegen_ssa_version_script_write_failure = failed to write version script: {$error} - -codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload - -codegen_ssa_xcrun_about = - the SDK is needed by the linker to know where to find symbols in system libraries and for embedding the SDK version in the final object file - -codegen_ssa_xcrun_command_line_tools_insufficient = - when compiling for iOS, tvOS, visionOS or watchOS, you need a full installation of Xcode - -codegen_ssa_xcrun_failed_invoking = invoking `{$command_formatted}` to find {$sdk_name}.sdk failed: {$error} - -codegen_ssa_xcrun_found_developer_dir = found active developer directory at "{$developer_dir}" - -# `xcrun` already outputs a message about missing Xcode installation, so we only augment it with details about env vars. -codegen_ssa_xcrun_no_developer_dir = - pass the path of an Xcode installation via the DEVELOPER_DIR environment variable, or an SDK with the SDKROOT environment variable - -codegen_ssa_xcrun_sdk_path_warning = output of `xcrun` while finding {$sdk_name}.sdk - .note = {$stderr} - -codegen_ssa_xcrun_unsuccessful = failed running `{$command_formatted}` to find {$sdk_name}.sdk - .note = {$stdout}{$stderr} diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index 23808ade6c85..3ed5793d10c5 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; use std::process::Command; use itertools::Itertools; +use rustc_errors::inline_fluent; use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_session::Session; pub(super) use rustc_target::spec::apple::OSVersion; @@ -10,7 +11,6 @@ use rustc_target::spec::{Arch, Env, Os, Target}; use tracing::debug; use crate::errors::{XcrunError, XcrunSdkPathWarning}; -use crate::fluent_generated as fluent; #[cfg(test)] mod tests; @@ -185,19 +185,21 @@ pub(super) fn get_sdk_root(sess: &Session) -> Option { // FIXME(madsmtm): Make this a lint, to allow deny warnings to work. // (Or fix ). let mut diag = sess.dcx().create_warn(err); - diag.note(fluent::codegen_ssa_xcrun_about); + diag.note(inline_fluent!("the SDK is needed by the linker to know where to find symbols in system libraries and for embedding the SDK version in the final object file")); // Recognize common error cases, and give more Rust-specific error messages for those. if let Some(developer_dir) = xcode_select_developer_dir() { diag.arg("developer_dir", &developer_dir); - diag.note(fluent::codegen_ssa_xcrun_found_developer_dir); + diag.note(inline_fluent!( + "found active developer directory at \"{$developer_dir}\"" + )); if developer_dir.as_os_str().to_string_lossy().contains("CommandLineTools") { if sdk_name != "MacOSX" { - diag.help(fluent::codegen_ssa_xcrun_command_line_tools_insufficient); + diag.help(inline_fluent!("when compiling for iOS, tvOS, visionOS or watchOS, you need a full installation of Xcode")); } } } else { - diag.help(fluent::codegen_ssa_xcrun_no_developer_dir); + diag.help(inline_fluent!("pass the path of an Xcode installation via the DEVELOPER_DIR environment variable, or an SDK with the SDKROOT environment variable")); } diag.emit(); diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index c8109db86e2f..9029c798b64f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -662,7 +662,7 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out } #[derive(LintDiagnostic)] -#[diag(codegen_ssa_linker_output)] +#[diag("{$inner}")] /// Translating this is kind of useless. We don't pass translation flags to the linker, so we'd just /// end up with inconsistent languages within the same diagnostic. struct LinkerOutput { diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 6a97de4c2b13..742e05973ee5 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -9,6 +9,7 @@ use std::process::ExitStatus; use rustc_errors::codes::*; use rustc_errors::{ Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, + inline_fluent, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::layout::LayoutError; @@ -17,10 +18,14 @@ use rustc_span::{Span, Symbol}; use crate::assert_module_sources::CguReuse; use crate::back::command::Command; -use crate::fluent_generated as fluent; #[derive(Diagnostic)] -#[diag(codegen_ssa_incorrect_cgu_reuse_type)] +#[diag( + "CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least -> + [one] {\"at least \"} + *[other] {\"\"} + }`{$expected_reuse}`" +)] pub(crate) struct IncorrectCguReuseType<'a> { #[primary_span] pub span: Span, @@ -31,14 +36,14 @@ pub(crate) struct IncorrectCguReuseType<'a> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_cgu_not_recorded)] +#[diag("CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded")] pub(crate) struct CguNotRecorded<'a> { pub cgu_user_name: &'a str, pub cgu_name: &'a str, } #[derive(Diagnostic)] -#[diag(codegen_ssa_unknown_reuse_kind)] +#[diag("unknown cgu-reuse-kind `{$kind}` specified")] pub(crate) struct UnknownReuseKind { #[primary_span] pub span: Span, @@ -46,14 +51,16 @@ pub(crate) struct UnknownReuseKind { } #[derive(Diagnostic)] -#[diag(codegen_ssa_missing_query_depgraph)] +#[diag("found CGU-reuse attribute but `-Zquery-dep-graph` was not specified")] pub(crate) struct MissingQueryDepGraph { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(codegen_ssa_malformed_cgu_name)] +#[diag( + "found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case)." +)] pub(crate) struct MalformedCguName { #[primary_span] pub span: Span, @@ -62,7 +69,7 @@ pub(crate) struct MalformedCguName { } #[derive(Diagnostic)] -#[diag(codegen_ssa_no_module_named)] +#[diag("no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names}")] pub(crate) struct NoModuleNamed<'a> { #[primary_span] pub span: Span, @@ -72,7 +79,7 @@ pub(crate) struct NoModuleNamed<'a> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_field_associated_value_expected)] +#[diag("associated value expected for `{$name}`")] pub(crate) struct FieldAssociatedValueExpected { #[primary_span] pub span: Span, @@ -80,7 +87,7 @@ pub(crate) struct FieldAssociatedValueExpected { } #[derive(Diagnostic)] -#[diag(codegen_ssa_no_field)] +#[diag("no field `{$name}`")] pub(crate) struct NoField { #[primary_span] pub span: Span, @@ -88,56 +95,56 @@ pub(crate) struct NoField { } #[derive(Diagnostic)] -#[diag(codegen_ssa_lib_def_write_failure)] +#[diag("failed to write lib.def file: {$error}")] pub(crate) struct LibDefWriteFailure { pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_version_script_write_failure)] +#[diag("failed to write version script: {$error}")] pub(crate) struct VersionScriptWriteFailure { pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_symbol_file_write_failure)] +#[diag("failed to write symbols file: {$error}")] pub(crate) struct SymbolFileWriteFailure { pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_ld64_unimplemented_modifier)] +#[diag("`as-needed` modifier not implemented yet for ld64")] pub(crate) struct Ld64UnimplementedModifier; #[derive(Diagnostic)] -#[diag(codegen_ssa_linker_unsupported_modifier)] +#[diag("`as-needed` modifier not supported for current linker")] pub(crate) struct LinkerUnsupportedModifier; #[derive(Diagnostic)] -#[diag(codegen_ssa_L4Bender_exporting_symbols_unimplemented)] +#[diag("exporting symbols not implemented yet for L4Bender")] pub(crate) struct L4BenderExportingSymbolsUnimplemented; #[derive(Diagnostic)] -#[diag(codegen_ssa_no_natvis_directory)] +#[diag("error enumerating natvis directory: {$error}")] pub(crate) struct NoNatvisDirectory { pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_no_saved_object_file)] +#[diag("cached cgu {$cgu_name} should have an object file, but doesn't")] pub(crate) struct NoSavedObjectFile<'a> { pub cgu_name: &'a str, } #[derive(Diagnostic)] -#[diag(codegen_ssa_requires_rust_abi, code = E0737)] +#[diag("`#[track_caller]` requires Rust ABI", code = E0737)] pub(crate) struct RequiresRustAbi { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(codegen_ssa_copy_path_buf)] +#[diag("unable to copy {$source_file} to {$output_path}: {$error}")] pub(crate) struct CopyPathBuf { pub source_file: PathBuf, pub output_path: PathBuf, @@ -146,7 +153,7 @@ pub(crate) struct CopyPathBuf { // Reports Paths using `Debug` implementation rather than Path's `Display` implementation. #[derive(Diagnostic)] -#[diag(codegen_ssa_copy_path)] +#[diag("could not copy {$from} to {$to}: {$error}")] pub struct CopyPath<'a> { from: DebugArgPath<'a>, to: DebugArgPath<'a>, @@ -168,38 +175,42 @@ impl IntoDiagArg for DebugArgPath<'_> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_binary_output_to_tty)] +#[diag( + "option `-o` or `--emit` is used to write binary output type `{$shorthand}` to stdout, but stdout is a tty" +)] pub struct BinaryOutputToTty { pub shorthand: &'static str, } #[derive(Diagnostic)] -#[diag(codegen_ssa_ignoring_emit_path)] +#[diag("ignoring emit path because multiple .{$extension} files were produced")] pub struct IgnoringEmitPath { pub extension: &'static str, } #[derive(Diagnostic)] -#[diag(codegen_ssa_ignoring_output)] +#[diag("ignoring -o because multiple .{$extension} files were produced")] pub struct IgnoringOutput { pub extension: &'static str, } #[derive(Diagnostic)] -#[diag(codegen_ssa_create_temp_dir)] +#[diag("couldn't create a temp dir: {$error}")] pub(crate) struct CreateTempDir { pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_add_native_library)] +#[diag("failed to add native library {$library_path}: {$error}")] pub(crate) struct AddNativeLibrary { pub library_path: PathBuf, pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_multiple_external_func_decl)] +#[diag( + "multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions" +)] pub(crate) struct MultipleExternalFuncDecl<'a> { #[primary_span] pub span: Span, @@ -209,16 +220,18 @@ pub(crate) struct MultipleExternalFuncDecl<'a> { #[derive(Diagnostic)] pub enum LinkRlibError { - #[diag(codegen_ssa_rlib_missing_format)] + #[diag("could not find formats for rlibs")] MissingFormat, - #[diag(codegen_ssa_rlib_only_rmeta_found)] + #[diag("could not find rlib for: `{$crate_name}`, found rmeta (metadata) file")] OnlyRmetaFound { crate_name: Symbol }, - #[diag(codegen_ssa_rlib_not_found)] + #[diag("could not find rlib for: `{$crate_name}`")] NotFound { crate_name: Symbol }, - #[diag(codegen_ssa_rlib_incompatible_dependency_formats)] + #[diag( + "`{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`)" + )] IncompatibleDependencyFormats { ty1: String, ty2: String, list1: String, list2: String }, } @@ -228,122 +241,122 @@ impl Diagnostic<'_, G> for ThorinErrorWrapper { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { let build = |msg| Diag::new(dcx, level, msg); match self.0 { - thorin::Error::ReadInput(_) => build(fluent::codegen_ssa_thorin_read_input_failure), + thorin::Error::ReadInput(_) => build(inline_fluent!("failed to read input file")), thorin::Error::ParseFileKind(_) => { - build(fluent::codegen_ssa_thorin_parse_input_file_kind) + build(inline_fluent!("failed to parse input file kind")) } thorin::Error::ParseObjectFile(_) => { - build(fluent::codegen_ssa_thorin_parse_input_object_file) + build(inline_fluent!("failed to parse input object file")) } thorin::Error::ParseArchiveFile(_) => { - build(fluent::codegen_ssa_thorin_parse_input_archive_file) + build(inline_fluent!("failed to parse input archive file")) } thorin::Error::ParseArchiveMember(_) => { - build(fluent::codegen_ssa_thorin_parse_archive_member) + build(inline_fluent!("failed to parse archive member")) } - thorin::Error::InvalidInputKind => build(fluent::codegen_ssa_thorin_invalid_input_kind), - thorin::Error::DecompressData(_) => build(fluent::codegen_ssa_thorin_decompress_data), + thorin::Error::InvalidInputKind => build(inline_fluent!("input is not an archive or elf object")), + thorin::Error::DecompressData(_) => build(inline_fluent!("failed to decompress compressed section")), thorin::Error::NamelessSection(_, offset) => { - build(fluent::codegen_ssa_thorin_section_without_name) + build(inline_fluent!("section without name at offset {$offset}")) .with_arg("offset", format!("0x{offset:08x}")) } thorin::Error::RelocationWithInvalidSymbol(section, offset) => { - build(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol) + build(inline_fluent!("relocation with invalid symbol for section `{$section}` at offset {$offset}")) .with_arg("section", section) .with_arg("offset", format!("0x{offset:08x}")) } thorin::Error::MultipleRelocations(section, offset) => { - build(fluent::codegen_ssa_thorin_multiple_relocations) + build(inline_fluent!("multiple relocations for section `{$section}` at offset {$offset}")) .with_arg("section", section) .with_arg("offset", format!("0x{offset:08x}")) } thorin::Error::UnsupportedRelocation(section, offset) => { - build(fluent::codegen_ssa_thorin_unsupported_relocation) + build(inline_fluent!("unsupported relocation for section {$section} at offset {$offset}")) .with_arg("section", section) .with_arg("offset", format!("0x{offset:08x}")) } - thorin::Error::MissingDwoName(id) => build(fluent::codegen_ssa_thorin_missing_dwo_name) + thorin::Error::MissingDwoName(id) => build(inline_fluent!("missing path attribute to DWARF object ({$id})")) .with_arg("id", format!("0x{id:08x}")), thorin::Error::NoCompilationUnits => { - build(fluent::codegen_ssa_thorin_no_compilation_units) + build(inline_fluent!("input object has no compilation units")) } - thorin::Error::NoDie => build(fluent::codegen_ssa_thorin_no_die), + thorin::Error::NoDie => build(inline_fluent!("no top-level debugging information entry in compilation/type unit")), thorin::Error::TopLevelDieNotUnit => { - build(fluent::codegen_ssa_thorin_top_level_die_not_unit) + build(inline_fluent!("top-level debugging information entry is not a compilation/type unit")) } thorin::Error::MissingRequiredSection(section) => { - build(fluent::codegen_ssa_thorin_missing_required_section) + build(inline_fluent!("input object missing required section `{$section}`")) .with_arg("section", section) } thorin::Error::ParseUnitAbbreviations(_) => { - build(fluent::codegen_ssa_thorin_parse_unit_abbreviations) + build(inline_fluent!("failed to parse unit abbreviations")) } thorin::Error::ParseUnitAttribute(_) => { - build(fluent::codegen_ssa_thorin_parse_unit_attribute) + build(inline_fluent!("failed to parse unit attribute")) } thorin::Error::ParseUnitHeader(_) => { - build(fluent::codegen_ssa_thorin_parse_unit_header) + build(inline_fluent!("failed to parse unit header")) } - thorin::Error::ParseUnit(_) => build(fluent::codegen_ssa_thorin_parse_unit), + thorin::Error::ParseUnit(_) => build(inline_fluent!("failed to parse unit")), thorin::Error::IncompatibleIndexVersion(section, format, actual) => { - build(fluent::codegen_ssa_thorin_incompatible_index_version) + build(inline_fluent!("incompatible `{$section}` index version: found version {$actual}, expected version {$format}")) .with_arg("section", section) .with_arg("actual", actual) .with_arg("format", format) } thorin::Error::OffsetAtIndex(_, index) => { - build(fluent::codegen_ssa_thorin_offset_at_index).with_arg("index", index) + build(inline_fluent!("read offset at index {$index} of `.debug_str_offsets.dwo` section")).with_arg("index", index) } thorin::Error::StrAtOffset(_, offset) => { - build(fluent::codegen_ssa_thorin_str_at_offset) + build(inline_fluent!("read string at offset {$offset} of `.debug_str.dwo` section")) .with_arg("offset", format!("0x{offset:08x}")) } thorin::Error::ParseIndex(_, section) => { - build(fluent::codegen_ssa_thorin_parse_index).with_arg("section", section) + build(inline_fluent!("failed to parse `{$section}` index section")).with_arg("section", section) } thorin::Error::UnitNotInIndex(unit) => { - build(fluent::codegen_ssa_thorin_unit_not_in_index) + build(inline_fluent!("unit {$unit} from input package is not in its index")) .with_arg("unit", format!("0x{unit:08x}")) } thorin::Error::RowNotInIndex(_, row) => { - build(fluent::codegen_ssa_thorin_row_not_in_index).with_arg("row", row) + build(inline_fluent!("row {$row} found in index's hash table not present in index")).with_arg("row", row) } - thorin::Error::SectionNotInRow => build(fluent::codegen_ssa_thorin_section_not_in_row), - thorin::Error::EmptyUnit(unit) => build(fluent::codegen_ssa_thorin_empty_unit) + thorin::Error::SectionNotInRow => build(inline_fluent!("section not found in unit's row in index")), + thorin::Error::EmptyUnit(unit) => build(inline_fluent!("unit {$unit} in input DWARF object with no data")) .with_arg("unit", format!("0x{unit:08x}")), thorin::Error::MultipleDebugInfoSection => { - build(fluent::codegen_ssa_thorin_multiple_debug_info_section) + build(inline_fluent!("multiple `.debug_info.dwo` sections")) } thorin::Error::MultipleDebugTypesSection => { - build(fluent::codegen_ssa_thorin_multiple_debug_types_section) + build(inline_fluent!("multiple `.debug_types.dwo` sections in a package")) } - thorin::Error::NotSplitUnit => build(fluent::codegen_ssa_thorin_not_split_unit), - thorin::Error::DuplicateUnit(unit) => build(fluent::codegen_ssa_thorin_duplicate_unit) + thorin::Error::NotSplitUnit => build(inline_fluent!("regular compilation unit in object (missing dwo identifier)")), + thorin::Error::DuplicateUnit(unit) => build(inline_fluent!("duplicate split compilation unit ({$unit})")) .with_arg("unit", format!("0x{unit:08x}")), thorin::Error::MissingReferencedUnit(unit) => { - build(fluent::codegen_ssa_thorin_missing_referenced_unit) + build(inline_fluent!("unit {$unit} referenced by executable was not found")) .with_arg("unit", format!("0x{unit:08x}")) } thorin::Error::NoOutputObjectCreated => { - build(fluent::codegen_ssa_thorin_not_output_object_created) + build(inline_fluent!("no output object was created from inputs")) } thorin::Error::MixedInputEncodings => { - build(fluent::codegen_ssa_thorin_mixed_input_encodings) + build(inline_fluent!("input objects have mixed encodings")) } thorin::Error::Io(e) => { - build(fluent::codegen_ssa_thorin_io).with_arg("error", format!("{e}")) + build(inline_fluent!("{$error}")).with_arg("error", format!("{e}")) } thorin::Error::ObjectRead(e) => { - build(fluent::codegen_ssa_thorin_object_read).with_arg("error", format!("{e}")) + build(inline_fluent!("{$error}")).with_arg("error", format!("{e}")) } thorin::Error::ObjectWrite(e) => { - build(fluent::codegen_ssa_thorin_object_write).with_arg("error", format!("{e}")) + build(inline_fluent!("{$error}")).with_arg("error", format!("{e}")) } thorin::Error::GimliRead(e) => { - build(fluent::codegen_ssa_thorin_gimli_read).with_arg("error", format!("{e}")) + build(inline_fluent!("{$error}")).with_arg("error", format!("{e}")) } thorin::Error::GimliWrite(e) => { - build(fluent::codegen_ssa_thorin_gimli_write).with_arg("error", format!("{e}")) + build(inline_fluent!("{$error}")).with_arg("error", format!("{e}")) } _ => unimplemented!("Untranslated thorin error"), } @@ -361,7 +374,11 @@ pub(crate) struct LinkingFailed<'a> { impl Diagnostic<'_, G> for LinkingFailed<'_> { fn into_diag(mut self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::codegen_ssa_linking_failed); + let mut diag = Diag::new( + dcx, + level, + inline_fluent!("linking with `{$linker_path}` failed: {$exit_status}"), + ); diag.arg("linker_path", format!("{}", self.linker_path.display())); diag.arg("exit_status", format!("{}", self.exit_status)); @@ -470,11 +487,11 @@ impl Diagnostic<'_, G> for LinkingFailed<'_> { // Trying to match an error from OS linkers // which by now we have no way to translate. if contains_undefined_ref { - diag.note(fluent::codegen_ssa_extern_funcs_not_found) - .note(fluent::codegen_ssa_specify_libraries_to_link); + diag.note(inline_fluent!("some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified")) + .note(inline_fluent!("use the `-l` flag to specify native libraries to link")); if rustc_session::utils::was_invoked_from_cargo() { - diag.note(fluent::codegen_ssa_use_cargo_directive); + diag.note(inline_fluent!("use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-link-lib)")); } } diag @@ -482,7 +499,7 @@ impl Diagnostic<'_, G> for LinkingFailed<'_> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_link_exe_unexpected_error)] +#[diag("`link.exe` returned an unexpected error")] pub(crate) struct LinkExeUnexpectedError; pub(crate) struct LinkExeStatusStackBufferOverrun; @@ -490,41 +507,43 @@ pub(crate) struct LinkExeStatusStackBufferOverrun; impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for LinkExeStatusStackBufferOverrun { fn into_diag(self, dcx: rustc_errors::DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let mut diag = - Diag::new(dcx, level, fluent::codegen_ssa_link_exe_status_stack_buffer_overrun); - diag.note(fluent::codegen_ssa_abort_note); - diag.note(fluent::codegen_ssa_event_log_note); + Diag::new(dcx, level, inline_fluent!("0xc0000409 is `STATUS_STACK_BUFFER_OVERRUN`")); + diag.note(inline_fluent!( + "this may have been caused by a program abort and not a stack buffer overrun" + )); + diag.note(inline_fluent!("consider checking the Application Event Log for Windows Error Reporting events to see the fail fast error code")); diag } } #[derive(Diagnostic)] -#[diag(codegen_ssa_repair_vs_build_tools)] +#[diag("the Visual Studio build tools may need to be repaired using the Visual Studio installer")] pub(crate) struct RepairVSBuildTools; #[derive(Diagnostic)] -#[diag(codegen_ssa_missing_cpp_build_tool_component)] +#[diag("or a necessary component may be missing from the \"C++ build tools\" workload")] pub(crate) struct MissingCppBuildToolComponent; #[derive(Diagnostic)] -#[diag(codegen_ssa_select_cpp_build_tool_workload)] +#[diag("in the Visual Studio installer, ensure the \"C++ build tools\" workload is selected")] pub(crate) struct SelectCppBuildToolWorkload; #[derive(Diagnostic)] -#[diag(codegen_ssa_visual_studio_not_installed)] +#[diag("you may need to install Visual Studio build tools with the \"C++ build tools\" workload")] pub(crate) struct VisualStudioNotInstalled; #[derive(Diagnostic)] -#[diag(codegen_ssa_linker_not_found)] -#[note] +#[diag("linker `{$linker_path}` not found")] +#[note("{$error}")] pub(crate) struct LinkerNotFound { pub linker_path: PathBuf, pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_unable_to_exe_linker)] -#[note] -#[note(codegen_ssa_command_note)] +#[diag("could not exec the linker `{$linker_path}`")] +#[note("{$error}")] +#[note("{$command_formatted}")] pub(crate) struct UnableToExeLinker { pub linker_path: PathBuf, pub error: Error, @@ -532,42 +551,46 @@ pub(crate) struct UnableToExeLinker { } #[derive(Diagnostic)] -#[diag(codegen_ssa_msvc_missing_linker)] +#[diag("the msvc targets depend on the msvc linker but `link.exe` was not found")] pub(crate) struct MsvcMissingLinker; #[derive(Diagnostic)] -#[diag(codegen_ssa_self_contained_linker_missing)] +#[diag( + "the self-contained linker was requested, but it wasn't found in the target's sysroot, or in rustc's sysroot" +)] pub(crate) struct SelfContainedLinkerMissing; #[derive(Diagnostic)] -#[diag(codegen_ssa_check_installed_visual_studio)] +#[diag( + "please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option." +)] pub(crate) struct CheckInstalledVisualStudio; #[derive(Diagnostic)] -#[diag(codegen_ssa_insufficient_vs_code_product)] +#[diag("VS Code is a different product, and is not sufficient.")] pub(crate) struct InsufficientVSCodeProduct; #[derive(Diagnostic)] -#[diag(codegen_ssa_cpu_required)] +#[diag("target requires explicitly specifying a cpu with `-C target-cpu`")] pub(crate) struct CpuRequired; #[derive(Diagnostic)] -#[diag(codegen_ssa_processing_dymutil_failed)] -#[note] +#[diag("processing debug info with `dsymutil` failed: {$status}")] +#[note("{$output}")] pub(crate) struct ProcessingDymutilFailed { pub status: ExitStatus, pub output: String, } #[derive(Diagnostic)] -#[diag(codegen_ssa_unable_to_run_dsymutil)] +#[diag("unable to run `dsymutil`: {$error}")] pub(crate) struct UnableToRunDsymutil { pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_stripping_debug_info_failed)] -#[note] +#[diag("stripping debug info with `{$util}` failed: {$status}")] +#[note("{$output}")] pub(crate) struct StrippingDebugInfoFailed<'a> { pub util: &'a str, pub status: ExitStatus, @@ -575,53 +598,57 @@ pub(crate) struct StrippingDebugInfoFailed<'a> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_unable_to_run)] +#[diag("unable to run `{$util}`: {$error}")] pub(crate) struct UnableToRun<'a> { pub util: &'a str, pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_linker_file_stem)] +#[diag("couldn't extract file stem from specified linker")] pub(crate) struct LinkerFileStem; #[derive(Diagnostic)] -#[diag(codegen_ssa_static_library_native_artifacts)] +#[diag( + "link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms." +)] pub(crate) struct StaticLibraryNativeArtifacts; #[derive(Diagnostic)] -#[diag(codegen_ssa_static_library_native_artifacts_to_file)] +#[diag( + "native artifacts to link against have been written to {$path}. The order and any duplication can be significant on some platforms." +)] pub(crate) struct StaticLibraryNativeArtifactsToFile<'a> { pub path: &'a Path, } #[derive(Diagnostic)] -#[diag(codegen_ssa_link_script_unavailable)] +#[diag("can only use link script when linking with GNU-like linker")] pub(crate) struct LinkScriptUnavailable; #[derive(Diagnostic)] -#[diag(codegen_ssa_link_script_write_failure)] +#[diag("failed to write link script to {$path}: {$error}")] pub(crate) struct LinkScriptWriteFailure { pub path: PathBuf, pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_failed_to_write)] +#[diag("failed to write {$path}: {$error}")] pub(crate) struct FailedToWrite { pub path: PathBuf, pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_unable_to_write_debugger_visualizer)] +#[diag("unable to write debugger visualizer file `{$path}`: {$error}")] pub(crate) struct UnableToWriteDebuggerVisualizer { pub path: PathBuf, pub error: Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_rlib_archive_build_failure)] +#[diag("failed to build archive from rlib at `{$path}`: {$error}")] pub(crate) struct RlibArchiveBuildFailure { pub path: PathBuf, pub error: Error, @@ -630,68 +657,70 @@ pub(crate) struct RlibArchiveBuildFailure { #[derive(Diagnostic)] // Public for ArchiveBuilderBuilder::extract_bundled_libs pub enum ExtractBundledLibsError<'a> { - #[diag(codegen_ssa_extract_bundled_libs_open_file)] + #[diag("failed to open file '{$rlib}': {$error}")] OpenFile { rlib: &'a Path, error: Box }, - #[diag(codegen_ssa_extract_bundled_libs_mmap_file)] + #[diag("failed to mmap file '{$rlib}': {$error}")] MmapFile { rlib: &'a Path, error: Box }, - #[diag(codegen_ssa_extract_bundled_libs_parse_archive)] + #[diag("failed to parse archive '{$rlib}': {$error}")] ParseArchive { rlib: &'a Path, error: Box }, - #[diag(codegen_ssa_extract_bundled_libs_read_entry)] + #[diag("failed to read entry '{$rlib}': {$error}")] ReadEntry { rlib: &'a Path, error: Box }, - #[diag(codegen_ssa_extract_bundled_libs_archive_member)] + #[diag("failed to get data from archive member '{$rlib}': {$error}")] ArchiveMember { rlib: &'a Path, error: Box }, - #[diag(codegen_ssa_extract_bundled_libs_convert_name)] + #[diag("failed to convert name '{$rlib}': {$error}")] ConvertName { rlib: &'a Path, error: Box }, - #[diag(codegen_ssa_extract_bundled_libs_write_file)] + #[diag("failed to write file '{$rlib}': {$error}")] WriteFile { rlib: &'a Path, error: Box }, - #[diag(codegen_ssa_extract_bundled_libs_write_file)] + #[diag("failed to write file '{$rlib}': {$error}")] ExtractSection { rlib: &'a Path, error: Box }, } #[derive(Diagnostic)] -#[diag(codegen_ssa_read_file)] +#[diag("failed to read file: {$message}")] pub(crate) struct ReadFileError { pub message: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_unsupported_link_self_contained)] +#[diag("option `-C link-self-contained` is not supported on this target")] pub(crate) struct UnsupportedLinkSelfContained; #[derive(Diagnostic)] -#[diag(codegen_ssa_archive_build_failure)] +#[diag("failed to build archive at `{$path}`: {$error}")] pub(crate) struct ArchiveBuildFailure { pub path: PathBuf, pub error: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_unknown_archive_kind)] +#[diag("don't know how to build archive of type: {$kind}")] pub(crate) struct UnknownArchiveKind<'a> { pub kind: &'a str, } #[derive(Diagnostic)] -#[diag(codegen_ssa_bpf_staticlib_not_supported)] +#[diag("linking static libraries is not supported for BPF")] pub(crate) struct BpfStaticlibNotSupported; #[derive(Diagnostic)] -#[diag(codegen_ssa_multiple_main_functions)] -#[help] +#[diag("entry symbol `main` declared multiple times")] +#[help( + "did you use `#[no_mangle]` on `fn main`? Use `#![no_main]` to suppress the usual Rust-generated entry point" +)] pub(crate) struct MultipleMainFunctions { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(codegen_ssa_shuffle_indices_evaluation)] +#[diag("could not evaluate shuffle_indices at compile time")] pub(crate) struct ShuffleIndicesEvaluation { #[primary_span] pub span: Span, @@ -699,7 +728,7 @@ pub(crate) struct ShuffleIndicesEvaluation { #[derive(Diagnostic)] pub enum InvalidMonomorphization<'tcx> { - #[diag(codegen_ssa_invalid_monomorphization_basic_integer_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`", code = E0511)] BasicIntegerType { #[primary_span] span: Span, @@ -707,7 +736,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_basic_integer_or_ptr_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected basic integer or pointer type, found `{$ty}`", code = E0511)] BasicIntegerOrPtrType { #[primary_span] span: Span, @@ -715,7 +744,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_basic_float_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}`", code = E0511)] BasicFloatType { #[primary_span] span: Span, @@ -723,14 +752,14 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_float_to_int_unchecked, code = E0511)] + #[diag("invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}`", code = E0511)] FloatToIntUnchecked { #[primary_span] span: Span, ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_floating_point_vector, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}`", code = E0511)] FloatingPointVector { #[primary_span] span: Span, @@ -739,7 +768,7 @@ pub enum InvalidMonomorphization<'tcx> { in_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_floating_point_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type", code = E0511)] FloatingPointType { #[primary_span] span: Span, @@ -747,14 +776,14 @@ pub enum InvalidMonomorphization<'tcx> { in_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_unrecognized_intrinsic, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`", code = E0511)] UnrecognizedIntrinsic { #[primary_span] span: Span, name: Symbol, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_argument, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}`", code = E0511)] SimdArgument { #[primary_span] span: Span, @@ -762,7 +791,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_input, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}`", code = E0511)] SimdInput { #[primary_span] span: Span, @@ -770,7 +799,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_first, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}`", code = E0511)] SimdFirst { #[primary_span] span: Span, @@ -778,7 +807,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_second, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}`", code = E0511)] SimdSecond { #[primary_span] span: Span, @@ -786,7 +815,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_third, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}`", code = E0511)] SimdThird { #[primary_span] span: Span, @@ -794,7 +823,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_return, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}`", code = E0511)] SimdReturn { #[primary_span] span: Span, @@ -802,7 +831,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_invalid_bitmask, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`", code = E0511)] InvalidBitmask { #[primary_span] span: Span, @@ -812,7 +841,7 @@ pub enum InvalidMonomorphization<'tcx> { expected_bytes: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_return_length_input_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}", code = E0511)] ReturnLengthInputType { #[primary_span] span: Span, @@ -823,7 +852,7 @@ pub enum InvalidMonomorphization<'tcx> { out_len: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_second_argument_length, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}", code = E0511)] SecondArgumentLength { #[primary_span] span: Span, @@ -834,7 +863,7 @@ pub enum InvalidMonomorphization<'tcx> { out_len: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_third_argument_length, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}", code = E0511)] ThirdArgumentLength { #[primary_span] span: Span, @@ -845,7 +874,7 @@ pub enum InvalidMonomorphization<'tcx> { out_len: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_return_integer_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`", code = E0511)] ReturnIntegerType { #[primary_span] span: Span, @@ -854,7 +883,7 @@ pub enum InvalidMonomorphization<'tcx> { out_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_shuffle, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be a SIMD vector of `u32`, got `{$ty}`", code = E0511)] SimdShuffle { #[primary_span] span: Span, @@ -862,7 +891,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_return_length, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}", code = E0511)] ReturnLength { #[primary_span] span: Span, @@ -872,7 +901,7 @@ pub enum InvalidMonomorphization<'tcx> { out_len: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_return_element, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`", code = E0511)] ReturnElement { #[primary_span] span: Span, @@ -883,7 +912,7 @@ pub enum InvalidMonomorphization<'tcx> { out_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_simd_index_out_of_bounds, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: SIMD index #{$arg_idx} is out of bounds (limit {$total_len})", code = E0511)] SimdIndexOutOfBounds { #[primary_span] span: Span, @@ -892,7 +921,7 @@ pub enum InvalidMonomorphization<'tcx> { total_len: u128, }, - #[diag(codegen_ssa_invalid_monomorphization_inserted_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`", code = E0511)] InsertedType { #[primary_span] span: Span, @@ -902,7 +931,7 @@ pub enum InvalidMonomorphization<'tcx> { out_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_return_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`", code = E0511)] ReturnType { #[primary_span] span: Span, @@ -912,7 +941,7 @@ pub enum InvalidMonomorphization<'tcx> { ret_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_expected_return_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}`", code = E0511)] ExpectedReturnType { #[primary_span] span: Span, @@ -921,7 +950,7 @@ pub enum InvalidMonomorphization<'tcx> { ret_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_mismatched_lengths, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`", code = E0511)] MismatchedLengths { #[primary_span] span: Span, @@ -930,7 +959,7 @@ pub enum InvalidMonomorphization<'tcx> { v_len: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_mask_wrong_element_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected mask element type to be an integer, found `{$ty}`", code = E0511)] MaskWrongElementType { #[primary_span] span: Span, @@ -938,7 +967,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_cannot_return, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`", code = E0511)] CannotReturn { #[primary_span] span: Span, @@ -948,7 +977,7 @@ pub enum InvalidMonomorphization<'tcx> { expected_bytes: u64, }, - #[diag(codegen_ssa_invalid_monomorphization_expected_element_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}`", code = E0511)] ExpectedElementType { #[primary_span] span: Span, @@ -960,7 +989,7 @@ pub enum InvalidMonomorphization<'tcx> { mutability: ExpectedPointerMutability, }, - #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}`", code = E0511)] UnsupportedSymbolOfSize { #[primary_span] span: Span, @@ -972,7 +1001,7 @@ pub enum InvalidMonomorphization<'tcx> { ret_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}`", code = E0511)] UnsupportedSymbol { #[primary_span] span: Span, @@ -983,7 +1012,7 @@ pub enum InvalidMonomorphization<'tcx> { ret_ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_cast_wide_pointer, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: cannot cast wide pointer `{$ty}`", code = E0511)] CastWidePointer { #[primary_span] span: Span, @@ -991,7 +1020,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_expected_pointer, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}`", code = E0511)] ExpectedPointer { #[primary_span] span: Span, @@ -999,7 +1028,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_expected_usize, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}`", code = E0511)] ExpectedUsize { #[primary_span] span: Span, @@ -1007,7 +1036,7 @@ pub enum InvalidMonomorphization<'tcx> { ty: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_unsupported_cast, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`", code = E0511)] UnsupportedCast { #[primary_span] span: Span, @@ -1018,7 +1047,7 @@ pub enum InvalidMonomorphization<'tcx> { out_elem: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_unsupported_operation, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`", code = E0511)] UnsupportedOperation { #[primary_span] span: Span, @@ -1027,7 +1056,7 @@ pub enum InvalidMonomorphization<'tcx> { in_elem: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_expected_vector_element_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type", code = E0511)] ExpectedVectorElementType { #[primary_span] span: Span, @@ -1036,7 +1065,7 @@ pub enum InvalidMonomorphization<'tcx> { vector_type: Ty<'tcx>, }, - #[diag(codegen_ssa_invalid_monomorphization_non_scalable_type, code = E0511)] + #[diag("invalid monomorphization of `{$name}` intrinsic: expected non-scalable type, found scalable type `{$ty}`", code = E0511)] NonScalableType { #[primary_span] span: Span, @@ -1060,17 +1089,17 @@ impl IntoDiagArg for ExpectedPointerMutability { } #[derive(Diagnostic)] -#[diag(codegen_ssa_target_feature_safe_trait)] +#[diag("`#[target_feature(..)]` cannot be applied to safe trait method")] pub(crate) struct TargetFeatureSafeTrait { #[primary_span] - #[label] + #[label("cannot be applied to safe trait method")] pub span: Span, - #[label(codegen_ssa_label_def)] + #[label("not an `unsafe` function")] pub def: Span, } #[derive(Diagnostic)] -#[diag(codegen_ssa_forbidden_target_feature_attr)] +#[diag("target feature `{$feature}` cannot be enabled with `#[target_feature]`: {$reason}")] pub struct ForbiddenTargetFeatureAttr<'a> { #[primary_span] pub span: Span, @@ -1079,7 +1108,7 @@ pub struct ForbiddenTargetFeatureAttr<'a> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_failed_to_get_layout)] +#[diag("failed to get layout for {$ty}: {$err}")] pub struct FailedToGetLayout<'tcx> { #[primary_span] pub span: Span, @@ -1088,7 +1117,11 @@ pub struct FailedToGetLayout<'tcx> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_dlltool_fail_import_library)] +#[diag( + "dlltool could not create import library with {$dlltool_path} {$dlltool_args}: +{$stdout} +{$stderr}" +)] pub(crate) struct DlltoolFailImportLibrary<'a> { pub dlltool_path: Cow<'a, str>, pub dlltool_args: String, @@ -1097,26 +1130,28 @@ pub(crate) struct DlltoolFailImportLibrary<'a> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_error_writing_def_file)] +#[diag("error writing .DEF file: {$error}")] pub(crate) struct ErrorWritingDEFFile { pub error: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_error_calling_dlltool)] +#[diag("error calling dlltool '{$dlltool_path}': {$error}")] pub(crate) struct ErrorCallingDllTool<'a> { pub dlltool_path: Cow<'a, str>, pub error: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_error_creating_remark_dir)] +#[diag("failed to create remark directory: {$error}")] pub(crate) struct ErrorCreatingRemarkDir { pub error: std::io::Error, } #[derive(Diagnostic)] -#[diag(codegen_ssa_compiler_builtins_cannot_call)] +#[diag( + "`compiler_builtins` cannot call functions through upstream monomorphizations; encountered invalid call from `{$caller}` to `{$callee}`" +)] pub struct CompilerBuiltinsCannotCall { pub caller: String, pub callee: String, @@ -1125,23 +1160,23 @@ pub struct CompilerBuiltinsCannotCall { } #[derive(Diagnostic)] -#[diag(codegen_ssa_error_creating_import_library)] +#[diag("error creating import library for {$lib_name}: {$error}")] pub(crate) struct ErrorCreatingImportLibrary<'a> { pub lib_name: &'a str, pub error: String, } #[derive(Diagnostic)] -#[diag(codegen_ssa_aix_strip_not_used)] +#[diag("using host's `strip` binary to cross-compile to AIX which is not guaranteed to work")] pub(crate) struct AixStripNotUsed; #[derive(Diagnostic, Debug)] pub(crate) enum XcrunError { - #[diag(codegen_ssa_xcrun_failed_invoking)] + #[diag("invoking `{$command_formatted}` to find {$sdk_name}.sdk failed: {$error}")] FailedInvoking { sdk_name: &'static str, command_formatted: String, error: std::io::Error }, - #[diag(codegen_ssa_xcrun_unsuccessful)] - #[note] + #[diag("failed running `{$command_formatted}` to find {$sdk_name}.sdk")] + #[note("{$stdout}{$stderr}")] Unsuccessful { sdk_name: &'static str, command_formatted: String, @@ -1151,35 +1186,37 @@ pub(crate) enum XcrunError { } #[derive(Diagnostic, Debug)] -#[diag(codegen_ssa_xcrun_sdk_path_warning)] -#[note] +#[diag("output of `xcrun` while finding {$sdk_name}.sdk")] +#[note("{$stderr}")] pub(crate) struct XcrunSdkPathWarning { pub sdk_name: &'static str, pub stderr: String, } #[derive(LintDiagnostic)] -#[diag(codegen_ssa_aarch64_softfloat_neon)] +#[diag("enabling the `neon` target feature on the current target is unsound due to ABI issues")] pub(crate) struct Aarch64SoftfloatNeon; #[derive(Diagnostic)] -#[diag(codegen_ssa_unknown_ctarget_feature_prefix)] -#[note] +#[diag("unknown feature specified for `-Ctarget-feature`: `{$feature}`")] +#[note("features must begin with a `+` to enable or `-` to disable it")] pub(crate) struct UnknownCTargetFeaturePrefix<'a> { pub feature: &'a str, } #[derive(Subdiagnostic)] pub(crate) enum PossibleFeature<'a> { - #[help(codegen_ssa_possible_feature)] + #[help("you might have meant: `{$rust_feature}`")] Some { rust_feature: &'a str }, - #[help(codegen_ssa_consider_filing_feature_request)] + #[help("consider filing a feature request")] None, } #[derive(Diagnostic)] -#[diag(codegen_ssa_unknown_ctarget_feature)] -#[note] +#[diag("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" +)] pub(crate) struct UnknownCTargetFeature<'a> { pub feature: &'a str, #[subdiagnostic] @@ -1187,16 +1224,18 @@ pub(crate) struct UnknownCTargetFeature<'a> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_unstable_ctarget_feature)] -#[note] +#[diag("unstable feature specified for `-Ctarget-feature`: `{$feature}`")] +#[note("this feature is not stably supported; its behavior can change in the future")] pub(crate) struct UnstableCTargetFeature<'a> { pub feature: &'a str, } #[derive(Diagnostic)] -#[diag(codegen_ssa_forbidden_ctarget_feature)] -#[note] -#[note(codegen_ssa_forbidden_ctarget_feature_issue)] +#[diag("target feature `{$feature}` cannot be {$enabled} with `-Ctarget-feature`: {$reason}")] +#[note( + "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 #116344 ")] pub(crate) struct ForbiddenCTargetFeature<'a> { pub feature: &'a str, pub enabled: &'a str, @@ -1210,12 +1249,18 @@ pub struct TargetFeatureDisableOrEnable<'a> { } #[derive(Subdiagnostic)] -#[help(codegen_ssa_missing_features)] +#[help("add the missing features in a `target_feature` attribute")] pub struct MissingFeatures; impl Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::codegen_ssa_target_feature_disable_or_enable); + let mut diag = Diag::new( + dcx, + level, + inline_fluent!( + "the target features {$features} must all be either enabled or disabled together" + ), + ); if let Some(span) = self.span { diag.span(span); }; @@ -1228,29 +1273,29 @@ impl Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_ } #[derive(Diagnostic)] -#[diag(codegen_ssa_feature_not_valid)] +#[diag("the feature named `{$feature}` is not valid for this target")] pub(crate) struct FeatureNotValid<'a> { pub feature: &'a str, #[primary_span] - #[label] + #[label("`{$feature}` is not valid for this target")] pub span: Span, - #[help] + #[help("consider removing the leading `+` in the feature name")] pub plus_hint: bool, } #[derive(Diagnostic)] -#[diag(codegen_ssa_lto_disallowed)] +#[diag("lto can only be run for executables, cdylibs and static library outputs")] pub(crate) struct LtoDisallowed; #[derive(Diagnostic)] -#[diag(codegen_ssa_lto_dylib)] +#[diag("lto cannot be used for `dylib` crate type without `-Zdylib-lto`")] pub(crate) struct LtoDylib; #[derive(Diagnostic)] -#[diag(codegen_ssa_lto_proc_macro)] +#[diag("lto cannot be used for `proc-macro` crate type without `-Zdylib-lto`")] pub(crate) struct LtoProcMacro; #[derive(Diagnostic)] -#[diag(codegen_ssa_dynamic_linking_with_lto)] -#[note] +#[diag("cannot prefer dynamic linking when performing LTO")] +#[note("only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO")] pub(crate) struct DynamicLinkingWithLTO; diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 5cca916c17b6..e3934065b0f7 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -55,8 +55,6 @@ pub mod size_of_val; pub mod target_features; pub mod traits; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub struct ModuleCodegen { /// The name of the module. When the crate may be saved between /// compilations, incremental compilation requires that name be diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 3059a4fefc61..80edfa789acb 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -118,7 +118,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_ast_passes::DEFAULT_LOCALE_RESOURCE, rustc_borrowck::DEFAULT_LOCALE_RESOURCE, rustc_builtin_macros::DEFAULT_LOCALE_RESOURCE, - rustc_codegen_ssa::DEFAULT_LOCALE_RESOURCE, rustc_const_eval::DEFAULT_LOCALE_RESOURCE, rustc_errors::DEFAULT_LOCALE_RESOURCE, rustc_expand::DEFAULT_LOCALE_RESOURCE, From 40695f18be8e43a3b74710f9a872dc3a78557cf9 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 4 Feb 2026 16:48:07 +0100 Subject: [PATCH 535/978] Convert to inline diagnostics in `rustc_mir_transform` --- Cargo.lock | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_mir_transform/Cargo.toml | 1 - compiler/rustc_mir_transform/messages.ftl | 114 ------------- compiler/rustc_mir_transform/src/errors.rs | 158 +++++++++++------- compiler/rustc_mir_transform/src/lib.rs | 2 - .../src/lint_tail_expr_drop_order.rs | 31 +++- 7 files changed, 121 insertions(+), 187 deletions(-) delete mode 100644 compiler/rustc_mir_transform/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 85d3fc1aa7bf..1eaeec8da2a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4347,7 +4347,6 @@ dependencies = [ "rustc_const_eval", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_infer", diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 3b9ca5ff7288..972f0a1d2bee 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -128,7 +128,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_metadata::DEFAULT_LOCALE_RESOURCE, rustc_middle::DEFAULT_LOCALE_RESOURCE, rustc_mir_build::DEFAULT_LOCALE_RESOURCE, - rustc_mir_transform::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE, rustc_passes::DEFAULT_LOCALE_RESOURCE, rustc_pattern_analysis::DEFAULT_LOCALE_RESOURCE, diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml index 404531eb3c91..395127edd1e0 100644 --- a/compiler/rustc_mir_transform/Cargo.toml +++ b/compiler/rustc_mir_transform/Cargo.toml @@ -13,7 +13,6 @@ rustc_ast = { path = "../rustc_ast" } rustc_const_eval = { path = "../rustc_const_eval" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl deleted file mode 100644 index 7924c015200f..000000000000 --- a/compiler/rustc_mir_transform/messages.ftl +++ /dev/null @@ -1,114 +0,0 @@ -mir_transform_arithmetic_overflow = this arithmetic operation will overflow - -mir_transform_asm_unwind_call = call to inline assembly that may unwind - -mir_transform_const_defined_here = `const` item defined here - -mir_transform_const_modify = attempting to modify a `const` item - .note = each usage of a `const` item creates a new temporary; the original `const` item will not be modified - -mir_transform_const_mut_borrow = taking a mutable reference to a `const` item - .note = each usage of a `const` item creates a new temporary - .note2 = the mutable reference will refer to this temporary, not the original `const` item - .note3 = mutable reference created due to call to this method - -mir_transform_ffi_unwind_call = call to {$foreign -> - [true] foreign function - *[false] function pointer - } with FFI-unwind ABI - -mir_transform_fn_item_ref = taking a reference to a function item does not give a function pointer - .suggestion = cast `{$ident}` to obtain a function pointer - -mir_transform_force_inline = - `{$callee}` could not be inlined into `{$caller}` but is required to be inlined - .call = ...`{$callee}` called here - .attr = inlining due to this annotation - .caller = within `{$caller}`... - .callee = `{$callee}` defined here - .note = could not be inlined due to: {$reason} - -mir_transform_force_inline_attr = - `{$callee}` is incompatible with `#[rustc_force_inline]` - .attr = annotation here - .callee = `{$callee}` defined here - .note = incompatible due to: {$reason} - -mir_transform_force_inline_justification = - `{$callee}` is required to be inlined to: {$sym} - -mir_transform_maybe_string_interpolation = you might have meant to use string interpolation in this string literal - -mir_transform_must_not_suspend = {$pre}`{$def_path}`{$post} held across a suspend point, but should not be - .label = the value is held across this suspend point - .note = {$reason} - .help = consider using a block (`{"{ ... }"}`) to shrink the value's scope, ending before the suspend point -mir_transform_operation_will_panic = this operation will panic at runtime - -mir_transform_string_interpolation_only_works = string interpolation only works in `format!` invocations - -mir_transform_tail_expr_drop_order = relative drop order changing in Rust 2024 - .temporaries = in Rust 2024, this temporary value will be dropped first - .observers = in Rust 2024, this local variable or temporary value will be dropped second - .note_dtors = - dropping the temporary value runs this custom `Drop` impl, which we could not prove to be side-effect free - .note_observer_dtors = - dropping the local runs this custom `Drop` impl, which we could not prove to be side-effect free - .drop_location = - now the temporary value is dropped here, before the local variables in the block or statement - .note_epilogue = most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages - .label_local_epilogue = {$is_dropped_first_edition_2024 -> - [true] up until Edition 2021 `{$name}` is dropped last but will be dropped earlier in Edition 2024 - *[false] `{$name}` will be dropped later as of Edition 2024 - } - -mir_transform_tail_expr_dtor = {$dtor_kind -> - [dyn] `{$name}` may invoke a custom destructor because it contains a trait object - *[concrete] `{$name}` invokes this custom destructor - } - -mir_transform_tail_expr_local = {$is_generated_name -> - [true] this value will be stored in a temporary; let us call it `{$name}` - *[false] `{$name}` calls a custom destructor - } - -mir_transform_unaligned_packed_ref = reference to field of packed {$ty_descr} is unaligned - .note = this {$ty_descr} is {$align -> - [one] {""} - *[other] {"at most "} - }{$align}-byte aligned, but the type of this field may require higher alignment - .note_ub = creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) - .help = copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) - -mir_transform_unconditional_recursion = function cannot return without recursing - .label = cannot return without recursing - .help = a `loop` may express intention better if this is on purpose - -mir_transform_unconditional_recursion_call_site_label = recursive call site - -mir_transform_unknown_pass_name = MIR pass `{$name}` is unknown and will be ignored - -mir_transform_unused_assign = value assigned to `{$name}` is never read - .help = maybe it is overwritten before being read? - -mir_transform_unused_assign_passed = value passed to `{$name}` is never read - .help = maybe it is overwritten before being read? - -mir_transform_unused_assign_suggestion = - you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding - -mir_transform_unused_capture_maybe_capture_ref = value captured by `{$name}` is never read - .help = did you mean to capture by reference instead? - -mir_transform_unused_var_assigned_only = variable `{$name}` is assigned to, but never used - .note = consider using `_{$name}` instead - -mir_transform_unused_var_underscore = if this is intentional, prefix it with an underscore - -mir_transform_unused_variable = unused variable: `{$name}` - -mir_transform_unused_variable_args_in_macro = `{$name}` is captured in macro and introduced a unused variable - -mir_transform_unused_variable_try_ignore = try ignoring the field - -mir_transform_unused_variable_typo = you might have meant to pattern match on the similarly named {$kind} `{$item_name}` diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index d4c58f7fe05d..7407a0e022d3 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -1,5 +1,7 @@ use rustc_errors::codes::*; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, LintDiagnostic, Subdiagnostic}; +use rustc_errors::{ + Applicability, Diag, EmissionGuarantee, LintDiagnostic, Subdiagnostic, inline_fluent, +}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::mir::AssertKind; use rustc_middle::query::Key; @@ -8,8 +10,6 @@ use rustc_session::lint::{self, Lint}; use rustc_span::def_id::DefId; use rustc_span::{Ident, Span, Symbol}; -use crate::fluent_generated as fluent; - /// Emit diagnostic for calls to `#[inline(always)]`-annotated functions with a /// `#[target_feature]` attribute where the caller enables a different set of target features. pub(crate) fn emit_inline_always_target_feature_diagnostic<'a, 'tcx>( @@ -51,22 +51,22 @@ pub(crate) fn emit_inline_always_target_feature_diagnostic<'a, 'tcx>( } #[derive(LintDiagnostic)] -#[diag(mir_transform_unconditional_recursion)] -#[help] +#[diag("function cannot return without recursing")] +#[help("a `loop` may express intention better if this is on purpose")] pub(crate) struct UnconditionalRecursion { - #[label] + #[label("cannot return without recursing")] pub(crate) span: Span, - #[label(mir_transform_unconditional_recursion_call_site_label)] + #[label("recursive call site")] pub(crate) call_sites: Vec, } #[derive(Diagnostic)] -#[diag(mir_transform_force_inline_attr)] -#[note] +#[diag("`{$callee}` is incompatible with `#[rustc_force_inline]`")] +#[note("incompatible due to: {$reason}")] pub(crate) struct InvalidForceInline { #[primary_span] pub attr_span: Span, - #[label(mir_transform_callee)] + #[label("`{$callee}` defined here")] pub callee_span: Span, pub callee: String, pub reason: &'static str, @@ -74,28 +74,39 @@ pub(crate) struct InvalidForceInline { #[derive(LintDiagnostic)] pub(crate) enum ConstMutate { - #[diag(mir_transform_const_modify)] - #[note] + #[diag("attempting to modify a `const` item")] + #[note( + "each usage of a `const` item creates a new temporary; the original `const` item will not be modified" + )] Modify { - #[note(mir_transform_const_defined_here)] + #[note("`const` item defined here")] konst: Span, }, - #[diag(mir_transform_const_mut_borrow)] - #[note] - #[note(mir_transform_note2)] + #[diag("taking a mutable reference to a `const` item")] + #[note("each usage of a `const` item creates a new temporary")] + #[note("the mutable reference will refer to this temporary, not the original `const` item")] MutBorrow { - #[note(mir_transform_note3)] + #[note("mutable reference created due to call to this method")] method_call: Option, - #[note(mir_transform_const_defined_here)] + #[note("`const` item defined here")] konst: Span, }, } #[derive(Diagnostic)] -#[diag(mir_transform_unaligned_packed_ref, code = E0793)] -#[note] -#[note(mir_transform_note_ub)] -#[help] +#[diag("reference to field of packed {$ty_descr} is unaligned", code = E0793)] +#[note( + "this {$ty_descr} is {$align -> + [one] {\"\"} + *[other] {\"at most \"} + }{$align}-byte aligned, but the type of this field may require higher alignment" +)] +#[note( + "creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)" +)] +#[help( + "copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)" +)] pub(crate) struct UnalignedPackedRef { #[primary_span] pub span: Span, @@ -104,7 +115,7 @@ pub(crate) struct UnalignedPackedRef { } #[derive(Diagnostic)] -#[diag(mir_transform_unknown_pass_name)] +#[diag("MIR pass `{$name}` is unknown and will be ignored")] pub(crate) struct UnknownPassName<'a> { pub(crate) name: &'a str, } @@ -123,8 +134,12 @@ pub(crate) enum AssertLintKind { impl<'a, P: std::fmt::Debug> LintDiagnostic<'a, ()> for AssertLint

{ fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { diag.primary_message(match self.lint_kind { - AssertLintKind::ArithmeticOverflow => fluent::mir_transform_arithmetic_overflow, - AssertLintKind::UnconditionalPanic => fluent::mir_transform_operation_will_panic, + AssertLintKind::ArithmeticOverflow => { + inline_fluent!("this arithmetic operation will overflow") + } + AssertLintKind::UnconditionalPanic => { + inline_fluent!("this operation will panic at runtime") + } }); let label = self.assert_kind.diagnostic_message(); self.assert_kind.add_args(&mut |name, value| { @@ -144,39 +159,53 @@ impl AssertLintKind { } #[derive(LintDiagnostic)] -#[diag(mir_transform_asm_unwind_call)] +#[diag("call to inline assembly that may unwind")] pub(crate) struct AsmUnwindCall { - #[label(mir_transform_asm_unwind_call)] + #[label("call to inline assembly that may unwind")] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(mir_transform_ffi_unwind_call)] +#[diag( + "call to {$foreign -> + [true] foreign function + *[false] function pointer + } with FFI-unwind ABI" +)] pub(crate) struct FfiUnwindCall { - #[label(mir_transform_ffi_unwind_call)] + #[label( + "call to {$foreign -> + [true] foreign function + *[false] function pointer + } with FFI-unwind ABI" + )] pub span: Span, pub foreign: bool, } #[derive(LintDiagnostic)] -#[diag(mir_transform_fn_item_ref)] +#[diag("taking a reference to a function item does not give a function pointer")] pub(crate) struct FnItemRef { - #[suggestion(code = "{sugg}", applicability = "unspecified")] + #[suggestion( + "cast `{$ident}` to obtain a function pointer", + code = "{sugg}", + applicability = "unspecified" + )] pub span: Span, pub sugg: String, pub ident: Ident, } #[derive(LintDiagnostic)] -#[diag(mir_transform_unused_capture_maybe_capture_ref)] -#[help] +#[diag("value captured by `{$name}` is never read")] +#[help("did you mean to capture by reference instead?")] pub(crate) struct UnusedCaptureMaybeCaptureRef { pub name: Symbol, } #[derive(LintDiagnostic)] -#[diag(mir_transform_unused_var_assigned_only)] -#[note] +#[diag("variable `{$name}` is assigned to, but never used")] +#[note("consider using `_{$name}` instead")] pub(crate) struct UnusedVarAssignedOnly { pub name: Symbol, #[subdiagnostic] @@ -184,17 +213,20 @@ pub(crate) struct UnusedVarAssignedOnly { } #[derive(LintDiagnostic)] -#[diag(mir_transform_unused_assign)] +#[diag("value assigned to `{$name}` is never read")] pub(crate) struct UnusedAssign { pub name: Symbol, #[subdiagnostic] pub suggestion: Option, - #[help] + #[help("maybe it is overwritten before being read?")] pub help: bool, } #[derive(Subdiagnostic)] -#[multipart_suggestion(mir_transform_unused_assign_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding", + applicability = "maybe-incorrect" +)] pub(crate) struct UnusedAssignSuggestion { pub pre: &'static str, #[suggestion_part(code = "{pre}mut ")] @@ -208,14 +240,14 @@ pub(crate) struct UnusedAssignSuggestion { } #[derive(LintDiagnostic)] -#[diag(mir_transform_unused_assign_passed)] -#[help] +#[diag("value passed to `{$name}` is never read")] +#[help("maybe it is overwritten before being read?")] pub(crate) struct UnusedAssignPassed { pub name: Symbol, } #[derive(LintDiagnostic)] -#[diag(mir_transform_unused_variable)] +#[diag("unused variable: `{$name}`")] pub(crate) struct UnusedVariable { pub name: Symbol, #[subdiagnostic] @@ -226,10 +258,7 @@ pub(crate) struct UnusedVariable { #[derive(Subdiagnostic)] pub(crate) enum UnusedVariableSugg { - #[multipart_suggestion( - mir_transform_unused_variable_try_ignore, - applicability = "machine-applicable" - )] + #[multipart_suggestion("try ignoring the field", applicability = "machine-applicable")] TryIgnore { #[suggestion_part(code = "{name}: _")] shorthands: Vec, @@ -239,7 +268,7 @@ pub(crate) enum UnusedVariableSugg { }, #[multipart_suggestion( - mir_transform_unused_var_underscore, + "if this is intentional, prefix it with an underscore", applicability = "machine-applicable" )] TryPrefix { @@ -250,7 +279,7 @@ pub(crate) enum UnusedVariableSugg { typo: Option, }, - #[help(mir_transform_unused_variable_args_in_macro)] + #[help("`{$name}` is captured in macro and introduced a unused variable")] NoSugg { #[primary_span] span: Span, @@ -266,10 +295,12 @@ impl Subdiagnostic for UnusedVariableStringInterp { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_label( self.lit, - crate::fluent_generated::mir_transform_maybe_string_interpolation, + inline_fluent!( + "you might have meant to use string interpolation in this string literal" + ), ); diag.multipart_suggestion( - crate::fluent_generated::mir_transform_string_interpolation_only_works, + inline_fluent!("string interpolation only works in `format!` invocations"), vec![ (self.lit.shrink_to_lo(), String::from("format!(")), (self.lit.shrink_to_hi(), String::from(")")), @@ -281,7 +312,7 @@ impl Subdiagnostic for UnusedVariableStringInterp { #[derive(Subdiagnostic)] #[multipart_suggestion( - mir_transform_unused_variable_typo, + "you might have meant to pattern match on the similarly named {$kind} `{$item_name}`", style = "verbose", applicability = "maybe-incorrect" )] @@ -306,12 +337,17 @@ pub(crate) struct MustNotSupend<'a, 'tcx> { // Needed for def_path_str impl<'a> LintDiagnostic<'a, ()> for MustNotSupend<'_, '_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) { - diag.primary_message(fluent::mir_transform_must_not_suspend); - diag.span_label(self.yield_sp, fluent::_subdiag::label); + diag.primary_message(inline_fluent!( + "{$pre}`{$def_path}`{$post} held across a suspend point, but should not be" + )); + diag.span_label( + self.yield_sp, + inline_fluent!("the value is held across this suspend point"), + ); if let Some(reason) = self.reason { diag.subdiagnostic(reason); } - diag.span_help(self.src_sp, fluent::_subdiag::help); + diag.span_help(self.src_sp, inline_fluent!("consider using a block (`{\"{ ... }\"}`) to shrink the value's scope, ending before the suspend point")); diag.arg("pre", self.pre); diag.arg("def_path", self.tcx.def_path_str(self.def_id)); diag.arg("post", self.post); @@ -319,7 +355,7 @@ impl<'a> LintDiagnostic<'a, ()> for MustNotSupend<'_, '_> { } #[derive(Subdiagnostic)] -#[note(mir_transform_note)] +#[note("{$reason}")] pub(crate) struct MustNotSuspendReason { #[primary_span] pub span: Span, @@ -327,17 +363,17 @@ pub(crate) struct MustNotSuspendReason { } #[derive(Diagnostic)] -#[diag(mir_transform_force_inline)] -#[note] +#[diag("`{$callee}` could not be inlined into `{$caller}` but is required to be inlined")] +#[note("could not be inlined due to: {$reason}")] pub(crate) struct ForceInlineFailure { - #[label(mir_transform_caller)] + #[label("within `{$caller}`...")] pub caller_span: Span, - #[label(mir_transform_callee)] + #[label("`{$callee}` defined here")] pub callee_span: Span, - #[label(mir_transform_attr)] + #[label("annotation here")] pub attr_span: Span, #[primary_span] - #[label(mir_transform_call)] + #[label("...`{$callee}` called here")] pub call_span: Span, pub callee: String, pub caller: String, @@ -347,7 +383,7 @@ pub(crate) struct ForceInlineFailure { } #[derive(Subdiagnostic)] -#[note(mir_transform_force_inline_justification)] +#[note("`{$callee}` is required to be inlined to: {$sym}")] pub(crate) struct ForceInlineJustification { pub sym: Symbol, } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 0e6a1a414e45..0610d90202a1 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -213,8 +213,6 @@ declare_passes! { mod validate : Validator; } -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn provide(providers: &mut Providers) { coverage::query::provide(providers); ffi_unwind_calls::provide(&mut providers.queries); diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index 61c9bbe31239..789398c58880 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -5,7 +5,7 @@ use std::rc::Rc; use itertools::Itertools as _; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::unord::{UnordMap, UnordSet}; -use rustc_errors::Subdiagnostic; +use rustc_errors::{Subdiagnostic, inline_fluent}; use rustc_hir::CRATE_HIR_ID; use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::MixedBitSet; @@ -499,13 +499,17 @@ fn assign_observables_names( } #[derive(LintDiagnostic)] -#[diag(mir_transform_tail_expr_drop_order)] +#[diag("relative drop order changing in Rust 2024")] struct TailExprDropOrderLint<'a> { #[subdiagnostic] local_labels: Vec>, - #[label(mir_transform_drop_location)] + #[label( + "now the temporary value is dropped here, before the local variables in the block or statement" + )] drop_span: Option, - #[note(mir_transform_note_epilogue)] + #[note( + "most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages" + )] _epilogue: (), } @@ -527,19 +531,32 @@ impl Subdiagnostic for LocalLabel<'_> { diag.arg("is_generated_name", self.is_generated_name); diag.remove_arg("is_dropped_first_edition_2024"); diag.arg("is_dropped_first_edition_2024", self.is_dropped_first_edition_2024); - let msg = diag.eagerly_translate(crate::fluent_generated::mir_transform_tail_expr_local); + let msg = diag.eagerly_translate(inline_fluent!( + "{$is_generated_name -> + [true] this value will be stored in a temporary; let us call it `{$name}` + *[false] `{$name}` calls a custom destructor + }" + )); diag.span_label(self.span, msg); for dtor in self.destructors { dtor.add_to_diag(diag); } let msg = - diag.eagerly_translate(crate::fluent_generated::mir_transform_label_local_epilogue); + diag.eagerly_translate(inline_fluent!("{$is_dropped_first_edition_2024 -> + [true] up until Edition 2021 `{$name}` is dropped last but will be dropped earlier in Edition 2024 + *[false] `{$name}` will be dropped later as of Edition 2024 + }")); diag.span_label(self.span, msg); } } #[derive(Subdiagnostic)] -#[note(mir_transform_tail_expr_dtor)] +#[note( + "{$dtor_kind -> + [dyn] `{$name}` may invoke a custom destructor because it contains a trait object + *[concrete] `{$name}` invokes this custom destructor + }" +)] struct DestructorLabel<'a> { #[primary_span] span: Span, From e005754c06f6a6115ae48721fcffaf62cbeeadad Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 3 Feb 2026 22:23:12 +0100 Subject: [PATCH 536/978] Convert to inline diagnostics in `rustc_resolve` --- Cargo.lock | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_resolve/Cargo.toml | 1 - compiler/rustc_resolve/messages.ftl | 531 ------------------------- compiler/rustc_resolve/src/errors.rs | 552 +++++++++++++++----------- compiler/rustc_resolve/src/lib.rs | 2 - 6 files changed, 310 insertions(+), 778 deletions(-) delete mode 100644 compiler/rustc_resolve/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 85d3fc1aa7bf..711892bcfdd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4581,7 +4581,6 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 3b9ca5ff7288..8c53d558133b 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -132,7 +132,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_parse::DEFAULT_LOCALE_RESOURCE, rustc_passes::DEFAULT_LOCALE_RESOURCE, rustc_pattern_analysis::DEFAULT_LOCALE_RESOURCE, - rustc_resolve::DEFAULT_LOCALE_RESOURCE, rustc_trait_selection::DEFAULT_LOCALE_RESOURCE, // tidy-alphabetical-end ]; diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index dd15e879c644..01e268d911d2 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -16,7 +16,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl deleted file mode 100644 index 4a980b2bd747..000000000000 --- a/compiler/rustc_resolve/messages.ftl +++ /dev/null @@ -1,531 +0,0 @@ -resolve_accessible_unsure = not sure whether the path is accessible or not - .note = the type may have associated items, but we are currently not checking them - -resolve_add_as_non_derive = - add as non-Derive macro - `#[{$macro_path}]` - -resolve_added_macro_use = - have you added the `#[macro_use]` on the module/import? - -resolve_ancestor_only = - visibilities can only be restricted to ancestor modules - -resolve_anonymous_lifetime_non_gat_report_error = missing lifetime in associated type - .label = this lifetime must come from the implemented type - .note = in the trait the associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type - -resolve_arguments_macro_use_not_allowed = arguments to `macro_use` are not allowed here - -resolve_associated_const_with_similar_name_exists = - there is an associated constant with a similar name - -resolve_associated_fn_with_similar_name_exists = - there is an associated function with a similar name - -resolve_associated_type_with_similar_name_exists = - there is an associated type with a similar name - -resolve_attempt_to_use_non_constant_value_in_constant = - attempt to use a non-constant value in a constant - -resolve_attempt_to_use_non_constant_value_in_constant_label_with_suggestion = - non-constant value - -resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion = - consider using `{$suggestion}` instead of `{$current}` - -resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion = - this would need to be a `{$suggestion}` - -resolve_attributes_starting_with_rustc_are_reserved = - attributes starting with `rustc` are reserved for use by the `rustc` compiler - -resolve_binding_in_never_pattern = - never patterns cannot contain variable bindings - .suggestion = use a wildcard `_` instead - -resolve_binding_shadows_something_unacceptable = - {$shadowing_binding}s cannot shadow {$shadowed_binding}s - .label = cannot be named the same as {$article} {$shadowed_binding} - .label_shadowed_binding = the {$shadowed_binding} `{$name}` is {$participle} here - -resolve_binding_shadows_something_unacceptable_suggestion = - try specify the pattern arguments - -resolve_cannot_be_reexported_crate_public = - `{$ident}` is only public within the crate, and cannot be re-exported outside - -resolve_cannot_be_reexported_private = - `{$ident}` is private, and cannot be re-exported - -resolve_cannot_capture_dynamic_environment_in_fn_item = - can't capture dynamic environment in a fn item - .help = use the `|| {"{"} ... {"}"}` closure form instead - -resolve_cannot_determine_import_resolution = - cannot determine resolution for the import - .note = import resolution is stuck, try simplifying other imports - -resolve_cannot_determine_macro_resolution = - cannot determine resolution for the {$kind} `{$path}` - .note = import resolution is stuck, try simplifying macro imports - -resolve_cannot_find_builtin_macro_with_name = - cannot find a built-in macro with name `{$ident}` - -resolve_cannot_find_ident_in_this_scope = - cannot find {$expected} `{$ident}` in this scope - -resolve_cannot_glob_import_possible_crates = - cannot glob-import all possible crates - -resolve_cannot_use_through_an_import = - cannot use {$article} {$descr} through an import - .note = the {$descr} imported here - -resolve_change_import_binding = - you can use `as` to change the binding name of the import - -resolve_consider_adding_a_derive = - consider adding a derive - -resolve_consider_adding_macro_export = - consider adding a `#[macro_export]` to the macro in the imported module - -resolve_consider_declaring_with_pub = - consider declaring type or module `{$ident}` with `pub` - -resolve_consider_making_the_field_public = - { $number_of_fields -> - [one] consider making the field publicly accessible - *[other] consider making the fields publicly accessible - } - -resolve_consider_marking_as_pub = - consider marking `{$ident}` as `pub` in the imported module - -resolve_consider_marking_as_pub_crate = - in case you want to use the macro within this crate only, reduce the visibility to `pub(crate)` - -resolve_consider_move_macro_position = - consider moving the definition of `{$ident}` before this call - - -resolve_const_not_member_of_trait = - const `{$const_}` is not a member of trait `{$trait_}` - .label = not a member of trait `{$trait_}` - -resolve_const_param_in_enum_discriminant = - const parameters may not be used in enum discriminant values - -resolve_const_param_in_non_trivial_anon_const = - const parameters may only be used as standalone arguments here, i.e. `{$name}` - -resolve_constructor_private_if_any_field_private = - a constructor is private if any of the fields is private - -resolve_elided_anonymous_lifetime_report_error = - `&` without an explicit lifetime name cannot be used here - .label = explicit lifetime name needed here - -resolve_elided_anonymous_lifetime_report_error_suggestion = - consider introducing a higher-ranked lifetime here - -resolve_expected_module_found = - expected module, found {$res} `{$path_str}` - .label = not a module - -resolve_explicit_anonymous_lifetime_report_error = - `'_` cannot be used here - .label = `'_` is a reserved lifetime name - -resolve_explicit_unsafe_traits = - unsafe traits like `{$ident}` should be implemented explicitly - -resolve_extern_crate_loading_macro_not_at_crate_root = - an `extern crate` loading macros must be at the crate root - -resolve_extern_crate_not_idiomatic = `extern crate` is not idiomatic in the new edition - .suggestion = convert it to a `use` - -resolve_extern_crate_self_requires_renaming = - `extern crate self;` requires renaming - .suggestion = rename the `self` crate to be able to import it - -resolve_forward_declared_generic_in_const_param_ty = - const parameter types cannot reference parameters before they are declared - .label = const parameter type cannot reference `{$param}` before it is declared - -resolve_forward_declared_generic_param = - generic parameter defaults cannot reference parameters before they are declared - .label = cannot reference `{$param}` before it is declared - -resolve_found_an_item_configured_out = - found an item that was configured out - -resolve_generic_arguments_in_macro_path = - generic arguments in macro path - -resolve_generic_params_from_outer_item = - can't use {$is_self -> - [true] `Self` - *[false] generic parameters - } from outer item - .label = use of {$is_self -> - [true] `Self` - *[false] generic parameter - } from outer item - .refer_to_type_directly = refer to the type directly here instead - .suggestion = try introducing a local generic parameter here - .note = nested items are independent from their parent item for everything except for privacy and name resolution - -resolve_generic_params_from_outer_item_const = a `const` is a separate item from the item that contains it - -resolve_generic_params_from_outer_item_const_param = const parameter from outer item - -resolve_generic_params_from_outer_item_inner_item = {$is_self -> - [true] `Self` - *[false] generic parameter - } used in this inner {$descr} - -resolve_generic_params_from_outer_item_self_ty_alias = `Self` type implicitly declared here, by this `impl` - -resolve_generic_params_from_outer_item_self_ty_param = can't use `Self` here - -resolve_generic_params_from_outer_item_static = a `static` is a separate item from the item that contains it - -resolve_generic_params_from_outer_item_ty_param = type parameter from outer item - -resolve_ident_bound_more_than_once_in_parameter_list = - identifier `{$identifier}` is bound more than once in this parameter list - .label = used as parameter more than once - -resolve_ident_bound_more_than_once_in_same_pattern = - identifier `{$identifier}` is bound more than once in the same pattern - .label = used in a pattern more than once - -resolve_ident_imported_here_but_it_is_desc = - `{$imported_ident}` is imported here, but it is {$imported_ident_desc} - -resolve_ident_in_scope_but_it_is_desc = - `{$imported_ident}` is in scope, but it is {$imported_ident_desc} - -resolve_implicit_elided_lifetimes_not_allowed_here = implicit elided lifetime not allowed here - -resolve_imported_crate = `$crate` may not be imported - -resolve_imported_macro_not_found = imported macro not found - -resolve_imports_cannot_refer_to = - imports cannot refer to {$what} - -resolve_indeterminate = - cannot determine resolution for the visibility - -resolve_invalid_asm_sym = - invalid `sym` operand - .label = is a local variable - .help = `sym` operands must refer to either a function or a static - -resolve_is_private = - {$ident_descr} `{$ident}` is private - .label = private {$ident_descr} - -resolve_item_was_behind_feature = - the item is gated behind the `{$feature}` feature - -resolve_item_was_cfg_out = the item is gated here - -resolve_label_with_similar_name_reachable = - a label with a similar name is reachable - -resolve_legacy_derive_helpers = derive helper attribute is used before it is introduced - .label = the attribute is introduced here - -resolve_lending_iterator_report_error = - associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type - .note = you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type - -resolve_lifetime_param_in_enum_discriminant = - lifetime parameters may not be used in enum discriminant values - -resolve_lifetime_param_in_non_trivial_anon_const = - lifetime parameters may not be used in const expressions - -resolve_lowercase_self = - attempt to use a non-constant value in a constant - .suggestion = try using `Self` - -resolve_macro_cannot_use_as_attr = - `{$ident}` exists, but has no `attr` rules - -resolve_macro_cannot_use_as_derive = - `{$ident}` exists, but has no `derive` rules - -resolve_macro_cannot_use_as_fn_like = - `{$ident}` exists, but has no rules for function-like invocation - -resolve_macro_defined_later = - a macro with the same name exists, but it appears later - -resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments = - macro-expanded `extern crate` items cannot shadow names passed with `--extern` - -resolve_macro_expanded_macro_exports_accessed_by_absolute_paths = macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths - .note = the macro is defined here - -resolve_macro_expected_found = - expected {$expected}, found {$found} `{$macro_path}` - .label = not {$article} {$expected} - -resolve_macro_extern_deprecated = - `#[macro_escape]` is a deprecated synonym for `#[macro_use]` - .help = try an outer attribute: `#[macro_use]` - -resolve_macro_is_private = macro `{$ident}` is private - -resolve_macro_rule_never_used = rule #{$n} of macro `{$name}` is never used - -resolve_macro_use_deprecated = - applying the `#[macro_use]` attribute to an `extern crate` item is deprecated - .help = remove it and import macros at use sites with a `use` item instead - -resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern crate self` - -resolve_macro_use_name_already_in_use = - `{$name}` is already in scope - .note = macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560) - -resolve_method_not_member_of_trait = - method `{$method}` is not a member of trait `{$trait_}` - .label = not a member of trait `{$trait_}` - -resolve_missing_macro_rules_name = maybe you have forgotten to define a name for this `macro_rules!` - -resolve_module_only = - visibility must resolve to a module - -resolve_name_defined_multiple_time = - the name `{$name}` is defined multiple times - .note = `{$name}` must be defined only once in the {$descr} namespace of this {$container} - -resolve_name_defined_multiple_time_old_binding_definition = - previous definition of the {$old_kind} `{$name}` here - -resolve_name_defined_multiple_time_old_binding_import = - previous import of the {$old_kind} `{$name}` here - -resolve_name_defined_multiple_time_redefined = - `{$name}` redefined here - -resolve_name_defined_multiple_time_reimported = - `{$name}` reimported here - -resolve_name_is_already_used_as_generic_parameter = - the name `{$name}` is already used for a generic parameter in this item's generic parameters - .label = already used - .first_use_of_name = first use of `{$name}` - -resolve_name_reserved_in_attribute_namespace = - name `{$ident}` is reserved in attribute namespace - -resolve_note_and_refers_to_the_item_defined_here = - {$first -> - [true] {$dots -> - [true] the {$binding_descr} `{$binding_name}` is defined here... - *[false] the {$binding_descr} `{$binding_name}` is defined here - } - *[false] {$dots -> - [true] ...and refers to the {$binding_descr} `{$binding_name}` which is defined here... - *[false] ...and refers to the {$binding_descr} `{$binding_name}` which is defined here - } - } - -resolve_out_of_scope_macro_calls = cannot find macro `{$path}` in the current scope when looking from {$location} - .label = not found from {$location} - .help = import `macro_rules` with `use` to make it callable above its definition - -resolve_outer_ident_is_not_publicly_reexported = - {$outer_ident_descr} `{$outer_ident}` is not publicly re-exported - -resolve_param_in_enum_discriminant = - generic parameters may not be used in enum discriminant values - .label = cannot perform const operation using `{$name}` - -resolve_param_in_non_trivial_anon_const = - generic parameters may not be used in const operations - .label = cannot perform const operation using `{$name}` - -resolve_param_in_non_trivial_anon_const_help = - add `#![feature(generic_const_exprs)]` to allow generic const expressions - -resolve_param_in_ty_of_const_param = - the type of const parameters must not depend on other generic parameters - .label = the type must not depend on the parameter `{$name}` - -resolve_pattern_doesnt_bind_name = pattern doesn't bind `{$name}` - -resolve_private_extern_crate_reexport = extern crate `{$ident}` is private and cannot be re-exported - .suggestion = consider making the `extern crate` item publicly accessible - -resolve_proc_macro_derive_resolution_fallback = cannot find {$ns_descr} `{$ident}` in this scope - .label = names from parent modules are not accessible without an explicit import - -resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it - .help = you can define integration tests in a directory named `tests` - -resolve_redundant_import_visibility = glob import doesn't reexport anything with visibility `{$import_vis}` because no imported item is public enough - .note = the most public imported item is `{$max_vis}` - .help = reduce the glob import's visibility or increase visibility of imported items - -resolve_reexport_of_crate_public = - re-export of crate public `{$ident}` - -resolve_reexport_of_private = - re-export of private `{$ident}` - -resolve_reexport_private_dependency = - {$kind} `{$name}` from private dependency '{$krate}' is re-exported - -resolve_relative_2018 = - relative paths are not supported in visibilities in 2018 edition or later - .suggestion = try - -resolve_remove_surrounding_derive = - remove from the surrounding `derive()` - -resolve_remove_unnecessary_import = remove unnecessary import - -resolve_self_import_can_only_appear_once_in_the_list = - `self` import can only appear once in an import list - .label = can only appear once in an import list - -resolve_self_import_only_in_import_list_with_non_empty_prefix = - `self` import can only appear in an import list with a non-empty prefix - .label = can only appear in an import list with a non-empty prefix - -resolve_self_imports_only_allowed_within = - `self` imports are only allowed within a {"{"} {"}"} list - -resolve_self_imports_only_allowed_within_multipart_suggestion = - alternatively, use the multi-path `use` syntax to import `self` - -resolve_self_imports_only_allowed_within_suggestion = - consider importing the module directly - -resolve_self_in_const_generic_ty = - cannot use `Self` in const parameter type - -resolve_self_in_generic_param_default = - generic parameters cannot use `Self` in their defaults - -resolve_similarly_named_defined_here = - similarly named {$candidate_descr} `{$candidate}` defined here - -resolve_single_item_defined_here = - {$candidate_descr} `{$candidate}` defined here - -resolve_static_lifetime_is_reserved = invalid lifetime parameter name: `{$lifetime}` - .label = 'static is a reserved lifetime name - -resolve_suggestion_import_ident_directly = - import `{$ident}` directly - -resolve_suggestion_import_ident_through_reexport = - import `{$ident}` through the re-export - -resolve_tool_module_imported = - cannot use a tool module through an import - .note = the tool module imported here - -resolve_tool_only_accepts_identifiers = - `{$tool}` only accepts identifiers - .label = not an identifier - -resolve_tool_was_already_registered = - tool `{$tool}` was already registered - .label = already registered here - -resolve_trait_impl_duplicate = - duplicate definitions with name `{$name}`: - .label = duplicate definition - .old_span_label = previous definition here - .trait_item_span = item in trait - -resolve_trait_impl_mismatch = - item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}` - .label = does not match trait - .trait_impl_mismatch_label_item = item in trait -resolve_try_using_similarly_named_label = - try using similarly named label - -resolve_type_not_member_of_trait = - type `{$type_}` is not a member of trait `{$trait_}` - .label = not a member of trait `{$trait_}` - -resolve_type_param_in_enum_discriminant = - type parameters may not be used in enum discriminant values - -resolve_type_param_in_non_trivial_anon_const = - type parameters may not be used in const expressions - -resolve_undeclared_label = - use of undeclared label `{$name}` - .label = undeclared label `{$name}` - -resolve_underscore_lifetime_is_reserved = `'_` cannot be used here - .label = `'_` is a reserved lifetime name - .help = use another lifetime specifier - -resolve_unexpected_res_change_ty_to_const_param_sugg = - you might have meant to write a const parameter here - -resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg = - if you meant to collect the rest of the slice in `{$ident}`, use the at operator - -resolve_unknown_diagnostic_attribute = unknown diagnostic attribute -resolve_unknown_diagnostic_attribute_typo_sugg = an attribute with a similar name exists - -resolve_unnamed_crate_root_import = - crate root imports need to be explicitly named: `use crate as name;` - -resolve_unreachable_label = - use of unreachable label `{$name}` - .label = unreachable label `{$name}` - .label_definition_span = unreachable label defined here - .note = labels are unreachable through functions, closures, async blocks and modules - -resolve_unreachable_label_similar_name_reachable = - a label with a similar name is reachable - -resolve_unreachable_label_similar_name_unreachable = - a label with a similar name exists but is also unreachable - -resolve_unreachable_label_suggestion_use_similarly_named = - try using similarly named label - -resolve_unreachable_label_with_similar_name_exists = - a label with a similar name exists but is unreachable - -resolve_unused_extern_crate = unused extern crate - .label = unused - .suggestion = remove the unused `extern crate` - -resolve_unused_label = unused label - -resolve_unused_macro_definition = unused macro definition: `{$name}` - -resolve_unused_macro_use = unused `#[macro_use]` import - -resolve_variable_bound_with_different_mode = - variable `{$variable_name}` is bound inconsistently across alternatives separated by `|` - .label = bound in different ways - .first_binding_span = first binding - -resolve_variable_is_a_typo = you might have meant to use the similarly named previously used binding `{$typo}` - -resolve_variable_is_not_bound_in_all_patterns = - variable `{$name}` is not bound in all patterns - -resolve_variable_not_in_all_patterns = variable not in all patterns diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 3e5446403052..7afdbf6a469f 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,21 +1,31 @@ use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagMessage, Diagnostic, ElidedLifetimeInPathSubdiag, - EmissionGuarantee, IntoDiagArg, Level, LintDiagnostic, MultiSpan, Subdiagnostic, + EmissionGuarantee, IntoDiagArg, Level, LintDiagnostic, MultiSpan, Subdiagnostic, inline_fluent, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::source_map::Spanned; use rustc_span::{Ident, Span, Symbol}; +use crate::Res; use crate::late::PatternSource; -use crate::{Res, fluent_generated as fluent}; #[derive(Diagnostic)] -#[diag(resolve_generic_params_from_outer_item, code = E0401)] -#[note] +#[diag("can't use {$is_self -> + [true] `Self` + *[false] generic parameters + } from outer item", code = E0401)] +#[note( + "nested items are independent from their parent item for everything except for privacy and name resolution" +)] pub(crate) struct GenericParamsFromOuterItem { #[primary_span] - #[label] + #[label( + "use of {$is_self -> + [true] `Self` + *[false] generic parameter + } from outer item" + )] pub(crate) span: Span, #[subdiagnostic] pub(crate) label: Option, @@ -31,7 +41,12 @@ pub(crate) struct GenericParamsFromOuterItem { } #[derive(Subdiagnostic)] -#[label(resolve_generic_params_from_outer_item_inner_item)] +#[label( + "{$is_self -> + [true] `Self` + *[false] generic parameter + } used in this inner {$descr}" +)] pub(crate) struct GenericParamsFromOuterItemInnerItem { #[primary_span] pub(crate) span: Span, @@ -40,27 +55,27 @@ pub(crate) struct GenericParamsFromOuterItemInnerItem { #[derive(Subdiagnostic)] pub(crate) enum GenericParamsFromOuterItemStaticOrConst { - #[note(resolve_generic_params_from_outer_item_static)] + #[note("a `static` is a separate item from the item that contains it")] Static, - #[note(resolve_generic_params_from_outer_item_const)] + #[note("a `const` is a separate item from the item that contains it")] Const, } #[derive(Subdiagnostic)] pub(crate) enum GenericParamsFromOuterItemLabel { - #[label(resolve_generic_params_from_outer_item_self_ty_param)] + #[label("can't use `Self` here")] SelfTyParam(#[primary_span] Span), - #[label(resolve_generic_params_from_outer_item_self_ty_alias)] + #[label("`Self` type implicitly declared here, by this `impl`")] SelfTyAlias(#[primary_span] Span), - #[label(resolve_generic_params_from_outer_item_ty_param)] + #[label("type parameter from outer item")] TyParam(#[primary_span] Span), - #[label(resolve_generic_params_from_outer_item_const_param)] + #[label("const parameter from outer item")] ConstParam(#[primary_span] Span), } #[derive(Subdiagnostic)] #[suggestion( - resolve_suggestion, + "try introducing a local generic parameter here", code = "{snippet}", applicability = "maybe-incorrect", style = "verbose" @@ -72,7 +87,7 @@ pub(crate) struct GenericParamsFromOuterItemSugg { } #[derive(Subdiagnostic)] #[suggestion( - resolve_refer_to_type_directly, + "refer to the type directly here instead", code = "{snippet}", applicability = "maybe-incorrect", style = "verbose" @@ -84,21 +99,21 @@ pub(crate) struct UseTypeDirectly { } #[derive(Diagnostic)] -#[diag(resolve_name_is_already_used_as_generic_parameter, code = E0403)] +#[diag("the name `{$name}` is already used for a generic parameter in this item's generic parameters", code = E0403)] pub(crate) struct NameAlreadyUsedInParameterList { #[primary_span] - #[label] + #[label("already used")] pub(crate) span: Span, - #[label(resolve_first_use_of_name)] + #[label("first use of `{$name}`")] pub(crate) first_use_span: Span, pub(crate) name: Ident, } #[derive(Diagnostic)] -#[diag(resolve_method_not_member_of_trait, code = E0407)] +#[diag("method `{$method}` is not a member of trait `{$trait_}`", code = E0407)] pub(crate) struct MethodNotMemberOfTrait { #[primary_span] - #[label] + #[label("not a member of trait `{$trait_}`")] pub(crate) span: Span, pub(crate) method: Ident, pub(crate) trait_: String, @@ -108,7 +123,7 @@ pub(crate) struct MethodNotMemberOfTrait { #[derive(Subdiagnostic)] #[suggestion( - resolve_associated_fn_with_similar_name_exists, + "there is an associated function with a similar name", code = "{candidate}", applicability = "maybe-incorrect" )] @@ -119,10 +134,10 @@ pub(crate) struct AssociatedFnWithSimilarNameExists { } #[derive(Diagnostic)] -#[diag(resolve_type_not_member_of_trait, code = E0437)] +#[diag("type `{$type_}` is not a member of trait `{$trait_}`", code = E0437)] pub(crate) struct TypeNotMemberOfTrait { #[primary_span] - #[label] + #[label("not a member of trait `{$trait_}`")] pub(crate) span: Span, pub(crate) type_: Ident, pub(crate) trait_: String, @@ -132,7 +147,7 @@ pub(crate) struct TypeNotMemberOfTrait { #[derive(Subdiagnostic)] #[suggestion( - resolve_associated_type_with_similar_name_exists, + "there is an associated type with a similar name", code = "{candidate}", applicability = "maybe-incorrect" )] @@ -143,10 +158,10 @@ pub(crate) struct AssociatedTypeWithSimilarNameExists { } #[derive(Diagnostic)] -#[diag(resolve_const_not_member_of_trait, code = E0438)] +#[diag("const `{$const_}` is not a member of trait `{$trait_}`", code = E0438)] pub(crate) struct ConstNotMemberOfTrait { #[primary_span] - #[label] + #[label("not a member of trait `{$trait_}`")] pub(crate) span: Span, pub(crate) const_: Ident, pub(crate) trait_: String, @@ -156,7 +171,7 @@ pub(crate) struct ConstNotMemberOfTrait { #[derive(Subdiagnostic)] #[suggestion( - resolve_associated_const_with_similar_name_exists, + "there is an associated constant with a similar name", code = "{candidate}", applicability = "maybe-incorrect" )] @@ -167,39 +182,39 @@ pub(crate) struct AssociatedConstWithSimilarNameExists { } #[derive(Diagnostic)] -#[diag(resolve_variable_bound_with_different_mode, code = E0409)] +#[diag("variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`", code = E0409)] pub(crate) struct VariableBoundWithDifferentMode { #[primary_span] - #[label] + #[label("bound in different ways")] pub(crate) span: Span, - #[label(resolve_first_binding_span)] + #[label("first binding")] pub(crate) first_binding_span: Span, pub(crate) variable_name: Ident, } #[derive(Diagnostic)] -#[diag(resolve_ident_bound_more_than_once_in_parameter_list, code = E0415)] +#[diag("identifier `{$identifier}` is bound more than once in this parameter list", code = E0415)] pub(crate) struct IdentifierBoundMoreThanOnceInParameterList { #[primary_span] - #[label] + #[label("used as parameter more than once")] pub(crate) span: Span, pub(crate) identifier: Ident, } #[derive(Diagnostic)] -#[diag(resolve_ident_bound_more_than_once_in_same_pattern, code = E0416)] +#[diag("identifier `{$identifier}` is bound more than once in the same pattern", code = E0416)] pub(crate) struct IdentifierBoundMoreThanOnceInSamePattern { #[primary_span] - #[label] + #[label("used in a pattern more than once")] pub(crate) span: Span, pub(crate) identifier: Ident, } #[derive(Diagnostic)] -#[diag(resolve_undeclared_label, code = E0426)] +#[diag("use of undeclared label `{$name}`", code = E0426)] pub(crate) struct UndeclaredLabel { #[primary_span] - #[label] + #[label("undeclared label `{$name}`")] pub(crate) span: Span, pub(crate) name: Symbol, #[subdiagnostic] @@ -211,12 +226,12 @@ pub(crate) struct UndeclaredLabel { } #[derive(Subdiagnostic)] -#[label(resolve_label_with_similar_name_reachable)] +#[label("a label with a similar name is reachable")] pub(crate) struct LabelWithSimilarNameReachable(#[primary_span] pub(crate) Span); #[derive(Subdiagnostic)] #[suggestion( - resolve_try_using_similarly_named_label, + "try using similarly named label", code = "{ident_name}", applicability = "maybe-incorrect" )] @@ -227,38 +242,38 @@ pub(crate) struct TryUsingSimilarlyNamedLabel { } #[derive(Subdiagnostic)] -#[label(resolve_unreachable_label_with_similar_name_exists)] +#[label("a label with a similar name exists but is unreachable")] pub(crate) struct UnreachableLabelWithSimilarNameExists { #[primary_span] pub(crate) ident_span: Span, } #[derive(Diagnostic)] -#[diag(resolve_self_import_can_only_appear_once_in_the_list, code = E0430)] +#[diag("`self` import can only appear once in an import list", code = E0430)] pub(crate) struct SelfImportCanOnlyAppearOnceInTheList { #[primary_span] - #[label] + #[label("can only appear once in an import list")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_self_import_only_in_import_list_with_non_empty_prefix, code = E0431)] +#[diag("`self` import can only appear in an import list with a non-empty prefix", code = E0431)] pub(crate) struct SelfImportOnlyInImportListWithNonEmptyPrefix { #[primary_span] - #[label] + #[label("can only appear in an import list with a non-empty prefix")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_cannot_capture_dynamic_environment_in_fn_item, code = E0434)] -#[help] +#[diag("can't capture dynamic environment in a fn item", code = E0434)] +#[help("use the `|| {\"{\"} ... {\"}\"}` closure form instead")] pub(crate) struct CannotCaptureDynamicEnvironmentInFnItem { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_attempt_to_use_non_constant_value_in_constant, code = E0435)] +#[diag("attempt to use a non-constant value in a constant", code = E0435)] pub(crate) struct AttemptToUseNonConstantValueInConstant<'a> { #[primary_span] pub(crate) span: Span, @@ -272,7 +287,7 @@ pub(crate) struct AttemptToUseNonConstantValueInConstant<'a> { #[derive(Subdiagnostic)] #[multipart_suggestion( - resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion, + "consider using `{$suggestion}` instead of `{$current}`", style = "verbose", applicability = "has-placeholders" )] @@ -287,14 +302,14 @@ pub(crate) struct AttemptToUseNonConstantValueInConstantWithSuggestion<'a> { } #[derive(Subdiagnostic)] -#[label(resolve_attempt_to_use_non_constant_value_in_constant_label_with_suggestion)] +#[label("non-constant value")] pub(crate) struct AttemptToUseNonConstantValueInConstantLabelWithSuggestion { #[primary_span] pub(crate) span: Span, } #[derive(Subdiagnostic)] -#[label(resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion)] +#[label("this would need to be a `{$suggestion}`")] pub(crate) struct AttemptToUseNonConstantValueInConstantWithoutSuggestion<'a> { #[primary_span] pub(crate) ident_span: Span, @@ -302,7 +317,7 @@ pub(crate) struct AttemptToUseNonConstantValueInConstantWithoutSuggestion<'a> { } #[derive(Diagnostic)] -#[diag(resolve_self_imports_only_allowed_within, code = E0429)] +#[diag("`self` imports are only allowed within a {\"{\"} {\"}\"} list", code = E0429)] pub(crate) struct SelfImportsOnlyAllowedWithin { #[primary_span] pub(crate) span: Span, @@ -314,7 +329,7 @@ pub(crate) struct SelfImportsOnlyAllowedWithin { #[derive(Subdiagnostic)] #[suggestion( - resolve_self_imports_only_allowed_within_suggestion, + "consider importing the module directly", code = "", applicability = "machine-applicable" )] @@ -325,7 +340,7 @@ pub(crate) struct SelfImportsOnlyAllowedWithinSuggestion { #[derive(Subdiagnostic)] #[multipart_suggestion( - resolve_self_imports_only_allowed_within_multipart_suggestion, + "alternatively, use the multi-path `use` syntax to import `self`", applicability = "machine-applicable" )] pub(crate) struct SelfImportsOnlyAllowedWithinMultipartSuggestion { @@ -336,17 +351,17 @@ pub(crate) struct SelfImportsOnlyAllowedWithinMultipartSuggestion { } #[derive(Diagnostic)] -#[diag(resolve_binding_shadows_something_unacceptable, code = E0530)] +#[diag("{$shadowing_binding}s cannot shadow {$shadowed_binding}s", code = E0530)] pub(crate) struct BindingShadowsSomethingUnacceptable<'a> { #[primary_span] - #[label] + #[label("cannot be named the same as {$article} {$shadowed_binding}")] pub(crate) span: Span, pub(crate) shadowing_binding: PatternSource, pub(crate) shadowed_binding: Res, pub(crate) article: &'a str, #[subdiagnostic] pub(crate) sub_suggestion: Option, - #[label(resolve_label_shadowed_binding)] + #[label("the {$shadowed_binding} `{$name}` is {$participle} here")] pub(crate) shadowed_binding_span: Span, pub(crate) participle: &'a str, pub(crate) name: Symbol, @@ -354,7 +369,7 @@ pub(crate) struct BindingShadowsSomethingUnacceptable<'a> { #[derive(Subdiagnostic)] #[suggestion( - resolve_binding_shadows_something_unacceptable_suggestion, + "try specify the pattern arguments", code = "{name}(..)", applicability = "unspecified" )] @@ -365,51 +380,51 @@ pub(crate) struct BindingShadowsSomethingUnacceptableSuggestion { } #[derive(Diagnostic)] -#[diag(resolve_forward_declared_generic_param, code = E0128)] +#[diag("generic parameter defaults cannot reference parameters before they are declared", code = E0128)] pub(crate) struct ForwardDeclaredGenericParam { #[primary_span] - #[label] + #[label("cannot reference `{$param}` before it is declared")] pub(crate) span: Span, pub(crate) param: Symbol, } #[derive(Diagnostic)] -#[diag(resolve_forward_declared_generic_in_const_param_ty)] +#[diag("const parameter types cannot reference parameters before they are declared")] pub(crate) struct ForwardDeclaredGenericInConstParamTy { #[primary_span] - #[label] + #[label("const parameter type cannot reference `{$param}` before it is declared")] pub(crate) span: Span, pub(crate) param: Symbol, } #[derive(Diagnostic)] -#[diag(resolve_param_in_ty_of_const_param, code = E0770)] +#[diag("the type of const parameters must not depend on other generic parameters", code = E0770)] pub(crate) struct ParamInTyOfConstParam { #[primary_span] - #[label] + #[label("the type must not depend on the parameter `{$name}`")] pub(crate) span: Span, pub(crate) name: Symbol, } #[derive(Diagnostic)] -#[diag(resolve_self_in_generic_param_default, code = E0735)] +#[diag("generic parameters cannot use `Self` in their defaults", code = E0735)] pub(crate) struct SelfInGenericParamDefault { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_self_in_const_generic_ty)] +#[diag("cannot use `Self` in const parameter type")] pub(crate) struct SelfInConstGenericTy { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_param_in_non_trivial_anon_const)] +#[diag("generic parameters may not be used in const operations")] pub(crate) struct ParamInNonTrivialAnonConst { #[primary_span] - #[label] + #[label("cannot perform const operation using `{$name}`")] pub(crate) span: Span, pub(crate) name: Symbol, #[subdiagnostic] @@ -419,29 +434,29 @@ pub(crate) struct ParamInNonTrivialAnonConst { } #[derive(Subdiagnostic)] -#[help(resolve_param_in_non_trivial_anon_const_help)] +#[help("add `#![feature(generic_const_exprs)]` to allow generic const expressions")] pub(crate) struct ParamInNonTrivialAnonConstHelp; #[derive(Debug)] #[derive(Subdiagnostic)] pub(crate) enum ParamKindInNonTrivialAnonConst { - #[note(resolve_type_param_in_non_trivial_anon_const)] + #[note("type parameters may not be used in const expressions")] Type, - #[help(resolve_const_param_in_non_trivial_anon_const)] + #[help("const parameters may only be used as standalone arguments here, i.e. `{$name}`")] Const { name: Symbol }, - #[note(resolve_lifetime_param_in_non_trivial_anon_const)] + #[note("lifetime parameters may not be used in const expressions")] Lifetime, } #[derive(Diagnostic)] -#[diag(resolve_unreachable_label, code = E0767)] -#[note] +#[diag("use of unreachable label `{$name}`", code = E0767)] +#[note("labels are unreachable through functions, closures, async blocks and modules")] pub(crate) struct UnreachableLabel { #[primary_span] - #[label] + #[label("unreachable label `{$name}`")] pub(crate) span: Span, pub(crate) name: Symbol, - #[label(resolve_label_definition_span)] + #[label("unreachable label defined here")] pub(crate) definition_span: Span, #[subdiagnostic] pub(crate) sub_suggestion: Option, @@ -453,7 +468,7 @@ pub(crate) struct UnreachableLabel { #[derive(Subdiagnostic)] #[suggestion( - resolve_unreachable_label_suggestion_use_similarly_named, + "try using similarly named label", code = "{ident_name}", applicability = "maybe-incorrect" )] @@ -464,104 +479,114 @@ pub(crate) struct UnreachableLabelSubSuggestion { } #[derive(Subdiagnostic)] -#[label(resolve_unreachable_label_similar_name_reachable)] +#[label("a label with a similar name is reachable")] pub(crate) struct UnreachableLabelSubLabel { #[primary_span] pub(crate) ident_span: Span, } #[derive(Subdiagnostic)] -#[label(resolve_unreachable_label_similar_name_unreachable)] +#[label("a label with a similar name exists but is also unreachable")] pub(crate) struct UnreachableLabelSubLabelUnreachable { #[primary_span] pub(crate) ident_span: Span, } #[derive(Diagnostic)] -#[diag(resolve_invalid_asm_sym)] -#[help] +#[diag("invalid `sym` operand")] +#[help("`sym` operands must refer to either a function or a static")] pub(crate) struct InvalidAsmSym { #[primary_span] - #[label] + #[label("is a local variable")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_lowercase_self)] +#[diag("attempt to use a non-constant value in a constant")] pub(crate) struct LowercaseSelf { #[primary_span] - #[suggestion(code = "Self", applicability = "maybe-incorrect", style = "short")] + #[suggestion( + "try using `Self`", + code = "Self", + applicability = "maybe-incorrect", + style = "short" + )] pub(crate) span: Span, } #[derive(Debug)] #[derive(Diagnostic)] -#[diag(resolve_binding_in_never_pattern)] +#[diag("never patterns cannot contain variable bindings")] pub(crate) struct BindingInNeverPattern { #[primary_span] - #[suggestion(code = "_", applicability = "machine-applicable", style = "short")] + #[suggestion( + "use a wildcard `_` instead", + code = "_", + applicability = "machine-applicable", + style = "short" + )] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_trait_impl_duplicate, code = E0201)] +#[diag("duplicate definitions with name `{$name}`:", code = E0201)] pub(crate) struct TraitImplDuplicate { #[primary_span] - #[label] + #[label("duplicate definition")] pub(crate) span: Span, - #[label(resolve_old_span_label)] + #[label("previous definition here")] pub(crate) old_span: Span, - #[label(resolve_trait_item_span)] + #[label("item in trait")] pub(crate) trait_item_span: Span, pub(crate) name: Ident, } #[derive(Diagnostic)] -#[diag(resolve_relative_2018)] +#[diag("relative paths are not supported in visibilities in 2018 edition or later")] pub(crate) struct Relative2018 { #[primary_span] pub(crate) span: Span, - #[suggestion(code = "crate::{path_str}", applicability = "maybe-incorrect")] + #[suggestion("try", code = "crate::{path_str}", applicability = "maybe-incorrect")] pub(crate) path_span: Span, pub(crate) path_str: String, } #[derive(Diagnostic)] -#[diag(resolve_ancestor_only, code = E0742)] +#[diag("visibilities can only be restricted to ancestor modules", code = E0742)] pub(crate) struct AncestorOnly(#[primary_span] pub(crate) Span); #[derive(Diagnostic)] -#[diag(resolve_expected_module_found, code = E0577)] +#[diag("expected module, found {$res} `{$path_str}`", code = E0577)] pub(crate) struct ExpectedModuleFound { #[primary_span] - #[label] + #[label("not a module")] pub(crate) span: Span, pub(crate) res: Res, pub(crate) path_str: String, } #[derive(Diagnostic)] -#[diag(resolve_indeterminate, code = E0578)] +#[diag("cannot determine resolution for the visibility", code = E0578)] pub(crate) struct Indeterminate(#[primary_span] pub(crate) Span); #[derive(Diagnostic)] -#[diag(resolve_tool_module_imported)] +#[diag("cannot use a tool module through an import")] pub(crate) struct ToolModuleImported { #[primary_span] pub(crate) span: Span, - #[note] + #[note("the tool module imported here")] pub(crate) import: Span, } #[derive(Diagnostic)] -#[diag(resolve_module_only)] +#[diag("visibility must resolve to a module")] pub(crate) struct ModuleOnly(#[primary_span] pub(crate) Span); #[derive(Diagnostic)] -#[diag(resolve_macro_expected_found)] +#[diag("expected {$expected}, found {$found} `{$macro_path}`")] pub(crate) struct MacroExpectedFound<'a> { #[primary_span] - #[label] + #[label("not {$article} {$expected}")] pub(crate) span: Span, pub(crate) found: &'a str, pub(crate) article: &'static str, @@ -574,60 +599,66 @@ pub(crate) struct MacroExpectedFound<'a> { } #[derive(Subdiagnostic)] -#[help(resolve_remove_surrounding_derive)] +#[help("remove from the surrounding `derive()`")] pub(crate) struct RemoveSurroundingDerive { #[primary_span] pub(crate) span: Span, } #[derive(Subdiagnostic)] -#[help(resolve_add_as_non_derive)] +#[help( + " + add as non-Derive macro + `#[{$macro_path}]`" +)] pub(crate) struct AddAsNonDerive<'a> { pub(crate) macro_path: &'a str, } #[derive(Diagnostic)] -#[diag(resolve_proc_macro_same_crate)] +#[diag("can't use a procedural macro from the same crate that defines it")] pub(crate) struct ProcMacroSameCrate { #[primary_span] pub(crate) span: Span, - #[help] + #[help("you can define integration tests in a directory named `tests`")] pub(crate) is_test: bool, } #[derive(LintDiagnostic)] -#[diag(resolve_proc_macro_derive_resolution_fallback)] +#[diag("cannot find {$ns_descr} `{$ident}` in this scope")] pub(crate) struct ProcMacroDeriveResolutionFallback { - #[label] + #[label("names from parent modules are not accessible without an explicit import")] pub span: Span, pub ns_descr: &'static str, pub ident: Symbol, } #[derive(LintDiagnostic)] -#[diag(resolve_macro_expanded_macro_exports_accessed_by_absolute_paths)] +#[diag( + "macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths" +)] pub(crate) struct MacroExpandedMacroExportsAccessedByAbsolutePaths { - #[note] + #[note("the macro is defined here")] pub definition: Span, } #[derive(Diagnostic)] -#[diag(resolve_imported_crate)] +#[diag("`$crate` may not be imported")] pub(crate) struct CrateImported { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_macro_use_extern_crate_self)] +#[diag("`#[macro_use]` is not supported on `extern crate self`")] pub(crate) struct MacroUseExternCrateSelf { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_accessible_unsure)] -#[note] +#[diag("not sure whether the path is accessible or not")] +#[note("the type may have associated items, but we are currently not checking them")] pub(crate) struct CfgAccessibleUnsure { #[primary_span] pub(crate) span: Span, @@ -635,10 +666,10 @@ pub(crate) struct CfgAccessibleUnsure { #[derive(Debug)] #[derive(Diagnostic)] -#[diag(resolve_param_in_enum_discriminant)] +#[diag("generic parameters may not be used in enum discriminant values")] pub(crate) struct ParamInEnumDiscriminant { #[primary_span] - #[label] + #[label("cannot perform const operation using `{$name}`")] pub(crate) span: Span, pub(crate) name: Symbol, #[subdiagnostic] @@ -648,16 +679,16 @@ pub(crate) struct ParamInEnumDiscriminant { #[derive(Debug)] #[derive(Subdiagnostic)] pub(crate) enum ParamKindInEnumDiscriminant { - #[note(resolve_type_param_in_enum_discriminant)] + #[note("type parameters may not be used in enum discriminant values")] Type, - #[note(resolve_const_param_in_enum_discriminant)] + #[note("const parameters may not be used in enum discriminant values")] Const, - #[note(resolve_lifetime_param_in_enum_discriminant)] + #[note("lifetime parameters may not be used in enum discriminant values")] Lifetime, } #[derive(Subdiagnostic)] -#[label(resolve_change_import_binding)] +#[label("you can use `as` to change the binding name of the import")] pub(crate) struct ChangeImportBinding { #[primary_span] pub(crate) span: Span, @@ -665,7 +696,7 @@ pub(crate) struct ChangeImportBinding { #[derive(Subdiagnostic)] #[suggestion( - resolve_change_import_binding, + "you can use `as` to change the binding name of the import", code = "{suggestion}", applicability = "maybe-incorrect" )] @@ -676,7 +707,7 @@ pub(crate) struct ChangeImportBindingSuggestion { } #[derive(Diagnostic)] -#[diag(resolve_imports_cannot_refer_to)] +#[diag("imports cannot refer to {$what}")] pub(crate) struct ImportsCannotReferTo<'a> { #[primary_span] pub(crate) span: Span, @@ -684,7 +715,7 @@ pub(crate) struct ImportsCannotReferTo<'a> { } #[derive(Diagnostic)] -#[diag(resolve_cannot_find_ident_in_this_scope)] +#[diag("cannot find {$expected} `{$ident}` in this scope")] pub(crate) struct CannotFindIdentInThisScope<'a> { #[primary_span] pub(crate) span: Span, @@ -693,7 +724,7 @@ pub(crate) struct CannotFindIdentInThisScope<'a> { } #[derive(Subdiagnostic)] -#[note(resolve_explicit_unsafe_traits)] +#[note("unsafe traits like `{$ident}` should be implemented explicitly")] pub(crate) struct ExplicitUnsafeTraits { #[primary_span] pub(crate) span: Span, @@ -701,14 +732,14 @@ pub(crate) struct ExplicitUnsafeTraits { } #[derive(Subdiagnostic)] -#[note(resolve_macro_defined_later)] +#[note("a macro with the same name exists, but it appears later")] pub(crate) struct MacroDefinedLater { #[primary_span] pub(crate) span: Span, } #[derive(Subdiagnostic)] -#[label(resolve_consider_move_macro_position)] +#[label("consider moving the definition of `{$ident}` before this call")] pub(crate) struct MacroSuggMovePosition { #[primary_span] pub(crate) span: Span, @@ -717,19 +748,19 @@ pub(crate) struct MacroSuggMovePosition { #[derive(Subdiagnostic)] pub(crate) enum MacroRulesNot { - #[label(resolve_macro_cannot_use_as_fn_like)] + #[label("`{$ident}` exists, but has no rules for function-like invocation")] Func { #[primary_span] span: Span, ident: Ident, }, - #[label(resolve_macro_cannot_use_as_attr)] + #[label("`{$ident}` exists, but has no `attr` rules")] Attr { #[primary_span] span: Span, ident: Ident, }, - #[label(resolve_macro_cannot_use_as_derive)] + #[label("`{$ident}` exists, but has no `derive` rules")] Derive { #[primary_span] span: Span, @@ -738,22 +769,18 @@ pub(crate) enum MacroRulesNot { } #[derive(Subdiagnostic)] -#[note(resolve_missing_macro_rules_name)] +#[note("maybe you have forgotten to define a name for this `macro_rules!`")] pub(crate) struct MaybeMissingMacroRulesName { #[primary_span] pub(crate) spans: MultiSpan, } #[derive(Subdiagnostic)] -#[help(resolve_added_macro_use)] +#[help("have you added the `#[macro_use]` on the module/import?")] pub(crate) struct AddedMacroUse; #[derive(Subdiagnostic)] -#[suggestion( - resolve_consider_adding_a_derive, - code = "{suggestion}", - applicability = "maybe-incorrect" -)] +#[suggestion("consider adding a derive", code = "{suggestion}", applicability = "maybe-incorrect")] pub(crate) struct ConsiderAddingADerive { #[primary_span] pub(crate) span: Span, @@ -761,15 +788,15 @@ pub(crate) struct ConsiderAddingADerive { } #[derive(Diagnostic)] -#[diag(resolve_cannot_determine_import_resolution)] +#[diag("cannot determine resolution for the import")] pub(crate) struct CannotDetermineImportResolution { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_cannot_determine_macro_resolution)] -#[note] +#[diag("cannot determine resolution for the {$kind} `{$path}`")] +#[note("import resolution is stuck, try simplifying macro imports")] pub(crate) struct CannotDetermineMacroResolution { #[primary_span] pub(crate) span: Span, @@ -778,7 +805,7 @@ pub(crate) struct CannotDetermineMacroResolution { } #[derive(Diagnostic)] -#[diag(resolve_cannot_be_reexported_private, code = E0364)] +#[diag("`{$ident}` is private, and cannot be re-exported", code = E0364)] pub(crate) struct CannotBeReexportedPrivate { #[primary_span] pub(crate) span: Span, @@ -786,7 +813,7 @@ pub(crate) struct CannotBeReexportedPrivate { } #[derive(Diagnostic)] -#[diag(resolve_cannot_be_reexported_crate_public, code = E0364)] +#[diag("`{$ident}` is only public within the crate, and cannot be re-exported outside", code = E0364)] pub(crate) struct CannotBeReexportedCratePublic { #[primary_span] pub(crate) span: Span, @@ -794,35 +821,40 @@ pub(crate) struct CannotBeReexportedCratePublic { } #[derive(Diagnostic)] -#[diag(resolve_cannot_be_reexported_private, code = E0365)] -#[note(resolve_consider_declaring_with_pub)] +#[diag("`{$ident}` is private, and cannot be re-exported", code = E0365)] +#[note("consider declaring type or module `{$ident}` with `pub`")] pub(crate) struct CannotBeReexportedPrivateNS { #[primary_span] - #[label(resolve_reexport_of_private)] + #[label("re-export of private `{$ident}`")] pub(crate) span: Span, pub(crate) ident: Ident, } #[derive(Diagnostic)] -#[diag(resolve_cannot_be_reexported_crate_public, code = E0365)] -#[note(resolve_consider_declaring_with_pub)] +#[diag("`{$ident}` is only public within the crate, and cannot be re-exported outside", code = E0365)] +#[note("consider declaring type or module `{$ident}` with `pub`")] pub(crate) struct CannotBeReexportedCratePublicNS { #[primary_span] - #[label(resolve_reexport_of_crate_public)] + #[label("re-export of crate public `{$ident}`")] pub(crate) span: Span, pub(crate) ident: Ident, } #[derive(LintDiagnostic)] -#[diag(resolve_private_extern_crate_reexport, code = E0365)] +#[diag("extern crate `{$ident}` is private and cannot be re-exported", code = E0365)] pub(crate) struct PrivateExternCrateReexport { pub ident: Ident, - #[suggestion(code = "pub ", style = "verbose", applicability = "maybe-incorrect")] + #[suggestion( + "consider making the `extern crate` item publicly accessible", + code = "pub ", + style = "verbose", + applicability = "maybe-incorrect" + )] pub sugg: Span, } #[derive(Subdiagnostic)] -#[help(resolve_consider_adding_macro_export)] +#[help("consider adding a `#[macro_export]` to the macro in the imported module")] pub(crate) struct ConsiderAddingMacroExport { #[primary_span] pub(crate) span: Span, @@ -830,7 +862,7 @@ pub(crate) struct ConsiderAddingMacroExport { #[derive(Subdiagnostic)] #[suggestion( - resolve_consider_marking_as_pub_crate, + "in case you want to use the macro within this crate only, reduce the visibility to `pub(crate)`", code = "pub(crate)", applicability = "maybe-incorrect" )] @@ -840,7 +872,7 @@ pub(crate) struct ConsiderMarkingAsPubCrate { } #[derive(Subdiagnostic)] -#[note(resolve_consider_marking_as_pub)] +#[note("consider marking `{$ident}` as `pub` in the imported module")] pub(crate) struct ConsiderMarkingAsPub { #[primary_span] pub(crate) span: Span, @@ -848,7 +880,7 @@ pub(crate) struct ConsiderMarkingAsPub { } #[derive(Diagnostic)] -#[diag(resolve_cannot_glob_import_possible_crates)] +#[diag("cannot glob-import all possible crates")] pub(crate) struct CannotGlobImportAllCrates { #[primary_span] pub(crate) span: Span, @@ -856,7 +888,7 @@ pub(crate) struct CannotGlobImportAllCrates { #[derive(Subdiagnostic)] #[suggestion( - resolve_unexpected_res_change_ty_to_const_param_sugg, + "you might have meant to write a const parameter here", code = "const ", style = "verbose" )] @@ -869,7 +901,7 @@ pub(crate) struct UnexpectedResChangeTyToConstParamSugg { #[derive(Subdiagnostic)] #[multipart_suggestion( - resolve_unexpected_res_change_ty_to_const_param_sugg, + "you might have meant to write a const parameter here", applicability = "has-placeholders", style = "verbose" )] @@ -882,7 +914,7 @@ pub(crate) struct UnexpectedResChangeTyParamToConstParamSugg { #[derive(Subdiagnostic)] #[suggestion( - resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg, + "if you meant to collect the rest of the slice in `{$ident}`, use the at operator", code = "{snippet}", applicability = "maybe-incorrect", style = "verbose" @@ -895,23 +927,27 @@ pub(crate) struct UnexpectedResUseAtOpInSlicePatWithRangeSugg { } #[derive(Diagnostic)] -#[diag(resolve_extern_crate_loading_macro_not_at_crate_root, code = E0468)] +#[diag("an `extern crate` loading macros must be at the crate root", code = E0468)] pub(crate) struct ExternCrateLoadingMacroNotAtCrateRoot { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_extern_crate_self_requires_renaming)] +#[diag("`extern crate self;` requires renaming")] pub(crate) struct ExternCrateSelfRequiresRenaming { #[primary_span] - #[suggestion(code = "extern crate self as name;", applicability = "has-placeholders")] + #[suggestion( + "rename the `self` crate to be able to import it", + code = "extern crate self as name;", + applicability = "has-placeholders" + )] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_macro_use_name_already_in_use)] -#[note] +#[diag("`{$name}` is already in scope")] +#[note("macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)")] pub(crate) struct MacroUseNameAlreadyInUse { #[primary_span] pub(crate) span: Span, @@ -919,74 +955,80 @@ pub(crate) struct MacroUseNameAlreadyInUse { } #[derive(Diagnostic)] -#[diag(resolve_imported_macro_not_found, code = E0469)] +#[diag("imported macro not found", code = E0469)] pub(crate) struct ImportedMacroNotFound { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_macro_extern_deprecated)] +#[diag("`#[macro_escape]` is a deprecated synonym for `#[macro_use]`")] pub(crate) struct MacroExternDeprecated { #[primary_span] pub(crate) span: Span, - #[help] + #[help("try an outer attribute: `#[macro_use]`")] pub inner_attribute: bool, } #[derive(Diagnostic)] -#[diag(resolve_arguments_macro_use_not_allowed)] +#[diag("arguments to `macro_use` are not allowed here")] pub(crate) struct ArgumentsMacroUseNotAllowed { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_unnamed_crate_root_import)] +#[diag("crate root imports need to be explicitly named: `use crate as name;`")] pub(crate) struct UnnamedCrateRootImport { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments)] +#[diag("macro-expanded `extern crate` items cannot shadow names passed with `--extern`")] pub(crate) struct MacroExpandedExternCrateCannotShadowExternArguments { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_elided_anonymous_lifetime_report_error, code = E0637)] +#[diag("`&` without an explicit lifetime name cannot be used here", code = E0637)] pub(crate) struct ElidedAnonymousLifetimeReportError { #[primary_span] - #[label] + #[label("explicit lifetime name needed here")] pub(crate) span: Span, #[subdiagnostic] pub(crate) suggestion: Option, } #[derive(Diagnostic)] -#[diag(resolve_lending_iterator_report_error)] +#[diag( + "associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type" +)] pub(crate) struct LendingIteratorReportError { #[primary_span] pub(crate) lifetime: Span, - #[note] + #[note( + "you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type" + )] pub(crate) ty: Span, } #[derive(Diagnostic)] -#[diag(resolve_anonymous_lifetime_non_gat_report_error)] +#[diag("missing lifetime in associated type")] pub(crate) struct AnonymousLifetimeNonGatReportError { #[primary_span] - #[label] + #[label("this lifetime must come from the implemented type")] pub(crate) lifetime: Span, - #[note] + #[note( + "in the trait the associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type" + )] pub(crate) decl: MultiSpan, } #[derive(Subdiagnostic)] #[multipart_suggestion( - resolve_elided_anonymous_lifetime_report_error_suggestion, + "consider introducing a higher-ranked lifetime here", applicability = "machine-applicable" )] pub(crate) struct ElidedAnonymousLifetimeReportErrorSuggestion { @@ -997,15 +1039,15 @@ pub(crate) struct ElidedAnonymousLifetimeReportErrorSuggestion { } #[derive(Diagnostic)] -#[diag(resolve_explicit_anonymous_lifetime_report_error, code = E0637)] +#[diag("`'_` cannot be used here", code = E0637)] pub(crate) struct ExplicitAnonymousLifetimeReportError { #[primary_span] - #[label] + #[label("`'_` is a reserved lifetime name")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_implicit_elided_lifetimes_not_allowed_here, code = E0726)] +#[diag("implicit elided lifetime not allowed here", code = E0726)] pub(crate) struct ImplicitElidedLifetimeNotAllowedHere { #[primary_span] pub(crate) span: Span, @@ -1014,25 +1056,25 @@ pub(crate) struct ImplicitElidedLifetimeNotAllowedHere { } #[derive(Diagnostic)] -#[diag(resolve_underscore_lifetime_is_reserved, code = E0637)] -#[help] +#[diag("`'_` cannot be used here", code = E0637)] +#[help("use another lifetime specifier")] pub(crate) struct UnderscoreLifetimeIsReserved { #[primary_span] - #[label] + #[label("`'_` is a reserved lifetime name")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_static_lifetime_is_reserved, code = E0262)] +#[diag("invalid lifetime parameter name: `{$lifetime}`", code = E0262)] pub(crate) struct StaticLifetimeIsReserved { #[primary_span] - #[label] + #[label("'static is a reserved lifetime name")] pub(crate) span: Span, pub(crate) lifetime: Ident, } #[derive(Diagnostic)] -#[diag(resolve_variable_is_not_bound_in_all_patterns, code = E0408)] +#[diag("variable `{$name}` is not bound in all patterns", code = E0408)] pub(crate) struct VariableIsNotBoundInAllPatterns { #[primary_span] pub(crate) multispan: MultiSpan, @@ -1040,7 +1082,7 @@ pub(crate) struct VariableIsNotBoundInAllPatterns { } #[derive(Subdiagnostic, Debug, Clone)] -#[label(resolve_pattern_doesnt_bind_name)] +#[label("pattern doesn't bind `{$name}`")] pub(crate) struct PatternDoesntBindName { #[primary_span] pub(crate) span: Span, @@ -1048,7 +1090,7 @@ pub(crate) struct PatternDoesntBindName { } #[derive(Subdiagnostic, Debug, Clone)] -#[label(resolve_variable_not_in_all_patterns)] +#[label("variable not in all patterns")] pub(crate) struct VariableNotInAllPatterns { #[primary_span] pub(crate) span: Span, @@ -1056,7 +1098,7 @@ pub(crate) struct VariableNotInAllPatterns { #[derive(Subdiagnostic)] #[multipart_suggestion( - resolve_variable_is_a_typo, + "you might have meant to use the similarly named previously used binding `{$typo}`", applicability = "maybe-incorrect", style = "verbose" )] @@ -1067,8 +1109,8 @@ pub(crate) struct PatternBindingTypo { } #[derive(Diagnostic)] -#[diag(resolve_name_defined_multiple_time)] -#[note] +#[diag("the name `{$name}` is defined multiple times")] +#[note("`{$name}` must be defined only once in the {$descr} namespace of this {$container}")] pub(crate) struct NameDefinedMultipleTime { #[primary_span] pub(crate) span: Span, @@ -1083,12 +1125,12 @@ pub(crate) struct NameDefinedMultipleTime { #[derive(Subdiagnostic)] pub(crate) enum NameDefinedMultipleTimeLabel { - #[label(resolve_name_defined_multiple_time_reimported)] + #[label("`{$name}` reimported here")] Reimported { #[primary_span] span: Span, }, - #[label(resolve_name_defined_multiple_time_redefined)] + #[label("`{$name}` redefined here")] Redefined { #[primary_span] span: Span, @@ -1097,13 +1139,13 @@ pub(crate) enum NameDefinedMultipleTimeLabel { #[derive(Subdiagnostic)] pub(crate) enum NameDefinedMultipleTimeOldBindingLabel { - #[label(resolve_name_defined_multiple_time_old_binding_import)] + #[label("previous import of the {$old_kind} `{$name}` here")] Import { #[primary_span] span: Span, old_kind: &'static str, }, - #[label(resolve_name_defined_multiple_time_old_binding_definition)] + #[label("previous definition of the {$old_kind} `{$name}` here")] Definition { #[primary_span] span: Span, @@ -1112,42 +1154,42 @@ pub(crate) enum NameDefinedMultipleTimeOldBindingLabel { } #[derive(Diagnostic)] -#[diag(resolve_is_private, code = E0603)] +#[diag("{$ident_descr} `{$ident}` is private", code = E0603)] pub(crate) struct IsPrivate<'a> { #[primary_span] - #[label] + #[label("private {$ident_descr}")] pub(crate) span: Span, pub(crate) ident_descr: &'a str, pub(crate) ident: Ident, } #[derive(Diagnostic)] -#[diag(resolve_generic_arguments_in_macro_path)] +#[diag("generic arguments in macro path")] pub(crate) struct GenericArgumentsInMacroPath { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_attributes_starting_with_rustc_are_reserved)] +#[diag("attributes starting with `rustc` are reserved for use by the `rustc` compiler")] pub(crate) struct AttributesStartingWithRustcAreReserved { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(resolve_cannot_use_through_an_import)] +#[diag("cannot use {$article} {$descr} through an import")] pub(crate) struct CannotUseThroughAnImport { #[primary_span] pub(crate) span: Span, pub(crate) article: &'static str, pub(crate) descr: &'static str, - #[note] + #[note("the {$descr} imported here")] pub(crate) binding_span: Option, } #[derive(Diagnostic)] -#[diag(resolve_name_reserved_in_attribute_namespace)] +#[diag("name `{$ident}` is reserved in attribute namespace")] pub(crate) struct NameReservedInAttributeNamespace { #[primary_span] pub(crate) span: Span, @@ -1155,7 +1197,7 @@ pub(crate) struct NameReservedInAttributeNamespace { } #[derive(Diagnostic)] -#[diag(resolve_cannot_find_builtin_macro_with_name)] +#[diag("cannot find a built-in macro with name `{$ident}`")] pub(crate) struct CannotFindBuiltinMacroWithName { #[primary_span] pub(crate) span: Span, @@ -1163,34 +1205,34 @@ pub(crate) struct CannotFindBuiltinMacroWithName { } #[derive(Diagnostic)] -#[diag(resolve_tool_was_already_registered)] +#[diag("tool `{$tool}` was already registered")] pub(crate) struct ToolWasAlreadyRegistered { #[primary_span] pub(crate) span: Span, pub(crate) tool: Ident, - #[label] + #[label("already registered here")] pub(crate) old_ident_span: Span, } #[derive(Diagnostic)] -#[diag(resolve_tool_only_accepts_identifiers)] +#[diag("`{$tool}` only accepts identifiers")] pub(crate) struct ToolOnlyAcceptsIdentifiers { #[primary_span] - #[label] + #[label("not an identifier")] pub(crate) span: Span, pub(crate) tool: Symbol, } #[derive(Subdiagnostic)] pub(crate) enum DefinedHere { - #[label(resolve_similarly_named_defined_here)] + #[label("similarly named {$candidate_descr} `{$candidate}` defined here")] SimilarlyNamed { #[primary_span] span: Span, candidate_descr: &'static str, candidate: Symbol, }, - #[label(resolve_single_item_defined_here)] + #[label("{$candidate_descr} `{$candidate}` defined here")] SingleItem { #[primary_span] span: Span, @@ -1200,7 +1242,7 @@ pub(crate) enum DefinedHere { } #[derive(Subdiagnostic)] -#[label(resolve_outer_ident_is_not_publicly_reexported)] +#[label("{$outer_ident_descr} `{$outer_ident}` is not publicly re-exported")] pub(crate) struct OuterIdentIsNotPubliclyReexported { #[primary_span] pub(crate) span: Span, @@ -1209,7 +1251,7 @@ pub(crate) struct OuterIdentIsNotPubliclyReexported { } #[derive(Subdiagnostic)] -#[label(resolve_constructor_private_if_any_field_private)] +#[label("a constructor is private if any of the fields is private")] pub(crate) struct ConstructorPrivateIfAnyFieldPrivate { #[primary_span] pub(crate) span: Span, @@ -1217,7 +1259,10 @@ pub(crate) struct ConstructorPrivateIfAnyFieldPrivate { #[derive(Subdiagnostic)] #[multipart_suggestion( - resolve_consider_making_the_field_public, + "{ $number_of_fields -> + [one] consider making the field publicly accessible + *[other] consider making the fields publicly accessible + }", applicability = "maybe-incorrect", style = "verbose" )] @@ -1230,7 +1275,7 @@ pub(crate) struct ConsiderMakingTheFieldPublic { #[derive(Subdiagnostic)] pub(crate) enum ImportIdent { #[suggestion( - resolve_suggestion_import_ident_through_reexport, + "import `{$ident}` through the re-export", code = "{path}", applicability = "machine-applicable", style = "verbose" @@ -1242,7 +1287,7 @@ pub(crate) enum ImportIdent { path: String, }, #[suggestion( - resolve_suggestion_import_ident_directly, + "import `{$ident}` directly", code = "{path}", applicability = "machine-applicable", style = "verbose" @@ -1256,7 +1301,18 @@ pub(crate) enum ImportIdent { } #[derive(Subdiagnostic)] -#[note(resolve_note_and_refers_to_the_item_defined_here)] +#[note( + "{$first -> + [true] {$dots -> + [true] the {$binding_descr} `{$binding_name}` is defined here... + *[false] the {$binding_descr} `{$binding_name}` is defined here + } + *[false] {$dots -> + [true] ...and refers to the {$binding_descr} `{$binding_name}` which is defined here... + *[false] ...and refers to the {$binding_descr} `{$binding_name}` which is defined here + } + }" +)] pub(crate) struct NoteAndRefersToTheItemDefinedHere<'a> { #[primary_span] pub(crate) span: MultiSpan, @@ -1267,7 +1323,7 @@ pub(crate) struct NoteAndRefersToTheItemDefinedHere<'a> { } #[derive(Subdiagnostic)] -#[suggestion(resolve_remove_unnecessary_import, code = "", applicability = "maybe-incorrect")] +#[suggestion("remove unnecessary import", code = "", applicability = "maybe-incorrect")] pub(crate) struct RemoveUnnecessaryImport { #[primary_span] pub(crate) span: Span, @@ -1275,7 +1331,7 @@ pub(crate) struct RemoveUnnecessaryImport { #[derive(Subdiagnostic)] #[suggestion( - resolve_remove_unnecessary_import, + "remove unnecessary import", code = "", applicability = "maybe-incorrect", style = "tool-only" @@ -1286,7 +1342,7 @@ pub(crate) struct ToolOnlyRemoveUnnecessaryImport { } #[derive(Subdiagnostic)] -#[note(resolve_ident_imported_here_but_it_is_desc)] +#[note("`{$imported_ident}` is imported here, but it is {$imported_ident_desc}")] pub(crate) struct IdentImporterHereButItIsDesc<'a> { #[primary_span] pub(crate) span: Span, @@ -1295,7 +1351,7 @@ pub(crate) struct IdentImporterHereButItIsDesc<'a> { } #[derive(Subdiagnostic)] -#[note(resolve_ident_in_scope_but_it_is_desc)] +#[note("`{$imported_ident}` is in scope, but it is {$imported_ident_desc}")] pub(crate) struct IdentInScopeButItIsDesc<'a> { pub(crate) imported_ident: Ident, pub(crate) imported_ident_desc: &'a str, @@ -1319,50 +1375,55 @@ impl Subdiagnostic for FoundItemConfigureOut { let key = "feature".into(); let value = feature.into_diag_arg(&mut None); let msg = diag.dcx.eagerly_translate_to_string( - fluent::resolve_item_was_behind_feature, + inline_fluent!("the item is gated behind the `{$feature}` feature"), [(&key, &value)].into_iter(), ); multispan.push_span_label(span, msg); } ItemWas::CfgOut { span } => { - multispan.push_span_label(span, fluent::resolve_item_was_cfg_out); + multispan.push_span_label(span, inline_fluent!("the item is gated here")); } } - diag.span_note(multispan, fluent::resolve_found_an_item_configured_out); + diag.span_note(multispan, inline_fluent!("found an item that was configured out")); } } #[derive(Diagnostic)] -#[diag(resolve_trait_impl_mismatch)] +#[diag("item `{$name}` is an associated {$kind}, which doesn't match its trait `{$trait_path}`")] pub(crate) struct TraitImplMismatch { #[primary_span] - #[label] + #[label("does not match trait")] pub(crate) span: Span, pub(crate) name: Ident, pub(crate) kind: &'static str, pub(crate) trait_path: String, - #[label(resolve_trait_impl_mismatch_label_item)] + #[label("item in trait")] pub(crate) trait_item_span: Span, } #[derive(LintDiagnostic)] -#[diag(resolve_legacy_derive_helpers)] +#[diag("derive helper attribute is used before it is introduced")] pub(crate) struct LegacyDeriveHelpers { - #[label] + #[label("the attribute is introduced here")] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(resolve_unused_extern_crate)] +#[diag("unused extern crate")] pub(crate) struct UnusedExternCrate { - #[label] + #[label("unused")] pub span: Span, - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove the unused `extern crate`", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub removal_span: Span, } #[derive(LintDiagnostic)] -#[diag(resolve_reexport_private_dependency)] +#[diag("{$kind} `{$name}` from private dependency '{$krate}' is re-exported")] pub(crate) struct ReexportPrivateDependency { pub name: Symbol, pub kind: &'static str, @@ -1370,32 +1431,32 @@ pub(crate) struct ReexportPrivateDependency { } #[derive(LintDiagnostic)] -#[diag(resolve_unused_label)] +#[diag("unused label")] pub(crate) struct UnusedLabel; #[derive(LintDiagnostic)] -#[diag(resolve_unused_macro_use)] +#[diag("unused `#[macro_use]` import")] pub(crate) struct UnusedMacroUse; #[derive(LintDiagnostic)] -#[diag(resolve_macro_use_deprecated)] -#[help] +#[diag("applying the `#[macro_use]` attribute to an `extern crate` item is deprecated")] +#[help("remove it and import macros at use sites with a `use` item instead")] pub(crate) struct MacroUseDeprecated; #[derive(LintDiagnostic)] -#[diag(resolve_macro_is_private)] +#[diag("macro `{$ident}` is private")] pub(crate) struct MacroIsPrivate { pub ident: Ident, } #[derive(LintDiagnostic)] -#[diag(resolve_unused_macro_definition)] +#[diag("unused macro definition: `{$name}`")] pub(crate) struct UnusedMacroDefinition { pub name: Symbol, } #[derive(LintDiagnostic)] -#[diag(resolve_macro_rule_never_used)] +#[diag("rule #{$n} of macro `{$name}` is never used")] pub(crate) struct MacroRuleNeverUsed { pub n: usize, pub name: Symbol, @@ -1412,36 +1473,43 @@ impl<'a> LintDiagnostic<'a, ()> for UnstableFeature { } #[derive(LintDiagnostic)] -#[diag(resolve_extern_crate_not_idiomatic)] +#[diag("`extern crate` is not idiomatic in the new edition")] pub(crate) struct ExternCrateNotIdiomatic { - #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] + #[suggestion( + "convert it to a `use`", + style = "verbose", + code = "{code}", + applicability = "machine-applicable" + )] pub span: Span, pub code: &'static str, } #[derive(LintDiagnostic)] -#[diag(resolve_out_of_scope_macro_calls)] -#[help] +#[diag("cannot find macro `{$path}` in the current scope when looking from {$location}")] +#[help("import `macro_rules` with `use` to make it callable above its definition")] pub(crate) struct OutOfScopeMacroCalls { - #[label] + #[label("not found from {$location}")] pub span: Span, pub path: String, pub location: String, } #[derive(LintDiagnostic)] -#[diag(resolve_redundant_import_visibility)] +#[diag( + "glob import doesn't reexport anything with visibility `{$import_vis}` because no imported item is public enough" +)] pub(crate) struct RedundantImportVisibility { - #[note] + #[note("the most public imported item is `{$max_vis}`")] pub span: Span, - #[help] + #[help("reduce the glob import's visibility or increase visibility of imported items")] pub help: (), pub import_vis: String, pub max_vis: String, } #[derive(LintDiagnostic)] -#[diag(resolve_unknown_diagnostic_attribute)] +#[diag("unknown diagnostic attribute")] pub(crate) struct UnknownDiagnosticAttribute { #[subdiagnostic] pub typo: Option, @@ -1449,7 +1517,7 @@ pub(crate) struct UnknownDiagnosticAttribute { #[derive(Subdiagnostic)] #[suggestion( - resolve_unknown_diagnostic_attribute_typo_sugg, + "an attribute with a similar name exists", style = "verbose", code = "{typo_name}", applicability = "machine-applicable" diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 659b74b74df7..36ec173cc571 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -98,8 +98,6 @@ pub use macros::registered_tools_ast; use crate::ref_mut::{CmCell, CmRefCell}; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - #[derive(Copy, Clone, PartialEq, Debug)] enum Determinacy { Determined, From 534b6c60e0786cb422b97c7dd7119da82505d24f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 Feb 2026 17:06:46 +0100 Subject: [PATCH 537/978] Convert to inline diagnostics in `rustc_metadata` --- Cargo.lock | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_metadata/Cargo.toml | 1 - compiler/rustc_metadata/messages.ftl | 240 ---------------------- compiler/rustc_metadata/src/errors.rs | 281 +++++++++++++++++--------- compiler/rustc_metadata/src/lib.rs | 2 - 6 files changed, 182 insertions(+), 344 deletions(-) delete mode 100644 compiler/rustc_metadata/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 1631d5362612..b53fc5e161ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4241,7 +4241,6 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", - "rustc_fluent_macro", "rustc_fs_util", "rustc_hir", "rustc_hir_pretty", diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 3059a4fefc61..46d975dcc181 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -125,7 +125,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE, rustc_hir_typeck::DEFAULT_LOCALE_RESOURCE, rustc_lint::DEFAULT_LOCALE_RESOURCE, - rustc_metadata::DEFAULT_LOCALE_RESOURCE, rustc_middle::DEFAULT_LOCALE_RESOURCE, rustc_mir_build::DEFAULT_LOCALE_RESOURCE, rustc_mir_transform::DEFAULT_LOCALE_RESOURCE, diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index 1b40d9f684ef..3a70ee130c27 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -15,7 +15,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_hir = { path = "../rustc_hir" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl deleted file mode 100644 index fac7b6c21f60..000000000000 --- a/compiler/rustc_metadata/messages.ftl +++ /dev/null @@ -1,240 +0,0 @@ -metadata_async_drop_types_in_dependency = - found async drop types in dependency `{$extern_crate}`, but async_drop feature is disabled for `{$local_crate}` - .help = if async drop type will be dropped in a crate without `feature(async_drop)`, sync Drop will be used - -metadata_bad_panic_strategy = - the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}` - -metadata_binary_output_to_tty = - option `-o` or `--emit` is used to write binary output type `metadata` to stdout, but stdout is a tty - -metadata_cannot_find_crate = - can't find crate for `{$crate_name}`{$add_info} - -metadata_cant_find_crate = - can't find crate - -metadata_compiler_missing_profiler = - the compiler may have been built without the profiler runtime - -metadata_conflicting_alloc_error_handler = - the `#[alloc_error_handler]` in {$other_crate_name} conflicts with allocation error handler in: {$crate_name} - -metadata_conflicting_global_alloc = - the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name} - -metadata_consider_adding_std = - consider adding the standard library to the sysroot with `x build library --target {$locator_triple}` - -metadata_consider_building_std = - consider building the standard library from source with `cargo build -Zbuild-std` - -metadata_consider_downloading_target = - consider downloading the target with `rustup target add {$locator_triple}` - -metadata_crate_dep_multiple = - cannot satisfy dependencies so `{$crate_name}` only shows up once - .help = having upstream crates all available in one format will likely make this go away - -metadata_crate_dep_not_static = - `{$crate_name}` was unavailable as a static crate, preventing fully static linking - -metadata_crate_dep_rustc_driver = - `feature(rustc_private)` is needed to link to the compiler's `rustc_driver` library - -metadata_crate_location_unknown_type = - extern location for {$crate_name} is of an unknown type: {$path} - -metadata_crate_not_compiler_builtins = - the crate `{$crate_name}` resolved as `compiler_builtins` but is not `#![compiler_builtins]` - -metadata_crate_not_panic_runtime = - the crate `{$crate_name}` is not a panic runtime - -metadata_dl_error = - {$path}{$err} - -metadata_empty_renaming_target = - an empty renaming target was specified for library `{$lib_name}` - -metadata_extern_location_not_exist = - extern location for {$crate_name} does not exist: {$location} - -metadata_extern_location_not_file = - extern location for {$crate_name} is not a file: {$location} - -metadata_fail_create_file_encoder = - failed to create file encoder: {$err} - -metadata_fail_write_file = - failed to write to `{$path}`: {$err} - -metadata_failed_copy_to_stdout = - failed to copy {$filename} to stdout: {$err} - -metadata_failed_create_encoded_metadata = - failed to create encoded metadata from file: {$err} - -metadata_failed_create_file = - failed to create the file {$filename}: {$err} - -metadata_failed_create_tempdir = - couldn't create a temp dir: {$err} - -metadata_failed_write_error = - failed to write {$filename}: {$err} - -metadata_found_crate_versions = - the following crate versions were found:{$found_crates} - -metadata_found_staticlib = - found staticlib `{$crate_name}` instead of rlib or dylib{$add_info} - .help = please recompile that crate using --crate-type lib - -metadata_full_metadata_not_found = - only metadata stub found for `{$flavor}` dependency `{$crate_name}` - please provide path to the corresponding .rmeta file with full metadata - -metadata_global_alloc_required = - no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait - -metadata_incompatible_panic_in_drop_strategy = - the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}` - -metadata_incompatible_rustc = - found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info} - .help = please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first) - -metadata_incompatible_target_modifiers = - mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}` - .note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}` - .help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely -metadata_incompatible_target_modifiers_help_allow = if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch={$flag_name}` to silence this error -metadata_incompatible_target_modifiers_help_fix = set `{$flag_name_prefixed}={$extern_value}` in this crate or `{$flag_name_prefixed}={$local_value}` in `{$extern_crate}` - -metadata_incompatible_target_modifiers_help_fix_l_missed = set `{$flag_name_prefixed}={$extern_value}` in this crate or unset `{$flag_name_prefixed}` in `{$extern_crate}` - -metadata_incompatible_target_modifiers_help_fix_r_missed = unset `{$flag_name_prefixed}` in this crate or set `{$flag_name_prefixed}={$local_value}` in `{$extern_crate}` - -metadata_incompatible_target_modifiers_l_missed = - mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}` - .note = unset `{$flag_name_prefixed}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}` - .help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely -metadata_incompatible_target_modifiers_r_missed = - mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}` - .note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with unset `{$flag_name_prefixed}` in dependency `{$extern_crate}` - .help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely - -metadata_incompatible_with_immediate_abort = - the crate `{$crate_name}` was compiled with a panic strategy which is incompatible with `immediate-abort` - -metadata_incompatible_with_immediate_abort_core = - the crate `core` was compiled with a panic strategy which is incompatible with `immediate-abort` - .help = consider building the standard library from source with `cargo build -Zbuild-std` - -metadata_install_missing_components = - maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview` - -metadata_invalid_meta_files = - found invalid metadata files for crate `{$crate_name}`{$add_info} - -metadata_lib_filename_form = - file name should be lib*.rlib or {$dll_prefix}*{$dll_suffix} - -metadata_lib_framework_apple = - library kind `framework` is only supported on Apple targets - -metadata_lib_required = - crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form - -metadata_link_ordinal_raw_dylib = - `#[link_ordinal]` is only supported if link kind is `raw-dylib` - -metadata_missing_native_library = - could not find native static library `{$libname}`, perhaps an -L flag is missing? - -metadata_multiple_candidates = - multiple candidates for `{$flavor}` dependency `{$crate_name}` found - -metadata_multiple_renamings = - multiple renamings were specified for library `{$lib_name}` - -metadata_newer_crate_version = - found possibly newer version of crate `{$crate_name}`{$add_info} - .note = perhaps that crate needs to be recompiled? - -metadata_no_crate_with_triple = - couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info} - -metadata_no_link_mod_override = - overriding linking modifiers from command line is not supported - -metadata_no_multiple_alloc_error_handler = - cannot define multiple allocation error handlers - .label = cannot define a new allocation error handler - -metadata_no_multiple_global_alloc = - cannot define multiple global allocators - .label = cannot define a new global allocator - -metadata_no_panic_strategy = - the crate `{$crate_name}` does not have the panic strategy `{$strategy}` - -metadata_no_transitive_needs_dep = - the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}` - -metadata_non_ascii_name = - cannot load a crate with a non-ascii name `{$crate_name}` - -metadata_not_profiler_runtime = - the crate `{$crate_name}` is not a profiler runtime - -metadata_only_provide_library_name = only provide the library name `{$suggested_name}`, not the full filename - -metadata_prev_alloc_error_handler = - previous allocation error handler defined here - -metadata_prev_global_alloc = - previous global allocator defined here - -metadata_raw_dylib_malformed = - link name must be well-formed if link kind is `raw-dylib` -metadata_raw_dylib_unsupported_abi = - ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture - -metadata_renaming_no_link = - renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library - -metadata_required_panic_strategy = - the crate `{$crate_name}` requires panic strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}` - -metadata_rlib_required = - crate `{$crate_name}` required to be available in rlib format, but was not found in this form - -metadata_rustc_lib_required = - crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form - .note = only .rmeta files are distributed for `rustc_private` crates other than `rustc_driver` - .help = try adding `extern crate rustc_driver;` at the top level of this crate - -metadata_stable_crate_id_collision = - found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values - -metadata_std_required = - `std` is required by `{$current_crate}` because it does not declare `#![no_std]` - -metadata_symbol_conflicts_current = - the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments, so this will result in symbol conflicts between the two - -metadata_target_no_std_support = - the `{$locator_triple}` target may not support the standard library - -metadata_target_not_installed = - the `{$locator_triple}` target may not be installed - -metadata_two_panic_runtimes = - cannot link together two panic runtimes: {$prev_name} and {$cur_name} - -metadata_unknown_target_modifier_unsafe_allowed = unknown target modifier `{$flag_name}`, requested by `-Cunsafe-allow-abi-mismatch={$flag_name}` - -metadata_wasm_c_abi = - older versions of the `wasm-bindgen` crate are incompatible with current versions of Rust; please update to `wasm-bindgen` v0.2.88 diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 8eb4fad078fe..da26f855b6c7 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -2,38 +2,43 @@ use std::io::Error; use std::path::{Path, PathBuf}; use rustc_errors::codes::*; -use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level}; +use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, inline_fluent}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol, sym}; use rustc_target::spec::{PanicStrategy, TargetTuple}; -use crate::fluent_generated as fluent; use crate::locator::CrateFlavor; #[derive(Diagnostic)] -#[diag(metadata_rlib_required)] +#[diag( + "crate `{$crate_name}` required to be available in rlib format, but was not found in this form" +)] pub struct RlibRequired { pub crate_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_lib_required)] +#[diag( + "crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form" +)] pub struct LibRequired<'a> { pub crate_name: Symbol, pub kind: &'a str, } #[derive(Diagnostic)] -#[diag(metadata_rustc_lib_required)] -#[help] +#[diag( + "crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form" +)] +#[help("try adding `extern crate rustc_driver;` at the top level of this crate")] pub struct RustcLibRequired<'a> { pub crate_name: Symbol, pub kind: &'a str, } #[derive(Diagnostic)] -#[diag(metadata_crate_dep_multiple)] -#[help] +#[diag("cannot satisfy dependencies so `{$crate_name}` only shows up once")] +#[help("having upstream crates all available in one format will likely make this go away")] pub struct CrateDepMultiple { pub crate_name: Symbol, #[subdiagnostic] @@ -43,32 +48,36 @@ pub struct CrateDepMultiple { } #[derive(Subdiagnostic)] -#[note(metadata_crate_dep_not_static)] +#[note("`{$crate_name}` was unavailable as a static crate, preventing fully static linking")] pub struct NonStaticCrateDep { /// It's different from `crate_name` in main Diagnostic. pub crate_name_: Symbol, } #[derive(Subdiagnostic)] -#[help(metadata_crate_dep_rustc_driver)] +#[help("`feature(rustc_private)` is needed to link to the compiler's `rustc_driver` library")] pub struct RustcDriverHelp; #[derive(Diagnostic)] -#[diag(metadata_two_panic_runtimes)] +#[diag("cannot link together two panic runtimes: {$prev_name} and {$cur_name}")] pub struct TwoPanicRuntimes { pub prev_name: Symbol, pub cur_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_bad_panic_strategy)] +#[diag( + "the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}`" +)] pub struct BadPanicStrategy { pub runtime: Symbol, pub strategy: PanicStrategy, } #[derive(Diagnostic)] -#[diag(metadata_required_panic_strategy)] +#[diag( + "the crate `{$crate_name}` requires panic strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`" +)] pub struct RequiredPanicStrategy { pub crate_name: Symbol, pub found_strategy: PanicStrategy, @@ -76,17 +85,23 @@ pub struct RequiredPanicStrategy { } #[derive(Diagnostic)] -#[diag(metadata_incompatible_with_immediate_abort)] +#[diag( + "the crate `{$crate_name}` was compiled with a panic strategy which is incompatible with `immediate-abort`" +)] pub struct IncompatibleWithImmediateAbort { pub crate_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_incompatible_with_immediate_abort_core)] +#[diag( + "the crate `core` was compiled with a panic strategy which is incompatible with `immediate-abort`" +)] pub struct IncompatibleWithImmediateAbortCore; #[derive(Diagnostic)] -#[diag(metadata_incompatible_panic_in_drop_strategy)] +#[diag( + "the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`" +)] pub struct IncompatiblePanicInDropStrategy { pub crate_name: Symbol, pub found_strategy: PanicStrategy, @@ -94,126 +109,138 @@ pub struct IncompatiblePanicInDropStrategy { } #[derive(Diagnostic)] -#[diag(metadata_link_ordinal_raw_dylib)] +#[diag("`#[link_ordinal]` is only supported if link kind is `raw-dylib`")] pub struct LinkOrdinalRawDylib { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(metadata_lib_framework_apple)] +#[diag("library kind `framework` is only supported on Apple targets")] pub struct LibFrameworkApple; #[derive(Diagnostic)] -#[diag(metadata_empty_renaming_target)] +#[diag("an empty renaming target was specified for library `{$lib_name}`")] pub struct EmptyRenamingTarget<'a> { pub lib_name: &'a str, } #[derive(Diagnostic)] -#[diag(metadata_renaming_no_link)] +#[diag( + "renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library" +)] pub struct RenamingNoLink<'a> { pub lib_name: &'a str, } #[derive(Diagnostic)] -#[diag(metadata_multiple_renamings)] +#[diag("multiple renamings were specified for library `{$lib_name}`")] pub struct MultipleRenamings<'a> { pub lib_name: &'a str, } #[derive(Diagnostic)] -#[diag(metadata_no_link_mod_override)] +#[diag("overriding linking modifiers from command line is not supported")] pub struct NoLinkModOverride { #[primary_span] pub span: Option, } #[derive(Diagnostic)] -#[diag(metadata_raw_dylib_unsupported_abi)] +#[diag("ABI not supported by `#[link(kind = \"raw-dylib\")]` on this architecture")] pub struct RawDylibUnsupportedAbi { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(metadata_fail_create_file_encoder)] +#[diag("failed to create file encoder: {$err}")] pub struct FailCreateFileEncoder { pub err: Error, } #[derive(Diagnostic)] -#[diag(metadata_fail_write_file)] +#[diag("failed to write to `{$path}`: {$err}")] pub struct FailWriteFile<'a> { pub path: &'a Path, pub err: Error, } #[derive(Diagnostic)] -#[diag(metadata_crate_not_panic_runtime)] +#[diag("the crate `{$crate_name}` is not a panic runtime")] pub struct CrateNotPanicRuntime { pub crate_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_crate_not_compiler_builtins)] +#[diag( + "the crate `{$crate_name}` resolved as `compiler_builtins` but is not `#![compiler_builtins]`" +)] pub struct CrateNotCompilerBuiltins { pub crate_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_no_panic_strategy)] +#[diag("the crate `{$crate_name}` does not have the panic strategy `{$strategy}`")] pub struct NoPanicStrategy { pub crate_name: Symbol, pub strategy: PanicStrategy, } #[derive(Diagnostic)] -#[diag(metadata_not_profiler_runtime)] +#[diag("the crate `{$crate_name}` is not a profiler runtime")] pub struct NotProfilerRuntime { pub crate_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_no_multiple_global_alloc)] +#[diag("cannot define multiple global allocators")] pub struct NoMultipleGlobalAlloc { #[primary_span] - #[label] + #[label("cannot define a new global allocator")] pub span2: Span, - #[label(metadata_prev_global_alloc)] + #[label("previous global allocator defined here")] pub span1: Span, } #[derive(Diagnostic)] -#[diag(metadata_no_multiple_alloc_error_handler)] +#[diag("cannot define multiple allocation error handlers")] pub struct NoMultipleAllocErrorHandler { #[primary_span] - #[label] + #[label("cannot define a new allocation error handler")] pub span2: Span, - #[label(metadata_prev_alloc_error_handler)] + #[label("previous allocation error handler defined here")] pub span1: Span, } #[derive(Diagnostic)] -#[diag(metadata_conflicting_global_alloc)] +#[diag( + "the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name}" +)] pub struct ConflictingGlobalAlloc { pub crate_name: Symbol, pub other_crate_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_conflicting_alloc_error_handler)] +#[diag( + "the `#[alloc_error_handler]` in {$other_crate_name} conflicts with allocation error handler in: {$crate_name}" +)] pub struct ConflictingAllocErrorHandler { pub crate_name: Symbol, pub other_crate_name: Symbol, } #[derive(Diagnostic)] -#[diag(metadata_global_alloc_required)] +#[diag( + "no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait" +)] pub struct GlobalAllocRequired; #[derive(Diagnostic)] -#[diag(metadata_no_transitive_needs_dep)] +#[diag( + "the crate `{$crate_name}` cannot depend on a crate that needs {$needs_crate_name}, but it depends on `{$deps_crate_name}`" +)] pub struct NoTransitiveNeedsDep<'a> { pub crate_name: Symbol, pub needs_crate_name: &'a str, @@ -221,25 +248,27 @@ pub struct NoTransitiveNeedsDep<'a> { } #[derive(Diagnostic)] -#[diag(metadata_failed_write_error)] +#[diag("failed to write {$filename}: {$err}")] pub struct FailedWriteError { pub filename: PathBuf, pub err: Error, } #[derive(Diagnostic)] -#[diag(metadata_failed_copy_to_stdout)] +#[diag("failed to copy {$filename} to stdout: {$err}")] pub struct FailedCopyToStdout { pub filename: PathBuf, pub err: Error, } #[derive(Diagnostic)] -#[diag(metadata_binary_output_to_tty)] +#[diag( + "option `-o` or `--emit` is used to write binary output type `metadata` to stdout, but stdout is a tty" +)] pub struct BinaryOutputToTty; #[derive(Diagnostic)] -#[diag(metadata_missing_native_library)] +#[diag("could not find native static library `{$libname}`, perhaps an -L flag is missing?")] pub struct MissingNativeLibrary<'a> { libname: &'a str, #[subdiagnostic] @@ -273,32 +302,32 @@ impl<'a> MissingNativeLibrary<'a> { } #[derive(Subdiagnostic)] -#[help(metadata_only_provide_library_name)] +#[help("only provide the library name `{$suggested_name}`, not the full filename")] pub struct SuggestLibraryName<'a> { suggested_name: &'a str, } #[derive(Diagnostic)] -#[diag(metadata_failed_create_tempdir)] +#[diag("couldn't create a temp dir: {$err}")] pub struct FailedCreateTempdir { pub err: Error, } #[derive(Diagnostic)] -#[diag(metadata_failed_create_file)] +#[diag("failed to create the file {$filename}: {$err}")] pub struct FailedCreateFile<'a> { pub filename: &'a Path, pub err: Error, } #[derive(Diagnostic)] -#[diag(metadata_failed_create_encoded_metadata)] +#[diag("failed to create encoded metadata from file: {$err}")] pub struct FailedCreateEncodedMetadata { pub err: Error, } #[derive(Diagnostic)] -#[diag(metadata_non_ascii_name)] +#[diag("cannot load a crate with a non-ascii name `{$crate_name}`")] pub struct NonAsciiName { #[primary_span] pub span: Span, @@ -306,7 +335,7 @@ pub struct NonAsciiName { } #[derive(Diagnostic)] -#[diag(metadata_extern_location_not_exist)] +#[diag("extern location for {$crate_name} does not exist: {$location}")] pub struct ExternLocationNotExist<'a> { #[primary_span] pub span: Span, @@ -315,7 +344,7 @@ pub struct ExternLocationNotExist<'a> { } #[derive(Diagnostic)] -#[diag(metadata_extern_location_not_file)] +#[diag("extern location for {$crate_name} is not a file: {$location}")] pub struct ExternLocationNotFile<'a> { #[primary_span] pub span: Span, @@ -332,7 +361,11 @@ pub(crate) struct MultipleCandidates { impl Diagnostic<'_, G> for MultipleCandidates { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::metadata_multiple_candidates); + let mut diag = Diag::new( + dcx, + level, + inline_fluent!("multiple candidates for `{$flavor}` dependency `{$crate_name}` found"), + ); diag.arg("crate_name", self.crate_name); diag.arg("flavor", self.flavor); diag.code(E0464); @@ -345,7 +378,9 @@ impl Diagnostic<'_, G> for MultipleCandidates { } #[derive(Diagnostic)] -#[diag(metadata_full_metadata_not_found)] +#[diag( + "only metadata stub found for `{$flavor}` dependency `{$crate_name}` please provide path to the corresponding .rmeta file with full metadata" +)] pub(crate) struct FullMetadataNotFound { #[primary_span] pub span: Span, @@ -354,7 +389,7 @@ pub(crate) struct FullMetadataNotFound { } #[derive(Diagnostic)] -#[diag(metadata_symbol_conflicts_current, code = E0519)] +#[diag("the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments, so this will result in symbol conflicts between the two", code = E0519)] pub struct SymbolConflictsCurrent { #[primary_span] pub span: Span, @@ -362,7 +397,7 @@ pub struct SymbolConflictsCurrent { } #[derive(Diagnostic)] -#[diag(metadata_stable_crate_id_collision)] +#[diag("found crates (`{$crate_name0}` and `{$crate_name1}`) with colliding StableCrateId values")] pub struct StableCrateIdCollision { #[primary_span] pub span: Span, @@ -371,7 +406,7 @@ pub struct StableCrateIdCollision { } #[derive(Diagnostic)] -#[diag(metadata_dl_error)] +#[diag("{$path}{$err}")] pub struct DlError { #[primary_span] pub span: Span, @@ -380,9 +415,9 @@ pub struct DlError { } #[derive(Diagnostic)] -#[diag(metadata_newer_crate_version, code = E0460)] -#[note] -#[note(metadata_found_crate_versions)] +#[diag("found possibly newer version of crate `{$crate_name}`{$add_info}", code = E0460)] +#[note("perhaps that crate needs to be recompiled?")] +#[note("the following crate versions were found:{$found_crates}")] pub struct NewerCrateVersion { #[primary_span] pub span: Span, @@ -392,8 +427,8 @@ pub struct NewerCrateVersion { } #[derive(Diagnostic)] -#[diag(metadata_no_crate_with_triple, code = E0461)] -#[note(metadata_found_crate_versions)] +#[diag("couldn't find crate `{$crate_name}` with expected target triple {$locator_triple}{$add_info}", code = E0461)] +#[note("the following crate versions were found:{$found_crates}")] pub struct NoCrateWithTriple<'a> { #[primary_span] pub span: Span, @@ -404,9 +439,9 @@ pub struct NoCrateWithTriple<'a> { } #[derive(Diagnostic)] -#[diag(metadata_found_staticlib, code = E0462)] -#[note(metadata_found_crate_versions)] -#[help] +#[diag("found staticlib `{$crate_name}` instead of rlib or dylib{$add_info}", code = E0462)] +#[note("the following crate versions were found:{$found_crates}")] +#[help("please recompile that crate using --crate-type lib")] pub struct FoundStaticlib { #[primary_span] pub span: Span, @@ -416,9 +451,11 @@ pub struct FoundStaticlib { } #[derive(Diagnostic)] -#[diag(metadata_incompatible_rustc, code = E0514)] -#[note(metadata_found_crate_versions)] -#[help] +#[diag("found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info}", code = E0514)] +#[note("the following crate versions were found:{$found_crates}")] +#[help( + "please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first)" +)] pub struct IncompatibleRustc { #[primary_span] pub span: Span, @@ -438,7 +475,11 @@ pub struct InvalidMetadataFiles { impl Diagnostic<'_, G> for InvalidMetadataFiles { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::metadata_invalid_meta_files); + let mut diag = Diag::new( + dcx, + level, + inline_fluent!("found invalid metadata files for crate `{$crate_name}`{$add_info}"), + ); diag.arg("crate_name", self.crate_name); diag.arg("add_info", self.add_info); diag.code(E0786); @@ -466,7 +507,11 @@ pub struct CannotFindCrate { impl Diagnostic<'_, G> for CannotFindCrate { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::metadata_cannot_find_crate); + let mut diag = Diag::new( + dcx, + level, + inline_fluent!("can't find crate for `{$crate_name}`{$add_info}"), + ); diag.arg("crate_name", self.crate_name); diag.arg("current_crate", self.current_crate); diag.arg("add_info", self.add_info); @@ -475,9 +520,11 @@ impl Diagnostic<'_, G> for CannotFindCrate { diag.span(self.span); if self.crate_name == sym::std || self.crate_name == sym::core { if self.missing_core { - diag.note(fluent::metadata_target_not_installed); + diag.note(inline_fluent!("the `{$locator_triple}` target may not be installed")); } else { - diag.note(fluent::metadata_target_no_std_support); + diag.note(inline_fluent!( + "the `{$locator_triple}` target may not support the standard library" + )); } let has_precompiled_std = !self.is_tier_3; @@ -485,12 +532,14 @@ impl Diagnostic<'_, G> for CannotFindCrate { if self.missing_core { if env!("CFG_RELEASE_CHANNEL") == "dev" && !self.is_ui_testing { // Note: Emits the nicer suggestion only for the dev channel. - diag.help(fluent::metadata_consider_adding_std); + diag.help(inline_fluent!("consider adding the standard library to the sysroot with `x build library --target {$locator_triple}`")); } else if has_precompiled_std { // NOTE: this suggests using rustup, even though the user may not have it installed. // That's because they could choose to install it; or this may give them a hint which // target they need to install from their distro. - diag.help(fluent::metadata_consider_downloading_target); + diag.help(inline_fluent!( + "consider downloading the target with `rustup target add {$locator_triple}`" + )); } } @@ -499,25 +548,27 @@ impl Diagnostic<'_, G> for CannotFindCrate { // If it's not a dummy, that means someone added `extern crate std` explicitly and // `#![no_std]` won't help. if !self.missing_core && self.span.is_dummy() { - diag.note(fluent::metadata_std_required); + diag.note(inline_fluent!("`std` is required by `{$current_crate}` because it does not declare `#![no_std]`")); } // Recommend -Zbuild-std even on stable builds for Tier 3 targets because // it's the recommended way to use the target, the user should switch to nightly. if self.is_nightly_build || !has_precompiled_std { - diag.help(fluent::metadata_consider_building_std); + diag.help(inline_fluent!("consider building the standard library from source with `cargo build -Zbuild-std`")); } } else if self.crate_name == self.profiler_runtime { - diag.note(fluent::metadata_compiler_missing_profiler); + diag.note(inline_fluent!( + "the compiler may have been built without the profiler runtime" + )); } else if self.crate_name.as_str().starts_with("rustc_") { - diag.help(fluent::metadata_install_missing_components); + diag.help(inline_fluent!("maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`")); } - diag.span_label(self.span, fluent::metadata_cant_find_crate); + diag.span_label(self.span, inline_fluent!("can't find crate")); diag } } #[derive(Diagnostic)] -#[diag(metadata_crate_location_unknown_type)] +#[diag("extern location for {$crate_name} is of an unknown type: {$path}")] pub struct CrateLocationUnknownType<'a> { #[primary_span] pub span: Span, @@ -526,7 +577,7 @@ pub struct CrateLocationUnknownType<'a> { } #[derive(Diagnostic)] -#[diag(metadata_lib_filename_form)] +#[diag("file name should be lib*.rlib or {$dll_prefix}*{$dll_suffix}")] pub struct LibFilenameForm<'a> { #[primary_span] pub span: Span, @@ -535,18 +586,28 @@ pub struct LibFilenameForm<'a> { } #[derive(Diagnostic)] -#[diag(metadata_wasm_c_abi)] +#[diag( + "older versions of the `wasm-bindgen` crate are incompatible with current versions of Rust; please update to `wasm-bindgen` v0.2.88" +)] pub(crate) struct WasmCAbi { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(metadata_incompatible_target_modifiers)] -#[help] -#[note] -#[help(metadata_incompatible_target_modifiers_help_fix)] -#[help(metadata_incompatible_target_modifiers_help_allow)] +#[diag("mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`")] +#[help( + "the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely" +)] +#[note( + "`{$flag_name_prefixed}={$local_value}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}`" +)] +#[help( + "set `{$flag_name_prefixed}={$extern_value}` in this crate or `{$flag_name_prefixed}={$local_value}` in `{$extern_crate}`" +)] +#[help( + "if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch={$flag_name}` to silence this error" +)] pub struct IncompatibleTargetModifiers { #[primary_span] pub span: Span, @@ -559,11 +620,19 @@ pub struct IncompatibleTargetModifiers { } #[derive(Diagnostic)] -#[diag(metadata_incompatible_target_modifiers_l_missed)] -#[help] -#[note] -#[help(metadata_incompatible_target_modifiers_help_fix_l_missed)] -#[help(metadata_incompatible_target_modifiers_help_allow)] +#[diag("mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`")] +#[help( + "the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely" +)] +#[note( + "unset `{$flag_name_prefixed}` in this crate is incompatible with `{$flag_name_prefixed}={$extern_value}` in dependency `{$extern_crate}`" +)] +#[help( + "set `{$flag_name_prefixed}={$extern_value}` in this crate or unset `{$flag_name_prefixed}` in `{$extern_crate}`" +)] +#[help( + "if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch={$flag_name}` to silence this error" +)] pub struct IncompatibleTargetModifiersLMissed { #[primary_span] pub span: Span, @@ -575,11 +644,19 @@ pub struct IncompatibleTargetModifiersLMissed { } #[derive(Diagnostic)] -#[diag(metadata_incompatible_target_modifiers_r_missed)] -#[help] -#[note] -#[help(metadata_incompatible_target_modifiers_help_fix_r_missed)] -#[help(metadata_incompatible_target_modifiers_help_allow)] +#[diag("mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`")] +#[help( + "the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely" +)] +#[note( + "`{$flag_name_prefixed}={$local_value}` in this crate is incompatible with unset `{$flag_name_prefixed}` in dependency `{$extern_crate}`" +)] +#[help( + "unset `{$flag_name_prefixed}` in this crate or set `{$flag_name_prefixed}={$local_value}` in `{$extern_crate}`" +)] +#[help( + "if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch={$flag_name}` to silence this error" +)] pub struct IncompatibleTargetModifiersRMissed { #[primary_span] pub span: Span, @@ -591,7 +668,9 @@ pub struct IncompatibleTargetModifiersRMissed { } #[derive(Diagnostic)] -#[diag(metadata_unknown_target_modifier_unsafe_allowed)] +#[diag( + "unknown target modifier `{$flag_name}`, requested by `-Cunsafe-allow-abi-mismatch={$flag_name}`" +)] pub struct UnknownTargetModifierUnsafeAllowed { #[primary_span] pub span: Span, @@ -599,8 +678,12 @@ pub struct UnknownTargetModifierUnsafeAllowed { } #[derive(Diagnostic)] -#[diag(metadata_async_drop_types_in_dependency)] -#[help] +#[diag( + "found async drop types in dependency `{$extern_crate}`, but async_drop feature is disabled for `{$local_crate}`" +)] +#[help( + "if async drop type will be dropped in a crate without `feature(async_drop)`, sync Drop will be used" +)] pub struct AsyncDropTypesInDependency { #[primary_span] pub span: Span, @@ -609,7 +692,7 @@ pub struct AsyncDropTypesInDependency { } #[derive(Diagnostic)] -#[diag(metadata_raw_dylib_malformed)] +#[diag("link name must be well-formed if link kind is `raw-dylib`")] pub struct RawDylibMalformed { #[primary_span] pub span: Span, diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index f3b738f93d2d..22c8a0c4cd7e 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -34,5 +34,3 @@ pub use native_libs::{ try_find_native_static_library, walk_native_lib_search_dirs, }; pub use rmeta::{EncodedMetadata, METADATA_HEADER, encode_metadata, rendered_const}; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } From 23e5b2499f2938cc9cab5271a5f75cc641b210bf Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 4 Feb 2026 19:20:07 +0100 Subject: [PATCH 538/978] Adopt matches-logical-or-141497.rs to LLVM HEAD After http://github.com/llvm/llvm-project/pull/178977, the and + icmp are folded to trunc. --- tests/codegen-llvm/issues/matches-logical-or-141497.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/codegen-llvm/issues/matches-logical-or-141497.rs b/tests/codegen-llvm/issues/matches-logical-or-141497.rs index 348f62096a5f..59869fd70012 100644 --- a/tests/codegen-llvm/issues/matches-logical-or-141497.rs +++ b/tests/codegen-llvm/issues/matches-logical-or-141497.rs @@ -2,7 +2,7 @@ // `f == FrameType::Inter || f == FrameType::Switch`. //@ compile-flags: -Copt-level=3 -//@ min-llvm-version: 21 +//@ min-llvm-version: 23 #![crate_type = "lib"] @@ -18,8 +18,7 @@ pub enum FrameType { #[no_mangle] pub fn is_inter_or_switch(f: FrameType) -> bool { // CHECK-NEXT: start: - // CHECK-NEXT: and i8 - // CHECK-NEXT: icmp + // CHECK-NEXT: trunc i8 %{{.*}} to i1 // CHECK-NEXT: ret matches!(f, FrameType::Inter | FrameType::Switch) } From 01c0c147c5ba624cc9eb7dcc51577bef16f6a630 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Mon, 5 Jan 2026 19:31:26 +0100 Subject: [PATCH 539/978] library/std: Rename `ON_BROKEN_PIPE_FLAG_USED` to `ON_BROKEN_PIPE_USED` This commmit is a pure rename and does not change any functionality. The `FLAG_` part of `ON_BROKEN_PIPE_FLAG_USED` comes from that the compiler flag `-Zon-broken-pipe=...` is used to enable the feature. Remove the `FLAG_` part so the name works both for the flag `-Zon-broken-pipe=...` and for the upcoming Externally Implementable Item `#[std::io::on_broken_pipe]`. This makes the diff of that PR smaller. The local variable name `sigpipe_attr_specified` comes from way back when the feature was controlled with an `fn main()` attribute called `#[unix_sigpipe = "..."]`. Rename that too. --- library/std/src/sys/pal/unix/mod.rs | 12 ++++++------ library/std/src/sys/process/unix/unix.rs | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 6127bb98f80e..0fbf37fda7fb 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -169,15 +169,15 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { pub const SIG_DFL: u8 = 3; } - let (sigpipe_attr_specified, handler) = match sigpipe { + let (on_broken_pipe_used, handler) = match sigpipe { sigpipe::DEFAULT => (false, Some(libc::SIG_IGN)), sigpipe::INHERIT => (true, None), sigpipe::SIG_IGN => (true, Some(libc::SIG_IGN)), sigpipe::SIG_DFL => (true, Some(libc::SIG_DFL)), _ => unreachable!(), }; - if sigpipe_attr_specified { - ON_BROKEN_PIPE_FLAG_USED.store(true, crate::sync::atomic::Ordering::Relaxed); + if on_broken_pipe_used { + ON_BROKEN_PIPE_USED.store(true, crate::sync::atomic::Ordering::Relaxed); } if let Some(handler) = handler { rtassert!(signal(libc::SIGPIPE, handler) != libc::SIG_ERR); @@ -199,7 +199,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { target_os = "vxworks", target_os = "vita", )))] -static ON_BROKEN_PIPE_FLAG_USED: crate::sync::atomic::Atomic = +static ON_BROKEN_PIPE_USED: crate::sync::atomic::Atomic = crate::sync::atomic::AtomicBool::new(false); #[cfg(not(any( @@ -211,8 +211,8 @@ static ON_BROKEN_PIPE_FLAG_USED: crate::sync::atomic::Atomic = target_os = "vita", target_os = "nuttx", )))] -pub(crate) fn on_broken_pipe_flag_used() -> bool { - ON_BROKEN_PIPE_FLAG_USED.load(crate::sync::atomic::Ordering::Relaxed) +pub(crate) fn on_broken_pipe_used() -> bool { + ON_BROKEN_PIPE_USED.load(crate::sync::atomic::Ordering::Relaxed) } // SAFETY: must be called only once during runtime cleanup. diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs index 62d6e0581e6c..82ff94fb1e03 100644 --- a/library/std/src/sys/process/unix/unix.rs +++ b/library/std/src/sys/process/unix/unix.rs @@ -356,7 +356,7 @@ impl Command { // If -Zon-broken-pipe is not used, reset SIGPIPE to SIG_DFL for backward compatibility. // // -Zon-broken-pipe is an opportunity to change the default here. - if !crate::sys::pal::on_broken_pipe_flag_used() { + if !crate::sys::pal::on_broken_pipe_used() { #[cfg(target_os = "android")] // see issue #88585 { let mut action: libc::sigaction = mem::zeroed(); @@ -455,7 +455,7 @@ impl Command { use core::sync::atomic::{Atomic, AtomicU8, Ordering}; use crate::mem::MaybeUninit; - use crate::sys::{self, cvt_nz, on_broken_pipe_flag_used}; + use crate::sys::{self, cvt_nz, on_broken_pipe_used}; if self.get_gid().is_some() || self.get_uid().is_some() @@ -731,7 +731,7 @@ impl Command { // If -Zon-broken-pipe is not used, reset SIGPIPE to SIG_DFL for backward compatibility. // // -Zon-broken-pipe is an opportunity to change the default here. - if !on_broken_pipe_flag_used() { + if !on_broken_pipe_used() { let mut default_set = MaybeUninit::::uninit(); cvt(sigemptyset(default_set.as_mut_ptr()))?; cvt(sigaddset(default_set.as_mut_ptr(), libc::SIGPIPE))?; From bdf8d3b63ffb6dee0e6c3ab7d27f818584253882 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 4 Feb 2026 10:51:43 -0800 Subject: [PATCH 540/978] Set crt_static_allow_dylibs to true for Emscripten target And add a test. This is followup work to PR 151704. It introduced a regression where cargo is now unwilling to build cdylibs for Emscripten because `crt_static_default` is `true` but `crt_static_allows_dylibs` is `false`. Unfortunately the added test does not fail without the change because the validation logic is in Cargo, not in rustc. But it's good to have some coverage of this anyways. --- .../spec/targets/wasm32_unknown_emscripten.rs | 7 ++++++ .../src/directives/directive_names.rs | 1 + tests/run-make/wasm-emscripten-cdylib/foo.rs | 4 +++ .../run-make/wasm-emscripten-cdylib/rmake.rs | 25 +++++++++++++++++++ 4 files changed, 37 insertions(+) create mode 100644 tests/run-make/wasm-emscripten-cdylib/foo.rs create mode 100644 tests/run-make/wasm-emscripten-cdylib/rmake.rs diff --git a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs index fb735b54dd82..4b6f5b655760 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs @@ -19,8 +19,15 @@ pub(crate) fn target() -> Target { pre_link_args, post_link_args, relocation_model: RelocModel::Pic, + // crt_static should always be true for an executable and always false + // for a shared library. There is no easy way to indicate this and it + // doesn't seem to matter much so we set crt_static_allows_dylibs to + // true and leave crt_static as true when linking dynamic libraries. + // wasi also sets crt_static_allows_dylibs: true so this is at least + // aligned between wasm targets. crt_static_respected: true, crt_static_default: true, + crt_static_allows_dylibs: true, panic_strategy: PanicStrategy::Unwind, no_default_libraries: false, families: cvs!["unix", "wasm"], diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs index 9813ac7ff500..230578d79ffb 100644 --- a/src/tools/compiletest/src/directives/directive_names.rs +++ b/src/tools/compiletest/src/directives/directive_names.rs @@ -249,6 +249,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-unix", "only-visionos", "only-wasm32", + "only-wasm32-unknown-emscripten", "only-wasm32-unknown-unknown", "only-wasm32-wasip1", "only-watchos", diff --git a/tests/run-make/wasm-emscripten-cdylib/foo.rs b/tests/run-make/wasm-emscripten-cdylib/foo.rs new file mode 100644 index 000000000000..08ad8e7b5c61 --- /dev/null +++ b/tests/run-make/wasm-emscripten-cdylib/foo.rs @@ -0,0 +1,4 @@ +#[no_mangle] +pub extern "C" fn foo() -> i32 { + 42 +} diff --git a/tests/run-make/wasm-emscripten-cdylib/rmake.rs b/tests/run-make/wasm-emscripten-cdylib/rmake.rs new file mode 100644 index 000000000000..ef5fc17c2bbe --- /dev/null +++ b/tests/run-make/wasm-emscripten-cdylib/rmake.rs @@ -0,0 +1,25 @@ +//! Check that cdylib crate type is supported for the wasm32-unknown-emscripten +//! target and produces a valid Emscripten dynamic library. + +//@ only-wasm32-unknown-emscripten + +use run_make_support::{bare_rustc, rfs, wasmparser}; + +fn main() { + bare_rustc().input("foo.rs").target("wasm32-unknown-emscripten").crate_type("cdylib").run(); + + // Verify the output is a valid wasm file with a dylink.0 section + let file = rfs::read("foo.wasm"); + let mut has_dylink = false; + + for payload in wasmparser::Parser::new(0).parse_all(&file) { + let payload = payload.unwrap(); + if let wasmparser::Payload::CustomSection(s) = payload { + if s.name() == "dylink.0" { + has_dylink = true; + } + } + } + + assert!(has_dylink, "expected dylink.0 section in emscripten cdylib output"); +} From 13141af9492b3cc91b7afeb32ee9c0fb4b24ca64 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Wed, 4 Feb 2026 19:26:13 +0000 Subject: [PATCH 541/978] Consolidate type const checks on `tcx.is_type_const` --- compiler/rustc_hir_analysis/src/check/check.rs | 2 +- .../rustc_hir_analysis/src/check/compare_impl_item.rs | 11 +++-------- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 2 +- .../rustc_hir_analysis/src/hir_ty_lowering/bounds.rs | 8 ++------ .../rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 7 +++---- compiler/rustc_hir_analysis/src/lib.rs | 7 ++----- compiler/rustc_middle/src/ty/context.rs | 9 +++++++-- .../src/traits/dyn_compatibility.rs | 5 ++--- 8 files changed, 21 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index c00122bce559..e0bfae9617ff 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -923,7 +923,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ); check_where_clauses(wfcx, def_id); - if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_)) { + if tcx.is_type_const(def_id.into()) { wfcheck::check_type_const(wfcx, def_id, ty, true)?; } Ok(()) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 9e07d5260d20..f418dec940bb 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -6,10 +6,9 @@ use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err}; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::VisitorExt; -use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, find_attr, intravisit}; +use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit}; use rustc_infer::infer::{self, BoundRegionConversionTime, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -2051,12 +2050,8 @@ fn compare_type_const<'tcx>( impl_const_item: ty::AssocItem, trait_const_item: ty::AssocItem, ) -> Result<(), ErrorGuaranteed> { - let impl_is_type_const = - find_attr!(tcx.get_all_attrs(impl_const_item.def_id), AttributeKind::TypeConst(_)); - let trait_type_const_span = find_attr!( - tcx.get_all_attrs(trait_const_item.def_id), - AttributeKind::TypeConst(sp) => *sp - ); + let impl_is_type_const = tcx.is_type_const(impl_const_item.def_id); + let trait_type_const_span = tcx.type_const_span(trait_const_item.def_id); if let Some(trait_type_const_span) = trait_type_const_span && !impl_is_type_const diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 8b50eceb26e4..acead42c9a0e 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -953,7 +953,7 @@ pub(crate) fn check_associated_item( wfcx.register_wf_obligation(span, loc, ty.into()); let has_value = item.defaultness(tcx).has_value(); - if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_)) { + if tcx.is_type_const(def_id.into()) { check_type_const(wfcx, def_id, ty, has_value)?; } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 3515ce4ea939..a1c3af5f999d 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -4,10 +4,9 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; -use rustc_hir::attrs::AttributeKind; +use rustc_hir::PolyTraitRef; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; -use rustc_hir::{PolyTraitRef, find_attr}; use rustc_middle::bug; use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -603,10 +602,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }); if let ty::AssocTag::Const = assoc_tag - && !find_attr!( - self.tcx().get_all_attrs(assoc_item.def_id), - AttributeKind::TypeConst(_) - ) + && !self.tcx().is_type_const(assoc_item.def_id) { if tcx.features().min_generic_const_args() { let mut err = self.dcx().struct_span_err( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 9f84f652698b..d4b9d2e359d5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -28,10 +28,9 @@ use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, struct_span_code_err, }; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId, find_attr}; +use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::DynCompatibilityViolation; use rustc_macros::{TypeFoldable, TypeVisitable}; @@ -1423,7 +1422,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { LowerTypeRelativePathMode::Const, )? { TypeRelativePath::AssocItem(def_id, args) => { - if !find_attr!(self.tcx().get_all_attrs(def_id), AttributeKind::TypeConst(_)) { + if !self.tcx().is_type_const(def_id) { let mut err = self.dcx().struct_span_err( span, "use of trait associated const without `#[type_const]`", @@ -1896,7 +1895,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::AssocTag::Const, ) { Ok((item_def_id, item_args)) => { - if !find_attr!(self.tcx().get_all_attrs(item_def_id), AttributeKind::TypeConst(_)) { + if !self.tcx().is_type_const(item_def_id) { let mut err = self.dcx().struct_span_err( span, "use of `const` in the type system without `#[type_const]`", diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index f7a143435959..01f57f3a56df 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -85,12 +85,9 @@ mod variance; pub use errors::NoVariantNamed; use rustc_abi::{CVariadicStatus, ExternAbi}; -use rustc_hir::attrs::AttributeKind; +use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::lints::DelayedLint; -use rustc_hir::{ - find_attr, {self as hir}, -}; use rustc_middle::mir::interpret::GlobalId; use rustc_middle::query::Providers; use rustc_middle::ty::{Const, Ty, TyCtxt}; @@ -238,7 +235,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } DefKind::Const if !tcx.generics_of(item_def_id).own_requires_monomorphization() - && !find_attr!(tcx.get_all_attrs(item_def_id), AttributeKind::TypeConst(_)) => + && !tcx.is_type_const(item_def_id.into()) => { // FIXME(generic_const_items): Passing empty instead of identity args is fishy but // seems to be fine for now. Revisit this! diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 41e1388e3146..348e5ccf6217 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1886,10 +1886,15 @@ impl<'tcx> TyCtxt<'tcx> { self.is_lang_item(self.parent(def_id), LangItem::AsyncDropInPlace) } + pub fn type_const_span(self, def_id: DefId) -> Option { + matches!(self.def_kind(def_id), DefKind::Const | DefKind::AssocConst) + .then(|| find_attr!(self.get_all_attrs(def_id), AttributeKind::TypeConst(sp) => *sp)) + .flatten() + } + /// Check if the given `def_id` is a const with the `#[type_const]` attribute. pub fn is_type_const(self, def_id: DefId) -> bool { - matches!(self.def_kind(def_id), DefKind::Const | DefKind::AssocConst) - && find_attr!(self.get_all_attrs(def_id), AttributeKind::TypeConst(_)) + self.type_const_span(def_id).is_some() } /// Returns the movability of the coroutine of `def_id`, or panics diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 9371b55b6363..512973e45287 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -7,10 +7,9 @@ use std::ops::ControlFlow; use rustc_errors::FatalError; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, LangItem, find_attr}; +use rustc_hir::{self as hir, LangItem}; use rustc_middle::query::Providers; use rustc_middle::ty::{ self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, @@ -333,7 +332,7 @@ pub fn dyn_compatibility_violations_for_assoc_item( if tcx.features().min_generic_const_args() { if !tcx.generics_of(item.def_id).is_own_empty() { errors.push(AssocConstViolation::Generic); - } else if !find_attr!(tcx.get_all_attrs(item.def_id), AttributeKind::TypeConst(_)) { + } else if !tcx.is_type_const(item.def_id) { errors.push(AssocConstViolation::NonType); } From 44a14c1f304089a3ca6bfa4dc82734bca8985b6b Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 4 Feb 2026 21:36:48 +0100 Subject: [PATCH 542/978] Convert to inline diagnostics in `rustc_hir_typeck` --- Cargo.lock | 2 - compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_hir_typeck/Cargo.toml | 1 - compiler/rustc_hir_typeck/messages.ftl | 315 ----------- compiler/rustc_hir_typeck/src/callee.rs | 14 +- compiler/rustc_hir_typeck/src/errors.rs | 522 ++++++++++++------ .../src/fn_ctxt/suggestions.rs | 6 +- compiler/rustc_hir_typeck/src/lib.rs | 2 - 9 files changed, 357 insertions(+), 507 deletions(-) delete mode 100644 compiler/rustc_hir_typeck/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 85d3fc1aa7bf..85fb0de46879 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3787,7 +3787,6 @@ dependencies = [ "rustc_feature", "rustc_hir_analysis", "rustc_hir_pretty", - "rustc_hir_typeck", "rustc_index", "rustc_interface", "rustc_lexer", @@ -4017,7 +4016,6 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_hir_analysis", "rustc_hir_pretty", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index cae2e3b066ee..dec91490c96d 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -22,7 +22,6 @@ rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } rustc_hir_analysis = { path = "../rustc_hir_analysis" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } -rustc_hir_typeck = { path = "../rustc_hir_typeck" } rustc_index = { path = "../rustc_index" } rustc_interface = { path = "../rustc_interface" } rustc_lexer = { path = "../rustc_lexer" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 3b9ca5ff7288..b2e973c76868 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -123,7 +123,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_errors::DEFAULT_LOCALE_RESOURCE, rustc_expand::DEFAULT_LOCALE_RESOURCE, rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE, - rustc_hir_typeck::DEFAULT_LOCALE_RESOURCE, rustc_lint::DEFAULT_LOCALE_RESOURCE, rustc_metadata::DEFAULT_LOCALE_RESOURCE, rustc_middle::DEFAULT_LOCALE_RESOURCE, diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 246134665174..43db09b0eab8 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -10,7 +10,6 @@ rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_hir_analysis = { path = "../rustc_hir_analysis" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl deleted file mode 100644 index 0c4b1f891ead..000000000000 --- a/compiler/rustc_hir_typeck/messages.ftl +++ /dev/null @@ -1,315 +0,0 @@ -hir_typeck_abi_cannot_be_called = - functions with the {$abi} ABI cannot be called - .note = an `extern {$abi}` function can only be called using inline assembly - -hir_typeck_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function - -hir_typeck_add_return_type_add = try adding a return type - -hir_typeck_add_return_type_missing_here = a return type might be missing here - -hir_typeck_address_of_temporary_taken = cannot take address of a temporary - .label = temporary value - -hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where - .note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new - -hir_typeck_as_deref_suggestion = consider using `as_deref` here -hir_typeck_base_expression_double_dot = base expression required after `..` -hir_typeck_base_expression_double_dot_add_expr = add a base expression here -hir_typeck_base_expression_double_dot_enable_default_field_values = - add `#![feature(default_field_values)]` to the crate attributes to enable default values on `struct` fields -hir_typeck_base_expression_double_dot_remove = remove the `..` as all the fields are already present - -hir_typeck_break_inside_closure = - `{$name}` inside of a closure - .label = cannot `{$name}` inside of a closure - .closure_label = enclosing closure - -hir_typeck_break_inside_coroutine = - `{$name}` inside `{$kind}` {$source} - .label = cannot `{$name}` inside `{$kind}` {$source} - .coroutine_label = enclosing `{$kind}` {$source} - -hir_typeck_break_non_loop = - `break` with value from a `{$kind}` loop - .label = can only break with a value inside `loop` or breakable block - .label2 = you can't `break` with a value in a `{$kind}` loop - .suggestion = use `break` on its own without a value inside this `{$kind}` loop - .break_expr_suggestion = alternatively, you might have meant to use the available loop label - - -hir_typeck_candidate_trait_note = `{$trait_name}` defines an item `{$item_name}`{$action_or_ty -> - [NONE] {""} - [implement] , perhaps you need to implement it - *[other] , perhaps you need to restrict type parameter `{$action_or_ty}` with it -} - -hir_typeck_cannot_cast_to_bool = cannot cast `{$expr_ty}` as `bool` - .suggestion = compare with zero instead - .help = compare with zero instead - .label = unsupported cast - -hir_typeck_cant_dereference = type `{$ty}` cannot be dereferenced -hir_typeck_cant_dereference_label = can't be dereferenced - -hir_typeck_cast_enum_drop = cannot cast enum `{$expr_ty}` into integer `{$cast_ty}` because it implements `Drop` - -hir_typeck_cast_thin_pointer_to_wide_pointer = cannot cast thin pointer `{$expr_ty}` to wide pointer `{$cast_ty}` - .teach_help = Thin pointers are "simple" pointers: they are purely a reference to a - memory address. - - Wide pointers are pointers referencing "Dynamically Sized Types" (also - called DST). DST don't have a statically known size, therefore they can - only exist behind some kind of pointers that contain additional - information. Slices and trait objects are DSTs. In the case of slices, - the additional information the wide pointer holds is their size. - - To fix this error, don't try to cast directly between thin and wide - pointers. - - For more information about casts, take a look at The Book: - https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions", - -hir_typeck_cast_unknown_pointer = cannot cast {$to -> - [true] to - *[false] from - } a pointer of an unknown kind - .label_to = needs more type information - .note = the type information given here is insufficient to check whether the pointer cast is valid - .label_from = the type information given here is insufficient to check whether the pointer cast is valid - -hir_typeck_const_continue_bad_label = - `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]` - -hir_typeck_continue_labeled_block = - `continue` pointing to a labeled block - .label = labeled blocks cannot be `continue`'d - .block_label = labeled block the `continue` points to - - -hir_typeck_convert_to_str = try converting the passed type into a `&str` - -hir_typeck_convert_using_method = try using `{$sugg}` to convert `{$found}` to `{$expected}` - -hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private - -hir_typeck_dependency_on_unit_never_type_fallback = this function depends on never type fallback being `()` - .note = in edition 2024, the requirement `{$obligation}` will fail - .help = specify the types explicitly - -hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty` - -hir_typeck_expected_array_or_slice = expected an array or slice, found `{$ty}` -hir_typeck_expected_array_or_slice_label = pattern cannot match with input type `{$ty}` - -hir_typeck_expected_default_return_type = expected `()` because of default return type - -hir_typeck_expected_return_type = expected `{$expected}` because of return type - -hir_typeck_explicit_destructor = explicit use of destructor method - .label = explicit destructor calls not allowed - .suggestion = consider using `drop` function - -hir_typeck_field_multiply_specified_in_initializer = - field `{$ident}` specified more than once - .label = used more than once - .previous_use_label = first use of `{$ident}` - -hir_typeck_fn_item_to_variadic_function = can't pass a function item to a variadic function - .suggestion = use a function pointer instead - .help = a function item is zero-sized and needs to be cast into a function pointer to be used in FFI - .note = for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html - -hir_typeck_fru_expr = this expression does not end in a comma... -hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax -hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression -hir_typeck_fru_suggestion = - to set the remaining fields{$expr -> - [NONE]{""} - *[other] {" "}from `{$expr}` - }, separate the last named field with a comma - -hir_typeck_functional_record_update_on_non_struct = - functional record update syntax requires a struct - -hir_typeck_gpu_kernel_abi_cannot_be_called = - functions with the "gpu-kernel" ABI cannot be called - .note = an `extern "gpu-kernel"` function must be launched on the GPU by the runtime - -hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml` -hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc` - -hir_typeck_int_to_fat = cannot cast `{$expr_ty}` to a pointer that {$known_wide -> - [true] is - *[false] may be - } wide -hir_typeck_int_to_fat_label = creating a `{$cast_ty}` requires both an address and {$metadata} -hir_typeck_int_to_fat_label_nightly = consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` - -hir_typeck_invalid_callee = expected function, found {$found} -hir_typeck_invalid_defined = `{$path}` defined here -hir_typeck_invalid_defined_kind = {$kind} `{$path}` defined here -hir_typeck_invalid_fn_defined = `{$func}` defined here returns `{$ty}` -hir_typeck_invalid_local = `{$local_name}` has type `{$ty}` - -hir_typeck_lossy_provenance_int2ptr = - strict provenance disallows casting integer `{$expr_ty}` to pointer `{$cast_ty}` - .suggestion = use `.with_addr()` to adjust a valid pointer in the same allocation, to this address - .help = if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::with_exposed_provenance()` instead - -hir_typeck_lossy_provenance_ptr2int = - under strict provenance it is considered bad style to cast pointer `{$expr_ty}` to integer `{$cast_ty}` - .suggestion = use `.addr()` to obtain the address of a pointer - .help = if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead - -hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty}` - -hir_typeck_naked_asm_outside_naked_fn = - the `naked_asm!` macro can only be used in functions marked with `#[unsafe(naked)]` - -hir_typeck_naked_functions_asm_block = - naked functions must contain a single `naked_asm!` invocation - .label_multiple_asm = multiple `naked_asm!` invocations are not allowed in naked functions - .label_non_asm = not allowed in naked functions - -hir_typeck_naked_functions_must_naked_asm = - the `asm!` macro is not allowed in naked functions - .label = consider using the `naked_asm!` macro instead - -hir_typeck_never_type_fallback_flowing_into_unsafe_call = never type fallback affects this call to an `unsafe` function - .help = specify the type explicitly -hir_typeck_never_type_fallback_flowing_into_unsafe_deref = never type fallback affects this raw pointer dereference - .help = specify the type explicitly -hir_typeck_never_type_fallback_flowing_into_unsafe_method = never type fallback affects this call to an `unsafe` method - .help = specify the type explicitly -hir_typeck_never_type_fallback_flowing_into_unsafe_path = never type fallback affects this `unsafe` function - .help = specify the type explicitly -hir_typeck_never_type_fallback_flowing_into_unsafe_union_field = never type fallback affects this union access - .help = specify the type explicitly - -hir_typeck_no_associated_item = no {$item_kind} named `{$item_ident}` found for {$ty_prefix} `{$ty}`{$trait_missing_method -> - [true] {""} - *[other] {" "}in the current scope -} - -hir_typeck_no_field_on_type = no field `{$field}` on type `{$ty}` - -hir_typeck_no_field_on_variant = no field named `{$field}` on enum variant `{$container}::{$ident}` -hir_typeck_no_field_on_variant_enum = this enum variant... -hir_typeck_no_field_on_variant_field = ...does not have this field - -hir_typeck_no_patterns = - patterns not allowed in naked function parameters - -hir_typeck_note_caller_chooses_ty_for_ty_param = the caller chooses a type for `{$ty_param_name}` which can be different from `{$found_ty}` - -hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide - -hir_typeck_option_result_asref = use `{$def_path}::as_ref` to convert `{$expected_ty}` to `{$expr_ty}` -hir_typeck_option_result_cloned = use `{$def_path}::cloned` to clone the value inside the `{$def_path}` -hir_typeck_option_result_copied = use `{$def_path}::copied` to copy the value inside the `{$def_path}` - -hir_typeck_outside_loop = - `{$name}` outside of a loop{$is_break -> - [true] {" or labeled block"} - *[false] {""} - } - .label = cannot `{$name}` outside of a loop{$is_break -> - [true] {" or labeled block"} - *[false] {""} - } - -hir_typeck_outside_loop_suggestion = consider labeling this block to be able to break within it - - -hir_typeck_params_not_allowed = - referencing function parameters is not allowed in naked functions - .help = follow the calling convention in asm block to use parameters - -hir_typeck_pass_to_variadic_function = can't pass `{$ty}` to variadic function - .suggestion = cast the value to `{$cast_ty}` - .teach_help = certain types, like `{$ty}`, must be cast before passing them to a variadic function to match the implicit cast that a C compiler would perform as part of C's numeric promotion rules - -hir_typeck_project_on_non_pin_project_type = cannot project on type that is not `#[pin_v2]` - .note = type defined here - .suggestion = add `#[pin_v2]` here - -hir_typeck_ptr_cast_add_auto_to_object = cannot add {$traits_len -> - [1] auto trait {$traits} - *[other] auto traits {$traits} -} to dyn bound via pointer cast - .note = this could allow UB elsewhere - .help = use `transmute` if you're sure this is sound - .label = unsupported cast - -hir_typeck_register_type_unstable = - type `{$ty}` cannot be used with this register class in stable - -hir_typeck_remove_semi_for_coerce = you might have meant to return the `match` expression -hir_typeck_remove_semi_for_coerce_expr = this could be implicitly returned but it is a statement, not a tail expression -hir_typeck_remove_semi_for_coerce_ret = the `match` arms can conform to this return type -hir_typeck_remove_semi_for_coerce_semi = the `match` is a statement because of this semicolon, consider removing it -hir_typeck_remove_semi_for_coerce_suggestion = remove this semicolon - -hir_typeck_replace_comma_with_semicolon = replace the comma with a semicolon to create {$descr} - -hir_typeck_return_stmt_outside_of_fn_body = - {$statement_kind} statement outside of function body - .encl_body_label = the {$statement_kind} is part of this body... - .encl_fn_label = ...not the enclosing function body - -hir_typeck_rpit_box_return_expr = if you change the return type to expect trait objects, box the returned expressions - -hir_typeck_rpit_change_return_type = you could change the return type to be a boxed trait object - -hir_typeck_rustcall_incorrect_args = - functions with the "rust-call" ABI must take a single non-self tuple argument - -hir_typeck_self_ctor_from_outer_item = can't reference `Self` constructor from outer item - .label = the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference - .suggestion = replace `Self` with the actual type - -hir_typeck_self_ctor_from_outer_item_inner_item = `Self` used in this inner item - -hir_typeck_slicing_suggestion = consider slicing here - -hir_typeck_struct_expr_non_exhaustive = - cannot create non-exhaustive {$what} using struct expression - -hir_typeck_suggest_boxing_note = for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html - -hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling `Box::new` - -hir_typeck_suggest_ptr_null_mut = consider using `core::ptr::null_mut` instead - -hir_typeck_supertrait_item_multiple_shadowee = items from several supertraits are shadowed: {$traits} - -hir_typeck_supertrait_item_shadowee = item from `{$supertrait}` is shadowed by a subtrait item - -hir_typeck_supertrait_item_shadower = item from `{$subtrait}` shadows a supertrait item - -hir_typeck_supertrait_item_shadowing = trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait - -hir_typeck_trivial_cast = trivial {$numeric -> - [true] numeric cast - *[false] cast - }: `{$expr_ty}` as `{$cast_ty}` - .help = cast can be replaced by coercion; this might require a temporary variable - -hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns - -hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field - -hir_typeck_unlabeled_cf_in_while_condition = - `break` or `continue` with no label in the condition of a `while` loop - .label = unlabeled `{$cf_type}` in the condition of a `while` loop - -hir_typeck_unlabeled_in_labeled_block = - unlabeled `{$cf_type}` inside of a labeled block - .label = `{$cf_type}` statements that would diverge to or through a labeled block need to bear a label -hir_typeck_use_is_empty = - consider using the `is_empty` method on `{$expr_ty}` to determine if it contains anything - -hir_typeck_yield_expr_outside_of_coroutine = - yield expression outside of coroutine literal diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index a26b44e79dc7..d04bd6f2295a 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -2,7 +2,7 @@ use std::iter; use rustc_abi::{CanonAbi, ExternAbi}; use rustc_ast::util::parser::ExprPrecedence; -use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey}; +use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey, inline_fluent}; use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, HirId, LangItem}; @@ -25,8 +25,8 @@ use tracing::{debug, instrument}; use super::method::MethodCallee; use super::method::probe::ProbeScope; use super::{Expectation, FnCtxt, TupleArgumentsFlag}; +use crate::errors; use crate::method::TreatNotYetDefinedOpaques; -use crate::{errors, fluent_generated}; /// Checks that it is legal to call methods of the trait corresponding /// to `trait_id` (this only cares about the trait, not the specific @@ -832,12 +832,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (Some((_, kind, path)), _) => { err.arg("kind", kind); err.arg("path", path); - Some(fluent_generated::hir_typeck_invalid_defined_kind) + Some(inline_fluent!("{$kind} `{$path}` defined here")) } (_, Some(hir::QPath::Resolved(_, path))) => { self.tcx.sess.source_map().span_to_snippet(path.span).ok().map(|p| { err.arg("func", p); - fluent_generated::hir_typeck_invalid_fn_defined + inline_fluent!("`{$func}` defined here returns `{$ty}`") }) } _ => { @@ -846,15 +846,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // type definitions themselves, but rather variables *of* that type. Res::Local(hir_id) => { err.arg("local_name", self.tcx.hir_name(hir_id)); - Some(fluent_generated::hir_typeck_invalid_local) + Some(inline_fluent!("`{$local_name}` has type `{$ty}`")) } Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => { err.arg("path", self.tcx.def_path_str(def_id)); - Some(fluent_generated::hir_typeck_invalid_defined) + Some(inline_fluent!("`{$path}` defined here")) } _ => { err.arg("path", callee_ty); - Some(fluent_generated::hir_typeck_invalid_defined) + Some(inline_fluent!("`{$path}` defined here")) } } } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 0cf7f09e9376..0f330c3021c0 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -7,7 +7,7 @@ use rustc_ast::{AssignOpKind, Label}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, DiagSymbolList, Diagnostic, - EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, + EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, inline_fluent, }; use rustc_hir as hir; use rustc_hir::ExprKind; @@ -17,15 +17,15 @@ use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; use rustc_span::source_map::Spanned; use rustc_span::{Ident, Span, Symbol}; -use crate::{FnCtxt, fluent_generated as fluent}; +use crate::FnCtxt; #[derive(Diagnostic)] -#[diag(hir_typeck_base_expression_double_dot, code = E0797)] +#[diag("base expression required after `..`", code = E0797)] pub(crate) struct BaseExpressionDoubleDot { #[primary_span] pub span: Span, #[suggestion( - hir_typeck_base_expression_double_dot_enable_default_field_values, + "add `#![feature(default_field_values)]` to the crate attributes to enable default values on `struct` fields", code = "#![feature(default_field_values)]\n", applicability = "machine-applicable", style = "verbose" @@ -39,7 +39,7 @@ pub(crate) struct BaseExpressionDoubleDot { #[derive(Subdiagnostic)] #[suggestion( - hir_typeck_base_expression_double_dot_remove, + "remove the `..` as all the fields are already present", code = "", applicability = "machine-applicable", style = "verbose" @@ -51,7 +51,7 @@ pub(crate) struct BaseExpressionDoubleDotRemove { #[derive(Subdiagnostic)] #[suggestion( - hir_typeck_base_expression_double_dot_add_expr, + "add a base expression here", code = "/* expr */", applicability = "has-placeholders", style = "verbose" @@ -62,24 +62,24 @@ pub(crate) struct BaseExpressionDoubleDotAddExpr { } #[derive(Diagnostic)] -#[diag(hir_typeck_field_multiply_specified_in_initializer, code = E0062)] +#[diag("field `{$ident}` specified more than once", code = E0062)] pub(crate) struct FieldMultiplySpecifiedInInitializer { #[primary_span] - #[label] + #[label("used more than once")] pub span: Span, - #[label(hir_typeck_previous_use_label)] + #[label("first use of `{$ident}`")] pub prev_span: Span, pub ident: Ident, } #[derive(Diagnostic)] -#[diag(hir_typeck_return_stmt_outside_of_fn_body, code = E0572)] +#[diag("{$statement_kind} statement outside of function body", code = E0572)] pub(crate) struct ReturnStmtOutsideOfFnBody { #[primary_span] pub span: Span, - #[label(hir_typeck_encl_body_label)] + #[label("the {$statement_kind} is part of this body...")] pub encl_body_span: Option, - #[label(hir_typeck_encl_fn_label)] + #[label("...not the enclosing function body")] pub encl_fn_span: Option, pub statement_kind: ReturnLikeStatementKind, } @@ -102,21 +102,21 @@ impl IntoDiagArg for ReturnLikeStatementKind { } #[derive(Diagnostic)] -#[diag(hir_typeck_rustcall_incorrect_args)] +#[diag("functions with the \"rust-call\" ABI must take a single non-self tuple argument")] pub(crate) struct RustCallIncorrectArgs { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_yield_expr_outside_of_coroutine, code = E0627)] +#[diag("yield expression outside of coroutine literal", code = E0627)] pub(crate) struct YieldExprOutsideOfCoroutine { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_struct_expr_non_exhaustive, code = E0639)] +#[diag("cannot create non-exhaustive {$what} using struct expression", code = E0639)] pub(crate) struct StructExprNonExhaustive { #[primary_span] pub span: Span, @@ -124,24 +124,24 @@ pub(crate) struct StructExprNonExhaustive { } #[derive(Diagnostic)] -#[diag(hir_typeck_functional_record_update_on_non_struct, code = E0436)] +#[diag("functional record update syntax requires a struct", code = E0436)] pub(crate) struct FunctionalRecordUpdateOnNonStruct { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_address_of_temporary_taken, code = E0745)] +#[diag("cannot take address of a temporary", code = E0745)] pub(crate) struct AddressOfTemporaryTaken { #[primary_span] - #[label] + #[label("temporary value")] pub span: Span, } #[derive(Subdiagnostic)] pub(crate) enum AddReturnTypeSuggestion { #[suggestion( - hir_typeck_add_return_type_add, + "try adding a return type", code = " -> {found}", applicability = "machine-applicable" )] @@ -151,7 +151,7 @@ pub(crate) enum AddReturnTypeSuggestion { found: String, }, #[suggestion( - hir_typeck_add_return_type_missing_here, + "a return type might be missing here", code = " -> _", applicability = "has-placeholders" )] @@ -163,12 +163,12 @@ pub(crate) enum AddReturnTypeSuggestion { #[derive(Subdiagnostic)] pub(crate) enum ExpectedReturnTypeLabel<'tcx> { - #[label(hir_typeck_expected_default_return_type)] + #[label("expected `()` because of default return type")] Unit { #[primary_span] span: Span, }, - #[label(hir_typeck_expected_return_type)] + #[label("expected `{$expected}` because of return type")] Other { #[primary_span] span: Span, @@ -177,10 +177,10 @@ pub(crate) enum ExpectedReturnTypeLabel<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_explicit_destructor, code = E0040)] +#[diag("explicit use of destructor method", code = E0040)] pub(crate) struct ExplicitDestructorCall { #[primary_span] - #[label] + #[label("explicit destructor calls not allowed")] pub span: Span, #[subdiagnostic] pub sugg: ExplicitDestructorCallSugg, @@ -188,9 +188,13 @@ pub(crate) struct ExplicitDestructorCall { #[derive(Subdiagnostic)] pub(crate) enum ExplicitDestructorCallSugg { - #[suggestion(hir_typeck_suggestion, code = "drop", applicability = "maybe-incorrect")] + #[suggestion( + "consider using `drop` function", + code = "drop", + applicability = "maybe-incorrect" + )] Empty(#[primary_span] Span), - #[multipart_suggestion(hir_typeck_suggestion, style = "short")] + #[multipart_suggestion("consider using `drop` function", style = "short")] Snippet { #[suggestion_part(code = "drop(")] lo: Span, @@ -200,10 +204,10 @@ pub(crate) enum ExplicitDestructorCallSugg { } #[derive(Diagnostic)] -#[diag(hir_typeck_missing_parentheses_in_range, code = E0689)] +#[diag("can't call method `{$method_name}` on type `{$ty}`", code = E0689)] pub(crate) struct MissingParenthesesInRange<'tcx> { #[primary_span] - #[label(hir_typeck_missing_parentheses_in_range)] + #[label("can't call method `{$method_name}` on type `{$ty}`")] pub span: Span, pub ty: Ty<'tcx>, pub method_name: String, @@ -213,32 +217,32 @@ pub(crate) struct MissingParenthesesInRange<'tcx> { #[derive(LintDiagnostic)] pub(crate) enum NeverTypeFallbackFlowingIntoUnsafe { - #[help] - #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_call)] + #[help("specify the type explicitly")] + #[diag("never type fallback affects this call to an `unsafe` function")] Call { #[subdiagnostic] sugg: SuggestAnnotations, }, - #[help] - #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_method)] + #[help("specify the type explicitly")] + #[diag("never type fallback affects this call to an `unsafe` method")] Method { #[subdiagnostic] sugg: SuggestAnnotations, }, - #[help] - #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_path)] + #[help("specify the type explicitly")] + #[diag("never type fallback affects this `unsafe` function")] Path { #[subdiagnostic] sugg: SuggestAnnotations, }, - #[help] - #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_union_field)] + #[help("specify the type explicitly")] + #[diag("never type fallback affects this union access")] UnionField { #[subdiagnostic] sugg: SuggestAnnotations, }, - #[help] - #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_deref)] + #[help("specify the type explicitly")] + #[diag("never type fallback affects this raw pointer dereference")] Deref { #[subdiagnostic] sugg: SuggestAnnotations, @@ -246,10 +250,10 @@ pub(crate) enum NeverTypeFallbackFlowingIntoUnsafe { } #[derive(LintDiagnostic)] -#[help] -#[diag(hir_typeck_dependency_on_unit_never_type_fallback)] +#[help("specify the types explicitly")] +#[diag("this function depends on never type fallback being `()`")] pub(crate) struct DependencyOnUnitNeverTypeFallback<'tcx> { - #[note] + #[note("in edition 2024, the requirement `{$obligation}` will fail")] pub obligation_span: Span, pub obligation: ty::Predicate<'tcx>, #[subdiagnostic] @@ -310,7 +314,7 @@ impl Subdiagnostic for SuggestAnnotations { #[derive(Subdiagnostic)] #[multipart_suggestion( - hir_typeck_add_missing_parentheses_in_range, + "you must surround the range in parentheses to call its `{$func_name}` function", style = "verbose", applicability = "maybe-incorrect" )] @@ -337,17 +341,35 @@ impl Subdiagnostic for TypeMismatchFruTypo { // Only explain that `a ..b` is a range if it's split up if self.expr_span.between(self.fru_span).is_empty() { - diag.span_note(self.expr_span.to(self.fru_span), fluent::hir_typeck_fru_note); + diag.span_note( + self.expr_span.to(self.fru_span), + inline_fluent!( + "this expression may have been misinterpreted as a `..` range expression" + ), + ); } else { let mut multispan: MultiSpan = vec![self.expr_span, self.fru_span].into(); - multispan.push_span_label(self.expr_span, fluent::hir_typeck_fru_expr); - multispan.push_span_label(self.fru_span, fluent::hir_typeck_fru_expr2); - diag.span_note(multispan, fluent::hir_typeck_fru_note); + multispan.push_span_label( + self.expr_span, + inline_fluent!("this expression does not end in a comma..."), + ); + multispan.push_span_label(self.fru_span, inline_fluent!("... so this is interpreted as a `..` range expression, instead of functional record update syntax")); + diag.span_note( + multispan, + inline_fluent!( + "this expression may have been misinterpreted as a `..` range expression" + ), + ); } diag.span_suggestion( self.expr_span.shrink_to_hi(), - fluent::hir_typeck_fru_suggestion, + inline_fluent!( + "to set the remaining fields{$expr -> + [NONE]{\"\"} + *[other] {\" \"}from `{$expr}` + }, separate the last named field with a comma" + ), ", ", Applicability::MaybeIncorrect, ); @@ -355,8 +377,10 @@ impl Subdiagnostic for TypeMismatchFruTypo { } #[derive(LintDiagnostic)] -#[diag(hir_typeck_lossy_provenance_int2ptr)] -#[help] +#[diag("strict provenance disallows casting integer `{$expr_ty}` to pointer `{$cast_ty}`")] +#[help( + "if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::with_exposed_provenance()` instead" +)] pub(crate) struct LossyProvenanceInt2Ptr<'tcx> { pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, @@ -365,19 +389,25 @@ pub(crate) struct LossyProvenanceInt2Ptr<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_ptr_cast_add_auto_to_object, code = E0804)] -#[note] -#[help] +#[diag("cannot add {$traits_len -> + [1] auto trait {$traits} + *[other] auto traits {$traits} +} to dyn bound via pointer cast", code = E0804)] +#[note("this could allow UB elsewhere")] +#[help("use `transmute` if you're sure this is sound")] pub(crate) struct PtrCastAddAutoToObject { #[primary_span] - #[label] + #[label("unsupported cast")] pub span: Span, pub traits_len: usize, pub traits: DiagSymbolList, } #[derive(Subdiagnostic)] -#[multipart_suggestion(hir_typeck_suggestion, applicability = "has-placeholders")] +#[multipart_suggestion( + "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address", + applicability = "has-placeholders" +)] pub(crate) struct LossyProvenanceInt2PtrSuggestion { #[suggestion_part(code = "(...).with_addr(")] pub lo: Span, @@ -386,8 +416,12 @@ pub(crate) struct LossyProvenanceInt2PtrSuggestion { } #[derive(LintDiagnostic)] -#[diag(hir_typeck_lossy_provenance_ptr2int)] -#[help] +#[diag( + "under strict provenance it is considered bad style to cast pointer `{$expr_ty}` to integer `{$cast_ty}`" +)] +#[help( + "if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead" +)] pub(crate) struct LossyProvenancePtr2Int<'tcx> { pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, @@ -397,7 +431,10 @@ pub(crate) struct LossyProvenancePtr2Int<'tcx> { #[derive(Subdiagnostic)] pub(crate) enum LossyProvenancePtr2IntSuggestion<'tcx> { - #[multipart_suggestion(hir_typeck_suggestion, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "use `.addr()` to obtain the address of a pointer", + applicability = "maybe-incorrect" + )] NeedsParensCast { #[suggestion_part(code = "(")] expr_span: Span, @@ -405,7 +442,10 @@ pub(crate) enum LossyProvenancePtr2IntSuggestion<'tcx> { cast_span: Span, cast_ty: Ty<'tcx>, }, - #[multipart_suggestion(hir_typeck_suggestion, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "use `.addr()` to obtain the address of a pointer", + applicability = "maybe-incorrect" + )] NeedsParens { #[suggestion_part(code = "(")] expr_span: Span, @@ -413,7 +453,7 @@ pub(crate) enum LossyProvenancePtr2IntSuggestion<'tcx> { cast_span: Span, }, #[suggestion( - hir_typeck_suggestion, + "use `.addr()` to obtain the address of a pointer", code = ".addr() as {cast_ty}", applicability = "maybe-incorrect" )] @@ -422,7 +462,11 @@ pub(crate) enum LossyProvenancePtr2IntSuggestion<'tcx> { cast_span: Span, cast_ty: Ty<'tcx>, }, - #[suggestion(hir_typeck_suggestion, code = ".addr()", applicability = "maybe-incorrect")] + #[suggestion( + "use `.addr()` to obtain the address of a pointer", + code = ".addr()", + applicability = "maybe-incorrect" + )] Other { #[primary_span] cast_span: Span, @@ -431,11 +475,11 @@ pub(crate) enum LossyProvenancePtr2IntSuggestion<'tcx> { #[derive(Subdiagnostic)] pub(crate) enum HelpUseLatestEdition { - #[help(hir_typeck_help_set_edition_cargo)] - #[note(hir_typeck_note_edition_guide)] + #[help("set `edition = \"{$edition}\"` in `Cargo.toml`")] + #[note("for more on editions, read https://doc.rust-lang.org/edition-guide")] Cargo { edition: Edition }, - #[help(hir_typeck_help_set_edition_standalone)] - #[note(hir_typeck_note_edition_guide)] + #[help("pass `--edition {$edition}` to `rustc`")] + #[note("for more on editions, read https://doc.rust-lang.org/edition-guide")] Standalone { edition: Edition }, } @@ -451,7 +495,7 @@ impl HelpUseLatestEdition { } #[derive(Diagnostic)] -#[diag(hir_typeck_no_field_on_type, code = E0609)] +#[diag("no field `{$field}` on type `{$ty}`", code = E0609)] pub(crate) struct NoFieldOnType<'tcx> { #[primary_span] pub(crate) span: Span, @@ -460,33 +504,33 @@ pub(crate) struct NoFieldOnType<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_no_field_on_variant, code = E0609)] +#[diag("no field named `{$field}` on enum variant `{$container}::{$ident}`", code = E0609)] pub(crate) struct NoFieldOnVariant<'tcx> { #[primary_span] pub(crate) span: Span, pub(crate) container: Ty<'tcx>, pub(crate) ident: Ident, pub(crate) field: Ident, - #[label(hir_typeck_no_field_on_variant_enum)] + #[label("this enum variant...")] pub(crate) enum_span: Span, - #[label(hir_typeck_no_field_on_variant_field)] + #[label("...does not have this field")] pub(crate) field_span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_cant_dereference, code = E0614)] +#[diag("type `{$ty}` cannot be dereferenced", code = E0614)] pub(crate) struct CantDereference<'tcx> { #[primary_span] - #[label(hir_typeck_cant_dereference_label)] + #[label("can't be dereferenced")] pub(crate) span: Span, pub(crate) ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(hir_typeck_expected_array_or_slice, code = E0529)] +#[diag("expected an array or slice, found `{$ty}`", code = E0529)] pub(crate) struct ExpectedArrayOrSlice<'tcx> { #[primary_span] - #[label(hir_typeck_expected_array_or_slice_label)] + #[label("pattern cannot match with input type `{$ty}`")] pub(crate) span: Span, pub(crate) ty: Ty<'tcx>, pub(crate) slice_pat_semantics: bool, @@ -498,7 +542,7 @@ pub(crate) struct ExpectedArrayOrSlice<'tcx> { #[derive(Subdiagnostic)] #[suggestion( - hir_typeck_as_deref_suggestion, + "consider using `as_deref` here", code = ".as_deref()", style = "verbose", applicability = "maybe-incorrect" @@ -510,7 +554,7 @@ pub(crate) struct AsDerefSuggestion { #[derive(Subdiagnostic)] #[suggestion( - hir_typeck_slicing_suggestion, + "consider slicing here", code = "[..]", style = "verbose", applicability = "maybe-incorrect" @@ -521,7 +565,7 @@ pub(crate) struct SlicingSuggestion { } #[derive(Diagnostic)] -#[diag(hir_typeck_invalid_callee, code = E0618)] +#[diag("expected function, found {$found}", code = E0618)] pub(crate) struct InvalidCallee<'tcx> { #[primary_span] pub span: Span, @@ -530,15 +574,20 @@ pub(crate) struct InvalidCallee<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_int_to_fat, code = E0606)] +#[diag("cannot cast `{$expr_ty}` to a pointer that {$known_wide -> + [true] is + *[false] may be +} wide", code = E0606)] pub(crate) struct IntToWide<'tcx> { #[primary_span] - #[label(hir_typeck_int_to_fat_label)] + #[label("creating a `{$cast_ty}` requires both an address and {$metadata}")] pub span: Span, pub metadata: &'tcx str, pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, - #[label(hir_typeck_int_to_fat_label_nightly)] + #[label( + "consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`" + )] pub expr_if_nightly: Option, pub known_wide: bool, } @@ -546,7 +595,7 @@ pub(crate) struct IntToWide<'tcx> { #[derive(Subdiagnostic)] pub(crate) enum OptionResultRefMismatch { #[suggestion( - hir_typeck_option_result_copied, + "use `{$def_path}::copied` to copy the value inside the `{$def_path}`", code = ".copied()", style = "verbose", applicability = "machine-applicable" @@ -557,7 +606,7 @@ pub(crate) enum OptionResultRefMismatch { def_path: String, }, #[suggestion( - hir_typeck_option_result_cloned, + "use `{$def_path}::cloned` to clone the value inside the `{$def_path}`", code = ".cloned()", style = "verbose", applicability = "machine-applicable" @@ -569,7 +618,7 @@ pub(crate) enum OptionResultRefMismatch { }, // FIXME: #114050 // #[suggestion( - // hir_typeck_option_result_asref, + // "use `{$def_path}::as_ref` to convert `{$expected_ty}` to `{$expr_ty}`", // code = ".as_ref()", // style = "verbose", // applicability = "machine-applicable" @@ -592,14 +641,30 @@ pub(crate) struct RemoveSemiForCoerce { impl Subdiagnostic for RemoveSemiForCoerce { fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut multispan: MultiSpan = self.semi.into(); - multispan.push_span_label(self.expr, fluent::hir_typeck_remove_semi_for_coerce_expr); - multispan.push_span_label(self.ret, fluent::hir_typeck_remove_semi_for_coerce_ret); - multispan.push_span_label(self.semi, fluent::hir_typeck_remove_semi_for_coerce_semi); - diag.span_note(multispan, fluent::hir_typeck_remove_semi_for_coerce); + multispan.push_span_label( + self.expr, + inline_fluent!( + "this could be implicitly returned but it is a statement, not a tail expression" + ), + ); + multispan.push_span_label( + self.ret, + inline_fluent!("the `match` arms can conform to this return type"), + ); + multispan.push_span_label( + self.semi, + inline_fluent!( + "the `match` is a statement because of this semicolon, consider removing it" + ), + ); + diag.span_note( + multispan, + inline_fluent!("you might have meant to return the `match` expression"), + ); diag.tool_only_span_suggestion( self.semi, - fluent::hir_typeck_remove_semi_for_coerce_suggestion, + inline_fluent!("remove this semicolon"), "", Applicability::MaybeIncorrect, ); @@ -607,14 +672,14 @@ impl Subdiagnostic for RemoveSemiForCoerce { } #[derive(Diagnostic)] -#[diag(hir_typeck_union_pat_multiple_fields)] +#[diag("union patterns should have exactly one field")] pub(crate) struct UnionPatMultipleFields { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_union_pat_dotdot)] +#[diag("`..` cannot be used in union patterns")] pub(crate) struct UnionPatDotDot { #[primary_span] pub span: Span, @@ -622,7 +687,7 @@ pub(crate) struct UnionPatDotDot { #[derive(Subdiagnostic)] #[multipart_suggestion( - hir_typeck_use_is_empty, + "consider using the `is_empty` method on `{$expr_ty}` to determine if it contains anything", applicability = "maybe-incorrect", style = "verbose" )] @@ -635,7 +700,7 @@ pub(crate) struct UseIsEmpty<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_arg_mismatch_indeterminate)] +#[diag("argument type mismatch was detected, but rustc had trouble determining where")] pub(crate) struct ArgMismatchIndeterminate { #[primary_span] pub span: Span, @@ -643,9 +708,11 @@ pub(crate) struct ArgMismatchIndeterminate { #[derive(Subdiagnostic)] pub(crate) enum SuggestBoxing { - #[note(hir_typeck_suggest_boxing_note)] + #[note( + "for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html" + )] #[multipart_suggestion( - hir_typeck_suggest_boxing_when_appropriate, + "store this in the heap by calling `Box::new`", applicability = "machine-applicable" )] Unit { @@ -654,11 +721,15 @@ pub(crate) enum SuggestBoxing { #[suggestion_part(code = "")] end: Span, }, - #[note(hir_typeck_suggest_boxing_note)] + #[note( + "for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html" + )] AsyncBody, - #[note(hir_typeck_suggest_boxing_note)] + #[note( + "for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html" + )] #[multipart_suggestion( - hir_typeck_suggest_boxing_when_appropriate, + "store this in the heap by calling `Box::new`", applicability = "machine-applicable" )] ExprFieldShorthand { @@ -668,9 +739,11 @@ pub(crate) enum SuggestBoxing { end: Span, ident: Ident, }, - #[note(hir_typeck_suggest_boxing_note)] + #[note( + "for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html" + )] #[multipart_suggestion( - hir_typeck_suggest_boxing_when_appropriate, + "store this in the heap by calling `Box::new`", applicability = "machine-applicable" )] Other { @@ -683,7 +756,7 @@ pub(crate) enum SuggestBoxing { #[derive(Subdiagnostic)] #[suggestion( - hir_typeck_suggest_ptr_null_mut, + "consider using `core::ptr::null_mut` instead", applicability = "maybe-incorrect", style = "verbose", code = "core::ptr::null_mut()" @@ -694,8 +767,13 @@ pub(crate) struct SuggestPtrNullMut { } #[derive(LintDiagnostic)] -#[diag(hir_typeck_trivial_cast)] -#[help] +#[diag( + "trivial {$numeric -> + [true] numeric cast + *[false] cast + }: `{$expr_ty}` as `{$cast_ty}`" +)] +#[help("cast can be replaced by coercion; this might require a temporary variable")] pub(crate) struct TrivialCast<'tcx> { pub numeric: bool, pub expr_ty: Ty<'tcx>, @@ -716,17 +794,24 @@ pub(crate) struct BreakNonLoop<'a> { impl<'a, G: EmissionGuarantee> Diagnostic<'_, G> for BreakNonLoop<'a> { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::hir_typeck_break_non_loop); + let mut diag = + Diag::new(dcx, level, inline_fluent!("`break` with value from a `{$kind}` loop")); diag.span(self.span); diag.code(E0571); diag.arg("kind", self.kind); - diag.span_label(self.span, fluent::hir_typeck_label); + diag.span_label( + self.span, + inline_fluent!("can only break with a value inside `loop` or breakable block"), + ); if let Some(head) = self.head { - diag.span_label(head, fluent::hir_typeck_label2); + diag.span_label( + head, + inline_fluent!("you can't `break` with a value in a `{$kind}` loop"), + ); } diag.span_suggestion( self.span, - fluent::hir_typeck_suggestion, + inline_fluent!("use `break` on its own without a value inside this `{$kind}` loop"), self.suggestion, Applicability::MaybeIncorrect, ); @@ -744,7 +829,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'_, G> for BreakNonLoop<'a> { _ => { diag.span_suggestion( self.break_expr_span, - fluent::hir_typeck_break_expr_suggestion, + inline_fluent!( + "alternatively, you might have meant to use the available loop label" + ), label.ident, Applicability::MaybeIncorrect, ); @@ -756,33 +843,33 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'_, G> for BreakNonLoop<'a> { } #[derive(Diagnostic)] -#[diag(hir_typeck_continue_labeled_block, code = E0696)] +#[diag("`continue` pointing to a labeled block", code = E0696)] pub(crate) struct ContinueLabeledBlock { #[primary_span] - #[label] + #[label("labeled blocks cannot be `continue`'d")] pub span: Span, - #[label(hir_typeck_block_label)] + #[label("labeled block the `continue` points to")] pub block_span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_break_inside_closure, code = E0267)] +#[diag("`{$name}` inside of a closure", code = E0267)] pub(crate) struct BreakInsideClosure<'a> { #[primary_span] - #[label] + #[label("cannot `{$name}` inside of a closure")] pub span: Span, - #[label(hir_typeck_closure_label)] + #[label("enclosing closure")] pub closure_span: Span, pub name: &'a str, } #[derive(Diagnostic)] -#[diag(hir_typeck_break_inside_coroutine, code = E0267)] +#[diag("`{$name}` inside `{$kind}` {$source}", code = E0267)] pub(crate) struct BreakInsideCoroutine<'a> { #[primary_span] - #[label] + #[label("cannot `{$name}` inside `{$kind}` {$source}")] pub span: Span, - #[label(hir_typeck_coroutine_label)] + #[label("enclosing `{$kind}` {$source}")] pub coroutine_span: Span, pub name: &'a str, pub kind: &'a str, @@ -790,10 +877,18 @@ pub(crate) struct BreakInsideCoroutine<'a> { } #[derive(Diagnostic)] -#[diag(hir_typeck_outside_loop, code = E0268)] +#[diag("`{$name}` outside of a loop{$is_break -> + [true] {\" or labeled block\"} + *[false] {\"\"} + }", code = E0268)] pub(crate) struct OutsideLoop<'a> { #[primary_span] - #[label] + #[label( + "cannot `{$name}` outside of a loop{$is_break -> + [true] {\" or labeled block\"} + *[false] {\"\"} + }" + )] pub spans: Vec, pub name: &'a str, pub is_break: bool, @@ -801,7 +896,10 @@ pub(crate) struct OutsideLoop<'a> { pub suggestion: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion(hir_typeck_outside_loop_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "consider labeling this block to be able to break within it", + applicability = "maybe-incorrect" +)] pub(crate) struct OutsideLoopSuggestion { #[suggestion_part(code = "'block: ")] pub block_span: Span, @@ -810,25 +908,30 @@ pub(crate) struct OutsideLoopSuggestion { } #[derive(Diagnostic)] -#[diag(hir_typeck_unlabeled_in_labeled_block, code = E0695)] +#[diag("unlabeled `{$cf_type}` inside of a labeled block", code = E0695)] pub(crate) struct UnlabeledInLabeledBlock<'a> { #[primary_span] - #[label] + #[label( + "`{$cf_type}` statements that would diverge to or through a labeled block need to bear a label" + )] pub span: Span, pub cf_type: &'a str, } #[derive(Diagnostic)] -#[diag(hir_typeck_unlabeled_cf_in_while_condition, code = E0590)] +#[diag("`break` or `continue` with no label in the condition of a `while` loop", code = E0590)] pub(crate) struct UnlabeledCfInWhileCondition<'a> { #[primary_span] - #[label] + #[label("unlabeled `{$cf_type}` in the condition of a `while` loop")] pub span: Span, pub cf_type: &'a str, } #[derive(Diagnostic)] -#[diag(hir_typeck_no_associated_item, code = E0599)] +#[diag("no {$item_kind} named `{$item_ident}` found for {$ty_prefix} `{$ty}`{$trait_missing_method -> + [true] {\"\"} + *[other] {\" \"}in the current scope +}", code = E0599)] pub(crate) struct NoAssociatedItem<'tcx> { #[primary_span] pub span: Span, @@ -840,7 +943,13 @@ pub(crate) struct NoAssociatedItem<'tcx> { } #[derive(Subdiagnostic)] -#[note(hir_typeck_candidate_trait_note)] +#[note( + "`{$trait_name}` defines an item `{$item_name}`{$action_or_ty -> + [NONE] {\"\"} + [implement] , perhaps you need to implement it + *[other] , perhaps you need to restrict type parameter `{$action_or_ty}` with it + }" +)] pub(crate) struct CandidateTraitNote { #[primary_span] pub span: Span, @@ -850,7 +959,7 @@ pub(crate) struct CandidateTraitNote { } #[derive(Diagnostic)] -#[diag(hir_typeck_cannot_cast_to_bool, code = E0054)] +#[diag("cannot cast `{$expr_ty}` as `bool`", code = E0054)] pub(crate) struct CannotCastToBool<'tcx> { #[primary_span] pub span: Span, @@ -860,7 +969,7 @@ pub(crate) struct CannotCastToBool<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_cast_enum_drop)] +#[diag("cannot cast enum `{$expr_ty}` into integer `{$cast_ty}` because it implements `Drop`")] pub(crate) struct CastEnumDrop<'tcx> { #[primary_span] pub span: Span, @@ -869,7 +978,10 @@ pub(crate) struct CastEnumDrop<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_typeck_cast_unknown_pointer, code = E0641)] +#[diag("cannot cast {$to -> + [true] to + *[false] from +} a pointer of an unknown kind", code = E0641)] pub(crate) struct CastUnknownPointer { #[primary_span] pub span: Span, @@ -887,13 +999,13 @@ impl rustc_errors::Subdiagnostic for CastUnknownPointerSub { fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { CastUnknownPointerSub::To(span) => { - let msg = diag.eagerly_translate(fluent::hir_typeck_label_to); + let msg = diag.eagerly_translate(inline_fluent!("needs more type information")); diag.span_label(span, msg); - let msg = diag.eagerly_translate(fluent::hir_typeck_note); + let msg = diag.eagerly_translate(inline_fluent!("the type information given here is insufficient to check whether the pointer cast is valid")); diag.note(msg); } CastUnknownPointerSub::From(span) => { - let msg = diag.eagerly_translate(fluent::hir_typeck_label_from); + let msg = diag.eagerly_translate(inline_fluent!("the type information given here is insufficient to check whether the pointer cast is valid")); diag.span_label(span, msg); } } @@ -903,18 +1015,18 @@ impl rustc_errors::Subdiagnostic for CastUnknownPointerSub { #[derive(Subdiagnostic)] pub(crate) enum CannotCastToBoolHelp { #[suggestion( - hir_typeck_suggestion, + "compare with zero instead", applicability = "machine-applicable", code = " != 0", style = "verbose" )] Numeric(#[primary_span] Span), - #[label(hir_typeck_label)] + #[label("unsupported cast")] Unsupported(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(hir_typeck_ctor_is_private, code = E0603)] +#[diag("tuple struct constructor `{$def}` is private", code = E0603)] pub(crate) struct CtorIsPrivate { #[primary_span] pub span: Span, @@ -922,7 +1034,7 @@ pub(crate) struct CtorIsPrivate { } #[derive(Subdiagnostic)] -#[note(hir_typeck_deref_is_empty)] +#[note("this expression `Deref`s to `{$deref_ty}` which implements `is_empty`")] pub(crate) struct DerefImplsIsEmpty<'tcx> { #[primary_span] pub span: Span, @@ -931,7 +1043,7 @@ pub(crate) struct DerefImplsIsEmpty<'tcx> { #[derive(Subdiagnostic)] #[multipart_suggestion( - hir_typeck_convert_using_method, + "try using `{$sugg}` to convert `{$found}` to `{$expected}`", applicability = "machine-applicable", style = "verbose" )] @@ -946,7 +1058,9 @@ pub(crate) struct SuggestConvertViaMethod<'tcx> { } #[derive(Subdiagnostic)] -#[note(hir_typeck_note_caller_chooses_ty_for_ty_param)] +#[note( + "the caller chooses a type for `{$ty_param_name}` which can be different from `{$found_ty}`" +)] pub(crate) struct NoteCallerChoosesTyForTyParam<'tcx> { pub ty_param_name: Symbol, pub found_ty: Ty<'tcx>, @@ -954,14 +1068,20 @@ pub(crate) struct NoteCallerChoosesTyForTyParam<'tcx> { #[derive(Subdiagnostic)] pub(crate) enum SuggestBoxingForReturnImplTrait { - #[multipart_suggestion(hir_typeck_rpit_change_return_type, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "you could change the return type to be a boxed trait object", + applicability = "maybe-incorrect" + )] ChangeReturnType { #[suggestion_part(code = "Box, @@ -971,11 +1091,13 @@ pub(crate) enum SuggestBoxingForReturnImplTrait { } #[derive(Diagnostic)] -#[diag(hir_typeck_self_ctor_from_outer_item, code = E0401)] +#[diag("can't reference `Self` constructor from outer item", code = E0401)] pub(crate) struct SelfCtorFromOuterItem { #[primary_span] pub span: Span, - #[label] + #[label( + "the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference" + )] pub impl_span: Span, #[subdiagnostic] pub sugg: Option, @@ -984,16 +1106,18 @@ pub(crate) struct SelfCtorFromOuterItem { } #[derive(Subdiagnostic)] -#[label(hir_typeck_self_ctor_from_outer_item_inner_item)] +#[label("`Self` used in this inner item")] pub(crate) struct InnerItem { #[primary_span] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(hir_typeck_self_ctor_from_outer_item)] +#[diag("can't reference `Self` constructor from outer item")] pub(crate) struct SelfCtorFromOuterItemLint { - #[label] + #[label( + "the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference" + )] pub impl_span: Span, #[subdiagnostic] pub sugg: Option, @@ -1002,7 +1126,11 @@ pub(crate) struct SelfCtorFromOuterItemLint { } #[derive(Subdiagnostic)] -#[suggestion(hir_typeck_suggestion, code = "{name}", applicability = "machine-applicable")] +#[suggestion( + "replace `Self` with the actual type", + code = "{name}", + applicability = "machine-applicable" +)] pub(crate) struct ReplaceWithName { #[primary_span] pub span: Span, @@ -1010,44 +1138,75 @@ pub(crate) struct ReplaceWithName { } #[derive(Diagnostic)] -#[diag(hir_typeck_cast_thin_pointer_to_wide_pointer, code = E0607)] +#[diag("cannot cast thin pointer `{$expr_ty}` to wide pointer `{$cast_ty}`", code = E0607)] pub(crate) struct CastThinPointerToWidePointer<'tcx> { #[primary_span] pub span: Span, pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, - #[note(hir_typeck_teach_help)] + #[note( + "Thin pointers are \"simple\" pointers: they are purely a reference to a + memory address. + + Wide pointers are pointers referencing \"Dynamically Sized Types\" (also + called DST). DST don't have a statically known size, therefore they can + only exist behind some kind of pointers that contain additional + information. Slices and trait objects are DSTs. In the case of slices, + the additional information the wide pointer holds is their size. + + To fix this error, don't try to cast directly between thin and wide + pointers. + + For more information about casts, take a look at The Book: + https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions" + )] pub(crate) teach: bool, } #[derive(Diagnostic)] -#[diag(hir_typeck_pass_to_variadic_function, code = E0617)] +#[diag("can't pass `{$ty}` to variadic function", code = E0617)] pub(crate) struct PassToVariadicFunction<'a, 'tcx> { #[primary_span] pub span: Span, pub ty: Ty<'tcx>, pub cast_ty: &'a str, - #[suggestion(code = " as {cast_ty}", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "cast the value to `{$cast_ty}`", + code = " as {cast_ty}", + applicability = "machine-applicable", + style = "verbose" + )] pub sugg_span: Span, - #[note(hir_typeck_teach_help)] + #[note( + "certain types, like `{$ty}`, must be cast before passing them to a variadic function to match the implicit cast that a C compiler would perform as part of C's numeric promotion rules" + )] pub(crate) teach: bool, } #[derive(Diagnostic)] -#[diag(hir_typeck_fn_item_to_variadic_function, code = E0617)] -#[help] -#[note] +#[diag("can't pass a function item to a variadic function", code = E0617)] +#[help( + "a function item is zero-sized and needs to be cast into a function pointer to be used in FFI" +)] +#[note( + "for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html" +)] pub(crate) struct PassFnItemToVariadicFunction { #[primary_span] pub span: Span, - #[suggestion(code = " as {replace}", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "use a function pointer instead", + code = " as {replace}", + applicability = "machine-applicable", + style = "verbose" + )] pub sugg_span: Span, pub replace: String, } #[derive(Subdiagnostic)] #[suggestion( - hir_typeck_replace_comma_with_semicolon, + "replace the comma with a semicolon to create {$descr}", applicability = "machine-applicable", style = "verbose", code = "; " @@ -1059,7 +1218,7 @@ pub(crate) struct ReplaceCommaWithSemicolon { } #[derive(LintDiagnostic)] -#[diag(hir_typeck_supertrait_item_shadowing)] +#[diag("trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait")] pub(crate) struct SupertraitItemShadowing { pub item: Symbol, pub subtrait: Symbol, @@ -1070,7 +1229,7 @@ pub(crate) struct SupertraitItemShadowing { } #[derive(Subdiagnostic)] -#[note(hir_typeck_supertrait_item_shadower)] +#[note("item from `{$subtrait}` shadows a supertrait item")] pub(crate) struct SupertraitItemShadower { pub subtrait: Symbol, #[primary_span] @@ -1079,13 +1238,13 @@ pub(crate) struct SupertraitItemShadower { #[derive(Subdiagnostic)] pub(crate) enum SupertraitItemShadowee { - #[note(hir_typeck_supertrait_item_shadowee)] + #[note("item from `{$supertrait}` is shadowed by a subtrait item")] Labeled { #[primary_span] span: Span, supertrait: Symbol, }, - #[note(hir_typeck_supertrait_item_multiple_shadowee)] + #[note("items from several supertraits are shadowed: {$traits}")] Several { #[primary_span] spans: MultiSpan, @@ -1094,7 +1253,7 @@ pub(crate) enum SupertraitItemShadowee { } #[derive(Diagnostic)] -#[diag(hir_typeck_register_type_unstable)] +#[diag("type `{$ty}` cannot be used with this register class in stable")] pub(crate) struct RegisterTypeUnstable<'a> { #[primary_span] pub span: Span, @@ -1102,22 +1261,22 @@ pub(crate) struct RegisterTypeUnstable<'a> { } #[derive(Diagnostic)] -#[diag(hir_typeck_naked_asm_outside_naked_fn)] +#[diag("the `naked_asm!` macro can only be used in functions marked with `#[unsafe(naked)]`")] pub(crate) struct NakedAsmOutsideNakedFn { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_no_patterns)] +#[diag("patterns not allowed in naked function parameters")] pub(crate) struct NoPatterns { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_params_not_allowed)] -#[help] +#[diag("referencing function parameters is not allowed in naked functions")] +#[help("follow the calling convention in asm block to use parameters")] pub(crate) struct ParamsNotAllowed { #[primary_span] pub span: Span, @@ -1132,14 +1291,23 @@ pub(crate) struct NakedFunctionsAsmBlock { impl Diagnostic<'_, G> for NakedFunctionsAsmBlock { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::hir_typeck_naked_functions_asm_block); + let mut diag = Diag::new( + dcx, + level, + inline_fluent!("naked functions must contain a single `naked_asm!` invocation"), + ); diag.span(self.span); diag.code(E0787); for span in self.multiple_asms.iter() { - diag.span_label(*span, fluent::hir_typeck_label_multiple_asm); + diag.span_label( + *span, + inline_fluent!( + "multiple `naked_asm!` invocations are not allowed in naked functions" + ), + ); } for span in self.non_asms.iter() { - diag.span_label(*span, fluent::hir_typeck_label_non_asm); + diag.span_label(*span, inline_fluent!("not allowed in naked functions")); } diag } @@ -1182,44 +1350,48 @@ pub(crate) fn maybe_emit_plus_equals_diagnostic<'a>( } #[derive(Diagnostic)] -#[diag(hir_typeck_naked_functions_must_naked_asm, code = E0787)] +#[diag("the `asm!` macro is not allowed in naked functions", code = E0787)] pub(crate) struct NakedFunctionsMustNakedAsm { #[primary_span] - #[label] + #[label("consider using the `naked_asm!` macro instead")] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_abi_cannot_be_called)] +#[diag("functions with the {$abi} ABI cannot be called")] pub(crate) struct AbiCannotBeCalled { #[primary_span] - #[note] + #[note("an `extern {$abi}` function can only be called using inline assembly")] pub span: Span, pub abi: ExternAbi, } #[derive(Diagnostic)] -#[diag(hir_typeck_gpu_kernel_abi_cannot_be_called)] +#[diag("functions with the \"gpu-kernel\" ABI cannot be called")] pub(crate) struct GpuKernelAbiCannotBeCalled { #[primary_span] - #[note] + #[note("an `extern \"gpu-kernel\"` function must be launched on the GPU by the runtime")] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_const_continue_bad_label)] +#[diag("`#[const_continue]` must break to a labeled block that participates in a `#[loop_match]`")] pub(crate) struct ConstContinueBadLabel { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_typeck_project_on_non_pin_project_type)] +#[diag("cannot project on type that is not `#[pin_v2]`")] pub(crate) struct ProjectOnNonPinProjectType { #[primary_span] pub span: Span, - #[note] + #[note("type defined here")] pub def_span: Option, - #[suggestion(code = "#[pin_v2]\n", applicability = "machine-applicable")] + #[suggestion( + "add `#[pin_v2]` here", + code = "#[pin_v2]\n", + applicability = "machine-applicable" + )] pub sugg_span: Option, } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 3e4c194147f9..934aa0a99614 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -5,7 +5,7 @@ use core::iter; use hir::def_id::LocalDefId; use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::packed::Pu128; -use rustc_errors::{Applicability, Diag, MultiSpan, listify}; +use rustc_errors::{Applicability, Diag, MultiSpan, inline_fluent, listify}; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ @@ -33,10 +33,10 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _ use tracing::{debug, instrument}; use super::FnCtxt; +use crate::errors; use crate::fn_ctxt::rustc_span::BytePos; use crate::method::probe; use crate::method::probe::{IsSuggestion, Mode, ProbeScope}; -use crate::{errors, fluent_generated as fluent}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn body_fn_sig(&self) -> Option> { @@ -482,7 +482,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sugg = prefix_wrap(".map(|x| x.as_str())"); err.span_suggestion_verbose( expr.span.shrink_to_hi(), - fluent::hir_typeck_convert_to_str, + inline_fluent!("try converting the passed type into a `&str`"), sugg, Applicability::MachineApplicable, ); diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 6e126b3013c9..ac3db41a4d66 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -67,8 +67,6 @@ use crate::expectation::Expectation; use crate::fn_ctxt::LoweredTy; use crate::gather_locals::GatherLocalsVisitor; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - #[macro_export] macro_rules! type_error_struct { ($dcx:expr, $span:expr, $typ:expr, $code:expr, $($message:tt)*) => ({ From 94a0ba50e12740a68fa91a2890f63dcbaa0f9c33 Mon Sep 17 00:00:00 2001 From: Jamie Hill-Daniel Date: Wed, 4 Feb 2026 00:54:50 +0000 Subject: [PATCH 543/978] Port `rustc_clean` to attribute parser Also remove mentions of removed `rustc_dirty` --- Cargo.lock | 1 - .../src/attributes/rustc_internal.rs | 114 ++++++++++- compiler/rustc_attr_parsing/src/context.rs | 1 + .../rustc_hir/src/attrs/data_structures.rs | 23 ++- .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + .../rustc_hir/src/attrs/pretty_printing.rs | 4 +- compiler/rustc_incremental/Cargo.toml | 1 - .../rustc_incremental/src/assert_dep_graph.rs | 2 +- compiler/rustc_incremental/src/errors.rs | 32 +-- .../src/persist/{dirty_clean.rs => clean.rs} | 184 +++++++----------- compiler/rustc_incremental/src/persist/mod.rs | 2 +- .../rustc_incremental/src/persist/save.rs | 4 +- compiler/rustc_passes/messages.ftl | 5 +- compiler/rustc_passes/src/check_attr.rs | 15 +- compiler/rustc_passes/src/errors.rs | 4 +- compiler/rustc_query_system/src/ich/mod.rs | 1 - compiler/rustc_span/src/lib.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 - .../compiletest/src/runtest/incremental.rs | 2 +- .../incremental/{dirty_clean.rs => clean.rs} | 0 ...cked_dirty_clean.rs => unchecked_clean.rs} | 0 tests/ui/dep-graph/dep-graph-check-attr.rs | 4 +- .../ui/dep-graph/dep-graph-check-attr.stderr | 8 +- 23 files changed, 241 insertions(+), 169 deletions(-) rename compiler/rustc_incremental/src/persist/{dirty_clean.rs => clean.rs} (73%) rename tests/incremental/{dirty_clean.rs => clean.rs} (100%) rename tests/incremental/{unchecked_dirty_clean.rs => unchecked_clean.rs} (100%) diff --git a/Cargo.lock b/Cargo.lock index 85d3fc1aa7bf..6e088fc12d32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4051,7 +4051,6 @@ dependencies = [ "rustc_serialize", "rustc_session", "rustc_span", - "thin-vec", "tracing", ] diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 8961dc47706f..e30306d0791c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1,7 +1,10 @@ use std::path::PathBuf; use rustc_ast::{LitIntType, LitKind, MetaItemLit}; -use rustc_hir::attrs::{BorrowckGraphvizFormatKind, RustcLayoutType, RustcMirKind}; +use rustc_hir::attrs::{ + BorrowckGraphvizFormatKind, RustcCleanAttribute, RustcCleanQueries, RustcLayoutType, + RustcMirKind, +}; use rustc_session::errors; use super::prelude::*; @@ -497,3 +500,112 @@ impl NoArgsAttributeParser for RustcNonConstTraitMethodParser { ]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonConstTraitMethod; } + +pub(crate) struct RustcCleanParser; + +impl CombineAttributeParser for RustcCleanParser { + const PATH: &[Symbol] = &[sym::rustc_clean]; + + type Item = RustcCleanAttribute; + + const CONVERT: ConvertFn = |items, _| AttributeKind::RustcClean(items); + + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + // tidy-alphabetical-start + Allow(Target::AssocConst), + Allow(Target::AssocTy), + Allow(Target::Const), + Allow(Target::Enum), + Allow(Target::Expression), + Allow(Target::Field), + Allow(Target::Fn), + Allow(Target::ForeignMod), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Impl { of_trait: true }), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Mod), + Allow(Target::Static), + Allow(Target::Struct), + Allow(Target::Trait), + Allow(Target::TyAlias), + Allow(Target::Union), + // tidy-alphabetical-end + ]); + + const TEMPLATE: AttributeTemplate = + template!(List: &[r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#]); + + fn extend( + cx: &mut AcceptContext<'_, '_, S>, + args: &ArgParser, + ) -> impl IntoIterator { + let Some(list) = args.list() else { + cx.expected_list(cx.attr_span, args); + return None; + }; + let mut except = None; + let mut loaded_from_disk = None; + let mut cfg = None; + + for item in list.mixed() { + let Some((value, name)) = + item.meta_item().and_then(|m| Option::zip(m.args().name_value(), m.ident())) + else { + cx.expected_name_value(item.span(), None); + continue; + }; + let value_span = value.value_span; + let Some(value) = value.value_as_str() else { + cx.expected_string_literal(value_span, None); + continue; + }; + match name.name { + sym::cfg if cfg.is_some() => { + cx.duplicate_key(item.span(), sym::cfg); + } + + sym::cfg => { + cfg = Some(value); + } + sym::except if except.is_some() => { + cx.duplicate_key(item.span(), sym::except); + } + sym::except => { + let entries = + value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect(); + except = Some(RustcCleanQueries { entries, span: value_span }); + } + sym::loaded_from_disk if loaded_from_disk.is_some() => { + cx.duplicate_key(item.span(), sym::loaded_from_disk); + } + sym::loaded_from_disk => { + let entries = + value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect(); + loaded_from_disk = Some(RustcCleanQueries { entries, span: value_span }); + } + _ => { + cx.expected_specific_argument( + name.span, + &[sym::cfg, sym::except, sym::loaded_from_disk], + ); + } + } + } + let Some(cfg) = cfg else { + cx.expected_specific_argument(list.span, &[sym::cfg]); + return None; + }; + + Some(RustcCleanAttribute { + // Used for checking that all attributes have been checked + id: cx.cx.sess.psess.attr_id_generator.mk_attr_id(), + span: cx.attr_span, + cfg, + except, + loaded_from_disk, + }) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index fa9f5b585926..e26595ed7545 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -153,6 +153,7 @@ attribute_parsers!( Combine, Combine, Combine, + Combine, Combine, Combine, Combine, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index a53eff4637ff..7955183baf87 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -5,7 +5,7 @@ pub use ReprAttr::*; use rustc_abi::Align; pub use rustc_ast::attr::data_structures::*; use rustc_ast::token::DocFragmentKind; -use rustc_ast::{AttrStyle, ast}; +use rustc_ast::{AttrId, AttrStyle, ast}; use rustc_data_structures::fx::FxIndexMap; use rustc_error_messages::{DiagArgValue, IntoDiagArg}; use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute}; @@ -716,6 +716,24 @@ pub enum BorrowckGraphvizFormatKind { TwoPhase, } +#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(HashStable_Generic, Encodable, Decodable, PrintAttribute)] +pub struct RustcCleanAttribute { + pub id: AttrId, + pub span: Span, + pub cfg: Symbol, + pub except: Option, + pub loaded_from_disk: Option, +} + +/// Represents the `except=` or `loaded_from_disk=` argument of `#[rustc_clean]` +#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(HashStable_Generic, Encodable, Decodable, PrintAttribute)] +pub struct RustcCleanQueries { + pub entries: ThinVec, + pub span: Span, +} + /// Represents parsed *built-in* inert attributes. /// /// ## Overview @@ -1022,6 +1040,9 @@ pub enum AttributeKind { /// Represents `#[rustc_builtin_macro]`. RustcBuiltinMacro { builtin_name: Option, helper_attrs: ThinVec, span: Span }, + /// Represents `#[rustc_clean]` + RustcClean(ThinVec), + /// Represents `#[rustc_coherence_is_core]` RustcCoherenceIsCore(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 7ec1920152a5..500523567433 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -96,6 +96,7 @@ impl AttributeKind { RustcAsPtr(..) => Yes, RustcBodyStability { .. } => No, RustcBuiltinMacro { .. } => Yes, + RustcClean { .. } => No, RustcCoherenceIsCore(..) => No, RustcCoinductive(..) => No, RustcConfusables { .. } => Yes, diff --git a/compiler/rustc_hir/src/attrs/pretty_printing.rs b/compiler/rustc_hir/src/attrs/pretty_printing.rs index bd268d2c423f..20efd72e20f7 100644 --- a/compiler/rustc_hir/src/attrs/pretty_printing.rs +++ b/compiler/rustc_hir/src/attrs/pretty_printing.rs @@ -6,7 +6,7 @@ use rustc_abi::Align; use rustc_ast::attr::data_structures::CfgEntry; use rustc_ast::attr::version::RustcVersion; use rustc_ast::token::{CommentKind, DocFragmentKind}; -use rustc_ast::{AttrStyle, IntTy, UintTy}; +use rustc_ast::{AttrId, AttrStyle, IntTy, UintTy}; use rustc_ast_pretty::pp::Printer; use rustc_data_structures::fx::FxIndexMap; use rustc_span::def_id::DefId; @@ -179,7 +179,7 @@ macro_rules! print_tup { } print_tup!(A B C D E F G H); -print_skip!(Span, (), ErrorGuaranteed); +print_skip!(Span, (), ErrorGuaranteed, AttrId); print_disp!(u8, u16, u128, usize, bool, NonZero, Limit); print_debug!( Symbol, diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml index ae96cc62e54a..d5c3ad2f8337 100644 --- a/compiler/rustc_incremental/Cargo.toml +++ b/compiler/rustc_incremental/Cargo.toml @@ -18,6 +18,5 @@ rustc_middle = { path = "../rustc_middle" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 0e04a2a784ec..7849741802c8 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -5,7 +5,7 @@ //! annotations. These annotations can be used to test whether paths //! exist in the graph. These checks run after codegen, so they view the //! the final state of the dependency graph. Note that there are -//! similar assertions found in `persist::dirty_clean` which check the +//! similar assertions found in `persist::clean` which check the //! **initial** state of the dependency graph, just after it has been //! loaded from disk. //! diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs index 65109fdec03a..757392896d9e 100644 --- a/compiler/rustc_incremental/src/errors.rs +++ b/compiler/rustc_incremental/src/errors.rs @@ -1,7 +1,7 @@ use std::path::{Path, PathBuf}; use rustc_macros::Diagnostic; -use rustc_span::{Ident, Span, Symbol}; +use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] #[diag("unrecognized `DepNode` variant: {$name}")] @@ -106,42 +106,12 @@ pub(crate) struct NotLoaded<'a> { pub dep_node_str: &'a str, } -#[derive(Diagnostic)] -#[diag("unknown `rustc_clean` argument")] -pub(crate) struct UnknownRustcCleanArgument { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("no cfg attribute")] -pub(crate) struct NoCfg { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("associated value expected for `{$ident}`")] -pub(crate) struct AssociatedValueExpectedFor { - #[primary_span] - pub span: Span, - pub ident: Ident, -} - -#[derive(Diagnostic)] -#[diag("expected an associated value")] -pub(crate) struct AssociatedValueExpected { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag("found unchecked `#[rustc_clean]` attribute")] pub(crate) struct UncheckedClean { #[primary_span] pub span: Span, } - #[derive(Diagnostic)] #[diag("unable to delete old {$name} at `{$path}`: {$err}")] pub(crate) struct DeleteOld<'a> { diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/clean.rs similarity index 73% rename from compiler/rustc_incremental/src/persist/dirty_clean.rs rename to compiler/rustc_incremental/src/persist/clean.rs index 71fb18895246..c8ed91277aac 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/clean.rs @@ -19,26 +19,23 @@ //! Errors are reported if we are in the suitable configuration but //! the required condition is not met. -use rustc_ast::{self as ast, MetaItemInner}; +use rustc_ast::ast; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::unord::UnordSet; +use rustc_hir::attrs::{AttributeKind, RustcCleanAttribute}; use rustc_hir::def_id::LocalDefId; use rustc_hir::{ - Attribute, ImplItemKind, ItemKind as HirItem, Node as HirNode, TraitItemKind, intravisit, + Attribute, ImplItemKind, ItemKind as HirItem, Node as HirNode, TraitItemKind, find_attr, + intravisit, }; use rustc_middle::dep_graph::{DepNode, DepNodeExt, dep_kind_from_label, label_strs}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; -use rustc_span::{Span, Symbol, sym}; -use thin_vec::ThinVec; +use rustc_span::{Span, Symbol}; use tracing::debug; use crate::errors; -const LOADED_FROM_DISK: Symbol = sym::loaded_from_disk; -const EXCEPT: Symbol = sym::except; -const CFG: Symbol = sym::cfg; - // Base and Extra labels to build up the labels /// For typedef, constants, and statics @@ -127,14 +124,14 @@ const LABELS_ADT: &[&[&str]] = &[BASE_HIR, BASE_STRUCT]; type Labels = UnordSet; -/// Represents the requested configuration by rustc_clean/dirty +/// Represents the requested configuration by rustc_clean struct Assertion { clean: Labels, dirty: Labels, loaded_from_disk: Labels, } -pub(crate) fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { +pub(crate) fn check_clean_annotations(tcx: TyCtxt<'_>) { if !tcx.sess.opts.unstable_opts.query_dep_graph { return; } @@ -145,24 +142,24 @@ pub(crate) fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { } tcx.dep_graph.with_ignore(|| { - let mut dirty_clean_visitor = DirtyCleanVisitor { tcx, checked_attrs: Default::default() }; + let mut clean_visitor = CleanVisitor { tcx, checked_attrs: Default::default() }; let crate_items = tcx.hir_crate_items(()); for id in crate_items.free_items() { - dirty_clean_visitor.check_item(id.owner_id.def_id); + clean_visitor.check_item(id.owner_id.def_id); } for id in crate_items.trait_items() { - dirty_clean_visitor.check_item(id.owner_id.def_id); + clean_visitor.check_item(id.owner_id.def_id); } for id in crate_items.impl_items() { - dirty_clean_visitor.check_item(id.owner_id.def_id); + clean_visitor.check_item(id.owner_id.def_id); } for id in crate_items.foreign_items() { - dirty_clean_visitor.check_item(id.owner_id.def_id); + clean_visitor.check_item(id.owner_id.def_id); } let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] }; @@ -171,67 +168,62 @@ pub(crate) fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { // Note that we cannot use the existing "unused attribute"-infrastructure // here, since that is running before codegen. This is also the reason why // all codegen-specific attributes are `AssumedUsed` in rustc_ast::feature_gate. - all_attrs.report_unchecked_attrs(dirty_clean_visitor.checked_attrs); + all_attrs.report_unchecked_attrs(clean_visitor.checked_attrs); }) } -struct DirtyCleanVisitor<'tcx> { +struct CleanVisitor<'tcx> { tcx: TyCtxt<'tcx>, checked_attrs: FxHashSet, } -impl<'tcx> DirtyCleanVisitor<'tcx> { - /// Possibly "deserialize" the attribute into a clean/dirty assertion - fn assertion_maybe(&mut self, item_id: LocalDefId, attr: &Attribute) -> Option { - assert!(attr.has_name(sym::rustc_clean)); - if !check_config(self.tcx, attr) { - // skip: not the correct `cfg=` - return None; - } - let assertion = self.assertion_auto(item_id, attr); - Some(assertion) +impl<'tcx> CleanVisitor<'tcx> { + /// Convert the attribute to an [`Assertion`] if the relevant cfg is active + fn assertion_maybe( + &mut self, + item_id: LocalDefId, + attr: &RustcCleanAttribute, + ) -> Option { + self.tcx + .sess + .psess + .config + .contains(&(attr.cfg, None)) + .then(|| self.assertion_auto(item_id, attr)) } /// Gets the "auto" assertion on pre-validated attr, along with the `except` labels. - fn assertion_auto(&mut self, item_id: LocalDefId, attr: &Attribute) -> Assertion { - let (name, mut auto) = self.auto_labels(item_id, attr); + fn assertion_auto(&mut self, item_id: LocalDefId, attr: &RustcCleanAttribute) -> Assertion { + let (name, mut auto) = self.auto_labels(item_id, attr.span); let except = self.except(attr); let loaded_from_disk = self.loaded_from_disk(attr); for e in except.items().into_sorted_stable_ord() { if !auto.remove(e) { - self.tcx.dcx().emit_fatal(errors::AssertionAuto { span: attr.span(), name, e }); + self.tcx.dcx().emit_fatal(errors::AssertionAuto { span: attr.span, name, e }); } } Assertion { clean: auto, dirty: except, loaded_from_disk } } /// `loaded_from_disk=` attribute value - fn loaded_from_disk(&self, attr: &Attribute) -> Labels { - for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) { - if item.has_name(LOADED_FROM_DISK) { - let value = expect_associated_value(self.tcx, &item); - return self.resolve_labels(&item, value); - } - } - // If `loaded_from_disk=` is not specified, don't assert anything - Labels::default() + fn loaded_from_disk(&self, attr: &RustcCleanAttribute) -> Labels { + attr.loaded_from_disk + .as_ref() + .map(|queries| self.resolve_labels(&queries.entries, queries.span)) + .unwrap_or_default() } /// `except=` attribute value - fn except(&self, attr: &Attribute) -> Labels { - for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) { - if item.has_name(EXCEPT) { - let value = expect_associated_value(self.tcx, &item); - return self.resolve_labels(&item, value); - } - } - // if no `label` or `except` is given, only the node's group are asserted - Labels::default() + fn except(&self, attr: &RustcCleanAttribute) -> Labels { + attr.except + .as_ref() + .map(|queries| self.resolve_labels(&queries.entries, queries.span)) + .unwrap_or_default() } /// Return all DepNode labels that should be asserted for this item. /// index=0 is the "name" used for error messages - fn auto_labels(&mut self, item_id: LocalDefId, attr: &Attribute) -> (&'static str, Labels) { + fn auto_labels(&mut self, item_id: LocalDefId, span: Span) -> (&'static str, Labels) { let node = self.tcx.hir_node_by_def_id(item_id); let (name, labels) = match node { HirNode::Item(item) => { @@ -282,7 +274,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { HirItem::Impl { .. } => ("ItemKind::Impl", LABELS_IMPL), _ => self.tcx.dcx().emit_fatal(errors::UndefinedCleanDirtyItem { - span: attr.span(), + span, kind: format!("{:?}", item.kind), }), } @@ -297,31 +289,31 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL), ImplItemKind::Type(..) => ("NodeImplType", LABELS_CONST_IN_IMPL), }, - _ => self.tcx.dcx().emit_fatal(errors::UndefinedCleanDirty { - span: attr.span(), - kind: format!("{node:?}"), - }), + _ => self + .tcx + .dcx() + .emit_fatal(errors::UndefinedCleanDirty { span, kind: format!("{node:?}") }), }; let labels = Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| (*l).to_string()))); (name, labels) } - fn resolve_labels(&self, item: &MetaItemInner, value: Symbol) -> Labels { + fn resolve_labels(&self, values: &[Symbol], span: Span) -> Labels { let mut out = Labels::default(); - for label in value.as_str().split(',') { - let label = label.trim(); - if DepNode::has_label_string(label) { - if out.contains(label) { + for label in values { + let label_str = label.as_str(); + if DepNode::has_label_string(label_str) { + if out.contains(label_str) { self.tcx .dcx() - .emit_fatal(errors::RepeatedDepNodeLabel { span: item.span(), label }); + .emit_fatal(errors::RepeatedDepNodeLabel { span, label: label_str }); } - out.insert(label.to_string()); + out.insert(label_str.to_string()); } else { self.tcx .dcx() - .emit_fatal(errors::UnrecognizedDepNodeLabel { span: item.span(), label }); + .emit_fatal(errors::UnrecognizedDepNodeLabel { span, label: label_str }); } } out @@ -360,11 +352,18 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { fn check_item(&mut self, item_id: LocalDefId) { let item_span = self.tcx.def_span(item_id.to_def_id()); let def_path_hash = self.tcx.def_path_hash(item_id.to_def_id()); - for attr in self.tcx.get_attrs(item_id, sym::rustc_clean) { + + let Some(attr) = + find_attr!(self.tcx.get_all_attrs(item_id), AttributeKind::RustcClean(attr) => attr) + else { + return; + }; + + for attr in attr { let Some(assertion) = self.assertion_maybe(item_id, attr) else { continue; }; - self.checked_attrs.insert(attr.id()); + self.checked_attrs.insert(attr.id); for label in assertion.clean.items().into_sorted_stable_ord() { let dep_node = DepNode::from_label_string(self.tcx, label, def_path_hash).unwrap(); self.assert_clean(item_span, dep_node); @@ -400,61 +399,24 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { } } -/// Given a `#[rustc_clean]` attribute, scan for a `cfg="foo"` attribute and check whether we have -/// a cfg flag called `foo`. -fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool { - debug!("check_config(attr={:?})", attr); - let config = &tcx.sess.psess.config; - debug!("check_config: config={:?}", config); - let mut cfg = None; - for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) { - if item.has_name(CFG) { - let value = expect_associated_value(tcx, &item); - debug!("check_config: searching for cfg {:?}", value); - cfg = Some(config.contains(&(value, None))); - } else if !(item.has_name(EXCEPT) || item.has_name(LOADED_FROM_DISK)) { - tcx.dcx().emit_err(errors::UnknownRustcCleanArgument { span: item.span() }); - } - } - - match cfg { - None => tcx.dcx().emit_fatal(errors::NoCfg { span: attr.span() }), - Some(c) => c, - } -} - -fn expect_associated_value(tcx: TyCtxt<'_>, item: &MetaItemInner) -> Symbol { - if let Some(value) = item.value_str() { - value - } else if let Some(ident) = item.ident() { - tcx.dcx().emit_fatal(errors::AssociatedValueExpectedFor { span: item.span(), ident }); - } else { - tcx.dcx().emit_fatal(errors::AssociatedValueExpected { span: item.span() }); - } -} - /// A visitor that collects all `#[rustc_clean]` attributes from /// the HIR. It is used to verify that we really ran checks for all annotated /// nodes. struct FindAllAttrs<'tcx> { tcx: TyCtxt<'tcx>, - found_attrs: Vec<&'tcx Attribute>, + found_attrs: Vec<&'tcx RustcCleanAttribute>, } impl<'tcx> FindAllAttrs<'tcx> { - fn is_active_attr(&mut self, attr: &Attribute) -> bool { - if attr.has_name(sym::rustc_clean) && check_config(self.tcx, attr) { - return true; - } - - false + fn is_active_attr(&self, attr: &RustcCleanAttribute) -> bool { + self.tcx.sess.psess.config.contains(&(attr.cfg, None)) } fn report_unchecked_attrs(&self, mut checked_attrs: FxHashSet) { for attr in &self.found_attrs { - if !checked_attrs.contains(&attr.id()) { - self.tcx.dcx().emit_err(errors::UncheckedClean { span: attr.span() }); - checked_attrs.insert(attr.id()); + if !checked_attrs.contains(&attr.id) { + self.tcx.dcx().emit_err(errors::UncheckedClean { span: attr.span }); + checked_attrs.insert(attr.id); } } } @@ -468,8 +430,12 @@ impl<'tcx> intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> { } fn visit_attribute(&mut self, attr: &'tcx Attribute) { - if self.is_active_attr(attr) { - self.found_attrs.push(attr); + if let Attribute::Parsed(AttributeKind::RustcClean(attrs)) = attr { + for attr in attrs { + if self.is_active_attr(attr) { + self.found_attrs.push(attr); + } + } } } } diff --git a/compiler/rustc_incremental/src/persist/mod.rs b/compiler/rustc_incremental/src/persist/mod.rs index f5d5167e0e2c..a3857967ab08 100644 --- a/compiler/rustc_incremental/src/persist/mod.rs +++ b/compiler/rustc_incremental/src/persist/mod.rs @@ -2,8 +2,8 @@ //! into the given directory. At the same time, it also hashes the //! various HIR nodes. +mod clean; mod data; -mod dirty_clean; mod file_format; mod fs; mod load; diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 58fea3278a83..be16b543e824 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -14,7 +14,7 @@ use tracing::debug; use super::data::*; use super::fs::*; -use super::{dirty_clean, file_format, work_product}; +use super::{clean, file_format, work_product}; use crate::assert_dep_graph::assert_dep_graph; use crate::errors; @@ -42,7 +42,7 @@ pub(crate) fn save_dep_graph(tcx: TyCtxt<'_>) { let staging_dep_graph_path = staging_dep_graph_path(sess); sess.time("assert_dep_graph", || assert_dep_graph(tcx)); - sess.time("check_dirty_clean", || dirty_clean::check_dirty_clean_annotations(tcx)); + sess.time("check_clean", || clean::check_clean_annotations(tcx)); join( move || { diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index ab89af226793..d6d3d2a3e626 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -439,10 +439,11 @@ passes_rustc_allow_const_fn_unstable = attribute should be applied to `const fn` .label = not a `const fn` +passes_rustc_clean = + attribute requires -Z query-dep-graph to be enabled + passes_rustc_const_stable_indirect_pairing = `const_stable_indirect` attribute does not make sense on `rustc_const_stable` function, its behavior is already implied -passes_rustc_dirty_clean = - attribute requires -Z query-dep-graph to be enabled passes_rustc_force_inline_coro = attribute cannot be applied to a `async`, `gen` or `async gen` function diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4784456a59d9..cf2963e0c285 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -231,6 +231,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_rustc_must_implement_one_of(*attr_span, fn_names, hir_id,target) }, Attribute::Parsed(AttributeKind::DoNotRecommend{attr_span}) => {self.check_do_not_recommend(*attr_span, hir_id, target, item)}, + Attribute::Parsed(AttributeKind::RustcClean(attrs)) => { + for attr in attrs { + self.check_rustc_clean(attr.span); + } + } Attribute::Parsed( // tidy-alphabetical-start AttributeKind::RustcAllowIncoherentImpl(..) @@ -356,10 +361,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::diagnostic, sym::on_const, ..] => { self.check_diagnostic_on_const(attr.span(), hir_id, target, item) } - [sym::rustc_clean, ..] - | [sym::rustc_dirty, ..] - | [sym::rustc_if_this_changed, ..] - | [sym::rustc_then_this_would_need, ..] => self.check_rustc_dirty_clean(attr), + [sym::rustc_if_this_changed, ..] + | [sym::rustc_then_this_would_need, ..] => self.check_rustc_clean(attr.span()), [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => { self.check_autodiff(hir_id, attr, span, target) } @@ -1262,9 +1265,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Checks that the dep-graph debugging attributes are only present when the query-dep-graph /// option is passed to the compiler. - fn check_rustc_dirty_clean(&self, attr: &Attribute) { + fn check_rustc_clean(&self, span: Span) { if !self.tcx.sess.opts.unstable_opts.query_dep_graph { - self.dcx().emit_err(errors::RustcDirtyClean { span: attr.span() }); + self.dcx().emit_err(errors::RustcClean { span }); } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 29688dd4d537..9eec6a5ed8b6 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -218,8 +218,8 @@ pub(crate) struct RustcLegacyConstGenericsIndexExceed { } #[derive(Diagnostic)] -#[diag(passes_rustc_dirty_clean)] -pub(crate) struct RustcDirtyClean { +#[diag(passes_rustc_clean)] +pub(crate) struct RustcClean { #[primary_span] pub span: Span, } diff --git a/compiler/rustc_query_system/src/ich/mod.rs b/compiler/rustc_query_system/src/ich/mod.rs index 25778add60a9..72a7f3b8f970 100644 --- a/compiler/rustc_query_system/src/ich/mod.rs +++ b/compiler/rustc_query_system/src/ich/mod.rs @@ -11,7 +11,6 @@ pub const IGNORED_ATTRIBUTES: &[Symbol] = &[ sym::cfg_trace, // FIXME should this really be ignored? sym::rustc_if_this_changed, sym::rustc_then_this_would_need, - sym::rustc_dirty, sym::rustc_clean, sym::rustc_partition_reused, sym::rustc_partition_codegened, diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index a178f3260d30..17930d35a251 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1331,6 +1331,7 @@ impl Default for Span { rustc_index::newtype_index! { #[orderable] #[debug_format = "AttrId({})"] + #[derive(HashStable_Generic)] pub struct AttrId {} } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c88dd0948b2a..aac4cf1de8c2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1956,7 +1956,6 @@ symbols! { rustc_deprecated_safe_2024, rustc_diagnostic_item, rustc_diagnostic_macros, - rustc_dirty, rustc_do_not_const_check, rustc_doc_primitive, rustc_driver, diff --git a/src/tools/compiletest/src/runtest/incremental.rs b/src/tools/compiletest/src/runtest/incremental.rs index 44eb80300c39..5e7698e24858 100644 --- a/src/tools/compiletest/src/runtest/incremental.rs +++ b/src/tools/compiletest/src/runtest/incremental.rs @@ -21,7 +21,7 @@ impl TestCx<'_> { // - execute build/foo/bar.exe and save output // // FIXME -- use non-incremental mode as an oracle? That doesn't apply - // to #[rustc_dirty] and clean tests I guess + // to #[rustc_clean] tests I guess let revision = self.revision.expect("incremental tests require a list of revisions"); diff --git a/tests/incremental/dirty_clean.rs b/tests/incremental/clean.rs similarity index 100% rename from tests/incremental/dirty_clean.rs rename to tests/incremental/clean.rs diff --git a/tests/incremental/unchecked_dirty_clean.rs b/tests/incremental/unchecked_clean.rs similarity index 100% rename from tests/incremental/unchecked_dirty_clean.rs rename to tests/incremental/unchecked_clean.rs diff --git a/tests/ui/dep-graph/dep-graph-check-attr.rs b/tests/ui/dep-graph/dep-graph-check-attr.rs index a45bf24f8c1f..d1692a2166f8 100644 --- a/tests/ui/dep-graph/dep-graph-check-attr.rs +++ b/tests/ui/dep-graph/dep-graph-check-attr.rs @@ -5,7 +5,7 @@ #![allow(dead_code)] #![allow(unused_variables)] -#[rustc_clean(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph +#[rustc_clean(cfg = "foo")] //~ ERROR attribute requires -Z query-dep-graph fn main() {} #[rustc_if_this_changed(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph @@ -13,7 +13,7 @@ struct Foo { f: T, } -#[rustc_clean(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph +#[rustc_clean(cfg = "foo")] //~ ERROR attribute requires -Z query-dep-graph type TypeAlias = Foo; #[rustc_then_this_would_need(variances_of)] //~ ERROR attribute requires -Z query-dep-graph diff --git a/tests/ui/dep-graph/dep-graph-check-attr.stderr b/tests/ui/dep-graph/dep-graph-check-attr.stderr index 46f4e4358cf6..35df92a5874e 100644 --- a/tests/ui/dep-graph/dep-graph-check-attr.stderr +++ b/tests/ui/dep-graph/dep-graph-check-attr.stderr @@ -1,8 +1,8 @@ error: attribute requires -Z query-dep-graph to be enabled --> $DIR/dep-graph-check-attr.rs:8:1 | -LL | #[rustc_clean(hir_owner)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[rustc_clean(cfg = "foo")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: attribute requires -Z query-dep-graph to be enabled --> $DIR/dep-graph-check-attr.rs:11:1 @@ -13,8 +13,8 @@ LL | #[rustc_if_this_changed(hir_owner)] error: attribute requires -Z query-dep-graph to be enabled --> $DIR/dep-graph-check-attr.rs:16:1 | -LL | #[rustc_clean(hir_owner)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[rustc_clean(cfg = "foo")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: attribute requires -Z query-dep-graph to be enabled --> $DIR/dep-graph-check-attr.rs:19:1 From de7067938dd7e88022f8d72bdd0a9167d4205650 Mon Sep 17 00:00:00 2001 From: Jamie Hill-Daniel Date: Wed, 4 Feb 2026 02:22:48 +0000 Subject: [PATCH 544/978] Port `rustc_if_this_changed`/`rustc_then_this_would_need` to attr parser --- Cargo.lock | 1 - .../src/attributes/rustc_internal.rs | 127 ++++++++++++++++-- compiler/rustc_attr_parsing/src/context.rs | 2 + .../rustc_hir/src/attrs/data_structures.rs | 9 +- .../rustc_hir/src/attrs/encode_cross_crate.rs | 2 + compiler/rustc_incremental/Cargo.toml | 1 - .../rustc_incremental/src/assert_dep_graph.rs | 71 ++++------ compiler/rustc_incremental/src/errors.rs | 7 - .../rustc_incremental/src/persist/clean.rs | 11 +- compiler/rustc_passes/src/check_attr.rs | 5 +- compiler/rustc_span/src/lib.rs | 1 - .../dep-graph-assoc-type-codegen.stderr | 4 +- .../dep-graph/dep-graph-caller-callee.stderr | 8 +- tests/ui/dep-graph/dep-graph-check-attr.rs | 2 +- .../ui/dep-graph/dep-graph-check-attr.stderr | 4 +- .../dep-graph-struct-signature.stderr | 88 ++++++------ ...h-trait-impl-two-traits-same-method.stderr | 8 +- .../dep-graph-trait-impl-two-traits.stderr | 8 +- .../ui/dep-graph/dep-graph-trait-impl.stderr | 20 +-- .../ui/dep-graph/dep-graph-type-alias.stderr | 48 +++---- .../dep-graph/dep-graph-variance-alias.stderr | 4 +- 21 files changed, 256 insertions(+), 175 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e088fc12d32..76f61fcb0d3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4039,7 +4039,6 @@ name = "rustc_incremental" version = "0.0.0" dependencies = [ "rand 0.9.2", - "rustc_ast", "rustc_data_structures", "rustc_errors", "rustc_fs_util", diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index e30306d0791c..37372995faf1 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -6,6 +6,7 @@ use rustc_hir::attrs::{ RustcMirKind, }; use rustc_session::errors; +use rustc_span::Symbol; use super::prelude::*; use super::util::parse_single_integer; @@ -237,7 +238,7 @@ impl NoArgsAttributeParser for RustcLintUntrackedQueryInformationPa pub(crate) struct RustcObjectLifetimeDefaultParser; impl SingleAttributeParser for RustcObjectLifetimeDefaultParser { - const PATH: &[rustc_span::Symbol] = &[sym::rustc_object_lifetime_default]; + const PATH: &[Symbol] = &[sym::rustc_object_lifetime_default]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); @@ -274,7 +275,7 @@ impl SingleAttributeParser for RustcSimdMonomorphizeLaneLimitParser pub(crate) struct RustcScalableVectorParser; impl SingleAttributeParser for RustcScalableVectorParser { - const PATH: &[rustc_span::Symbol] = &[sym::rustc_scalable_vector]; + const PATH: &[Symbol] = &[sym::rustc_scalable_vector]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); @@ -347,7 +348,7 @@ impl NoArgsAttributeParser for RustcOffloadKernelParser { pub(crate) struct RustcLayoutParser; impl CombineAttributeParser for RustcLayoutParser { - const PATH: &[rustc_span::Symbol] = &[sym::rustc_layout]; + const PATH: &[Symbol] = &[sym::rustc_layout]; type Item = RustcLayoutType; @@ -404,7 +405,7 @@ impl CombineAttributeParser for RustcLayoutParser { pub(crate) struct RustcMirParser; impl CombineAttributeParser for RustcMirParser { - const PATH: &[rustc_span::Symbol] = &[sym::rustc_mir]; + const PATH: &[Symbol] = &[sym::rustc_mir]; type Item = RustcMirKind; @@ -599,13 +600,115 @@ impl CombineAttributeParser for RustcCleanParser { return None; }; - Some(RustcCleanAttribute { - // Used for checking that all attributes have been checked - id: cx.cx.sess.psess.attr_id_generator.mk_attr_id(), - span: cx.attr_span, - cfg, - except, - loaded_from_disk, - }) + Some(RustcCleanAttribute { span: cx.attr_span, cfg, except, loaded_from_disk }) + } +} + +pub(crate) struct RustcIfThisChangedParser; + +impl SingleAttributeParser for RustcIfThisChangedParser { + const PATH: &[Symbol] = &[sym::rustc_if_this_changed]; + + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + // tidy-alphabetical-start + Allow(Target::AssocConst), + Allow(Target::AssocTy), + Allow(Target::Const), + Allow(Target::Enum), + Allow(Target::Expression), + Allow(Target::Field), + Allow(Target::Fn), + Allow(Target::ForeignMod), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Impl { of_trait: true }), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Mod), + Allow(Target::Static), + Allow(Target::Struct), + Allow(Target::Trait), + Allow(Target::TyAlias), + Allow(Target::Union), + // tidy-alphabetical-end + ]); + + const TEMPLATE: AttributeTemplate = template!(Word, List: &["DepNode"]); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + match args { + ArgParser::NoArgs => Some(AttributeKind::RustcIfThisChanged(cx.attr_span, None)), + ArgParser::List(list) => { + let Some(item) = list.single() else { + cx.expected_single_argument(list.span); + return None; + }; + let Some(ident) = item.meta_item().and_then(|item| item.ident()) else { + cx.expected_identifier(item.span()); + return None; + }; + Some(AttributeKind::RustcIfThisChanged(cx.attr_span, Some(ident.name))) + } + ArgParser::NameValue(_) => { + cx.expected_list_or_no_args(cx.inner_span); + None + } + } + } +} + +pub(crate) struct RustcThenThisWouldNeedParser; + +impl CombineAttributeParser for RustcThenThisWouldNeedParser { + const PATH: &[Symbol] = &[sym::rustc_then_this_would_need]; + type Item = Ident; + + const CONVERT: ConvertFn = + |items, span| AttributeKind::RustcThenThisWouldNeed(span, items); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + // tidy-alphabetical-start + Allow(Target::AssocConst), + Allow(Target::AssocTy), + Allow(Target::Const), + Allow(Target::Enum), + Allow(Target::Expression), + Allow(Target::Field), + Allow(Target::Fn), + Allow(Target::ForeignMod), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Impl { of_trait: true }), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Mod), + Allow(Target::Static), + Allow(Target::Struct), + Allow(Target::Trait), + Allow(Target::TyAlias), + Allow(Target::Union), + // tidy-alphabetical-end + ]); + + const TEMPLATE: AttributeTemplate = template!(List: &["DepNode"]); + + fn extend( + cx: &mut AcceptContext<'_, '_, S>, + args: &ArgParser, + ) -> impl IntoIterator { + let Some(item) = args.list().and_then(|l| l.single()) else { + cx.expected_single_argument(cx.inner_span); + return None; + }; + let Some(ident) = item.meta_item().and_then(|item| item.ident()) else { + cx.expected_identifier(item.span()); + return None; + }; + Some(ident) } } diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index e26595ed7545..065a17819393 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -156,6 +156,7 @@ attribute_parsers!( Combine, Combine, Combine, + Combine, Combine, Combine, // tidy-alphabetical-end @@ -192,6 +193,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 7955183baf87..ebb34ea87066 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -5,7 +5,7 @@ pub use ReprAttr::*; use rustc_abi::Align; pub use rustc_ast::attr::data_structures::*; use rustc_ast::token::DocFragmentKind; -use rustc_ast::{AttrId, AttrStyle, ast}; +use rustc_ast::{AttrStyle, ast}; use rustc_data_structures::fx::FxIndexMap; use rustc_error_messages::{DiagArgValue, IntoDiagArg}; use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute}; @@ -719,7 +719,6 @@ pub enum BorrowckGraphvizFormatKind { #[derive(Clone, Debug, PartialEq, Eq)] #[derive(HashStable_Generic, Encodable, Decodable, PrintAttribute)] pub struct RustcCleanAttribute { - pub id: AttrId, pub span: Span, pub cfg: Symbol, pub except: Option, @@ -1098,6 +1097,9 @@ pub enum AttributeKind { /// Represents `#[rustc_hidden_type_of_opaques]` RustcHiddenTypeOfOpaques, + /// Represents `#[rustc_if_this_changed]` + RustcIfThisChanged(Span, Option), + /// Represents `#[rustc_layout]` RustcLayout(ThinVec), @@ -1199,6 +1201,9 @@ pub enum AttributeKind { /// Represents `#[rustc_std_internal_symbol]`. RustcStdInternalSymbol(Span), + /// Represents `#[rustc_then_this_would_need]` + RustcThenThisWouldNeed(Span, ThinVec), + /// Represents `#[rustc_unsafe_specialization_marker]`. RustcUnsafeSpecializationMarker(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 500523567433..e97093383b2c 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -113,6 +113,7 @@ impl AttributeKind { RustcDynIncompatibleTrait(..) => No, RustcHasIncoherentInherentImpls => Yes, RustcHiddenTypeOfOpaques => No, + RustcIfThisChanged(..) => No, RustcLayout(..) => No, RustcLayoutScalarValidRangeEnd(..) => Yes, RustcLayoutScalarValidRangeStart(..) => Yes, @@ -145,6 +146,7 @@ impl AttributeKind { RustcSkipDuringMethodDispatch { .. } => No, RustcSpecializationTrait(..) => No, RustcStdInternalSymbol(..) => No, + RustcThenThisWouldNeed(..) => No, RustcUnsafeSpecializationMarker(..) => No, RustcVariance => No, RustcVarianceOfOpaques => No, diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml index d5c3ad2f8337..ac4d7d8e1cbc 100644 --- a/compiler/rustc_incremental/Cargo.toml +++ b/compiler/rustc_incremental/Cargo.toml @@ -6,7 +6,6 @@ edition = "2024" [dependencies] # tidy-alphabetical-start rand = "0.9.0" -rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fs_util = { path = "../rustc_fs_util" } diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 7849741802c8..3447836598bf 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -39,14 +39,16 @@ use std::io::Write; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::graph::linked_graph::{Direction, INCOMING, NodeIndex, OUTGOING}; +use rustc_hir::Attribute; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; +use rustc_middle::bug; use rustc_middle::dep_graph::{ DepGraphQuery, DepKind, DepNode, DepNodeExt, DepNodeFilter, EdgeFilter, dep_kinds, }; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; -use rustc_middle::{bug, span_bug}; use rustc_span::{Span, Symbol, sym}; use tracing::debug; use {rustc_graphviz as dot, rustc_hir as hir}; @@ -105,29 +107,13 @@ struct IfThisChanged<'tcx> { } impl<'tcx> IfThisChanged<'tcx> { - fn argument(&self, attr: &hir::Attribute) -> Option { - let mut value = None; - for list_item in attr.meta_item_list().unwrap_or_default() { - match list_item.ident() { - Some(ident) if list_item.is_word() && value.is_none() => value = Some(ident.name), - _ => - // FIXME better-encapsulate meta_item (don't directly access `node`) - { - span_bug!(list_item.span(), "unexpected meta-item {:?}", list_item) - } - } - } - value - } - fn process_attrs(&mut self, def_id: LocalDefId) { let def_path_hash = self.tcx.def_path_hash(def_id.to_def_id()); let hir_id = self.tcx.local_def_id_to_hir_id(def_id); let attrs = self.tcx.hir_attrs(hir_id); for attr in attrs { - if attr.has_name(sym::rustc_if_this_changed) { - let dep_node_interned = self.argument(attr); - let dep_node = match dep_node_interned { + if let Attribute::Parsed(AttributeKind::RustcIfThisChanged(span, dep_node)) = *attr { + let dep_node = match dep_node { None => DepNode::from_def_path_hash( self.tcx, def_path_hash, @@ -136,36 +122,29 @@ impl<'tcx> IfThisChanged<'tcx> { Some(n) => { match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { Ok(n) => n, - Err(()) => self.tcx.dcx().emit_fatal(errors::UnrecognizedDepNode { - span: attr.span(), - name: n, - }), + Err(()) => self + .tcx + .dcx() + .emit_fatal(errors::UnrecognizedDepNode { span, name: n }), } } }; - self.if_this_changed.push((attr.span(), def_id.to_def_id(), dep_node)); - } else if attr.has_name(sym::rustc_then_this_would_need) { - let dep_node_interned = self.argument(attr); - let dep_node = match dep_node_interned { - Some(n) => { - match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { - Ok(n) => n, - Err(()) => self.tcx.dcx().emit_fatal(errors::UnrecognizedDepNode { - span: attr.span(), - name: n, - }), - } - } - None => { - self.tcx.dcx().emit_fatal(errors::MissingDepNode { span: attr.span() }); - } - }; - self.then_this_would_need.push(( - attr.span(), - dep_node_interned.unwrap(), - hir_id, - dep_node, - )); + self.if_this_changed.push((span, def_id.to_def_id(), dep_node)); + } else if let Attribute::Parsed(AttributeKind::RustcThenThisWouldNeed( + _, + ref dep_nodes, + )) = *attr + { + for &n in dep_nodes { + let Ok(dep_node) = + DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) + else { + self.tcx + .dcx() + .emit_fatal(errors::UnrecognizedDepNode { span: n.span, name: n.name }); + }; + self.then_this_would_need.push((n.span, n.name, hir_id, dep_node)); + } } } } diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs index 757392896d9e..9b33b49d4406 100644 --- a/compiler/rustc_incremental/src/errors.rs +++ b/compiler/rustc_incremental/src/errors.rs @@ -11,13 +11,6 @@ pub(crate) struct UnrecognizedDepNode { pub name: Symbol, } -#[derive(Diagnostic)] -#[diag("missing `DepNode` variant")] -pub(crate) struct MissingDepNode { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag("no `#[rustc_if_this_changed]` annotation detected")] pub(crate) struct MissingIfThisChanged { diff --git a/compiler/rustc_incremental/src/persist/clean.rs b/compiler/rustc_incremental/src/persist/clean.rs index c8ed91277aac..d83ba5a78bed 100644 --- a/compiler/rustc_incremental/src/persist/clean.rs +++ b/compiler/rustc_incremental/src/persist/clean.rs @@ -19,7 +19,6 @@ //! Errors are reported if we are in the suitable configuration but //! the required condition is not met. -use rustc_ast::ast; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::unord::UnordSet; use rustc_hir::attrs::{AttributeKind, RustcCleanAttribute}; @@ -174,7 +173,7 @@ pub(crate) fn check_clean_annotations(tcx: TyCtxt<'_>) { struct CleanVisitor<'tcx> { tcx: TyCtxt<'tcx>, - checked_attrs: FxHashSet, + checked_attrs: FxHashSet, } impl<'tcx> CleanVisitor<'tcx> { @@ -363,7 +362,7 @@ impl<'tcx> CleanVisitor<'tcx> { let Some(assertion) = self.assertion_maybe(item_id, attr) else { continue; }; - self.checked_attrs.insert(attr.id); + self.checked_attrs.insert(attr.span); for label in assertion.clean.items().into_sorted_stable_ord() { let dep_node = DepNode::from_label_string(self.tcx, label, def_path_hash).unwrap(); self.assert_clean(item_span, dep_node); @@ -412,11 +411,11 @@ impl<'tcx> FindAllAttrs<'tcx> { self.tcx.sess.psess.config.contains(&(attr.cfg, None)) } - fn report_unchecked_attrs(&self, mut checked_attrs: FxHashSet) { + fn report_unchecked_attrs(&self, mut checked_attrs: FxHashSet) { for attr in &self.found_attrs { - if !checked_attrs.contains(&attr.id) { + if !checked_attrs.contains(&attr.span) { self.tcx.dcx().emit_err(errors::UncheckedClean { span: attr.span }); - checked_attrs.insert(attr.id); + checked_attrs.insert(attr.span); } } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index cf2963e0c285..48580508b454 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -235,6 +235,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { for attr in attrs { self.check_rustc_clean(attr.span); } + }, + Attribute::Parsed(AttributeKind::RustcIfThisChanged(span, _) | AttributeKind::RustcThenThisWouldNeed(span, _)) => { + self.check_rustc_clean(*span); } Attribute::Parsed( // tidy-alphabetical-start @@ -361,8 +364,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::diagnostic, sym::on_const, ..] => { self.check_diagnostic_on_const(attr.span(), hir_id, target, item) } - [sym::rustc_if_this_changed, ..] - | [sym::rustc_then_this_would_need, ..] => self.check_rustc_clean(attr.span()), [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => { self.check_autodiff(hir_id, attr, span, target) } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 17930d35a251..a178f3260d30 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1331,7 +1331,6 @@ impl Default for Span { rustc_index::newtype_index! { #[orderable] #[debug_format = "AttrId({})"] - #[derive(HashStable_Generic)] pub struct AttrId {} } diff --git a/tests/ui/dep-graph/dep-graph-assoc-type-codegen.stderr b/tests/ui/dep-graph/dep-graph-assoc-type-codegen.stderr index f26b43aa3ec7..b0372051f026 100644 --- a/tests/ui/dep-graph/dep-graph-assoc-type-codegen.stderr +++ b/tests/ui/dep-graph/dep-graph-assoc-type-codegen.stderr @@ -1,8 +1,8 @@ error: OK - --> $DIR/dep-graph-assoc-type-codegen.rs:29:5 + --> $DIR/dep-graph-assoc-type-codegen.rs:29:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/dep-graph/dep-graph-caller-callee.stderr b/tests/ui/dep-graph/dep-graph-caller-callee.stderr index 4d06dc7f3ed3..33fe91b3500a 100644 --- a/tests/ui/dep-graph/dep-graph-caller-callee.stderr +++ b/tests/ui/dep-graph/dep-graph-caller-callee.stderr @@ -1,14 +1,14 @@ error: OK - --> $DIR/dep-graph-caller-callee.rs:21:5 + --> $DIR/dep-graph-caller-callee.rs:21:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: no path from `x` to `typeck` - --> $DIR/dep-graph-caller-callee.rs:32:5 + --> $DIR/dep-graph-caller-callee.rs:32:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/dep-graph/dep-graph-check-attr.rs b/tests/ui/dep-graph/dep-graph-check-attr.rs index d1692a2166f8..c0697a5316f7 100644 --- a/tests/ui/dep-graph/dep-graph-check-attr.rs +++ b/tests/ui/dep-graph/dep-graph-check-attr.rs @@ -8,7 +8,7 @@ #[rustc_clean(cfg = "foo")] //~ ERROR attribute requires -Z query-dep-graph fn main() {} -#[rustc_if_this_changed(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph +#[rustc_if_this_changed] //~ ERROR attribute requires -Z query-dep-graph struct Foo { f: T, } diff --git a/tests/ui/dep-graph/dep-graph-check-attr.stderr b/tests/ui/dep-graph/dep-graph-check-attr.stderr index 35df92a5874e..4b651c47ac83 100644 --- a/tests/ui/dep-graph/dep-graph-check-attr.stderr +++ b/tests/ui/dep-graph/dep-graph-check-attr.stderr @@ -7,8 +7,8 @@ LL | #[rustc_clean(cfg = "foo")] error: attribute requires -Z query-dep-graph to be enabled --> $DIR/dep-graph-check-attr.rs:11:1 | -LL | #[rustc_if_this_changed(hir_owner)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[rustc_if_this_changed] + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: attribute requires -Z query-dep-graph to be enabled --> $DIR/dep-graph-check-attr.rs:16:1 diff --git a/tests/ui/dep-graph/dep-graph-struct-signature.stderr b/tests/ui/dep-graph/dep-graph-struct-signature.stderr index cfe1e62d9318..98efedc7244c 100644 --- a/tests/ui/dep-graph/dep-graph-struct-signature.stderr +++ b/tests/ui/dep-graph/dep-graph-struct-signature.stderr @@ -1,134 +1,134 @@ error: no path from `WillChange` to `type_of` - --> $DIR/dep-graph-struct-signature.rs:28:5 + --> $DIR/dep-graph-struct-signature.rs:28:34 | LL | #[rustc_then_this_would_need(type_of)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: no path from `WillChange` to `associated_item` - --> $DIR/dep-graph-struct-signature.rs:29:5 + --> $DIR/dep-graph-struct-signature.rs:29:34 | LL | #[rustc_then_this_would_need(associated_item)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ error: no path from `WillChange` to `trait_def` - --> $DIR/dep-graph-struct-signature.rs:30:5 + --> $DIR/dep-graph-struct-signature.rs:30:34 | LL | #[rustc_then_this_would_need(trait_def)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:36:5 + --> $DIR/dep-graph-struct-signature.rs:36:34 | LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:37:5 + --> $DIR/dep-graph-struct-signature.rs:37:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:40:5 + --> $DIR/dep-graph-struct-signature.rs:40:34 | LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:41:5 + --> $DIR/dep-graph-struct-signature.rs:41:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:46:5 + --> $DIR/dep-graph-struct-signature.rs:46:34 | LL | #[rustc_then_this_would_need(type_of)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:53:5 + --> $DIR/dep-graph-struct-signature.rs:53:34 | LL | #[rustc_then_this_would_need(type_of)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:61:9 + --> $DIR/dep-graph-struct-signature.rs:61:38 | LL | #[rustc_then_this_would_need(type_of)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:63:9 + --> $DIR/dep-graph-struct-signature.rs:63:38 | LL | #[rustc_then_this_would_need(type_of)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: no path from `WillChange` to `type_of` - --> $DIR/dep-graph-struct-signature.rs:68:5 + --> $DIR/dep-graph-struct-signature.rs:68:34 | LL | #[rustc_then_this_would_need(type_of)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: no path from `WillChange` to `type_of` - --> $DIR/dep-graph-struct-signature.rs:75:5 + --> $DIR/dep-graph-struct-signature.rs:75:34 | LL | #[rustc_then_this_would_need(type_of)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: no path from `WillChange` to `fn_sig` - --> $DIR/dep-graph-struct-signature.rs:81:5 + --> $DIR/dep-graph-struct-signature.rs:81:34 | LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: no path from `WillChange` to `fn_sig` - --> $DIR/dep-graph-struct-signature.rs:84:5 + --> $DIR/dep-graph-struct-signature.rs:84:34 | LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: no path from `WillChange` to `typeck` - --> $DIR/dep-graph-struct-signature.rs:85:5 + --> $DIR/dep-graph-struct-signature.rs:85:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:32:9 + --> $DIR/dep-graph-struct-signature.rs:32:38 | LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: no path from `WillChange` to `fn_sig` - --> $DIR/dep-graph-struct-signature.rs:77:9 + --> $DIR/dep-graph-struct-signature.rs:77:38 | LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:48:9 + --> $DIR/dep-graph-struct-signature.rs:48:38 | LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:49:9 + --> $DIR/dep-graph-struct-signature.rs:49:38 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:55:9 + --> $DIR/dep-graph-struct-signature.rs:55:38 | LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-struct-signature.rs:56:9 + --> $DIR/dep-graph-struct-signature.rs:56:38 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: aborting due to 22 previous errors diff --git a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr index 6f56cbc8dd7a..293f918a3187 100644 --- a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr +++ b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.stderr @@ -1,14 +1,14 @@ error: OK - --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:33:5 + --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:33:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: no path from `x::` to `typeck` - --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:42:5 + --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:42:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr index 08f382cc024c..46cb0e9ea86f 100644 --- a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr +++ b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits.stderr @@ -1,14 +1,14 @@ error: no path from `x::` to `typeck` - --> $DIR/dep-graph-trait-impl-two-traits.rs:32:5 + --> $DIR/dep-graph-trait-impl-two-traits.rs:32:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: no path from `x::` to `typeck` - --> $DIR/dep-graph-trait-impl-two-traits.rs:41:5 + --> $DIR/dep-graph-trait-impl-two-traits.rs:41:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/dep-graph/dep-graph-trait-impl.stderr b/tests/ui/dep-graph/dep-graph-trait-impl.stderr index bfee6d5c87b3..a5fce64c3a1c 100644 --- a/tests/ui/dep-graph/dep-graph-trait-impl.stderr +++ b/tests/ui/dep-graph/dep-graph-trait-impl.stderr @@ -1,32 +1,32 @@ error: OK - --> $DIR/dep-graph-trait-impl.rs:28:5 + --> $DIR/dep-graph-trait-impl.rs:28:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-trait-impl.rs:33:5 + --> $DIR/dep-graph-trait-impl.rs:33:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-trait-impl.rs:38:5 + --> $DIR/dep-graph-trait-impl.rs:38:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-trait-impl.rs:43:5 + --> $DIR/dep-graph-trait-impl.rs:43:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: no path from `x::` to `typeck` - --> $DIR/dep-graph-trait-impl.rs:56:5 + --> $DIR/dep-graph-trait-impl.rs:56:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: aborting due to 5 previous errors diff --git a/tests/ui/dep-graph/dep-graph-type-alias.stderr b/tests/ui/dep-graph/dep-graph-type-alias.stderr index 42ac803b22ec..9f24c1113b98 100644 --- a/tests/ui/dep-graph/dep-graph-type-alias.stderr +++ b/tests/ui/dep-graph/dep-graph-type-alias.stderr @@ -1,74 +1,74 @@ error: no path from `TypeAlias` to `type_of` - --> $DIR/dep-graph-type-alias.rs:18:1 + --> $DIR/dep-graph-type-alias.rs:18:30 | LL | #[rustc_then_this_would_need(type_of)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:20:5 + --> $DIR/dep-graph-type-alias.rs:20:34 | LL | #[rustc_then_this_would_need(type_of)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: no path from `TypeAlias` to `type_of` - --> $DIR/dep-graph-type-alias.rs:25:1 + --> $DIR/dep-graph-type-alias.rs:25:30 | LL | #[rustc_then_this_would_need(type_of)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:28:9 + --> $DIR/dep-graph-type-alias.rs:28:38 | LL | #[rustc_then_this_would_need(type_of)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: no path from `TypeAlias` to `type_of` - --> $DIR/dep-graph-type-alias.rs:34:1 + --> $DIR/dep-graph-type-alias.rs:34:30 | LL | #[rustc_then_this_would_need(type_of)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: no path from `TypeAlias` to `type_of` - --> $DIR/dep-graph-type-alias.rs:42:1 + --> $DIR/dep-graph-type-alias.rs:42:30 | LL | #[rustc_then_this_would_need(type_of)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:49:1 + --> $DIR/dep-graph-type-alias.rs:49:30 | LL | #[rustc_then_this_would_need(type_of)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:52:1 + --> $DIR/dep-graph-type-alias.rs:52:30 | LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:53:1 + --> $DIR/dep-graph-type-alias.rs:53:30 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:36:5 + --> $DIR/dep-graph-type-alias.rs:36:34 | LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:44:5 + --> $DIR/dep-graph-type-alias.rs:44:34 | LL | #[rustc_then_this_would_need(fn_sig)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: OK - --> $DIR/dep-graph-type-alias.rs:45:5 + --> $DIR/dep-graph-type-alias.rs:45:34 | LL | #[rustc_then_this_would_need(typeck)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ error: aborting due to 12 previous errors diff --git a/tests/ui/dep-graph/dep-graph-variance-alias.stderr b/tests/ui/dep-graph/dep-graph-variance-alias.stderr index e11de2452899..83ef573aad48 100644 --- a/tests/ui/dep-graph/dep-graph-variance-alias.stderr +++ b/tests/ui/dep-graph/dep-graph-variance-alias.stderr @@ -1,8 +1,8 @@ error: OK - --> $DIR/dep-graph-variance-alias.rs:19:1 + --> $DIR/dep-graph-variance-alias.rs:19:30 | LL | #[rustc_then_this_would_need(variances_of)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ error: aborting due to 1 previous error From 522778e34826c70576163a207c641483e277419d Mon Sep 17 00:00:00 2001 From: Jamie Hill-Daniel Date: Wed, 4 Feb 2026 20:43:29 +0000 Subject: [PATCH 545/978] Move `query-dep-graph` opt check to attr parsing --- .../src/attributes/rustc_internal.rs | 11 ++++++++++- .../src/session_diagnostics.rs | 8 ++++++++ compiler/rustc_passes/messages.ftl | 3 --- compiler/rustc_passes/src/check_attr.rs | 19 +++---------------- compiler/rustc_passes/src/errors.rs | 7 ------- 5 files changed, 21 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 37372995faf1..348882dc59fc 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -10,7 +10,7 @@ use rustc_span::Symbol; use super::prelude::*; use super::util::parse_single_integer; -use crate::session_diagnostics::RustcScalableVectorCountOutOfRange; +use crate::session_diagnostics::{AttributeRequiresOpt, RustcScalableVectorCountOutOfRange}; pub(crate) struct RustcMainParser; @@ -543,6 +543,9 @@ impl CombineAttributeParser for RustcCleanParser { cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser, ) -> impl IntoIterator { + if !cx.cx.sess.opts.unstable_opts.query_dep_graph { + cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" }); + } let Some(list) = args.list() else { cx.expected_list(cx.attr_span, args); return None; @@ -641,6 +644,9 @@ impl SingleAttributeParser for RustcIfThisChangedParser { const TEMPLATE: AttributeTemplate = template!(Word, List: &["DepNode"]); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + if !cx.cx.sess.opts.unstable_opts.query_dep_graph { + cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" }); + } match args { ArgParser::NoArgs => Some(AttributeKind::RustcIfThisChanged(cx.attr_span, None)), ArgParser::List(list) => { @@ -701,6 +707,9 @@ impl CombineAttributeParser for RustcThenThisWouldNeedParser { cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser, ) -> impl IntoIterator { + if !cx.cx.sess.opts.unstable_opts.query_dep_graph { + cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" }); + } let Some(item) = args.list().and_then(|l| l.single()) else { cx.expected_single_argument(cx.inner_span); return None; diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index b0a334210f74..6ca47e8d698b 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -532,6 +532,14 @@ pub(crate) struct RustcScalableVectorCountOutOfRange { pub n: u128, } +#[derive(Diagnostic)] +#[diag("attribute requires {$opt} to be enabled")] +pub(crate) struct AttributeRequiresOpt { + #[primary_span] + pub span: Span, + pub opt: &'static str, +} + pub(crate) enum AttributeParseErrorReason<'a> { ExpectedNoArgs, ExpectedStringLiteral { diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index d6d3d2a3e626..fae0052ab7a4 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -439,9 +439,6 @@ passes_rustc_allow_const_fn_unstable = attribute should be applied to `const fn` .label = not a `const fn` -passes_rustc_clean = - attribute requires -Z query-dep-graph to be enabled - passes_rustc_const_stable_indirect_pairing = `const_stable_indirect` attribute does not make sense on `rustc_const_stable` function, its behavior is already implied diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 48580508b454..c46321788aed 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -231,14 +231,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_rustc_must_implement_one_of(*attr_span, fn_names, hir_id,target) }, Attribute::Parsed(AttributeKind::DoNotRecommend{attr_span}) => {self.check_do_not_recommend(*attr_span, hir_id, target, item)}, - Attribute::Parsed(AttributeKind::RustcClean(attrs)) => { - for attr in attrs { - self.check_rustc_clean(attr.span); - } - }, - Attribute::Parsed(AttributeKind::RustcIfThisChanged(span, _) | AttributeKind::RustcThenThisWouldNeed(span, _)) => { - self.check_rustc_clean(*span); - } Attribute::Parsed( // tidy-alphabetical-start AttributeKind::RustcAllowIncoherentImpl(..) @@ -300,6 +292,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcAsPtr(..) | AttributeKind::RustcBodyStability { .. } | AttributeKind::RustcBuiltinMacro { .. } + | AttributeKind::RustcClean(..) | AttributeKind::RustcCoherenceIsCore(..) | AttributeKind::RustcCoinductive(..) | AttributeKind::RustcConfusables { .. } @@ -315,6 +308,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcDynIncompatibleTrait(..) | AttributeKind::RustcHasIncoherentInherentImpls | AttributeKind::RustcHiddenTypeOfOpaques + | AttributeKind::RustcIfThisChanged(..) | AttributeKind::RustcLayout(..) | AttributeKind::RustcLayoutScalarValidRangeEnd(..) | AttributeKind::RustcLayoutScalarValidRangeStart(..) @@ -343,6 +337,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcSkipDuringMethodDispatch { .. } | AttributeKind::RustcSpecializationTrait(..) | AttributeKind::RustcStdInternalSymbol (..) + | AttributeKind::RustcThenThisWouldNeed(..) | AttributeKind::RustcUnsafeSpecializationMarker(..) | AttributeKind::RustcVariance | AttributeKind::RustcVarianceOfOpaques @@ -1264,14 +1259,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks that the dep-graph debugging attributes are only present when the query-dep-graph - /// option is passed to the compiler. - fn check_rustc_clean(&self, span: Span) { - if !self.tcx.sess.opts.unstable_opts.query_dep_graph { - self.dcx().emit_err(errors::RustcClean { span }); - } - } - /// Checks if the `#[repr]` attributes on `item` are valid. fn check_repr( &self, diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 9eec6a5ed8b6..d0fa1c4f0e03 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -217,13 +217,6 @@ pub(crate) struct RustcLegacyConstGenericsIndexExceed { pub arg_count: usize, } -#[derive(Diagnostic)] -#[diag(passes_rustc_clean)] -pub(crate) struct RustcClean { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(passes_repr_conflicting, code = E0566)] pub(crate) struct ReprConflicting { From a68bb0c3711ccb6d90aa039cac9a28c67a4e3cc0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 2 Feb 2026 15:27:05 +1100 Subject: [PATCH 546/978] Move `rustc_query_system::values` module into `rustc_middle`. It's a tiny module with one trait and a default impl. It's not used in `rustc_query_system`; all uses and non-default impls are in `rustc_middle` and `rustc_query_impl`. This commit moves it into `rustc_middle`, which makes things simpler overall. --- compiler/rustc_middle/src/lib.rs | 2 +- compiler/rustc_middle/src/values.rs | 41 +++++++++++++++++------ compiler/rustc_query_impl/src/lib.rs | 2 +- compiler/rustc_query_system/src/lib.rs | 2 -- compiler/rustc_query_system/src/values.rs | 21 ------------ 5 files changed, 32 insertions(+), 36 deletions(-) delete mode 100644 compiler/rustc_query_system/src/values.rs diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index bb94b4c927ae..a21427f6c819 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -81,7 +81,7 @@ pub mod thir; pub mod traits; pub mod ty; pub mod util; -mod values; +pub mod values; #[macro_use] pub mod query; diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index fd08b5a972c6..0828758cc94e 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -7,7 +7,6 @@ use rustc_errors::codes::*; use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_query_system::Value; use rustc_query_system::query::{CycleError, report_cycle}; use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span}; @@ -16,7 +15,27 @@ use crate::dep_graph::dep_kinds; use crate::query::plumbing::CyclePlaceholder; use crate::ty::{self, Representability, Ty, TyCtxt}; -impl<'tcx> Value> for Ty<'_> { +pub trait Value<'tcx>: Sized { + fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed) + -> Self; +} + +impl<'tcx, T> Value<'tcx> for T { + default fn from_cycle_error( + tcx: TyCtxt<'tcx>, + cycle_error: &CycleError, + _guar: ErrorGuaranteed, + ) -> T { + tcx.sess.dcx().abort_if_errors(); + bug!( + "<{} as Value>::from_cycle_error called without errors: {:#?}", + std::any::type_name::(), + cycle_error.cycle, + ); + } +} + +impl<'tcx> Value<'tcx> for Ty<'_> { fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &CycleError, guar: ErrorGuaranteed) -> Self { // SAFETY: This is never called when `Self` is not `Ty<'tcx>`. // FIXME: Represent the above fact in the trait system somehow. @@ -24,13 +43,13 @@ impl<'tcx> Value> for Ty<'_> { } } -impl<'tcx> Value> for Result>, CyclePlaceholder> { +impl<'tcx> Value<'tcx> for Result>, CyclePlaceholder> { fn from_cycle_error(_tcx: TyCtxt<'tcx>, _: &CycleError, guar: ErrorGuaranteed) -> Self { Err(CyclePlaceholder(guar)) } } -impl<'tcx> Value> for ty::SymbolName<'_> { +impl<'tcx> Value<'tcx> for ty::SymbolName<'_> { fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &CycleError, _guar: ErrorGuaranteed) -> Self { // SAFETY: This is never called when `Self` is not `SymbolName<'tcx>`. // FIXME: Represent the above fact in the trait system somehow. @@ -42,7 +61,7 @@ impl<'tcx> Value> for ty::SymbolName<'_> { } } -impl<'tcx> Value> for ty::Binder<'_, ty::FnSig<'_>> { +impl<'tcx> Value<'tcx> for ty::Binder<'_, ty::FnSig<'_>> { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, @@ -76,7 +95,7 @@ impl<'tcx> Value> for ty::Binder<'_, ty::FnSig<'_>> { } } -impl<'tcx> Value> for Representability { +impl<'tcx> Value<'tcx> for Representability { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, @@ -112,7 +131,7 @@ impl<'tcx> Value> for Representability { } } -impl<'tcx> Value> for ty::EarlyBinder<'_, Ty<'_>> { +impl<'tcx> Value<'tcx> for ty::EarlyBinder<'_, Ty<'_>> { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, @@ -122,7 +141,7 @@ impl<'tcx> Value> for ty::EarlyBinder<'_, Ty<'_>> { } } -impl<'tcx> Value> for ty::EarlyBinder<'_, ty::Binder<'_, ty::FnSig<'_>>> { +impl<'tcx> Value<'tcx> for ty::EarlyBinder<'_, ty::Binder<'_, ty::FnSig<'_>>> { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, @@ -132,7 +151,7 @@ impl<'tcx> Value> for ty::EarlyBinder<'_, ty::Binder<'_, ty::FnSig< } } -impl<'tcx> Value> for &[ty::Variance] { +impl<'tcx> Value<'tcx> for &[ty::Variance] { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, @@ -180,7 +199,7 @@ fn search_for_cycle_permutation( otherwise() } -impl<'tcx, T> Value> for Result> { +impl<'tcx, T> Value<'tcx> for Result> { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, @@ -273,7 +292,7 @@ impl<'tcx, T> Value> for Result> // item_and_field_ids should form a cycle where each field contains the // type in the next element in the list -pub fn recursive_type_error( +fn recursive_type_error( tcx: TyCtxt<'_>, mut item_and_field_ids: Vec<(LocalDefId, LocalDefId)>, representable_ids: &FxHashSet, diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index baa37111c807..44f3da7785f0 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -20,7 +20,7 @@ use rustc_middle::query::AsLocalKey; use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; use rustc_middle::query::plumbing::{QuerySystem, QuerySystemFns, QueryVTable}; use rustc_middle::ty::TyCtxt; -use rustc_query_system::Value; +use rustc_middle::values::Value; use rustc_query_system::dep_graph::SerializedDepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index d1907a8c582d..3175dbb54bea 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -10,7 +10,5 @@ pub mod dep_graph; mod error; pub mod ich; pub mod query; -mod values; pub use error::{QueryOverflow, QueryOverflowNote}; -pub use values::Value; diff --git a/compiler/rustc_query_system/src/values.rs b/compiler/rustc_query_system/src/values.rs deleted file mode 100644 index 133904f59af1..000000000000 --- a/compiler/rustc_query_system/src/values.rs +++ /dev/null @@ -1,21 +0,0 @@ -use rustc_span::ErrorGuaranteed; - -use crate::dep_graph::DepContext; -use crate::query::CycleError; - -pub trait Value: Sized { - fn from_cycle_error(tcx: Tcx, cycle_error: &CycleError, guar: ErrorGuaranteed) -> Self; -} - -impl Value for T { - default fn from_cycle_error(tcx: Tcx, cycle_error: &CycleError, _guar: ErrorGuaranteed) -> T { - tcx.sess().dcx().abort_if_errors(); - // Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's - // non-trivial to define it earlier. - panic!( - "<{} as Value>::from_cycle_error called without errors: {:#?}", - std::any::type_name::(), - cycle_error.cycle, - ); - } -} From 1851937577eaf46ef18c437ac2ad9b2a5f3e3606 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:59:06 +0000 Subject: [PATCH 547/978] Hard code the error code registry for custom drivers --- compiler/rustc_driver_impl/src/lib.rs | 11 ++++------- compiler/rustc_errors/src/codes.rs | 2 +- compiler/rustc_errors/src/lib.rs | 7 +------ compiler/rustc_errors/src/registry.rs | 4 ++-- compiler/rustc_interface/src/interface.rs | 5 ----- compiler/rustc_interface/src/tests.rs | 3 +-- compiler/rustc_session/src/session.rs | 6 ++---- .../examples/rustc-interface-example.rs | 4 ---- .../examples/rustc-interface-getting-diagnostics.rs | 3 +-- src/librustdoc/core.rs | 1 - src/librustdoc/doctest.rs | 1 - src/tools/rustfmt/src/parse/session.rs | 8 ++++---- tests/ui-fulldeps/run-compiler-twice.rs | 1 - 13 files changed, 16 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 3b9ca5ff7288..515b011b486d 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -197,10 +197,6 @@ impl Callbacks for TimePassesCallbacks { } } -pub fn diagnostics_registry() -> Registry { - Registry::new(rustc_errors::codes::DIAGNOSTICS) -} - /// This is the primary entry point for rustc. pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) { let mut default_early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); @@ -228,7 +224,7 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) let ice_file = ice_path_with_config(Some(&sopts.unstable_opts)).clone(); if let Some(ref code) = matches.opt_str("explain") { - handle_explain(&default_early_dcx, diagnostics_registry(), code, sopts.color); + handle_explain(&default_early_dcx, code, sopts.color); return; } @@ -255,7 +251,6 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) override_queries: None, extra_symbols: Vec::new(), make_codegen_backend: None, - registry: diagnostics_registry(), using_internal_features: &USING_INTERNAL_FEATURES, }; @@ -455,7 +450,9 @@ pub enum Compilation { Continue, } -fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, color: ColorConfig) { +fn handle_explain(early_dcx: &EarlyDiagCtxt, code: &str, color: ColorConfig) { + let registry = Registry::new(); + // Allow "E0123" or "0123" form. let upper_cased_code = code.to_ascii_uppercase(); if let Ok(code) = upper_cased_code.trim_prefix('E').parse::() diff --git a/compiler/rustc_errors/src/codes.rs b/compiler/rustc_errors/src/codes.rs index 924924f285eb..f266ae97d4c7 100644 --- a/compiler/rustc_errors/src/codes.rs +++ b/compiler/rustc_errors/src/codes.rs @@ -27,7 +27,7 @@ macro_rules! define_error_code_constants_and_diagnostics_table { $( pub const ${concat(E, $num)}: $crate::ErrCode = $crate::ErrCode::from_u32($num); )* - pub static DIAGNOSTICS: &[($crate::ErrCode, &str)] = &[ + pub(crate) static DIAGNOSTICS: &[($crate::ErrCode, &str)] = &[ $( ( ${concat(E, $num)}, include_str!( diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 68d825a4514a..02fbb969412a 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -482,11 +482,6 @@ impl DiagCtxt { self } - pub fn with_registry(mut self, registry: Registry) -> Self { - self.inner.get_mut().registry = registry; - self - } - pub fn new(emitter: Box) -> Self { Self { inner: Lock::new(DiagCtxtInner::new(emitter)) } } @@ -1186,7 +1181,7 @@ impl DiagCtxtInner { fn new(emitter: Box) -> Self { Self { flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() }, - registry: Registry::new(&[]), + registry: Registry::new(), err_guars: Vec::new(), lint_err_guars: Vec::new(), delayed_bugs: Vec::new(), diff --git a/compiler/rustc_errors/src/registry.rs b/compiler/rustc_errors/src/registry.rs index baca7700d90e..5ad6cdd9688f 100644 --- a/compiler/rustc_errors/src/registry.rs +++ b/compiler/rustc_errors/src/registry.rs @@ -11,8 +11,8 @@ pub struct Registry { } impl Registry { - pub fn new(long_descriptions: &[(ErrCode, &'static str)]) -> Registry { - Registry { long_descriptions: long_descriptions.iter().copied().collect() } + pub fn new() -> Registry { + Registry { long_descriptions: crate::codes::DIAGNOSTICS.iter().copied().collect() } } /// Returns `InvalidErrorCode` if the code requested does not exist in the diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 276fa5db7798..d3244acef2c1 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -7,7 +7,6 @@ use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::jobserver::{self, Proxy}; use rustc_data_structures::stable_hasher::StableHasher; -use rustc_errors::registry::Registry; use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed}; use rustc_lint::LintStore; use rustc_middle::ty; @@ -374,9 +373,6 @@ pub struct Config { pub make_codegen_backend: Option Box + Send>>, - /// Registry of diagnostics codes. - pub registry: Registry, - /// The inner atomic value is set to true when a feature marked as `internal` is /// enabled. Makes it so that "please report a bug" is hidden, as ICEs with /// internal features are wontfix, and they are usually the cause of the ICEs. @@ -464,7 +460,6 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se temps_dir, }, bundle, - config.registry, config.locale_resources, config.lint_caps, target, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index b0272d726bc3..4241af244941 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -6,8 +6,8 @@ use std::sync::atomic::AtomicBool; use rustc_abi::Align; use rustc_data_structures::profiling::TimePassesFormat; +use rustc_errors::ColorConfig; use rustc_errors::emitter::HumanReadableErrorType; -use rustc_errors::{ColorConfig, registry}; use rustc_hir::attrs::{CollapseMacroDebuginfo, NativeLibKind}; use rustc_session::config::{ AnnotateMoves, AutoDiff, BranchProtection, CFGuard, Cfg, CoverageLevel, CoverageOptions, @@ -72,7 +72,6 @@ where sessopts, io, None, - registry::Registry::new(&[]), vec![], Default::default(), target, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 27d6efb8b549..b141aada43bb 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -963,7 +963,6 @@ pub fn build_session( sopts: config::Options, io: CompilerIO, fluent_bundle: Option>, - registry: rustc_errors::registry::Registry, fluent_resources: Vec<&'static str>, driver_lint_caps: FxHashMap, target: Target, @@ -992,9 +991,8 @@ pub fn build_session( let source_map = rustc_span::source_map::get_source_map().unwrap(); let emitter = default_emitter(&sopts, Arc::clone(&source_map), translator); - let mut dcx = DiagCtxt::new(emitter) - .with_flags(sopts.unstable_opts.dcx_flags(can_emit_warnings)) - .with_registry(registry); + let mut dcx = + DiagCtxt::new(emitter).with_flags(sopts.unstable_opts.dcx_flags(can_emit_warnings)); if let Some(ice_file) = ice_file { dcx = dcx.with_ice_file(ice_file); } diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs index 360f70c8e865..fe9895d778fd 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs @@ -4,14 +4,12 @@ extern crate rustc_driver; extern crate rustc_error_codes; -extern crate rustc_errors; extern crate rustc_hash; extern crate rustc_hir; extern crate rustc_interface; extern crate rustc_session; extern crate rustc_span; -use rustc_errors::registry; use rustc_hash::FxHashMap; use rustc_session::config; @@ -50,8 +48,6 @@ fn main() { // // The second parameter is local providers and the third parameter is external providers. override_queries: None, // Option, &mut ty::query::Providers<'_>)> - // Registry of diagnostics codes. - registry: registry::Registry::new(rustc_errors::codes::DIAGNOSTICS), make_codegen_backend: None, expanded_args: Vec::new(), ice_file: None, diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs index 2512ba3c3f92..83b71b351bbc 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs @@ -15,7 +15,7 @@ extern crate rustc_span; use std::sync::{Arc, Mutex}; use rustc_errors::emitter::Emitter; -use rustc_errors::registry::{self, Registry}; +use rustc_errors::registry::Registry; use rustc_errors::translation::Translate; use rustc_errors::{DiagInner, FluentBundle}; use rustc_session::config; @@ -76,7 +76,6 @@ fn main() { })), register_lints: None, override_queries: None, - registry: registry::Registry::new(rustc_errors::codes::DIAGNOSTICS), make_codegen_backend: None, expanded_args: Vec::new(), ice_file: None, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 413163290ee3..a45175dc08f0 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -322,7 +322,6 @@ pub(crate) fn create_config( }), extra_symbols: Vec::new(), make_codegen_backend: None, - registry: rustc_driver::diagnostics_registry(), ice_file: None, using_internal_features: &USING_INTERNAL_FEATURES, } diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 6cd7d2c628d5..0605d16699fa 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -196,7 +196,6 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions override_queries: None, extra_symbols: Vec::new(), make_codegen_backend: None, - registry: rustc_driver::diagnostics_registry(), ice_file: None, using_internal_features: &rustc_driver::USING_INTERNAL_FEATURES, }; diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index 7b6ffa1e495f..e80b7d57c641 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -401,7 +401,7 @@ mod tests { let source = String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#); source_map.new_source_file(filename(&source_map, "foo.rs"), source); - let registry = Registry::new(&[]); + let registry = Registry::new(); let mut emitter = build_emitter( Arc::clone(&num_emitted_errors), Arc::clone(&can_reset_errors), @@ -424,7 +424,7 @@ mod tests { let source_map = Arc::new(SourceMap::new(FilePathMapping::empty())); let source = String::from(r#"pub fn bar() { 1x; }"#); source_map.new_source_file(filename(&source_map, "foo.rs"), source); - let registry = Registry::new(&[]); + let registry = Registry::new(); let mut emitter = build_emitter( Arc::clone(&num_emitted_errors), Arc::clone(&can_reset_errors), @@ -446,7 +446,7 @@ mod tests { let source_map = Arc::new(SourceMap::new(FilePathMapping::empty())); let source = String::from(r#"pub fn bar() { 1x; }"#); source_map.new_source_file(filename(&source_map, "foo.rs"), source); - let registry = Registry::new(&[]); + let registry = Registry::new(); let mut emitter = build_emitter( Arc::clone(&num_emitted_errors), Arc::clone(&can_reset_errors), @@ -474,7 +474,7 @@ mod tests { source_map.new_source_file(filename(&source_map, "bar.rs"), bar_source); source_map.new_source_file(filename(&source_map, "foo.rs"), foo_source); source_map.new_source_file(filename(&source_map, "fatal.rs"), fatal_source); - let registry = Registry::new(&[]); + let registry = Registry::new(); let mut emitter = build_emitter( Arc::clone(&num_emitted_errors), Arc::clone(&can_reset_errors), diff --git a/tests/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs index 241d9e7efbd7..8b5e99cbee8d 100644 --- a/tests/ui-fulldeps/run-compiler-twice.rs +++ b/tests/ui-fulldeps/run-compiler-twice.rs @@ -72,7 +72,6 @@ fn compile(code: String, output: PathBuf, sysroot: Sysroot, linker: Option<&Path override_queries: None, extra_symbols: Vec::new(), make_codegen_backend: None, - registry: rustc_driver::diagnostics_registry(), using_internal_features: &rustc_driver::USING_INTERNAL_FEATURES, }; From 7bcb7a281e6cb36d9d87ca28e4d0edbaddaf5eef Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Feb 2026 10:38:28 +1100 Subject: [PATCH 548/978] Move `rustc_middle::values` module to `rustc_middle::query::values`. It's a better place for it, because it relates to queries. --- compiler/rustc_middle/src/lib.rs | 1 - compiler/rustc_middle/src/query/mod.rs | 1 + compiler/rustc_middle/src/{ => query}/values.rs | 0 compiler/rustc_query_impl/src/lib.rs | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) rename compiler/rustc_middle/src/{ => query}/values.rs (100%) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index a21427f6c819..7d1b775cc4bc 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -81,7 +81,6 @@ pub mod thir; pub mod traits; pub mod ty; pub mod util; -pub mod values; #[macro_use] pub mod query; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 24a38e70ff6f..a7707cf48c49 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -13,6 +13,7 @@ mod keys; pub mod on_disk_cache; #[macro_use] pub mod plumbing; +pub mod values; pub fn describe_as_module(def_id: impl Into, tcx: TyCtxt<'_>) -> String { let def_id = def_id.into(); diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/query/values.rs similarity index 100% rename from compiler/rustc_middle/src/values.rs rename to compiler/rustc_middle/src/query/values.rs diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 44f3da7785f0..6c9a075177ad 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -19,8 +19,8 @@ use rustc_middle::queries::{ use rustc_middle::query::AsLocalKey; use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; use rustc_middle::query::plumbing::{QuerySystem, QuerySystemFns, QueryVTable}; +use rustc_middle::query::values::Value; use rustc_middle::ty::TyCtxt; -use rustc_middle::values::Value; use rustc_query_system::dep_graph::SerializedDepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ From 0932068b6c9330f54eab92d5888131e6c877b3ce Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 2 Feb 2026 16:05:26 +1100 Subject: [PATCH 549/978] Move the `QueryOverflow` and `QueryOverflowNote` errors. They are defined in `rustc_query_system` but used in `rustc_query_impl`. This is very much *not* how things are supposed to be done; I suspect someone got lazy and took a shortcut at some point. This commit moves the errors into `rustc_query_impl`. This requires more lines of code to give `rustc_query_impl` an errors module, but it's worthwhile to do things in the normal way instead of a weird exceptional way. --- Cargo.lock | 2 ++ compiler/rustc_query_impl/Cargo.toml | 2 ++ compiler/rustc_query_impl/src/error.rs | 24 +++++++++++++++++++++++ compiler/rustc_query_impl/src/lib.rs | 2 ++ compiler/rustc_query_impl/src/plumbing.rs | 2 +- compiler/rustc_query_system/src/error.rs | 24 +---------------------- compiler/rustc_query_system/src/lib.rs | 2 -- 7 files changed, 32 insertions(+), 26 deletions(-) create mode 100644 compiler/rustc_query_impl/src/error.rs diff --git a/Cargo.lock b/Cargo.lock index 85d3fc1aa7bf..363cb8a5dc05 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4534,9 +4534,11 @@ version = "0.0.0" dependencies = [ "measureme", "rustc_data_structures", + "rustc_errors", "rustc_hashes", "rustc_hir", "rustc_index", + "rustc_macros", "rustc_middle", "rustc_query_system", "rustc_serialize", diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 257785b10c8b..d611629671a0 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -7,9 +7,11 @@ edition = "2024" # tidy-alphabetical-start measureme = "12.0.1" rustc_data_structures = { path = "../rustc_data_structures" } +rustc_errors = { path = "../rustc_errors" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } +rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_query_system = { path = "../rustc_query_system" } rustc_serialize = { path = "../rustc_serialize" } diff --git a/compiler/rustc_query_impl/src/error.rs b/compiler/rustc_query_impl/src/error.rs new file mode 100644 index 000000000000..b109172d8e49 --- /dev/null +++ b/compiler/rustc_query_impl/src/error.rs @@ -0,0 +1,24 @@ +use rustc_hir::limit::Limit; +use rustc_macros::{Diagnostic, Subdiagnostic}; +use rustc_span::{Span, Symbol}; + +#[derive(Diagnostic)] +#[help( + "consider increasing the recursion limit by adding a `#![recursion_limit = \"{$suggested_limit}\"]` attribute to your crate (`{$crate_name}`)" +)] +#[diag("queries overflow the depth limit!")] +pub(crate) struct QueryOverflow { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub note: QueryOverflowNote, + pub suggested_limit: Limit, + pub crate_name: Symbol, +} + +#[derive(Subdiagnostic)] +#[note("query depth increased by {$depth} when {$desc}")] +pub(crate) struct QueryOverflowNote { + pub desc: String, + pub depth: usize, +} diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 6c9a075177ad..cb5010861e5f 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -39,6 +39,8 @@ pub use crate::plumbing::{QueryCtxt, query_key_hash_verify_all}; mod profiling_support; pub use self::profiling_support::alloc_self_profile_query_strings; +mod error; + #[derive(ConstParamTy)] // Allow this struct to be used for const-generic values. #[derive(Clone, Copy, Debug, PartialEq, Eq)] struct QueryFlags { diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index b074a9ca11b0..4147de7d2c4d 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -30,11 +30,11 @@ use rustc_query_system::query::{ QueryCache, QueryContext, QueryDispatcher, QueryJobId, QueryMap, QuerySideEffect, QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, force_query, }; -use rustc_query_system::{QueryOverflow, QueryOverflowNote}; use rustc_serialize::{Decodable, Encodable}; use rustc_span::def_id::LOCAL_CRATE; use crate::QueryDispatcherUnerased; +use crate::error::{QueryOverflow, QueryOverflowNote}; /// Implements [`QueryContext`] for use by [`rustc_query_system`], since that /// crate does not have direct access to [`TyCtxt`]. diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs index 55f2feba0d86..adce85bf31be 100644 --- a/compiler/rustc_query_system/src/error.rs +++ b/compiler/rustc_query_system/src/error.rs @@ -1,7 +1,6 @@ use rustc_errors::codes::*; -use rustc_hir::limit::Limit; use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_span::{Span, Symbol}; +use rustc_span::Span; #[derive(Subdiagnostic)] #[note("...which requires {$desc}...")] @@ -75,24 +74,3 @@ pub(crate) struct IncrementCompilation { pub run_cmd: String, pub dep_node: String, } - -#[derive(Diagnostic)] -#[help( - "consider increasing the recursion limit by adding a `#![recursion_limit = \"{$suggested_limit}\"]` attribute to your crate (`{$crate_name}`)" -)] -#[diag("queries overflow the depth limit!")] -pub struct QueryOverflow { - #[primary_span] - pub span: Span, - #[subdiagnostic] - pub note: QueryOverflowNote, - pub suggested_limit: Limit, - pub crate_name: Symbol, -} - -#[derive(Subdiagnostic)] -#[note("query depth increased by {$depth} when {$desc}")] -pub struct QueryOverflowNote { - pub desc: String, - pub depth: usize, -} diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index 3175dbb54bea..61edf397886b 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -10,5 +10,3 @@ pub mod dep_graph; mod error; pub mod ich; pub mod query; - -pub use error::{QueryOverflow, QueryOverflowNote}; From 0420a2e86405e2abf672046383e556e97b2cfac8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Feb 2026 10:48:39 +1100 Subject: [PATCH 550/978] Remove `Cache::clear`. It's unused. And it's nice to remove this function that didn't behave like normal `clear` does, as the comment explained. --- compiler/rustc_query_system/src/cache.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/compiler/rustc_query_system/src/cache.rs b/compiler/rustc_query_system/src/cache.rs index 1b8332ad9e01..4217d0a49b91 100644 --- a/compiler/rustc_query_system/src/cache.rs +++ b/compiler/rustc_query_system/src/cache.rs @@ -23,13 +23,6 @@ impl Default for Cache { } } -impl Cache { - /// Actually frees the underlying memory in contrast to what stdlib containers do on `clear` - pub fn clear(&self) { - *self.hashmap.borrow_mut() = Default::default(); - } -} - impl Cache { pub fn get(&self, key: &Key, tcx: Tcx) -> Option { Some(self.hashmap.borrow().get(key)?.get(tcx)) From aa0ce237b4e67c2481371b2b85475e10b44d33e6 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 8 Jan 2026 13:55:03 +0100 Subject: [PATCH 551/978] c-variadic: minor cleanups of `va_arg` --- compiler/rustc_codegen_llvm/src/va_arg.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index c7da2457ada5..fed0a8837c48 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -131,7 +131,7 @@ fn emit_ptr_va_arg<'ll, 'tcx>( ); if indirect { let tmp_ret = bx.load(llty, addr, addr_align); - bx.load(bx.cx.layout_of(target_ty).llvm_type(bx.cx), tmp_ret, align.abi) + bx.load(layout.llvm_type(bx.cx), tmp_ret, align.abi) } else { bx.load(llty, addr, addr_align) } @@ -1140,13 +1140,10 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( // This includes `target.is_like_darwin`, which on x86_64 targets is like sysv64. Arch::X86_64 => emit_x86_64_sysv64_va_arg(bx, addr, target_ty), Arch::Xtensa => emit_xtensa_va_arg(bx, addr, target_ty), - Arch::Hexagon => { - if target.env == Env::Musl { - emit_hexagon_va_arg_musl(bx, addr, target_ty) - } else { - emit_hexagon_va_arg_bare_metal(bx, addr, target_ty) - } - } + Arch::Hexagon => match target.env { + Env::Musl => emit_hexagon_va_arg_musl(bx, addr, target_ty), + _ => emit_hexagon_va_arg_bare_metal(bx, addr, target_ty), + }, // For all other architecture/OS combinations fall back to using // the LLVM va_arg instruction. // https://llvm.org/docs/LangRef.html#va-arg-instruction From d2b5ba2ff75106d39e36f1b06c3ff709390821f2 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 8 Jan 2026 14:05:34 +0100 Subject: [PATCH 552/978] c-variadic: make va_arg match on `Arch` exhaustive --- compiler/rustc_codegen_llvm/src/va_arg.rs | 77 ++++++++++++++++++----- 1 file changed, 60 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index fed0a8837c48..a491f30fd916 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -1007,6 +1007,8 @@ fn emit_xtensa_va_arg<'ll, 'tcx>( /// Determine the va_arg implementation to use. The LLVM va_arg instruction /// is lacking in some instances, so we should only use it as a fallback. +/// +/// pub(super) fn emit_va_arg<'ll, 'tcx>( bx: &mut Builder<'_, 'll, 'tcx>, addr: OperandRef<'tcx, &'ll Value>, @@ -1015,6 +1017,10 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( let layout = bx.cx.layout_of(target_ty); let target_ty_size = layout.layout.size().bytes(); + // Some ABIs have special behavior for zero-sized types. currently `VaArgSafe` is not + // implemented for any zero-sized types, so this assert should always hold. + assert!(!bx.layout_of(target_ty).is_zst()); + let target = &bx.cx.tcx.sess.target; match target.arch { Arch::X86 => emit_ptr_va_arg( @@ -1026,17 +1032,24 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes }, ForceRightAdjust::No, ), - Arch::AArch64 | Arch::Arm64EC if target.is_like_windows || target.is_like_darwin => { - emit_ptr_va_arg( - bx, - addr, - target_ty, - PassMode::Direct, - SlotSize::Bytes8, - if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes }, - ForceRightAdjust::No, - ) - } + Arch::Arm64EC => emit_ptr_va_arg( + bx, + addr, + target_ty, + PassMode::Direct, + SlotSize::Bytes8, + if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes }, + ForceRightAdjust::No, + ), + Arch::AArch64 if target.is_like_windows || target.is_like_darwin => emit_ptr_va_arg( + bx, + addr, + target_ty, + PassMode::Direct, + SlotSize::Bytes8, + if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes }, + ForceRightAdjust::No, + ), Arch::AArch64 => emit_aapcs_va_arg(bx, addr, target_ty), Arch::Arm => { // Types wider than 16 bytes are not currently supported. Clang has special logic for @@ -1064,7 +1077,16 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( AllowHigherAlign::Yes, ForceRightAdjust::Yes, ), - Arch::LoongArch32 => emit_ptr_va_arg( + Arch::RiscV32 if target.abi == Abi::Ilp32e => { + // FIXME: clang manually adjusts the alignment for this ABI. It notes: + // + // > To be compatible with GCC's behaviors, we force arguments with + // > 2×XLEN-bit alignment and size at most 2×XLEN bits like `long long`, + // > `unsigned long long` and `double` to have 4-byte alignment. This + // > behavior may be changed when RV32E/ILP32E is ratified. + bug!("c-variadic calls with ilp32e use a custom ABI and are not currently implemented"); + } + Arch::RiscV32 | Arch::LoongArch32 => emit_ptr_va_arg( bx, addr, target_ty, @@ -1073,7 +1095,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( AllowHigherAlign::Yes, ForceRightAdjust::No, ), - Arch::LoongArch64 => emit_ptr_va_arg( + Arch::RiscV64 | Arch::LoongArch64 => emit_ptr_va_arg( bx, addr, target_ty, @@ -1144,9 +1166,30 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( Env::Musl => emit_hexagon_va_arg_musl(bx, addr, target_ty), _ => emit_hexagon_va_arg_bare_metal(bx, addr, target_ty), }, - // For all other architecture/OS combinations fall back to using - // the LLVM va_arg instruction. - // https://llvm.org/docs/LangRef.html#va-arg-instruction - _ => bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx)), + Arch::Sparc64 => emit_ptr_va_arg( + bx, + addr, + target_ty, + if target_ty_size > 2 * 8 { PassMode::Indirect } else { PassMode::Direct }, + SlotSize::Bytes8, + AllowHigherAlign::Yes, + ForceRightAdjust::No, + ), + + Arch::Bpf => bug!("bpf does not support c-variadic functions"), + Arch::SpirV => bug!("spirv does not support c-variadic functions"), + + Arch::Mips | Arch::Mips32r6 | Arch::Mips64 | Arch::Mips64r6 => { + // FIXME: port MipsTargetLowering::lowerVAARG. + bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx)) + } + Arch::Sparc | Arch::Avr | Arch::M68k | Arch::Msp430 => { + // Clang uses the LLVM implementation for these architectures. + bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx)) + } + Arch::Other(_) => { + // For custom targets, use the LLVM va_arg instruction as a fallback. + bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx)) + } } } From 6970849fee93900b6eb28a64cf957157a9fb51b3 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 5 Feb 2026 12:32:07 +1100 Subject: [PATCH 553/978] Disable flaky test `oneshot::recv_timeout_before_send` --- library/std/tests/sync/oneshot.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/std/tests/sync/oneshot.rs b/library/std/tests/sync/oneshot.rs index 6a87c72b9cb5..8c47f35ebfea 100644 --- a/library/std/tests/sync/oneshot.rs +++ b/library/std/tests/sync/oneshot.rs @@ -127,6 +127,7 @@ fn recv_before_send() { } #[test] +#[ignore = "Inherently flaky and has caused several CI failures"] fn recv_timeout_before_send() { let (sender, receiver) = oneshot::channel(); @@ -135,6 +136,8 @@ fn recv_timeout_before_send() { sender.send(99u128).unwrap(); }); + // FIXME(#152145): Under load, there's no guarantee that thread `t` has + // ever been scheduled and run before this timeout expires. match receiver.recv_timeout(Duration::from_secs(1)) { Ok(99) => {} _ => panic!("expected Ok(99)"), From 8c404a764919b9155c0ac68978185d7db80cc351 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Thu, 5 Feb 2026 04:37:12 +0000 Subject: [PATCH 554/978] Prepare for merging from rust-lang/rust This updates the rust-version file to db3e99bbab28c6ca778b13222becdea54533d908. --- library/stdarch/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch/rust-version b/library/stdarch/rust-version index ccc0b55d4dc5..aa3876b14a22 100644 --- a/library/stdarch/rust-version +++ b/library/stdarch/rust-version @@ -1 +1 @@ -873d4682c7d285540b8f28bfe637006cef8918a6 +db3e99bbab28c6ca778b13222becdea54533d908 From 3a1743074587d193ed02762d5cb57de29b8ee71d Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Thu, 5 Feb 2026 04:42:48 +0000 Subject: [PATCH 555/978] Prepare for merging from rust-lang/rust This updates the rust-version file to db3e99bbab28c6ca778b13222becdea54533d908. --- library/compiler-builtins/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/compiler-builtins/rust-version b/library/compiler-builtins/rust-version index 209f4226eae7..aa3876b14a22 100644 --- a/library/compiler-builtins/rust-version +++ b/library/compiler-builtins/rust-version @@ -1 +1 @@ -44e34e1ac6d7e69b40856cf1403d3da145319c30 +db3e99bbab28c6ca778b13222becdea54533d908 From 892665ba11a7d40416837377bbd144d63e402c63 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 1 Feb 2026 17:37:22 +1100 Subject: [PATCH 556/978] Clean up query macros for `cache_on_disk_if` --- compiler/rustc_macros/src/query.rs | 65 ++++++++++++------- compiler/rustc_query_impl/src/plumbing.rs | 78 ++++++++++++----------- 2 files changed, 81 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 5d7204f7a30c..f479cb7b3042 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -90,7 +90,7 @@ struct QueryModifiers { arena_cache: Option, /// Cache the query to disk if the `Block` returns true. - cache: Option<(Option, Block)>, + cache_on_disk_if: Option<(Option, Block)>, /// A cycle error for this query aborting the compilation with a fatal error. cycle_fatal: Option, @@ -134,7 +134,7 @@ struct QueryModifiers { fn parse_query_modifiers(input: ParseStream<'_>) -> Result { let mut arena_cache = None; - let mut cache = None; + let mut cache_on_disk_if = None; let mut desc = None; let mut cycle_fatal = None; let mut cycle_delay_bug = None; @@ -175,8 +175,11 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { let list = attr_content.parse_terminated(Expr::parse, Token![,])?; try_insert!(desc = (tcx, list)); } else if modifier == "cache_on_disk_if" { - // Parse a cache modifier like: - // `cache(tcx) { |tcx| key.is_local() }` + // Parse a cache-on-disk modifier like: + // + // `cache_on_disk_if { true }` + // `cache_on_disk_if { key.is_local() }` + // `cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }` let args = if input.peek(token::Paren) { let args; parenthesized!(args in input); @@ -186,7 +189,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { None }; let block = input.parse()?; - try_insert!(cache = (args, block)); + try_insert!(cache_on_disk_if = (args, block)); } else if modifier == "arena_cache" { try_insert!(arena_cache = modifier); } else if modifier == "cycle_fatal" { @@ -218,7 +221,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { }; Ok(QueryModifiers { arena_cache, - cache, + cache_on_disk_if, desc, cycle_fatal, cycle_delay_bug, @@ -260,12 +263,18 @@ fn doc_comment_from_desc(list: &Punctuated) -> Result(#tcx: TyCtxt<'tcx>, #key: &crate::queries::#name::Key<'tcx>) -> bool { @@ -307,7 +316,7 @@ fn add_query_desc_cached_impl( } }; - descs.extend(quote! { + streams.description_fns_stream.extend(quote! { #desc }); } @@ -316,8 +325,7 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { let queries = parse_macro_input!(input as List); let mut query_stream = quote! {}; - let mut query_description_stream = quote! {}; - let mut query_cached_stream = quote! {}; + let mut helpers = HelperTokenStreams::default(); let mut feedable_queries = quote! {}; let mut errors = quote! {}; @@ -363,9 +371,11 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { return_result_from_ensure_ok, ); - // Pass on the cache modifier - if modifiers.cache.is_some() { - attributes.push(quote! { (cache) }); + // If there was a `cache_on_disk_if` modifier in the real input, pass + // on a synthetic `(cache_on_disk)` modifier that can be inspected by + // macro-rules macros. + if modifiers.cache_on_disk_if.is_some() { + attributes.push(quote! { (cache_on_disk) }); } // This uses the span of the query definition for the commas, @@ -399,9 +409,11 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { }); } - add_query_desc_cached_impl(&query, &mut query_description_stream, &mut query_cached_stream); + make_helpers_for_query(&query, &mut helpers); } + let HelperTokenStreams { description_fns_stream, cache_on_disk_if_fns_stream } = helpers; + TokenStream::from(quote! { /// Higher-order macro that invokes the specified macro with a prepared /// list of all query signatures (including modifiers). @@ -431,12 +443,17 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { } pub mod descs { use super::*; - #query_description_stream + #description_fns_stream } - pub mod cached { + + // FIXME(Zalathar): Instead of declaring these functions directly, can + // we put them in a macro and then expand that macro downstream in + // `rustc_query_impl`, where the functions are actually used? + pub mod _cache_on_disk_if_fns { use super::*; - #query_cached_stream + #cache_on_disk_if_fns_stream } + #errors }) } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index a28bbeccc078..af2441425ac1 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -300,15 +300,31 @@ macro_rules! call_provider { }; } -macro_rules! should_ever_cache_on_disk { - ([]$yes:tt $no:tt) => {{ +/// Expands to one of two token trees, depending on whether the current query +/// has the `cache_on_disk_if` modifier. +macro_rules! if_cache_on_disk { + ([] $yes:tt $no:tt) => { $no - }}; - ([(cache) $($rest:tt)*]$yes:tt $no:tt) => {{ + }; + // The `cache_on_disk_if` modifier generates a synthetic `(cache_on_disk)`, + // modifier, for use by this macro and similar macros. + ([(cache_on_disk) $($rest:tt)*] $yes:tt $no:tt) => { $yes - }}; - ([$other:tt $($modifiers:tt)*]$yes:tt $no:tt) => { - should_ever_cache_on_disk!([$($modifiers)*]$yes $no) + }; + ([$other:tt $($modifiers:tt)*] $yes:tt $no:tt) => { + if_cache_on_disk!([$($modifiers)*] $yes $no) + }; +} + +/// Conditionally expands to some token trees, if the current query has the +/// `cache_on_disk_if` modifier. +macro_rules! item_if_cache_on_disk { + ([] $($item:tt)*) => {}; + ([(cache_on_disk) $($rest:tt)*] $($item:tt)*) => { + $($item)* + }; + ([$other:tt $($modifiers:tt)*] $($item:tt)*) => { + item_if_cache_on_disk! { [$($modifiers)*] $($item)* } }; } @@ -544,28 +560,6 @@ where } } -macro_rules! item_if_cached { - ([] $tokens:tt) => {}; - ([(cache) $($rest:tt)*] { $($tokens:tt)* }) => { - $($tokens)* - }; - ([$other:tt $($modifiers:tt)*] $tokens:tt) => { - item_if_cached! { [$($modifiers)*] $tokens } - }; -} - -macro_rules! expand_if_cached { - ([], $tokens:expr) => {{ - None - }}; - ([(cache) $($rest:tt)*], $tokens:expr) => {{ - Some($tokens) - }}; - ([$other:tt $($modifiers:tt)*], $tokens:expr) => { - expand_if_cached!([$($modifiers)*], $tokens) - }; -} - // NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros // invoked by `rustc_with_all_queries`. macro_rules! define_queries { @@ -660,17 +654,17 @@ macro_rules! define_queries { cycle_error_handling: cycle_error_handling!([$($modifiers)*]), query_state: std::mem::offset_of!(QueryStates<'tcx>, $name), query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name), - will_cache_on_disk_for_key_fn: should_ever_cache_on_disk!([$($modifiers)*] { - Some(queries::cached::$name) + will_cache_on_disk_for_key_fn: if_cache_on_disk!([$($modifiers)*] { + Some(::rustc_middle::queries::_cache_on_disk_if_fns::$name) } { None }), execute_query: |tcx, key| erase::erase_val(tcx.$name(key)), compute_fn: self::compute_fn::__rust_begin_short_backtrace, - try_load_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] { + try_load_from_disk_fn: if_cache_on_disk!([$($modifiers)*] { Some(|tcx, key, prev_index, index| { // Check the `cache_on_disk_if` condition for this key. - if !queries::cached::$name(tcx, key) { + if !::rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) { return None; } @@ -683,9 +677,9 @@ macro_rules! define_queries { } { None }), - is_loadable_from_disk_fn: should_ever_cache_on_disk!([$($modifiers)*] { + is_loadable_from_disk_fn: if_cache_on_disk!([$($modifiers)*] { Some(|tcx, key, index| -> bool { - ::rustc_middle::queries::cached::$name(tcx, key) && + ::rustc_middle::queries::_cache_on_disk_if_fns::$name(tcx, key) && $crate::plumbing::loadable_from_disk(tcx, index) }) } { @@ -780,7 +774,7 @@ macro_rules! define_queries { ) } - item_if_cached! { [$($modifiers)*] { + item_if_cache_on_disk! { [$($modifiers)*] pub(crate) fn encode_query_results<'tcx>( tcx: TyCtxt<'tcx>, encoder: &mut CacheEncoder<'_, 'tcx>, @@ -793,7 +787,7 @@ macro_rules! define_queries { query_result_index, ) } - }} + } pub(crate) fn query_key_hash_verify<'tcx>(tcx: TyCtxt<'tcx>) { $crate::plumbing::query_key_hash_verify( @@ -847,7 +841,15 @@ macro_rules! define_queries { &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex) > - ] = &[$(expand_if_cached!([$($modifiers)*], query_impl::$name::encode_query_results)),*]; + ] = &[ + $( + if_cache_on_disk!([$($modifiers)*] { + Some(query_impl::$name::encode_query_results) + } { + None + }) + ),* + ]; const QUERY_KEY_HASH_VERIFY: &[ for<'tcx> fn(TyCtxt<'tcx>) From 691e2263690537f825e217d9ae03b45ad2637a5c Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 5 Feb 2026 00:35:07 -0500 Subject: [PATCH 557/978] fix: handle false negative for `str_to_string` Replace `ToString::to_string` with `ToOwned::to_owned` when the function is passed as is: ```rust fn issue16511(x: Option<&str>) -> String { // Replace with ToOwned::to_owned x.map(ToString::to_string) } ``` --- clippy_lints/src/strings.rs | 18 ++++++++++++++++++ tests/ui/str_to_string.fixed | 29 +++++++++++++++++++++++++++++ tests/ui/str_to_string.rs | 29 +++++++++++++++++++++++++++++ tests/ui/str_to_string.stderr | 32 +++++++++++++++++++++++++++++++- 4 files changed, 107 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index c0be724bcdee..509ad4e4fcb3 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -5,6 +5,7 @@ use clippy_utils::{ SpanlessEq, get_expr_use_or_unification_node, get_parent_expr, is_lint_allowed, method_calls, peel_blocks, sym, }; use rustc_errors::Applicability; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, Node}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -410,6 +411,23 @@ impl<'tcx> LateLintPass<'tcx> for StrToString { diag.span_suggestion(expr.span, "try", format!("{snippet}.to_owned()"), applicability); }, ); + } else if let ExprKind::Path(_) = expr.kind + && let Some(parent) = get_parent_expr(cx, expr) + && let ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) = &parent.kind + && args.iter().any(|a| a.hir_id == expr.hir_id) + && let Res::Def(DefKind::AssocFn, def_id) = expr.res(cx) + && cx.tcx.is_diagnostic_item(sym::to_string_method, def_id) + { + // Detected `ToString::to_string` passed as an argument (generic: any call or method call) + span_lint_and_sugg( + cx, + STR_TO_STRING, + expr.span, + "`ToString::to_string` used as `&str` to `String` converter", + "try", + "ToOwned::to_owned".to_string(), + Applicability::MachineApplicable, + ); } } } diff --git a/tests/ui/str_to_string.fixed b/tests/ui/str_to_string.fixed index 8713c4f9bc86..5b76cf78f069 100644 --- a/tests/ui/str_to_string.fixed +++ b/tests/ui/str_to_string.fixed @@ -22,3 +22,32 @@ fn issue16271(key: &[u8]) { let _value = t!(str::from_utf8(key)).to_owned(); //~^ str_to_string } + +struct GenericWrapper(T); + +impl GenericWrapper { + fn mapper U>(self, f: F) -> U { + f(self.0) + } +} + +fn issue16511(x: Option<&str>) { + let _ = x.map(ToOwned::to_owned); + //~^ str_to_string + + let _ = x.map(ToOwned::to_owned); + //~^ str_to_string + + let _ = ["a", "b"].iter().map(ToOwned::to_owned); + //~^ str_to_string + + fn mapper String>(f: F) -> String { + f("hello") + } + let _ = mapper(ToOwned::to_owned); + //~^ str_to_string + + let w = GenericWrapper("hello"); + let _ = w.mapper(ToOwned::to_owned); + //~^ str_to_string +} diff --git a/tests/ui/str_to_string.rs b/tests/ui/str_to_string.rs index b81759e1037b..f099eb29b1b5 100644 --- a/tests/ui/str_to_string.rs +++ b/tests/ui/str_to_string.rs @@ -22,3 +22,32 @@ fn issue16271(key: &[u8]) { let _value = t!(str::from_utf8(key)).to_string(); //~^ str_to_string } + +struct GenericWrapper(T); + +impl GenericWrapper { + fn mapper U>(self, f: F) -> U { + f(self.0) + } +} + +fn issue16511(x: Option<&str>) { + let _ = x.map(ToString::to_string); + //~^ str_to_string + + let _ = x.map(str::to_string); + //~^ str_to_string + + let _ = ["a", "b"].iter().map(ToString::to_string); + //~^ str_to_string + + fn mapper String>(f: F) -> String { + f("hello") + } + let _ = mapper(ToString::to_string); + //~^ str_to_string + + let w = GenericWrapper("hello"); + let _ = w.mapper(ToString::to_string); + //~^ str_to_string +} diff --git a/tests/ui/str_to_string.stderr b/tests/ui/str_to_string.stderr index c0a38c8ebe46..296b8e36f28c 100644 --- a/tests/ui/str_to_string.stderr +++ b/tests/ui/str_to_string.stderr @@ -19,5 +19,35 @@ error: `to_string()` called on a `&str` LL | let _value = t!(str::from_utf8(key)).to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t!(str::from_utf8(key)).to_owned()` -error: aborting due to 3 previous errors +error: `ToString::to_string` used as `&str` to `String` converter + --> tests/ui/str_to_string.rs:35:19 + | +LL | let _ = x.map(ToString::to_string); + | ^^^^^^^^^^^^^^^^^^^ help: try: `ToOwned::to_owned` + +error: `ToString::to_string` used as `&str` to `String` converter + --> tests/ui/str_to_string.rs:38:19 + | +LL | let _ = x.map(str::to_string); + | ^^^^^^^^^^^^^^ help: try: `ToOwned::to_owned` + +error: `ToString::to_string` used as `&str` to `String` converter + --> tests/ui/str_to_string.rs:41:35 + | +LL | let _ = ["a", "b"].iter().map(ToString::to_string); + | ^^^^^^^^^^^^^^^^^^^ help: try: `ToOwned::to_owned` + +error: `ToString::to_string` used as `&str` to `String` converter + --> tests/ui/str_to_string.rs:47:20 + | +LL | let _ = mapper(ToString::to_string); + | ^^^^^^^^^^^^^^^^^^^ help: try: `ToOwned::to_owned` + +error: `ToString::to_string` used as `&str` to `String` converter + --> tests/ui/str_to_string.rs:51:22 + | +LL | let _ = w.mapper(ToString::to_string); + | ^^^^^^^^^^^^^^^^^^^ help: try: `ToOwned::to_owned` + +error: aborting due to 8 previous errors From 34cdaebf37dba363d96c434fd4b6d6b3739660df Mon Sep 17 00:00:00 2001 From: Wolf Vollprecht Date: Thu, 5 Feb 2026 08:24:44 +0100 Subject: [PATCH 558/978] Fix typos in riscv64a23-unknown-linux-gnu.md --- .../src/platform-support/riscv64a23-unknown-linux-gnu.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc/src/platform-support/riscv64a23-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/riscv64a23-unknown-linux-gnu.md index e24e93f7a18f..df0c971f249a 100644 --- a/src/doc/rustc/src/platform-support/riscv64a23-unknown-linux-gnu.md +++ b/src/doc/rustc/src/platform-support/riscv64a23-unknown-linux-gnu.md @@ -3,7 +3,7 @@ **Tier: 2 (without Host Tools)** RISC-V target using the ratified [RVA23 Profile](https://github.com/riscv/riscv-profiles/blob/main/src/rva23-profile.adoc). -This target will enable all mandary features of rva23u64 by default. +This target will enable all mandatory features of rva23u64 by default. ## Target maintainers @@ -14,7 +14,7 @@ This target will enable all mandary features of rva23u64 by default. This target can be sucessfully build on the following platform: ubuntu 24.04 (Linux Kernel version 6.8.0, glibc 2.39). -Other platforms may work, but are not tested. Please contanct if you encounter any issues. +Other platforms may work, but are not tested. Please contact us if you encounter any issues. ## Building the target From 438220673f5bde3e4f183b8d2cad753f116b3504 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 5 Feb 2026 15:58:57 +1100 Subject: [PATCH 559/978] Incorporate query description functions into `QueryVTable` --- compiler/rustc_macros/src/query.rs | 9 ++- compiler/rustc_middle/src/query/plumbing.rs | 9 ++- compiler/rustc_query_impl/src/plumbing.rs | 63 ++++++++++----------- 3 files changed, 47 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 5d7204f7a30c..adcf4e00241e 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -429,7 +429,14 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { $macro!(#feedable_queries); } } - pub mod descs { + + /// Functions that format a human-readable description of each query + /// and its key, as specified by the `desc` query modifier. + /// + /// (The leading `_` avoids collisions with actual query names when + /// expanded in `rustc_middle::queries`, and makes this macro-generated + /// module easier to search for.) + pub mod _description_fns { use super::*; #query_description_stream } diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index b8f1fe9ec20b..abb02caef25d 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -32,7 +32,8 @@ pub type IsLoadableFromDiskFn<'tcx, Key> = /// Stores function pointers and other metadata for a particular query. /// -/// Used indirectly by query plumbing in `rustc_query_system`, via a trait. +/// Used indirectly by query plumbing in `rustc_query_system` via a trait, +/// and also used directly by query plumbing in `rustc_query_impl`. pub struct QueryVTable<'tcx, C: QueryCache> { pub name: &'static str, pub eval_always: bool, @@ -52,6 +53,12 @@ pub struct QueryVTable<'tcx, C: QueryCache> { pub value_from_cycle_error: fn(tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed) -> C::Value, pub format_value: fn(&C::Value) -> String, + + /// Formats a human-readable description of this query and its key, as + /// specified by the `desc` query modifier. + /// + /// Used when reporting query cycle errors and similar problems. + pub description_fn: fn(TyCtxt<'tcx>, C::Key) -> String, } pub struct QuerySystemFns { diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index a28bbeccc078..bce685cb9a6a 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -9,17 +9,18 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_data_structures::unord::UnordMap; use rustc_hashes::Hash64; +use rustc_hir::def_id::DefId; use rustc_hir::limit::Limit; use rustc_index::Idx; use rustc_middle::bug; use rustc_middle::dep_graph::{ - self, DepContext, DepKind, DepKindVTable, DepNode, DepNodeIndex, SerializedDepNodeIndex, - dep_kinds, + self, DepContext, DepKindVTable, DepNode, DepNodeIndex, SerializedDepNodeIndex, dep_kinds, }; use rustc_middle::query::Key; use rustc_middle::query::on_disk_cache::{ AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex, }; +use rustc_middle::query::plumbing::QueryVTable; use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::print::with_reduced_queries; use rustc_middle::ty::tls::{self, ImplicitCtxt}; @@ -312,15 +313,14 @@ macro_rules! should_ever_cache_on_disk { }; } -fn mk_query_stack_frame_extra<'tcx, K: Key + Copy + 'tcx>( - (tcx, key, kind, name, do_describe): ( - TyCtxt<'tcx>, - K, - DepKind, - &'static str, - fn(TyCtxt<'tcx>, K) -> String, - ), -) -> QueryStackFrameExtra { +/// The deferred part of a deferred query stack frame. +fn mk_query_stack_frame_extra<'tcx, Cache>( + (tcx, vtable, key): (TyCtxt<'tcx>, &'tcx QueryVTable<'tcx, Cache>, Cache::Key), +) -> QueryStackFrameExtra +where + Cache: QueryCache, + Cache::Key: Key, +{ let def_id = key.key_as_def_id(); // If reduced queries are requested, we may be printing a query stack due @@ -328,13 +328,13 @@ fn mk_query_stack_frame_extra<'tcx, K: Key + Copy + 'tcx>( let reduce_queries = with_reduced_queries(); // Avoid calling queries while formatting the description - let description = ty::print::with_no_queries!(do_describe(tcx, key)); + let description = ty::print::with_no_queries!((vtable.description_fn)(tcx, key)); let description = if tcx.sess.verbose_internals() { - format!("{description} [{name:?}]") + format!("{description} [{name:?}]", name = vtable.name) } else { description }; - let span = if kind == dep_graph::dep_kinds::def_span || reduce_queries { + let span = if vtable.dep_kind == dep_graph::dep_kinds::def_span || reduce_queries { // The `def_span` query is used to calculate `default_span`, // so exit to avoid infinite recursion. None @@ -342,7 +342,7 @@ fn mk_query_stack_frame_extra<'tcx, K: Key + Copy + 'tcx>( Some(key.default_span(tcx)) }; - let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries { + let def_kind = if vtable.dep_kind == dep_graph::dep_kinds::def_kind || reduce_queries { // Try to avoid infinite recursion. None } else { @@ -351,17 +351,16 @@ fn mk_query_stack_frame_extra<'tcx, K: Key + Copy + 'tcx>( QueryStackFrameExtra::new(description, span, def_kind) } -pub(crate) fn create_query_frame< - 'tcx, - K: Copy + DynSend + DynSync + Key + for<'a> HashStable> + 'tcx, ->( +pub(crate) fn create_deferred_query_stack_frame<'tcx, Cache>( tcx: TyCtxt<'tcx>, - do_describe: fn(TyCtxt<'tcx>, K) -> String, - key: K, - kind: DepKind, - name: &'static str, -) -> QueryStackFrame> { - let def_id = key.key_as_def_id(); + vtable: &'tcx QueryVTable<'tcx, Cache>, + key: Cache::Key, +) -> QueryStackFrame> +where + Cache: QueryCache, + Cache::Key: Key + DynSend + DynSync + for<'a> HashStable> + 'tcx, +{ + let kind = vtable.dep_kind; let hash = tcx.with_stable_hashing_context(|mut hcx| { let mut hasher = StableHasher::new(); @@ -369,11 +368,11 @@ pub(crate) fn create_query_frame< key.hash_stable(&mut hcx, &mut hasher); hasher.finish::() }); - let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle(); - let info = - QueryStackDeferred::new((tcx, key, kind, name, do_describe), mk_query_stack_frame_extra); + let def_id: Option = key.key_as_def_id(); + let def_id_for_ty_in_cycle: Option = key.def_id_for_ty_in_cycle(); + let info = QueryStackDeferred::new((tcx, vtable, key), mk_query_stack_frame_extra); QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle) } @@ -697,6 +696,7 @@ macro_rules! define_queries { }, hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]), format_value: |value| format!("{:?}", erase::restore_val::>(*value)), + description_fn: $crate::queries::_description_fns::$name, } } @@ -742,10 +742,9 @@ macro_rules! define_queries { qmap: &mut QueryMap<'tcx>, require_complete: bool, ) -> Option<()> { - let make_frame = |tcx, key| { - let kind = rustc_middle::dep_graph::dep_kinds::$name; - let name = stringify!($name); - $crate::plumbing::create_query_frame(tcx, queries::descs::$name, key, kind, name) + let make_frame = |tcx: TyCtxt<'tcx>, key| { + let vtable = &tcx.query_system.query_vtables.$name; + $crate::plumbing::create_deferred_query_stack_frame(tcx, vtable, key) }; // Call `gather_active_jobs_inner` to do the actual work. From 17305da24f57e8de6ef6c0931bcc7e8a03309f33 Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Thu, 5 Feb 2026 13:16:46 +0530 Subject: [PATCH 560/978] Fix error spans for asm!() args that are macros --- compiler/rustc_builtin_macros/src/asm.rs | 33 ++++++++++--------- tests/crashes/131292.rs | 7 ---- .../ice-bad-err-span-in-template-129503.rs | 13 +++++--- ...ice-bad-err-span-in-template-129503.stderr | 19 ++++++++--- 4 files changed, 41 insertions(+), 31 deletions(-) delete mode 100644 tests/crashes/131292.rs diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 2958686f86cd..62a39d957b9c 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -288,6 +288,18 @@ fn expand_preparsed_asm( let msg = "asm template must be a string literal"; let template_sp = template_expr.span; let template_is_mac_call = matches!(template_expr.kind, ast::ExprKind::MacCall(_)); + + // Gets the span inside `template_sp` corresponding to the given range + let span_in_template = |range: std::ops::Range| -> Span { + if template_is_mac_call { + // When the template is a macro call we can't reliably get inner spans + // so just use the entire template span (see ICEs #129503, #131292) + template_sp + } else { + template_sp.from_inner(InnerSpan::new(range.start, range.end)) + } + }; + let ExprToSpannedString { symbol: template_str, style: template_style, @@ -382,13 +394,8 @@ fn expand_preparsed_asm( if !parser.errors.is_empty() { let err = parser.errors.remove(0); - let err_sp = if template_is_mac_call { - // If the template is a macro call we can't reliably point to the error's - // span so just use the template's span as the error span (fixes #129503) - template_span - } else { - template_span.from_inner(InnerSpan::new(err.span.start, err.span.end)) - }; + + let err_sp = span_in_template(err.span); let msg = format!("invalid asm template string: {}", err.description); let mut e = ecx.dcx().struct_span_err(err_sp, msg); @@ -397,8 +404,7 @@ fn expand_preparsed_asm( e.note(note); } if let Some((label, span)) = err.secondary_label { - let err_sp = template_span.from_inner(InnerSpan::new(span.start, span.end)); - e.span_label(err_sp, label); + e.span_label(span_in_template(span), label); } let guar = e.emit(); return ExpandResult::Ready(Err(guar)); @@ -477,8 +483,7 @@ fn expand_preparsed_asm( ecx.dcx() .create_err(errors::AsmNoMatchedArgumentName { name: name.to_owned(), - span: template_span - .from_inner(InnerSpan::new(span.start, span.end)), + span: span_in_template(span), }) .emit(); None @@ -490,11 +495,7 @@ fn expand_preparsed_asm( let mut chars = arg.format.ty.chars(); let mut modifier = chars.next(); if chars.next().is_some() { - let span = arg - .format - .ty_span - .map(|sp| template_sp.from_inner(InnerSpan::new(sp.start, sp.end))) - .unwrap_or(template_sp); + let span = arg.format.ty_span.map(span_in_template).unwrap_or(template_sp); ecx.dcx().emit_err(errors::AsmModifierInvalid { span }); modifier = None; } diff --git a/tests/crashes/131292.rs b/tests/crashes/131292.rs deleted file mode 100644 index 05b93d06b055..000000000000 --- a/tests/crashes/131292.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: #131292 -//@ needs-asm-support -use std::arch::asm; - -unsafe fn f6() { - asm!(concat!(r#"lJ𐏿Æ�.𐏿�"#, "{}/day{:02}.txt")); -} diff --git a/tests/ui/asm/ice-bad-err-span-in-template-129503.rs b/tests/ui/asm/ice-bad-err-span-in-template-129503.rs index 3b4390f881a7..0a7d0d405d17 100644 --- a/tests/ui/asm/ice-bad-err-span-in-template-129503.rs +++ b/tests/ui/asm/ice-bad-err-span-in-template-129503.rs @@ -1,17 +1,22 @@ -// Regression test for ICE #129503 - - +// Regression test for ICEs #129503 and #131292 +// // Tests that we come up with decent error spans // when the template fed to `asm!()` is itself a // macro call like `concat!()` and should not ICE +//@ needs-asm-support + use std::arch::asm; fn main() { - // Should not ICE + // Should not ICE (test case for #129503) asm!(concat!(r#"lJ𐏿Æ�.𐏿�"#, "r} {}")); //~^ ERROR invalid asm template string: unmatched `}` found + // Should not ICE (test case for #131292) + asm!(concat!(r#"lJ𐏿Æ�.𐏿�"#, "{}/day{:02}.txt")); + //~^ ERROR invalid asm template string: expected `}`, found `0` + // Macro call template: should point to // everything within `asm!()` as error span diff --git a/tests/ui/asm/ice-bad-err-span-in-template-129503.stderr b/tests/ui/asm/ice-bad-err-span-in-template-129503.stderr index 066959a052d9..980338138c66 100644 --- a/tests/ui/asm/ice-bad-err-span-in-template-129503.stderr +++ b/tests/ui/asm/ice-bad-err-span-in-template-129503.stderr @@ -1,13 +1,24 @@ error: invalid asm template string: unmatched `}` found - --> $DIR/ice-bad-err-span-in-template-129503.rs:12:10 + --> $DIR/ice-bad-err-span-in-template-129503.rs:13:10 | LL | asm!(concat!(r#"lJ𐏿Æ�.𐏿�"#, "r} {}")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unmatched `}` in asm template string | = note: if you intended to print `}`, you can escape it using `}}` +error: invalid asm template string: expected `}`, found `0` + --> $DIR/ice-bad-err-span-in-template-129503.rs:17:10 + | +LL | asm!(concat!(r#"lJ𐏿Æ�.𐏿�"#, "{}/day{:02}.txt")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected `}` in asm template string + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + error: invalid asm template string: unmatched `}` found - --> $DIR/ice-bad-err-span-in-template-129503.rs:18:10 + --> $DIR/ice-bad-err-span-in-template-129503.rs:23:10 | LL | asm!(concat!("abc", "r} {}")); | ^^^^^^^^^^^^^^^^^^^^^^^ unmatched `}` in asm template string @@ -15,12 +26,12 @@ LL | asm!(concat!("abc", "r} {}")); = note: if you intended to print `}`, you can escape it using `}}` error: invalid asm template string: unmatched `}` found - --> $DIR/ice-bad-err-span-in-template-129503.rs:24:19 + --> $DIR/ice-bad-err-span-in-template-129503.rs:29:19 | LL | asm!("abc", "r} {}"); | ^ unmatched `}` in asm template string | = note: if you intended to print `}`, you can escape it using `}}` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors From 2184b446ce264d19e43cb6c38611da7cf1a14150 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova <58857108+ada4a@users.noreply.github.com> Date: Sat, 31 Jan 2026 18:29:28 +0100 Subject: [PATCH 561/978] Fix typo --- src/doc/rustc-dev-guide/src/const-generics.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/const-generics.md b/src/doc/rustc-dev-guide/src/const-generics.md index 4c2a0ddbabd5..344d9b1d26de 100644 --- a/src/doc/rustc-dev-guide/src/const-generics.md +++ b/src/doc/rustc-dev-guide/src/const-generics.md @@ -61,7 +61,7 @@ In some sense the desugarings from the previous examples are to: struct Foo; type Alias = [u8; 1 + 1]; -// sort-of desugars to psuedo-rust: +// sort-of desugars to pseudo-rust: struct Foo; const ANON = 1 + 1; @@ -178,7 +178,7 @@ To check this we have [`ClauseKind::ConstArgHasType(ty::Const, Ty)`][const_arg_h ```rust fn foo() {} -// desugars to in psuedo-rust +// desugars to in pseudo-rust fn foo() where From 639cb694df242aaa356ebcd4ddca47355af4240c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 4 Feb 2026 19:52:53 +0000 Subject: [PATCH 562/978] Replace Registry type with a lazily initialized static And move try_find_description to rustc_errors::codes. --- compiler/rustc_codegen_ssa/src/back/write.rs | 6 +--- compiler/rustc_driver_impl/src/lib.rs | 5 +-- .../src/annotate_snippet_emitter_writer.rs | 3 +- compiler/rustc_errors/src/codes.rs | 32 ++++++++++++++----- compiler/rustc_errors/src/emitter.rs | 11 +++---- compiler/rustc_errors/src/json.rs | 19 ++++------- compiler/rustc_errors/src/lib.rs | 12 ++----- compiler/rustc_errors/src/registry.rs | 23 ------------- .../passes/lint/check_code_block_syntax.rs | 3 +- src/tools/error_index_generator/main.rs | 20 ++++++++++-- src/tools/rustfmt/src/parse/session.rs | 29 +++++++---------- 11 files changed, 73 insertions(+), 90 deletions(-) delete mode 100644 compiler/rustc_errors/src/registry.rs diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 8321f7fde503..444f7877689f 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1981,11 +1981,7 @@ impl SharedEmitter { } impl Emitter for SharedEmitter { - fn emit_diagnostic( - &mut self, - mut diag: rustc_errors::DiagInner, - _registry: &rustc_errors::registry::Registry, - ) { + fn emit_diagnostic(&mut self, mut diag: rustc_errors::DiagInner) { // Check that we aren't missing anything interesting when converting to // the cut-down local `DiagInner`. assert!(!diag.span.has_span_labels()); diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 515b011b486d..2999848979f3 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -34,7 +34,6 @@ use rustc_data_structures::profiling::{ }; pub use rustc_errors::catch_fatal_errors; use rustc_errors::emitter::stderr_destination; -use rustc_errors::registry::Registry; use rustc_errors::translation::Translator; use rustc_errors::{ColorConfig, DiagCtxt, ErrCode, PResult, markdown}; use rustc_feature::find_gated_cfg; @@ -451,13 +450,11 @@ pub enum Compilation { } fn handle_explain(early_dcx: &EarlyDiagCtxt, code: &str, color: ColorConfig) { - let registry = Registry::new(); - // Allow "E0123" or "0123" form. let upper_cased_code = code.to_ascii_uppercase(); if let Ok(code) = upper_cased_code.trim_prefix('E').parse::() && code <= ErrCode::MAX_AS_U32 - && let Ok(description) = registry.try_find_description(ErrCode::from_u32(code)) + && let Ok(description) = rustc_errors::codes::try_find_description(ErrCode::from_u32(code)) { let mut is_in_code_block = false; let mut text = String::new(); diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 9bb318973958..bdd3266adb66 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -27,7 +27,6 @@ use crate::emitter::{ ConfusionType, Destination, MAX_SUGGESTIONS, OutputTheme, detect_confusion_type, is_different, normalize_whitespace, should_show_source_code, }; -use crate::registry::Registry; use crate::translation::{Translator, to_fluent_args}; use crate::{ CodeSuggestion, DiagInner, DiagMessage, Emitter, ErrCode, Level, MultiSpan, Style, Subdiag, @@ -73,7 +72,7 @@ impl Debug for AnnotateSnippetEmitter { impl Emitter for AnnotateSnippetEmitter { /// The entry point for the diagnostics generation - fn emit_diagnostic(&mut self, mut diag: DiagInner, _registry: &Registry) { + fn emit_diagnostic(&mut self, mut diag: DiagInner) { let fluent_args = to_fluent_args(diag.args.iter()); if self.track_diagnostics && diag.span.has_primary_spans() && !diag.span.is_dummy() { diff --git a/compiler/rustc_errors/src/codes.rs b/compiler/rustc_errors/src/codes.rs index f266ae97d4c7..c1e7b7c184c1 100644 --- a/compiler/rustc_errors/src/codes.rs +++ b/compiler/rustc_errors/src/codes.rs @@ -5,6 +5,9 @@ //! long description text. use std::fmt; +use std::sync::LazyLock; + +use rustc_data_structures::fx::FxHashMap; rustc_index::newtype_index! { #[max = 9999] // Because all error codes have four digits. @@ -27,15 +30,28 @@ macro_rules! define_error_code_constants_and_diagnostics_table { $( pub const ${concat(E, $num)}: $crate::ErrCode = $crate::ErrCode::from_u32($num); )* - pub(crate) static DIAGNOSTICS: &[($crate::ErrCode, &str)] = &[ - $( ( - ${concat(E, $num)}, - include_str!( - concat!("../../rustc_error_codes/src/error_codes/E", stringify!($num), ".md") - ) - ), )* - ]; + static DIAGNOSTICS: LazyLock> = LazyLock::new(|| { + [ + $( ( + ${concat(E, $num)}, + include_str!( + concat!("../../rustc_error_codes/src/error_codes/E", stringify!($num), ".md") + ) + ), )* + ] + .iter() + .copied() + .collect() + }); ) } rustc_error_codes::error_codes!(define_error_code_constants_and_diagnostics_table); + +#[derive(Debug)] +pub struct InvalidErrorCode; + +/// Returns `InvalidErrorCode` if the code requested does not exist. +pub fn try_find_description(code: ErrCode) -> Result<&'static str, InvalidErrorCode> { + DIAGNOSTICS.get(&code).copied().ok_or(InvalidErrorCode) +} diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 3433db1e0704..4ceb5cf06f93 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -24,7 +24,6 @@ use rustc_span::source_map::SourceMap; use rustc_span::{FileName, SourceFile, Span}; use tracing::{debug, warn}; -use crate::registry::Registry; use crate::timings::TimingRecord; use crate::translation::Translator; use crate::{ @@ -54,7 +53,7 @@ pub type DynEmitter = dyn Emitter + DynSend; /// Emitter trait for emitting errors and other structured information. pub trait Emitter { /// Emit a structured diagnostic. - fn emit_diagnostic(&mut self, diag: DiagInner, registry: &Registry); + fn emit_diagnostic(&mut self, diag: DiagInner); /// Emit a notification that an artifact has been output. /// Currently only supported for the JSON format. @@ -66,7 +65,7 @@ pub trait Emitter { /// Emit a report about future breakage. /// Currently only supported for the JSON format. - fn emit_future_breakage_report(&mut self, _diags: Vec, _registry: &Registry) {} + fn emit_future_breakage_report(&mut self, _diags: Vec) {} /// Emit list of unused externs. /// Currently only supported for the JSON format. @@ -380,9 +379,9 @@ impl Emitter for EmitterWithNote { None } - fn emit_diagnostic(&mut self, mut diag: DiagInner, registry: &Registry) { + fn emit_diagnostic(&mut self, mut diag: DiagInner) { diag.sub(Level::Note, self.note.clone(), MultiSpan::new()); - self.emitter.emit_diagnostic(diag, registry); + self.emitter.emit_diagnostic(diag); } fn translator(&self) -> &Translator { @@ -399,7 +398,7 @@ impl Emitter for SilentEmitter { None } - fn emit_diagnostic(&mut self, _diag: DiagInner, _registry: &Registry) {} + fn emit_diagnostic(&mut self, _diag: DiagInner) {} fn translator(&self) -> &Translator { &self.translator diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 85801245bea9..310a64745bad 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -31,7 +31,6 @@ use crate::emitter::{ ColorConfig, Destination, Emitter, HumanReadableErrorType, OutputTheme, TimingEvent, should_show_source_code, }; -use crate::registry::Registry; use crate::timings::{TimingRecord, TimingSection}; use crate::translation::{Translator, to_fluent_args}; use crate::{CodeSuggestion, MultiSpan, SpanLabel, Subdiag, Suggestions, TerminalUrl}; @@ -107,8 +106,8 @@ enum EmitTyped<'a> { } impl Emitter for JsonEmitter { - fn emit_diagnostic(&mut self, diag: crate::DiagInner, registry: &Registry) { - let data = Diagnostic::from_errors_diagnostic(diag, self, registry); + fn emit_diagnostic(&mut self, diag: crate::DiagInner) { + let data = Diagnostic::from_errors_diagnostic(diag, self); let result = self.emit(EmitTyped::Diagnostic(data)); if let Err(e) = result { panic!("failed to print diagnostics: {e:?}"); @@ -139,7 +138,7 @@ impl Emitter for JsonEmitter { } } - fn emit_future_breakage_report(&mut self, diags: Vec, registry: &Registry) { + fn emit_future_breakage_report(&mut self, diags: Vec) { let data: Vec> = diags .into_iter() .map(|mut diag| { @@ -153,7 +152,7 @@ impl Emitter for JsonEmitter { } FutureBreakageItem { diagnostic: EmitTyped::Diagnostic(Diagnostic::from_errors_diagnostic( - diag, self, registry, + diag, self, )), } }) @@ -307,11 +306,7 @@ struct UnusedExterns<'a> { impl Diagnostic { /// Converts from `rustc_errors::DiagInner` to `Diagnostic`. - fn from_errors_diagnostic( - diag: crate::DiagInner, - je: &JsonEmitter, - registry: &Registry, - ) -> Diagnostic { + fn from_errors_diagnostic(diag: crate::DiagInner, je: &JsonEmitter) -> Diagnostic { let args = to_fluent_args(diag.args.iter()); let sugg_to_diag = |sugg: &CodeSuggestion| { let translated_message = @@ -351,7 +346,7 @@ impl Diagnostic { let code = if let Some(code) = diag.code { Some(DiagnosticCode { code: code.to_string(), - explanation: registry.try_find_description(code).ok(), + explanation: crate::codes::try_find_description(code).ok(), }) } else if let Some(IsLint { name, .. }) = &diag.is_lint { Some(DiagnosticCode { code: name.to_string(), explanation: None }) @@ -388,7 +383,7 @@ impl Diagnostic { .ui_testing(je.ui_testing) .ignored_directories_in_source_blocks(je.ignored_directories_in_source_blocks.clone()) .theme(if je.json_rendered.unicode { OutputTheme::Unicode } else { OutputTheme::Ascii }) - .emit_diagnostic(diag, registry); + .emit_diagnostic(diag); let buf = Arc::try_unwrap(buf.0).unwrap().into_inner().unwrap(); let buf = String::from_utf8(buf).unwrap(); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 02fbb969412a..6730fbae35e2 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -71,7 +71,6 @@ use rustc_span::{DUMMY_SP, Span}; use tracing::debug; use crate::emitter::TimingEvent; -use crate::registry::Registry; use crate::timings::TimingRecord; pub mod annotate_snippet_emitter_writer; @@ -84,7 +83,6 @@ pub mod error; pub mod json; mod lock; pub mod markdown; -pub mod registry; #[cfg(test)] mod tests; pub mod timings; @@ -299,8 +297,6 @@ impl<'a> std::ops::Deref for DiagCtxtHandle<'a> { struct DiagCtxtInner { flags: DiagCtxtFlags, - registry: Registry, - /// The error guarantees from all emitted errors. The length gives the error count. err_guars: Vec, /// The error guarantee from all emitted lint errors. The length gives the @@ -534,7 +530,6 @@ impl DiagCtxt { let mut inner = self.inner.borrow_mut(); let DiagCtxtInner { flags: _, - registry: _, err_guars, lint_err_guars, delayed_bugs, @@ -808,7 +803,7 @@ impl<'a> DiagCtxtHandle<'a> { .emitted_diagnostic_codes .iter() .filter_map(|&code| { - if inner.registry.try_find_description(code).is_ok() { + if crate::codes::try_find_description(code).is_ok() { Some(code.to_string()) } else { None @@ -880,7 +875,7 @@ impl<'a> DiagCtxtHandle<'a> { let inner = &mut *self.inner.borrow_mut(); let diags = std::mem::take(&mut inner.future_breakage_diagnostics); if !diags.is_empty() { - inner.emitter.emit_future_breakage_report(diags, &inner.registry); + inner.emitter.emit_future_breakage_report(diags); } } @@ -1181,7 +1176,6 @@ impl DiagCtxtInner { fn new(emitter: Box) -> Self { Self { flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() }, - registry: Registry::new(), err_guars: Vec::new(), lint_err_guars: Vec::new(), delayed_bugs: Vec::new(), @@ -1357,7 +1351,7 @@ impl DiagCtxtInner { } self.has_printed = true; - self.emitter.emit_diagnostic(diagnostic, &self.registry); + self.emitter.emit_diagnostic(diagnostic); } if is_error { diff --git a/compiler/rustc_errors/src/registry.rs b/compiler/rustc_errors/src/registry.rs deleted file mode 100644 index 5ad6cdd9688f..000000000000 --- a/compiler/rustc_errors/src/registry.rs +++ /dev/null @@ -1,23 +0,0 @@ -use rustc_data_structures::fx::FxHashMap; - -use crate::ErrCode; - -#[derive(Debug)] -pub struct InvalidErrorCode; - -#[derive(Clone)] -pub struct Registry { - long_descriptions: FxHashMap, -} - -impl Registry { - pub fn new() -> Registry { - Registry { long_descriptions: crate::codes::DIAGNOSTICS.iter().copied().collect() } - } - - /// Returns `InvalidErrorCode` if the code requested does not exist in the - /// registry. - pub fn try_find_description(&self, code: ErrCode) -> Result<&'static str, InvalidErrorCode> { - self.long_descriptions.get(&code).copied().ok_or(InvalidErrorCode) - } -} diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index b08533317abe..5749b4ac081e 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -5,7 +5,6 @@ use std::sync::Arc; use rustc_data_structures::sync::Lock; use rustc_errors::emitter::Emitter; -use rustc_errors::registry::Registry; use rustc_errors::translation::{Translator, to_fluent_args}; use rustc_errors::{Applicability, DiagCtxt, DiagInner}; use rustc_parse::{source_str_to_stream, unwrap_or_emit_fatal}; @@ -150,7 +149,7 @@ struct BufferEmitter { } impl Emitter for BufferEmitter { - fn emit_diagnostic(&mut self, diag: DiagInner, _registry: &Registry) { + fn emit_diagnostic(&mut self, diag: DiagInner) { let mut buffer = self.buffer.borrow_mut(); let fluent_args = to_fluent_args(diag.args.iter()); diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 97ac47918c09..c78df2b60b56 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -1,10 +1,11 @@ #![feature(rustc_private)] extern crate rustc_driver; +extern crate rustc_error_codes; +extern crate rustc_errors; extern crate rustc_log; extern crate rustc_session; -extern crate rustc_errors; use std::env; use std::error::Error; use std::fs::{self, File}; @@ -16,7 +17,22 @@ use mdbook_driver::MDBook; use mdbook_driver::book::{BookItem, Chapter}; use mdbook_driver::config::Config; use mdbook_summary::parse_summary; -use rustc_errors::codes::DIAGNOSTICS; +use rustc_errors::codes::ErrCode; + +macro_rules! define_error_codes_table { + ($($num:literal,)*) => ( + static DIAGNOSTICS: &[(ErrCode, &str)] = &[ + $( ( + ErrCode::from_u32($num), + include_str!( + concat!("../../../compiler/rustc_error_codes/src/error_codes/E", stringify!($num), ".md") + ) + ), )* + ]; + ) +} + +rustc_error_codes::error_codes!(define_error_codes_table); enum OutputFormat { HTML, diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index e80b7d57c641..2a5c8f776427 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -5,7 +5,6 @@ use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter; use rustc_errors::emitter::{DynEmitter, Emitter, SilentEmitter, stderr_destination}; -use rustc_errors::registry::Registry; use rustc_errors::translation::Translator; use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel}; use rustc_session::parse::ParseSess as RawParseSess; @@ -41,10 +40,10 @@ struct SilentOnIgnoredFilesEmitter { } impl SilentOnIgnoredFilesEmitter { - fn handle_non_ignoreable_error(&mut self, diag: DiagInner, registry: &Registry) { + fn handle_non_ignoreable_error(&mut self, diag: DiagInner) { self.has_non_ignorable_parser_errors = true; self.can_reset.store(false, Ordering::Release); - self.emitter.emit_diagnostic(diag, registry); + self.emitter.emit_diagnostic(diag); } } @@ -53,9 +52,9 @@ impl Emitter for SilentOnIgnoredFilesEmitter { None } - fn emit_diagnostic(&mut self, diag: DiagInner, registry: &Registry) { + fn emit_diagnostic(&mut self, diag: DiagInner) { if diag.level() == DiagnosticLevel::Fatal { - return self.handle_non_ignoreable_error(diag, registry); + return self.handle_non_ignoreable_error(diag); } if let Some(primary_span) = &diag.span.primary_span() { let file_name = self.source_map.span_to_filename(*primary_span); @@ -73,7 +72,7 @@ impl Emitter for SilentOnIgnoredFilesEmitter { } } } - self.handle_non_ignoreable_error(diag, registry); + self.handle_non_ignoreable_error(diag); } fn translator(&self) -> &Translator { @@ -340,7 +339,7 @@ mod tests { None } - fn emit_diagnostic(&mut self, _diag: DiagInner, _registry: &Registry) { + fn emit_diagnostic(&mut self, _diag: DiagInner) { self.num_emitted_errors.fetch_add(1, Ordering::Release); } @@ -401,7 +400,6 @@ mod tests { let source = String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#); source_map.new_source_file(filename(&source_map, "foo.rs"), source); - let registry = Registry::new(); let mut emitter = build_emitter( Arc::clone(&num_emitted_errors), Arc::clone(&can_reset_errors), @@ -410,7 +408,7 @@ mod tests { ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, Some(span)); - emitter.emit_diagnostic(fatal_diagnostic, ®istry); + emitter.emit_diagnostic(fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } @@ -424,7 +422,6 @@ mod tests { let source_map = Arc::new(SourceMap::new(FilePathMapping::empty())); let source = String::from(r#"pub fn bar() { 1x; }"#); source_map.new_source_file(filename(&source_map, "foo.rs"), source); - let registry = Registry::new(); let mut emitter = build_emitter( Arc::clone(&num_emitted_errors), Arc::clone(&can_reset_errors), @@ -433,7 +430,7 @@ mod tests { ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); - emitter.emit_diagnostic(non_fatal_diagnostic, ®istry); + emitter.emit_diagnostic(non_fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 0); assert_eq!(can_reset_errors.load(Ordering::Acquire), true); } @@ -446,7 +443,6 @@ mod tests { let source_map = Arc::new(SourceMap::new(FilePathMapping::empty())); let source = String::from(r#"pub fn bar() { 1x; }"#); source_map.new_source_file(filename(&source_map, "foo.rs"), source); - let registry = Registry::new(); let mut emitter = build_emitter( Arc::clone(&num_emitted_errors), Arc::clone(&can_reset_errors), @@ -455,7 +451,7 @@ mod tests { ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); - emitter.emit_diagnostic(non_fatal_diagnostic, ®istry); + emitter.emit_diagnostic(non_fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } @@ -474,7 +470,6 @@ mod tests { source_map.new_source_file(filename(&source_map, "bar.rs"), bar_source); source_map.new_source_file(filename(&source_map, "foo.rs"), foo_source); source_map.new_source_file(filename(&source_map, "fatal.rs"), fatal_source); - let registry = Registry::new(); let mut emitter = build_emitter( Arc::clone(&num_emitted_errors), Arc::clone(&can_reset_errors), @@ -486,9 +481,9 @@ mod tests { let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(bar_span)); let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(foo_span)); let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, None); - emitter.emit_diagnostic(bar_diagnostic, ®istry); - emitter.emit_diagnostic(foo_diagnostic, ®istry); - emitter.emit_diagnostic(fatal_diagnostic, ®istry); + emitter.emit_diagnostic(bar_diagnostic); + emitter.emit_diagnostic(foo_diagnostic); + emitter.emit_diagnostic(fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 2); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } From 8cbc623c3a81b49b7f669b659cf3fa202bcbf7d7 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Fri, 9 Jan 2026 22:28:05 +0900 Subject: [PATCH 563/978] Add avr_target_feature --- compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/target_features.rs | 29 ++++++++++++++++++-- tests/ui/check-cfg/target_feature.stderr | 17 ++++++++++++ tests/ui/target-feature/gate.rs | 1 + tests/ui/target-feature/gate.stderr | 2 +- 6 files changed, 48 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index c99af9658cde..e2abf50cbd39 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -373,6 +373,8 @@ declare_features! ( (unstable, async_for_loop, "1.77.0", Some(118898)), /// Allows `async` trait bound modifier. (unstable, async_trait_bounds, "1.85.0", Some(62290)), + /// Target features on avr. + (unstable, avr_target_feature, "CURRENT_RUSTC_VERSION", Some(146889)), /// Allows using Intel AVX10 target features and intrinsics (unstable, avx10_target_feature, "1.88.0", Some(138843)), /// Target features on bpf. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index aac4cf1de8c2..1915ff0380fd 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -577,6 +577,7 @@ symbols! { automatically_derived, available_externally, avr, + avr_target_feature, avx, avx10_target_feature, avx512_target_feature, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index bc12e1eb9737..3b10613b6457 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -898,6 +898,28 @@ static M68K_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; +static AVR_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("addsubiw", Unstable(sym::avr_target_feature), &[]), + ("break", Unstable(sym::avr_target_feature), &[]), + ("eijmpcall", Unstable(sym::avr_target_feature), &[]), + ("elpm", Unstable(sym::avr_target_feature), &[]), + ("elpmx", Unstable(sym::avr_target_feature), &[]), + ("ijmpcall", Unstable(sym::avr_target_feature), &[]), + ("jmpcall", Unstable(sym::avr_target_feature), &[]), + ("lowbytefirst", Unstable(sym::avr_target_feature), &[]), + ("lpm", Unstable(sym::avr_target_feature), &[]), + ("lpmx", Unstable(sym::avr_target_feature), &[]), + ("movw", Unstable(sym::avr_target_feature), &[]), + ("mul", Unstable(sym::avr_target_feature), &[]), + ("rmw", Unstable(sym::avr_target_feature), &[]), + ("spm", Unstable(sym::avr_target_feature), &[]), + ("spmx", Unstable(sym::avr_target_feature), &[]), + ("sram", Unstable(sym::avr_target_feature), &[]), + ("tinyencoding", Unstable(sym::avr_target_feature), &[]), + // tidy-alphabetical-end +]; + /// When rustdoc is running, provide a list of all known features so that all their respective /// primitives may be documented. /// @@ -919,6 +941,7 @@ pub fn all_rust_features() -> impl Iterator { .chain(IBMZ_FEATURES) .chain(SPARC_FEATURES) .chain(M68K_FEATURES) + .chain(AVR_FEATURES) .cloned() .map(|(f, s, _)| (f, s)) } @@ -996,8 +1019,8 @@ impl Target { Arch::S390x => IBMZ_FEATURES, Arch::Sparc | Arch::Sparc64 => SPARC_FEATURES, Arch::M68k => M68K_FEATURES, + Arch::Avr => AVR_FEATURES, Arch::AmdGpu - | Arch::Avr | Arch::Msp430 | Arch::SpirV | Arch::Xtensa @@ -1023,11 +1046,11 @@ impl Target { MIPS_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI } Arch::AmdGpu => AMDGPU_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI, - Arch::Nvptx64 | Arch::Bpf | Arch::M68k => &[], // no vector ABI + Arch::Nvptx64 | Arch::Bpf | Arch::M68k | Arch::Avr => &[], // no vector ABI Arch::CSky => CSKY_FEATURES_FOR_CORRECT_FIXED_LENGTH_VECTOR_ABI, // FIXME: for some tier3 targets, we are overly cautious and always give warnings // when passing args in vector registers. - Arch::Avr | Arch::Msp430 | Arch::SpirV | Arch::Xtensa | Arch::Other(_) => &[], + Arch::Msp430 | Arch::SpirV | Arch::Xtensa | Arch::Other(_) => &[], } } diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 89123c910082..8f887eaaca8c 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -14,6 +14,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `7e10` `a` `aclass` +`addsubiw` `adx` `aes` `altivec` @@ -57,6 +58,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `bf16` `bmi1` `bmi2` +`break` `bti` `bulk-memory` `c` @@ -83,6 +85,9 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `e2` `ecv` `edsp` +`eijmpcall` +`elpm` +`elpmx` `elrw` `enhanced-sort` `ermsb` @@ -148,6 +153,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `hvxv79` `hwdiv` `i8mm` +`ijmpcall` `isa-68000` `isa-68010` `isa-68020` @@ -156,6 +162,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `isa-68060` `isa-68881` `isa-68882` +`jmpcall` `jsconv` `kl` `lahfsahf` @@ -166,6 +173,9 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `ld-seq-sa` `leoncasa` `lor` +`lowbytefirst` +`lpm` +`lpmx` `lse` `lse128` `lse2` @@ -187,11 +197,13 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `mops` `movbe` `movrs` +`movw` `mp` `mp1e2` `msa` `msync` `mte` +`mul` `multivalue` `mutable-globals` `neon` @@ -256,6 +268,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `reference-types` `relax` `relaxed-simd` +`rmw` `rtm` `rva23u64` `sb` @@ -308,6 +321,9 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `sme2p1` `soft-float` `spe` +`spm` +`spmx` +`sram` `ssbs` `sse` `sse2` @@ -332,6 +348,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `tbm` `thumb-mode` `thumb2` +`tinyencoding` `tme` `transactional-execution` `trust` diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index fc3763820cbe..ea3bbbed273c 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -20,6 +20,7 @@ // gate-test-sparc_target_feature // gate-test-x87_target_feature // gate-test-m68k_target_feature +// gate-test-avr_target_feature #[target_feature(enable = "x87")] //~^ ERROR: currently unstable diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index 67df09fd369e..f0de5a958e86 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `x87` is currently unstable - --> $DIR/gate.rs:24:18 + --> $DIR/gate.rs:25:18 | LL | #[target_feature(enable = "x87")] | ^^^^^^^^^^^^^^ From d40e60fc447e36afc664c69353a0b1e6ab4d2738 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 4 Feb 2026 18:05:19 +0100 Subject: [PATCH 564/978] Convert to inline diagnostics in `rustc_builtin_macros` --- Cargo.lock | 2 - compiler/rustc_builtin_macros/Cargo.toml | 1 - compiler/rustc_builtin_macros/messages.ftl | 320 ------------ .../src/deriving/coerce_pointee.rs | 14 +- compiler/rustc_builtin_macros/src/errors.rs | 490 +++++++++++------- compiler/rustc_builtin_macros/src/lib.rs | 2 - compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - 8 files changed, 298 insertions(+), 533 deletions(-) delete mode 100644 compiler/rustc_builtin_macros/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 9c98946c9d39..07afb4a27779 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3600,7 +3600,6 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_lexer", @@ -3775,7 +3774,6 @@ dependencies = [ "rustc_ast_passes", "rustc_ast_pretty", "rustc_borrowck", - "rustc_builtin_macros", "rustc_codegen_ssa", "rustc_const_eval", "rustc_data_structures", diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index ce9a3ce3f248..dd84a2c1802d 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -15,7 +15,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_lexer = { path = "../rustc_lexer" } diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl deleted file mode 100644 index f9ffddf79084..000000000000 --- a/compiler/rustc_builtin_macros/messages.ftl +++ /dev/null @@ -1,320 +0,0 @@ -builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function -builtin_macros_alloc_must_statics = allocators must be statics - -builtin_macros_asm_attribute_not_supported = - this attribute is not supported on assembly - -builtin_macros_asm_clobber_abi = clobber_abi -builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs -builtin_macros_asm_clobber_outputs = generic outputs - -builtin_macros_asm_duplicate_arg = duplicate argument named `{$name}` - .label = previously here - .arg = duplicate argument - -builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names - -builtin_macros_asm_mayunwind = asm labels are not allowed with the `may_unwind` option - -builtin_macros_asm_modifier_invalid = asm template modifier must be a single character - -builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive - -builtin_macros_asm_no_matched_argument_name = there is no argument named `{$name}` - -builtin_macros_asm_noreturn = asm outputs are not allowed with the `noreturn` option - -builtin_macros_asm_opt_already_provided = the `{$symbol}` option was already provided - .label = this option was already provided - .suggestion = remove this option - -builtin_macros_asm_pos_after = positional arguments cannot follow named arguments or explicit register arguments - .pos = positional argument - .named = named argument - .explicit = explicit register argument - -builtin_macros_asm_pure_combine = the `pure` option must be combined with either `nomem` or `readonly` - -builtin_macros_asm_pure_no_output = asm with the `pure` option must have at least one output - -builtin_macros_asm_unsupported_clobber_abi = `clobber_abi` cannot be used with `{$macro_name}!` - -builtin_macros_asm_unsupported_option = the `{$symbol}` option cannot be used with `{$macro_name}!` - .label = the `{$symbol}` option is not meaningful for global-scoped inline assembly - .suggestion = remove this option - -builtin_macros_assert_missing_comma = unexpected string literal - .suggestion = try adding a comma - -builtin_macros_assert_requires_boolean = macro requires a boolean expression as an argument - .label = boolean expression required - -builtin_macros_assert_requires_expression = macro requires an expression as an argument - .suggestion = try removing semicolon - -builtin_macros_autodiff = autodiff must be applied to function -builtin_macros_autodiff_missing_config = autodiff requires at least a name and mode -builtin_macros_autodiff_mode_activity = {$act} can not be used in {$mode} Mode -builtin_macros_autodiff_number_activities = expected {$expected} activities, but found {$found} -builtin_macros_autodiff_ret_activity = invalid return activity {$act} in {$mode} Mode -builtin_macros_autodiff_ty_activity = {$act} can not be used for this type -builtin_macros_autodiff_unknown_activity = did not recognize Activity: `{$act}` - -builtin_macros_autodiff_width = autodiff width must fit u32, but is {$width} - -builtin_macros_avoid_att_syntax = avoid using `.att_syntax`, prefer using `options(att_syntax)` instead - -builtin_macros_avoid_intel_syntax = avoid using `.intel_syntax`, Intel syntax is the default - -builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s - .label = not applicable here - .label2 = not a `struct`, `enum` or `union` - -builtin_macros_bench_sig = functions used as benches must have signature `fn(&mut Bencher) -> impl Termination` - - -builtin_macros_cannot_derive_union = this trait cannot be derived for unions - -builtin_macros_cfg_accessible_has_args = `cfg_accessible` path cannot accept arguments - -builtin_macros_cfg_accessible_indeterminate = cannot determine whether the path is accessible or not - -builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a literal -builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified -builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified - -builtin_macros_cfg_select_no_matches = none of the predicates in this `cfg_select` evaluated to true - -builtin_macros_cfg_select_unreachable = unreachable predicate - .label = always matches - .label2 = this predicate is never reached - -builtin_macros_coerce_pointee_requires_maybe_sized = `derive(CoercePointee)` requires `{$name}` to be marked `?Sized` - -builtin_macros_coerce_pointee_requires_one_field = `CoercePointee` can only be derived on `struct`s with at least one field - -builtin_macros_coerce_pointee_requires_one_generic = `CoercePointee` can only be derived on `struct`s that are generic over at least one type - -builtin_macros_coerce_pointee_requires_one_pointee = exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits - -builtin_macros_coerce_pointee_requires_transparent = `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]` - -builtin_macros_coerce_pointee_too_many_pointees = only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits - .label = here another type parameter is marked as `#[pointee]` - - -builtin_macros_concat_bytes_array = cannot concatenate doubly nested array - .note = byte strings are treated as arrays of bytes - .help = try flattening the array - -builtin_macros_concat_bytes_bad_repeat = repeat count is not a positive number - -builtin_macros_concat_bytes_invalid = cannot concatenate {$lit_kind} literals - .byte_char = try using a byte character - .byte_str = try using a byte string - .c_str = try using a null-terminated byte string - .c_str_note = concatenating C strings is ambiguous about including the '\0' - .number_array = try wrapping the number in an array - -builtin_macros_concat_bytes_missing_literal = expected a byte literal - .note = only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()` - -builtin_macros_concat_bytes_non_u8 = numeric literal is not a `u8` - -builtin_macros_concat_bytes_oob = numeric literal is out of bounds - -builtin_macros_concat_bytestr = cannot concatenate a byte string literal -builtin_macros_concat_c_str_lit = cannot concatenate a C string literal - -builtin_macros_concat_missing_literal = expected a literal - .note = only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()` - -builtin_macros_default_arg = `#[default]` attribute does not accept a value - .suggestion = try using `#[default]` - -builtin_macros_derive_from_usage_note = `#[derive(From)]` can only be used on structs with exactly one field - -builtin_macros_derive_from_wrong_field_count = `#[derive(From)]` used on a struct with {$multiple_fields -> - [true] multiple fields - *[false] no fields -} - -builtin_macros_derive_from_wrong_target = `#[derive(From)]` used on {$kind} - -builtin_macros_derive_macro_call = `derive` cannot be used on items with type macros - -builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept arguments - .suggestion = remove the arguments - -builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values - .suggestion = remove the value - -builtin_macros_duplicate_macro_attribute = duplicated attribute - -builtin_macros_eii_declaration_expected_list = `#[eii_declaration(...)]` expects a list of one or two elements -builtin_macros_eii_declaration_expected_macro = `#[eii_declaration(...)]` is only valid on macros -builtin_macros_eii_declaration_expected_unsafe = expected this argument to be "unsafe" - .note = the second argument is optional - -builtin_macros_eii_only_once = `#[{$name}]` can only be specified once - .note = specified again here - -builtin_macros_eii_shared_macro_expected_function = `#[{$name}]` is only valid on functions -builtin_macros_eii_shared_macro_expected_max_one_argument = `#[{$name}]` expected no arguments or a single argument: `#[{$name}(default)]` -builtin_macros_eii_shared_macro_in_statement_position = `#[{$name}]` can only be used on functions inside a module - .label = `#[{$name}]` is used on this item, which is part of another item's local scope - -builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time - .cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead - .cargo_typo = there is a similar Cargo environment variable: `{$suggested_var}` - .custom = use `std::env::var({$var_expr})` to read the variable at run time - -builtin_macros_env_not_unicode = environment variable `{$var}` is not a valid Unicode string - -builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments - -builtin_macros_expected_comma_in_list = expected token: `,` - -builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern - -builtin_macros_expected_other = expected operand, {$is_inline_asm -> - [false] options - *[true] clobber_abi, options - }, or additional template string - -builtin_macros_export_macro_rules = cannot export macro_rules! macros from a `proc-macro` crate type currently - -builtin_macros_format_add_missing_colon = add a colon before the format specifier - -builtin_macros_format_duplicate_arg = duplicate argument named `{$ident}` - .label1 = previously here - .label2 = duplicate argument - -builtin_macros_format_no_arg_named = there is no argument named `{$name}` - .note = did you intend to capture a variable `{$name}` from the surrounding scope? - .note2 = to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro - -builtin_macros_format_pos_mismatch = {$n} positional {$n -> - [one] argument - *[more] arguments - } in format string, but {$desc} - -builtin_macros_format_positional_after_named = positional arguments cannot follow named arguments - .label = positional arguments must be before named arguments - .named_args = named argument - -builtin_macros_format_redundant_args = redundant {$n -> - [one] argument - *[more] arguments - } - .help = {$n -> - [one] the formatting string already captures the binding directly, it doesn't need to be included in the argument list - *[more] the formatting strings already captures the bindings directly, they don't need to be included in the argument list - } - .note = {$n -> - [one] the formatting specifier is referencing the binding already - *[more] the formatting specifiers are referencing the bindings already - } - .suggestion = this can be removed - -builtin_macros_format_remove_raw_ident = remove the `r#` - -builtin_macros_format_reorder_format_parameter = did you mean `{$replacement}`? - -builtin_macros_format_requires_string = requires at least a format string argument - -builtin_macros_format_string_invalid = invalid format string: {$desc} - .label = {$label1} in format string - .note = {$note} - .second_label = {$label} - -builtin_macros_format_unknown_trait = unknown format trait `{$ty}` - .note = the only appropriate formatting traits are: - - ``, which uses the `Display` trait - - `?`, which uses the `Debug` trait - - `e`, which uses the `LowerExp` trait - - `E`, which uses the `UpperExp` trait - - `o`, which uses the `Octal` trait - - `p`, which uses the `Pointer` trait - - `b`, which uses the `Binary` trait - - `x`, which uses the `LowerHex` trait - - `X`, which uses the `UpperHex` trait - .suggestion = use the `{$trait_name}` trait - -builtin_macros_format_unused_arg = {$named -> - [true] named argument - *[false] argument - } never used - -builtin_macros_format_unused_args = multiple unused formatting arguments - .label = multiple missing formatting specifiers - -builtin_macros_format_use_positional = consider using a positional formatting argument instead - -builtin_macros_incomplete_include = include macro expected single expression in source - -builtin_macros_multiple_default_attrs = multiple `#[default]` attributes - .note = only one `#[default]` attribute is needed - .label = `#[default]` used here - .label_again = `#[default]` used again here - .help = try removing {$only_one -> - [true] this - *[false] these - } - -builtin_macros_multiple_defaults = multiple declared defaults - .label = first default - .additional = additional default - .note = only one variant can be default - .suggestion = make `{$ident}` default - -builtin_macros_naked_functions_testing_attribute = - cannot use `#[unsafe(naked)]` with testing attributes - .label = function marked with testing attribute here - .naked_attribute = `#[unsafe(naked)]` is incompatible with testing attributes - -builtin_macros_no_default_variant = `#[derive(Default)]` on enum with no `#[default]` - .label = this enum needs a unit variant marked with `#[default]` - .suggestion = make this unit variant default by placing `#[default]` on it - -builtin_macros_non_exhaustive_default = default variant must be exhaustive - .label = declared `#[non_exhaustive]` here - .help = consider a manual implementation of `Default` - -builtin_macros_non_generic_pointee = the `#[pointee]` attribute may only be used on generic parameters - -builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants{$post} - .help = consider a manual implementation of `Default` - -builtin_macros_only_one_argument = {$name} takes 1 argument - -builtin_macros_proc_macro = `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` - -builtin_macros_proc_macro_attribute_only_usable_with_crate_type = the `#[{$path}]` attribute is only usable with crates of the `proc-macro` crate type - -builtin_macros_requires_cfg_pattern = - macro requires a cfg-pattern as an argument - .label = cfg-pattern required - -builtin_macros_source_utils_expected_item = expected item, found `{$token}` - -builtin_macros_takes_no_arguments = {$name} takes no arguments - -builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests - .label = `{$kind}` because of this - -builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on items - -builtin_macros_test_runner_invalid = `test_runner` argument must be a path -builtin_macros_test_runner_nargs = `#![test_runner(..)]` accepts exactly 1 argument - -builtin_macros_tests_not_support = building tests with panic=abort is not supported without `-Zpanic_abort_tests` - -builtin_macros_trace_macros = trace_macros! accepts only `true` or `false` - -builtin_macros_unexpected_lit = expected path to a trait, found literal - .label = not a trait - .str_lit = try using `#[derive({$sym})]` - .other = for example, write `#[derive(Debug)]` for `Debug` - -builtin_macros_unnameable_test_items = cannot test inner items diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index d6fdf088b0d1..8984e51c0844 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -463,44 +463,44 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for AlwaysErrorOnGenericParam<'a, 'b> } #[derive(Diagnostic)] -#[diag(builtin_macros_coerce_pointee_requires_transparent, code = E0802)] +#[diag("`CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`", code = E0802)] struct RequireTransparent { #[primary_span] span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_coerce_pointee_requires_one_field, code = E0802)] +#[diag("`CoercePointee` can only be derived on `struct`s with at least one field", code = E0802)] struct RequireOneField { #[primary_span] span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_coerce_pointee_requires_one_generic, code = E0802)] +#[diag("`CoercePointee` can only be derived on `struct`s that are generic over at least one type", code = E0802)] struct RequireOneGeneric { #[primary_span] span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_coerce_pointee_requires_one_pointee, code = E0802)] +#[diag("exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits", code = E0802)] struct RequireOnePointee { #[primary_span] span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_coerce_pointee_too_many_pointees, code = E0802)] +#[diag("only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits", code = E0802)] struct TooManyPointees { #[primary_span] one: Span, - #[label] + #[label("here another type parameter is marked as `#[pointee]`")] another: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_coerce_pointee_requires_maybe_sized, code = E0802)] +#[diag("`derive(CoercePointee)` requires `{$name}` to be marked `?Sized`", code = E0802)] struct RequiresMaybeSized { #[primary_span] span: Span, diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 0aaa8cf558c4..d3f7e1c5d8e3 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,150 +1,157 @@ use rustc_errors::codes::*; use rustc_errors::{ Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, SingleLabelManySpans, - Subdiagnostic, + Subdiagnostic, inline_fluent, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; #[derive(LintDiagnostic)] -#[diag(builtin_macros_avoid_intel_syntax)] +#[diag("avoid using `.intel_syntax`, Intel syntax is the default")] pub(crate) struct AvoidIntelSyntax; #[derive(LintDiagnostic)] -#[diag(builtin_macros_avoid_att_syntax)] +#[diag("avoid using `.att_syntax`, prefer using `options(att_syntax)` instead")] pub(crate) struct AvoidAttSyntax; #[derive(LintDiagnostic)] -#[diag(builtin_macros_incomplete_include)] +#[diag("include macro expected single expression in source")] pub(crate) struct IncompleteInclude; #[derive(LintDiagnostic)] -#[diag(builtin_macros_unnameable_test_items)] +#[diag("cannot test inner items")] pub(crate) struct UnnameableTestItems; #[derive(LintDiagnostic)] -#[diag(builtin_macros_duplicate_macro_attribute)] +#[diag("duplicated attribute")] pub(crate) struct DuplicateMacroAttribute; #[derive(Diagnostic)] -#[diag(builtin_macros_requires_cfg_pattern)] +#[diag("macro requires a cfg-pattern as an argument")] pub(crate) struct RequiresCfgPattern { #[primary_span] - #[label] + #[label("cfg-pattern required")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_expected_one_cfg_pattern)] +#[diag("expected 1 cfg-pattern")] pub(crate) struct OneCfgPattern { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_alloc_error_must_be_fn)] +#[diag("alloc_error_handler must be a function")] pub(crate) struct AllocErrorMustBeFn { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_assert_requires_boolean)] +#[diag("macro requires a boolean expression as an argument")] pub(crate) struct AssertRequiresBoolean { #[primary_span] - #[label] + #[label("boolean expression required")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_assert_requires_expression)] +#[diag("macro requires an expression as an argument")] pub(crate) struct AssertRequiresExpression { #[primary_span] pub(crate) span: Span, - #[suggestion(code = "", applicability = "maybe-incorrect")] + #[suggestion("try removing semicolon", code = "", applicability = "maybe-incorrect")] pub(crate) token: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_assert_missing_comma)] +#[diag("unexpected string literal")] pub(crate) struct AssertMissingComma { #[primary_span] pub(crate) span: Span, - #[suggestion(code = ", ", applicability = "maybe-incorrect", style = "short")] + #[suggestion( + "try adding a comma", + code = ", ", + applicability = "maybe-incorrect", + style = "short" + )] pub(crate) comma: Span, } #[derive(Diagnostic)] pub(crate) enum CfgAccessibleInvalid { - #[diag(builtin_macros_cfg_accessible_unspecified_path)] + #[diag("`cfg_accessible` path is not specified")] UnspecifiedPath(#[primary_span] Span), - #[diag(builtin_macros_cfg_accessible_multiple_paths)] + #[diag("multiple `cfg_accessible` paths are specified")] MultiplePaths(#[primary_span] Span), - #[diag(builtin_macros_cfg_accessible_literal_path)] + #[diag("`cfg_accessible` path cannot be a literal")] LiteralPath(#[primary_span] Span), - #[diag(builtin_macros_cfg_accessible_has_args)] + #[diag("`cfg_accessible` path cannot accept arguments")] HasArguments(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(builtin_macros_cfg_accessible_indeterminate)] +#[diag("cannot determine whether the path is accessible or not")] pub(crate) struct CfgAccessibleIndeterminate { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_missing_literal)] -#[note] +#[diag("expected a literal")] +#[note("only literals (like `\"foo\"`, `-42` and `3.14`) can be passed to `concat!()`")] pub(crate) struct ConcatMissingLiteral { #[primary_span] pub(crate) spans: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_bytestr)] +#[diag("cannot concatenate a byte string literal")] pub(crate) struct ConcatBytestr { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_c_str_lit)] +#[diag("cannot concatenate a C string literal")] pub(crate) struct ConcatCStrLit { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_export_macro_rules)] +#[diag("cannot export macro_rules! macros from a `proc-macro` crate type currently")] pub(crate) struct ExportMacroRules { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_proc_macro)] +#[diag( + "`proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`" +)] pub(crate) struct ProcMacro { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_trace_macros)] +#[diag("trace_macros! accepts only `true` or `false`")] pub(crate) struct TraceMacros { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_bench_sig)] +#[diag("functions used as benches must have signature `fn(&mut Bencher) -> impl Termination`")] pub(crate) struct BenchSig { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_alloc_must_statics)] +#[diag("allocators must be statics")] pub(crate) struct AllocMustStatics { #[primary_span] pub(crate) span: Span, @@ -155,27 +162,27 @@ pub(crate) use autodiff::*; mod autodiff { use super::*; #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_missing_config)] + #[diag("autodiff requires at least a name and mode")] pub(crate) struct AutoDiffMissingConfig { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_unknown_activity)] + #[diag("did not recognize Activity: `{$act}`")] pub(crate) struct AutoDiffUnknownActivity { #[primary_span] pub(crate) span: Span, pub(crate) act: String, } #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_ty_activity)] + #[diag("{$act} can not be used for this type")] pub(crate) struct AutoDiffInvalidTypeForActivity { #[primary_span] pub(crate) span: Span, pub(crate) act: String, } #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_number_activities)] + #[diag("expected {$expected} activities, but found {$found}")] pub(crate) struct AutoDiffInvalidNumberActivities { #[primary_span] pub(crate) span: Span, @@ -183,7 +190,7 @@ mod autodiff { pub(crate) found: usize, } #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_mode_activity)] + #[diag("{$act} can not be used in {$mode} Mode")] pub(crate) struct AutoDiffInvalidApplicationModeAct { #[primary_span] pub(crate) span: Span, @@ -192,7 +199,7 @@ mod autodiff { } #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_ret_activity)] + #[diag("invalid return activity {$act} in {$mode} Mode")] pub(crate) struct AutoDiffInvalidRetAct { #[primary_span] pub(crate) span: Span, @@ -201,7 +208,7 @@ mod autodiff { } #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff_width)] + #[diag("autodiff width must fit u32, but is {$width}")] pub(crate) struct AutoDiffInvalidWidth { #[primary_span] pub(crate) span: Span, @@ -209,7 +216,7 @@ mod autodiff { } #[derive(Diagnostic)] - #[diag(builtin_macros_autodiff)] + #[diag("autodiff must be applied to function")] pub(crate) struct AutoDiffInvalidApplication { #[primary_span] pub(crate) span: Span, @@ -217,21 +224,21 @@ mod autodiff { } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_bytes_invalid)] +#[diag("cannot concatenate {$lit_kind} literals")] pub(crate) struct ConcatBytesInvalid { #[primary_span] pub(crate) span: Span, pub(crate) lit_kind: &'static str, #[subdiagnostic] pub(crate) sugg: Option, - #[note(builtin_macros_c_str_note)] + #[note("concatenating C strings is ambiguous about including the '\\0'")] pub(crate) cs_note: Option<()>, } #[derive(Subdiagnostic)] pub(crate) enum ConcatBytesInvalidSuggestion { #[suggestion( - builtin_macros_byte_char, + "try using a byte character", code = "b{snippet}", applicability = "machine-applicable" )] @@ -241,7 +248,7 @@ pub(crate) enum ConcatBytesInvalidSuggestion { snippet: String, }, #[suggestion( - builtin_macros_byte_str, + "try using a byte string", code = "b{snippet}", applicability = "machine-applicable" )] @@ -250,15 +257,19 @@ pub(crate) enum ConcatBytesInvalidSuggestion { span: Span, snippet: String, }, - #[note(builtin_macros_c_str_note)] - #[suggestion(builtin_macros_c_str, code = "{as_bstr}", applicability = "machine-applicable")] + #[note("concatenating C strings is ambiguous about including the '\\0'")] + #[suggestion( + "try using a null-terminated byte string", + code = "{as_bstr}", + applicability = "machine-applicable" + )] CStrLit { #[primary_span] span: Span, as_bstr: String, }, #[suggestion( - builtin_macros_number_array, + "try wrapping the number in an array", code = "[{snippet}]", applicability = "machine-applicable" )] @@ -270,63 +281,65 @@ pub(crate) enum ConcatBytesInvalidSuggestion { } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_bytes_oob)] +#[diag("numeric literal is out of bounds")] pub(crate) struct ConcatBytesOob { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_bytes_non_u8)] +#[diag("numeric literal is not a `u8`")] pub(crate) struct ConcatBytesNonU8 { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_bytes_missing_literal)] -#[note] +#[diag("expected a byte literal")] +#[note( + "only byte literals (like `b\"foo\"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`" +)] pub(crate) struct ConcatBytesMissingLiteral { #[primary_span] pub(crate) spans: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_bytes_array)] +#[diag("cannot concatenate doubly nested array")] pub(crate) struct ConcatBytesArray { #[primary_span] pub(crate) span: Span, - #[note] - #[help] + #[note("byte strings are treated as arrays of bytes")] + #[help("try flattening the array")] pub(crate) bytestr: bool, } #[derive(Diagnostic)] -#[diag(builtin_macros_concat_bytes_bad_repeat)] +#[diag("repeat count is not a positive number")] pub(crate) struct ConcatBytesBadRepeat { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_bad_derive_target, code = E0774)] +#[diag("`derive` may only be applied to `struct`s, `enum`s and `union`s", code = E0774)] pub(crate) struct BadDeriveTarget { #[primary_span] - #[label] + #[label("not applicable here")] pub(crate) span: Span, - #[label(builtin_macros_label2)] + #[label("not a `struct`, `enum` or `union`")] pub(crate) item: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_tests_not_support)] +#[diag("building tests with panic=abort is not supported without `-Zpanic_abort_tests`")] pub(crate) struct TestsNotSupport {} #[derive(Diagnostic)] -#[diag(builtin_macros_unexpected_lit, code = E0777)] +#[diag("expected path to a trait, found literal", code = E0777)] pub(crate) struct BadDeriveLit { #[primary_span] - #[label] + #[label("not a trait")] pub(crate) span: Span, #[subdiagnostic] pub help: BadDeriveLitHelp, @@ -334,55 +347,59 @@ pub(crate) struct BadDeriveLit { #[derive(Subdiagnostic)] pub(crate) enum BadDeriveLitHelp { - #[help(builtin_macros_str_lit)] + #[help("try using `#[derive({$sym})]`")] StrLit { sym: Symbol }, - #[help(builtin_macros_other)] + #[help("for example, write `#[derive(Debug)]` for `Debug`")] Other, } #[derive(Diagnostic)] -#[diag(builtin_macros_derive_path_args_list)] +#[diag("traits in `#[derive(...)]` don't accept arguments")] pub(crate) struct DerivePathArgsList { - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove the arguments", code = "", applicability = "machine-applicable")] #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_derive_path_args_value)] +#[diag("traits in `#[derive(...)]` don't accept values")] pub(crate) struct DerivePathArgsValue { - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove the value", code = "", applicability = "machine-applicable")] #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_no_default_variant, code = E0665)] +#[diag("`#[derive(Default)]` on enum with no `#[default]`", code = E0665)] pub(crate) struct NoDefaultVariant { #[primary_span] pub(crate) span: Span, - #[label] + #[label("this enum needs a unit variant marked with `#[default]`")] pub(crate) item_span: Span, #[subdiagnostic] pub(crate) suggs: Vec, } #[derive(Subdiagnostic)] -#[suggestion(builtin_macros_suggestion, code = "#[default] ", applicability = "maybe-incorrect")] +#[suggestion( + "make this unit variant default by placing `#[default]` on it", + code = "#[default] ", + applicability = "maybe-incorrect" +)] pub(crate) struct NoDefaultVariantSugg { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_multiple_defaults)] -#[note] +#[diag("multiple declared defaults")] +#[note("only one variant can be default")] pub(crate) struct MultipleDefaults { #[primary_span] pub(crate) span: Span, - #[label] + #[label("first default")] pub(crate) first: Span, - #[label(builtin_macros_additional)] + #[label("additional default")] pub additional: Vec, #[subdiagnostic] pub suggs: Vec, @@ -390,7 +407,7 @@ pub(crate) struct MultipleDefaults { #[derive(Subdiagnostic)] #[multipart_suggestion( - builtin_macros_suggestion, + "make `{$ident}` default", applicability = "maybe-incorrect", style = "tool-only" )] @@ -401,8 +418,8 @@ pub(crate) struct MultipleDefaultsSugg { } #[derive(Diagnostic)] -#[diag(builtin_macros_non_unit_default)] -#[help] +#[diag("the `#[default]` attribute may only be used on unit enum variants{$post}")] +#[help("consider a manual implementation of `Default`")] pub(crate) struct NonUnitDefault { #[primary_span] pub(crate) span: Span, @@ -410,26 +427,31 @@ pub(crate) struct NonUnitDefault { } #[derive(Diagnostic)] -#[diag(builtin_macros_non_exhaustive_default)] -#[help] +#[diag("default variant must be exhaustive")] +#[help("consider a manual implementation of `Default`")] pub(crate) struct NonExhaustiveDefault { #[primary_span] pub(crate) span: Span, - #[label] + #[label("declared `#[non_exhaustive]` here")] pub(crate) non_exhaustive: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_multiple_default_attrs)] -#[note] +#[diag("multiple `#[default]` attributes")] +#[note("only one `#[default]` attribute is needed")] pub(crate) struct MultipleDefaultAttrs { #[primary_span] pub(crate) span: Span, - #[label] + #[label("`#[default]` used here")] pub(crate) first: Span, - #[label(builtin_macros_label_again)] + #[label("`#[default]` used again here")] pub(crate) first_rest: Span, - #[help] + #[help( + "try removing {$only_one -> + [true] this + *[false] these + }" + )] pub(crate) rest: MultiSpan, pub(crate) only_one: bool, #[subdiagnostic] @@ -438,7 +460,7 @@ pub(crate) struct MultipleDefaultAttrs { #[derive(Subdiagnostic)] #[multipart_suggestion( - builtin_macros_help, + "consider a manual implementation of `Default`", applicability = "machine-applicable", style = "tool-only" )] @@ -448,16 +470,21 @@ pub(crate) struct MultipleDefaultAttrsSugg { } #[derive(Diagnostic)] -#[diag(builtin_macros_default_arg)] +#[diag("`#[default]` attribute does not accept a value")] pub(crate) struct DefaultHasArg { #[primary_span] - #[suggestion(code = "#[default]", style = "hidden", applicability = "maybe-incorrect")] + #[suggestion( + "try using `#[default]`", + code = "#[default]", + style = "hidden", + applicability = "maybe-incorrect" + )] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_derive_from_wrong_target)] -#[note(builtin_macros_derive_from_usage_note)] +#[diag("`#[derive(From)]` used on {$kind}")] +#[note("`#[derive(From)]` can only be used on structs with exactly one field")] pub(crate) struct DeriveFromWrongTarget<'a> { #[primary_span] pub(crate) span: MultiSpan, @@ -465,8 +492,13 @@ pub(crate) struct DeriveFromWrongTarget<'a> { } #[derive(Diagnostic)] -#[diag(builtin_macros_derive_from_wrong_field_count)] -#[note(builtin_macros_derive_from_usage_note)] +#[diag( + "`#[derive(From)]` used on a struct with {$multiple_fields -> + [true] multiple fields + *[false] no fields + }" +)] +#[note("`#[derive(From)]` can only be used on structs with exactly one field")] pub(crate) struct DeriveFromWrongFieldCount { #[primary_span] pub(crate) span: MultiSpan, @@ -474,21 +506,21 @@ pub(crate) struct DeriveFromWrongFieldCount { } #[derive(Diagnostic)] -#[diag(builtin_macros_derive_macro_call)] +#[diag("`derive` cannot be used on items with type macros")] pub(crate) struct DeriveMacroCall { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_cannot_derive_union)] +#[diag("this trait cannot be derived for unions")] pub(crate) struct DeriveUnion { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_env_takes_args)] +#[diag("`env!()` takes 1 or 2 arguments")] pub(crate) struct EnvTakesArgs { #[primary_span] pub(crate) span: Span, @@ -511,24 +543,26 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for EnvNotDefinedWithUserMessag #[derive(Diagnostic)] pub(crate) enum EnvNotDefined<'a> { - #[diag(builtin_macros_env_not_defined)] - #[help(builtin_macros_cargo)] + #[diag("environment variable `{$var}` not defined at compile time")] + #[help( + "Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead" + )] CargoEnvVar { #[primary_span] span: Span, var: Symbol, var_expr: &'a rustc_ast::Expr, }, - #[diag(builtin_macros_env_not_defined)] - #[help(builtin_macros_cargo_typo)] + #[diag("environment variable `{$var}` not defined at compile time")] + #[help("there is a similar Cargo environment variable: `{$suggested_var}`")] CargoEnvVarTypo { #[primary_span] span: Span, var: Symbol, suggested_var: Symbol, }, - #[diag(builtin_macros_env_not_defined)] - #[help(builtin_macros_custom)] + #[diag("environment variable `{$var}` not defined at compile time")] + #[help("use `std::env::var({$var_expr})` to read the variable at run time")] CustomEnvVar { #[primary_span] span: Span, @@ -538,7 +572,7 @@ pub(crate) enum EnvNotDefined<'a> { } #[derive(Diagnostic)] -#[diag(builtin_macros_env_not_unicode)] +#[diag("environment variable `{$var}` is not a valid Unicode string")] pub(crate) struct EnvNotUnicode { #[primary_span] pub(crate) span: Span, @@ -546,39 +580,39 @@ pub(crate) struct EnvNotUnicode { } #[derive(Diagnostic)] -#[diag(builtin_macros_format_requires_string)] +#[diag("requires at least a format string argument")] pub(crate) struct FormatRequiresString { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_format_duplicate_arg)] +#[diag("duplicate argument named `{$ident}`")] pub(crate) struct FormatDuplicateArg { #[primary_span] pub(crate) span: Span, - #[label(builtin_macros_label1)] + #[label("previously here")] pub(crate) prev: Span, - #[label(builtin_macros_label2)] + #[label("duplicate argument")] pub(crate) duplicate: Span, pub(crate) ident: Ident, } #[derive(Diagnostic)] -#[diag(builtin_macros_format_positional_after_named)] +#[diag("positional arguments cannot follow named arguments")] pub(crate) struct PositionalAfterNamed { #[primary_span] - #[label] + #[label("positional arguments must be before named arguments")] pub(crate) span: Span, - #[label(builtin_macros_named_args)] + #[label("named argument")] pub(crate) args: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_format_string_invalid)] +#[diag("invalid format string: {$desc}")] pub(crate) struct InvalidFormatString { #[primary_span] - #[label] + #[label("{$label1} in format string")] pub(crate) span: Span, pub(crate) desc: String, pub(crate) label1: String, @@ -591,13 +625,13 @@ pub(crate) struct InvalidFormatString { } #[derive(Subdiagnostic)] -#[note(builtin_macros_note)] +#[note("{$note}")] pub(crate) struct InvalidFormatStringNote { pub(crate) note: String, } #[derive(Subdiagnostic)] -#[label(builtin_macros_second_label)] +#[label("{$label}")] pub(crate) struct InvalidFormatStringLabel { #[primary_span] pub(crate) span: Span, @@ -607,7 +641,7 @@ pub(crate) struct InvalidFormatStringLabel { #[derive(Subdiagnostic)] pub(crate) enum InvalidFormatStringSuggestion { #[multipart_suggestion( - builtin_macros_format_use_positional, + "consider using a positional formatting argument instead", style = "verbose", applicability = "machine-applicable" )] @@ -619,17 +653,13 @@ pub(crate) enum InvalidFormatStringSuggestion { span: Span, arg: String, }, - #[suggestion( - builtin_macros_format_remove_raw_ident, - code = "", - applicability = "machine-applicable" - )] + #[suggestion("remove the `r#`", code = "", applicability = "machine-applicable")] RemoveRawIdent { #[primary_span] span: Span, }, #[suggestion( - builtin_macros_format_reorder_format_parameter, + "did you mean `{$replacement}`?", code = "{replacement}", style = "verbose", applicability = "machine-applicable" @@ -640,7 +670,7 @@ pub(crate) enum InvalidFormatStringSuggestion { replacement: String, }, #[suggestion( - builtin_macros_format_add_missing_colon, + "add a colon before the format specifier", code = ":?", applicability = "machine-applicable" )] @@ -651,9 +681,11 @@ pub(crate) enum InvalidFormatStringSuggestion { } #[derive(Diagnostic)] -#[diag(builtin_macros_format_no_arg_named)] -#[note] -#[note(builtin_macros_note2)] +#[diag("there is no argument named `{$name}`")] +#[note("did you intend to capture a variable `{$name}` from the surrounding scope?")] +#[note( + "to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro" +)] pub(crate) struct FormatNoArgNamed { #[primary_span] pub(crate) span: Span, @@ -661,8 +693,19 @@ pub(crate) struct FormatNoArgNamed { } #[derive(Diagnostic)] -#[diag(builtin_macros_format_unknown_trait)] -#[note] +#[diag("unknown format trait `{$ty}`")] +#[note( + "the only appropriate formatting traits are: + - ``, which uses the `Display` trait + - `?`, which uses the `Debug` trait + - `e`, which uses the `LowerExp` trait + - `E`, which uses the `UpperExp` trait + - `o`, which uses the `Octal` trait + - `p`, which uses the `Pointer` trait + - `b`, which uses the `Binary` trait + - `x`, which uses the `LowerHex` trait + - `X`, which uses the `UpperHex` trait" +)] pub(crate) struct FormatUnknownTrait<'a> { #[primary_span] pub(crate) span: Span, @@ -673,7 +716,7 @@ pub(crate) struct FormatUnknownTrait<'a> { #[derive(Subdiagnostic)] #[suggestion( - builtin_macros_suggestion, + "use the `{$trait_name}` trait", code = "{fmt}", style = "tool-only", applicability = "maybe-incorrect" @@ -686,10 +729,20 @@ pub(crate) struct FormatUnknownTraitSugg { } #[derive(Diagnostic)] -#[diag(builtin_macros_format_unused_arg)] +#[diag( + "{$named -> + [true] named argument + *[false] argument + } never used" +)] pub(crate) struct FormatUnusedArg { #[primary_span] - #[label(builtin_macros_format_unused_arg)] + #[label( + "{$named -> + [true] named argument + *[false] argument + } never used" + )] pub(crate) span: Span, pub(crate) named: bool, } @@ -699,25 +752,35 @@ pub(crate) struct FormatUnusedArg { impl Subdiagnostic for FormatUnusedArg { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("named", self.named); - let msg = diag.eagerly_translate(crate::fluent_generated::builtin_macros_format_unused_arg); + let msg = diag.eagerly_translate(inline_fluent!( + "{$named -> + [true] named argument + *[false] argument + } never used" + )); diag.remove_arg("named"); diag.span_label(self.span, msg); } } #[derive(Diagnostic)] -#[diag(builtin_macros_format_unused_args)] +#[diag("multiple unused formatting arguments")] pub(crate) struct FormatUnusedArgs { #[primary_span] pub(crate) unused: Vec, - #[label] + #[label("multiple missing formatting specifiers")] pub(crate) fmt: Span, #[subdiagnostic] pub(crate) unused_labels: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_format_pos_mismatch)] +#[diag( + "{$n} positional {$n -> + [one] argument + *[more] arguments + } in format string, but {$desc}" +)] pub(crate) struct FormatPositionalMismatch { #[primary_span] pub(crate) span: MultiSpan, @@ -728,13 +791,23 @@ pub(crate) struct FormatPositionalMismatch { } #[derive(Diagnostic)] -#[diag(builtin_macros_format_redundant_args)] +#[diag( + "redundant {$n -> + [one] argument + *[more] arguments + }" +)] pub(crate) struct FormatRedundantArgs { #[primary_span] pub(crate) span: MultiSpan, pub(crate) n: usize, - #[note] + #[note( + "{$n -> + [one] the formatting specifier is referencing the binding already + *[more] the formatting specifiers are referencing the bindings already + }" + )] pub(crate) note: MultiSpan, #[subdiagnostic] @@ -742,38 +815,38 @@ pub(crate) struct FormatRedundantArgs { } #[derive(Subdiagnostic)] -#[multipart_suggestion(builtin_macros_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion("this can be removed", applicability = "machine-applicable")] pub(crate) struct FormatRedundantArgsSugg { #[suggestion_part(code = "")] pub(crate) spans: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_test_case_non_item)] +#[diag("`#[test_case]` attribute is only allowed on items")] pub(crate) struct TestCaseNonItem { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_test_bad_fn)] +#[diag("{$kind} functions cannot be used for tests")] pub(crate) struct TestBadFn { #[primary_span] pub(crate) span: Span, - #[label] + #[label("`{$kind}` because of this")] pub(crate) cause: Span, pub(crate) kind: &'static str, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_explicit_register_name)] +#[diag("explicit register arguments cannot have names")] pub(crate) struct AsmExplicitRegisterName { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_mutually_exclusive)] +#[diag("the `{$opt1}` and `{$opt2}` options are mutually exclusive")] pub(crate) struct AsmMutuallyExclusive { #[primary_span] pub(crate) spans: Vec, @@ -782,65 +855,65 @@ pub(crate) struct AsmMutuallyExclusive { } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_pure_combine)] +#[diag("the `pure` option must be combined with either `nomem` or `readonly`")] pub(crate) struct AsmPureCombine { #[primary_span] pub(crate) spans: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_pure_no_output)] +#[diag("asm with the `pure` option must have at least one output")] pub(crate) struct AsmPureNoOutput { #[primary_span] pub(crate) spans: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_modifier_invalid)] +#[diag("asm template modifier must be a single character")] pub(crate) struct AsmModifierInvalid { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_attribute_not_supported)] +#[diag("this attribute is not supported on assembly")] pub(crate) struct AsmAttributeNotSupported { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_duplicate_arg)] +#[diag("duplicate argument named `{$name}`")] pub(crate) struct AsmDuplicateArg { #[primary_span] - #[label(builtin_macros_arg)] + #[label("duplicate argument")] pub(crate) span: Span, - #[label] + #[label("previously here")] pub(crate) prev: Span, pub(crate) name: Symbol, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_pos_after)] +#[diag("positional arguments cannot follow named arguments or explicit register arguments")] pub(crate) struct AsmPositionalAfter { #[primary_span] - #[label(builtin_macros_pos)] + #[label("positional argument")] pub(crate) span: Span, - #[label(builtin_macros_named)] + #[label("named argument")] pub(crate) named: Vec, - #[label(builtin_macros_explicit)] + #[label("explicit register argument")] pub(crate) explicit: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_noreturn)] +#[diag("asm outputs are not allowed with the `noreturn` option")] pub(crate) struct AsmNoReturn { #[primary_span] pub(crate) outputs_sp: Vec, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_no_matched_argument_name)] +#[diag("there is no argument named `{$name}`")] pub(crate) struct AsmNoMatchedArgumentName { pub(crate) name: String, #[primary_span] @@ -848,7 +921,7 @@ pub(crate) struct AsmNoMatchedArgumentName { } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_mayunwind)] +#[diag("asm labels are not allowed with the `may_unwind` option")] pub(crate) struct AsmMayUnwind { #[primary_span] pub(crate) labels_sp: Vec, @@ -862,46 +935,55 @@ pub(crate) struct AsmClobberNoReg { impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AsmClobberNoReg { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { // eager translation as `span_labels` takes `AsRef` - let lbl1 = dcx.eagerly_translate_to_string( - crate::fluent_generated::builtin_macros_asm_clobber_abi, - [].into_iter(), - ); - let lbl2 = dcx.eagerly_translate_to_string( - crate::fluent_generated::builtin_macros_asm_clobber_outputs, - [].into_iter(), - ); - Diag::new(dcx, level, crate::fluent_generated::builtin_macros_asm_clobber_no_reg) - .with_span(self.spans.clone()) - .with_span_labels(self.clobbers, &lbl1) - .with_span_labels(self.spans, &lbl2) + let lbl1 = dcx.eagerly_translate_to_string(inline_fluent!("clobber_abi"), [].into_iter()); + let lbl2 = + dcx.eagerly_translate_to_string(inline_fluent!("generic outputs"), [].into_iter()); + Diag::new( + dcx, + level, + inline_fluent!("asm with `clobber_abi` must specify explicit registers for outputs"), + ) + .with_span(self.spans.clone()) + .with_span_labels(self.clobbers, &lbl1) + .with_span_labels(self.spans, &lbl2) } } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_opt_already_provided)] +#[diag("the `{$symbol}` option was already provided")] pub(crate) struct AsmOptAlreadyprovided { #[primary_span] - #[label] + #[label("this option was already provided")] pub(crate) span: Span, pub(crate) symbol: Symbol, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove this option", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub(crate) span_with_comma: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_unsupported_option)] +#[diag("the `{$symbol}` option cannot be used with `{$macro_name}!`")] pub(crate) struct AsmUnsupportedOption { #[primary_span] - #[label] + #[label("the `{$symbol}` option is not meaningful for global-scoped inline assembly")] pub(crate) span: Span, pub(crate) symbol: Symbol, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove this option", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub(crate) span_with_comma: Span, pub(crate) macro_name: &'static str, } #[derive(Diagnostic)] -#[diag(builtin_macros_asm_unsupported_clobber_abi)] +#[diag("`clobber_abi` cannot be used with `{$macro_name}!`")] pub(crate) struct AsmUnsupportedClobberAbi { #[primary_span] pub(crate) spans: Vec, @@ -909,28 +991,28 @@ pub(crate) struct AsmUnsupportedClobberAbi { } #[derive(Diagnostic)] -#[diag(builtin_macros_test_runner_invalid)] +#[diag("`test_runner` argument must be a path")] pub(crate) struct TestRunnerInvalid { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_test_runner_nargs)] +#[diag("`#![test_runner(..)]` accepts exactly 1 argument")] pub(crate) struct TestRunnerNargs { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_expected_comma_in_list)] +#[diag("expected token: `,`")] pub(crate) struct ExpectedCommaInList { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_only_one_argument)] +#[diag("{$name} takes 1 argument")] pub(crate) struct OnlyOneArgument<'a> { #[primary_span] pub span: Span, @@ -938,7 +1020,7 @@ pub(crate) struct OnlyOneArgument<'a> { } #[derive(Diagnostic)] -#[diag(builtin_macros_takes_no_arguments)] +#[diag("{$name} takes no arguments")] pub(crate) struct TakesNoArguments<'a> { #[primary_span] pub span: Span, @@ -946,7 +1028,7 @@ pub(crate) struct TakesNoArguments<'a> { } #[derive(Diagnostic)] -#[diag(builtin_macros_proc_macro_attribute_only_usable_with_crate_type)] +#[diag("the `#[{$path}]` attribute is only usable with crates of the `proc-macro` crate type")] pub(crate) struct AttributeOnlyUsableWithCrateType<'a> { #[primary_span] pub span: Span, @@ -954,7 +1036,7 @@ pub(crate) struct AttributeOnlyUsableWithCrateType<'a> { } #[derive(Diagnostic)] -#[diag(builtin_macros_source_utils_expected_item)] +#[diag("expected item, found `{$token}`")] pub(crate) struct ExpectedItem<'a> { #[primary_span] pub span: Span, @@ -962,73 +1044,83 @@ pub(crate) struct ExpectedItem<'a> { } #[derive(Diagnostic)] -#[diag(builtin_macros_naked_functions_testing_attribute, code = E0736)] +#[diag("cannot use `#[unsafe(naked)]` with testing attributes", code = E0736)] pub(crate) struct NakedFunctionTestingAttribute { #[primary_span] - #[label(builtin_macros_naked_attribute)] + #[label("`#[unsafe(naked)]` is incompatible with testing attributes")] pub naked_span: Span, - #[label] + #[label("function marked with testing attribute here")] pub testing_span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_non_generic_pointee)] +#[diag("the `#[pointee]` attribute may only be used on generic parameters")] pub(crate) struct NonGenericPointee { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_expected_other)] +#[diag( + "expected operand, {$is_inline_asm -> + [false] options + *[true] clobber_abi, options + }, or additional template string" +)] pub(crate) struct AsmExpectedOther { #[primary_span] - #[label(builtin_macros_expected_other)] + #[label( + "expected operand, {$is_inline_asm -> + [false] options + *[true] clobber_abi, options + }, or additional template string" + )] pub(crate) span: Span, pub(crate) is_inline_asm: bool, } #[derive(Diagnostic)] -#[diag(builtin_macros_cfg_select_no_matches)] +#[diag("none of the predicates in this `cfg_select` evaluated to true")] pub(crate) struct CfgSelectNoMatches { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_cfg_select_unreachable)] +#[diag("unreachable predicate")] pub(crate) struct CfgSelectUnreachable { #[primary_span] - #[label(builtin_macros_label2)] + #[label("this predicate is never reached")] pub span: Span, - #[label] + #[label("always matches")] pub wildcard_span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_eii_declaration_expected_macro)] +#[diag("`#[eii_declaration(...)]` is only valid on macros")] pub(crate) struct EiiExternTargetExpectedMacro { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_eii_declaration_expected_list)] +#[diag("`#[eii_declaration(...)]` expects a list of one or two elements")] pub(crate) struct EiiExternTargetExpectedList { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_eii_declaration_expected_unsafe)] +#[diag("expected this argument to be \"unsafe\"")] pub(crate) struct EiiExternTargetExpectedUnsafe { #[primary_span] - #[note] + #[note("the second argument is optional")] pub span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_eii_shared_macro_expected_function)] +#[diag("`#[{$name}]` is only valid on functions")] pub(crate) struct EiiSharedMacroExpectedFunction { #[primary_span] pub span: Span, @@ -1036,27 +1128,27 @@ pub(crate) struct EiiSharedMacroExpectedFunction { } #[derive(Diagnostic)] -#[diag(builtin_macros_eii_shared_macro_in_statement_position)] +#[diag("`#[{$name}]` can only be used on functions inside a module")] pub(crate) struct EiiSharedMacroInStatementPosition { #[primary_span] pub span: Span, pub name: String, - #[label] + #[label("`#[{$name}]` is used on this item, which is part of another item's local scope")] pub item_span: Span, } #[derive(Diagnostic)] -#[diag(builtin_macros_eii_only_once)] +#[diag("`#[{$name}]` can only be specified once")] pub(crate) struct EiiOnlyOnce { #[primary_span] pub span: Span, - #[note] + #[note("specified again here")] pub first_span: Span, pub name: String, } #[derive(Diagnostic)] -#[diag(builtin_macros_eii_shared_macro_expected_max_one_argument)] +#[diag("`#[{$name}]` expected no arguments or a single argument: `#[{$name}(default)]`")] pub(crate) struct EiiMacroExpectedMaxOneArgument { #[primary_span] pub span: Span, diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 120e3f849ff6..8ac15ceb4bbe 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -57,8 +57,6 @@ pub mod standard_library_imports; pub mod test_harness; pub mod util; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { let mut register = |name, kind| resolver.register_builtin_macro(name, kind); macro register_bang($($name:ident: $f:expr,)*) { diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index c24a4ca53219..e7b266552f4f 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -12,7 +12,6 @@ rustc_ast = { path = "../rustc_ast" } rustc_ast_passes = { path = "../rustc_ast_passes" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_borrowck = { path = "../rustc_borrowck" } -rustc_builtin_macros = { path = "../rustc_builtin_macros" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_const_eval = { path = "../rustc_const_eval" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 02298dbf8267..9dbdfb141fc1 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -116,7 +116,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ // tidy-alphabetical-start rustc_ast_passes::DEFAULT_LOCALE_RESOURCE, rustc_borrowck::DEFAULT_LOCALE_RESOURCE, - rustc_builtin_macros::DEFAULT_LOCALE_RESOURCE, rustc_const_eval::DEFAULT_LOCALE_RESOURCE, rustc_errors::DEFAULT_LOCALE_RESOURCE, rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE, From 46753b1b4330683096345638011077f117f80099 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 4 Feb 2026 17:48:13 +0100 Subject: [PATCH 565/978] Convert to inline diagnostics in `rustc_middle` --- Cargo.lock | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_middle/Cargo.toml | 1 - compiler/rustc_middle/messages.ftl | 133 ------------------ compiler/rustc_middle/src/error.rs | 66 +++++---- compiler/rustc_middle/src/lib.rs | 2 - compiler/rustc_middle/src/middle/stability.rs | 19 ++- compiler/rustc_middle/src/mir/terminator.rs | 55 +++++--- compiler/rustc_middle/src/ty/layout.rs | 28 ++-- 9 files changed, 103 insertions(+), 203 deletions(-) delete mode 100644 compiler/rustc_middle/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 9c98946c9d39..a87921056331 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4262,7 +4262,6 @@ dependencies = [ "rustc_error_messages", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_graphviz", "rustc_hashes", "rustc_hir", diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 02298dbf8267..d15121614693 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -121,7 +121,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_errors::DEFAULT_LOCALE_RESOURCE, rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE, rustc_lint::DEFAULT_LOCALE_RESOURCE, - rustc_middle::DEFAULT_LOCALE_RESOURCE, rustc_mir_build::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE, rustc_passes::DEFAULT_LOCALE_RESOURCE, diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index fbcce16cedca..f9d5e7c02789 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -18,7 +18,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_error_messages = { path = "../rustc_error_messages" } # Used for intra-doc links rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_graphviz = { path = "../rustc_graphviz" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl deleted file mode 100644 index b46f43841c8e..000000000000 --- a/compiler/rustc_middle/messages.ftl +++ /dev/null @@ -1,133 +0,0 @@ -middle_assert_async_resume_after_drop = `async fn` resumed after async drop - -middle_assert_async_resume_after_panic = `async fn` resumed after panicking - -middle_assert_async_resume_after_return = `async fn` resumed after completion - -middle_assert_coroutine_resume_after_drop = coroutine resumed after async drop - -middle_assert_coroutine_resume_after_panic = coroutine resumed after panicking - -middle_assert_coroutine_resume_after_return = coroutine resumed after completion - -middle_assert_divide_by_zero = - attempt to divide `{$val}` by zero - -middle_assert_gen_resume_after_drop = `gen` fn or block cannot be further iterated on after it async dropped - -middle_assert_gen_resume_after_panic = `gen` fn or block cannot be further iterated on after it panicked - -middle_assert_invalid_enum_construction = - trying to construct an enum from an invalid value `{$source}` - -middle_assert_misaligned_ptr_deref = - misaligned pointer dereference: address must be a multiple of {$required} but is {$found} - -middle_assert_null_ptr_deref = - null pointer dereference occurred - -middle_assert_op_overflow = - attempt to compute `{$left} {$op} {$right}`, which would overflow - -middle_assert_overflow_neg = - attempt to negate `{$val}`, which would overflow - -middle_assert_remainder_by_zero = - attempt to calculate the remainder of `{$val}` with a divisor of zero - -middle_assert_shl_overflow = - attempt to shift left by `{$val}`, which would overflow - -middle_assert_shr_overflow = - attempt to shift right by `{$val}`, which would overflow - -middle_autodiff_unsafe_inner_const_ref = reading from a `Duplicated` const {$ty} is unsafe - -middle_bounds_check = - index out of bounds: the length is {$len} but the index is {$index} - -middle_conflict_types = - this expression supplies two conflicting concrete types for the same opaque type - -middle_consider_type_length_limit = - consider adding a `#![type_length_limit="{$type_length}"]` attribute to your crate - -middle_const_eval_non_int = - constant evaluation of enum discriminant resulted in non-integer - -middle_const_not_used_in_type_alias = - const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias - -middle_deprecated = use of deprecated {$kind} `{$path}`{$has_note -> - [true] : {$note} - *[other] {""} - } -middle_deprecated_in_future = use of {$kind} `{$path}` that will be deprecated in a future Rust version{$has_note -> - [true] : {$note} - *[other] {""} - } -middle_deprecated_in_version = use of {$kind} `{$path}` that will be deprecated in future version {$version}{$has_note -> - [true] : {$note} - *[other] {""} - } -middle_deprecated_suggestion = replace the use of the deprecated {$kind} - -middle_drop_check_overflow = - overflow while adding drop-check rules for `{$ty}` - .note = overflowed on `{$overflow_ty}` - -middle_erroneous_constant = erroneous constant encountered - -middle_failed_writing_file = - failed to write file {$path}: {$error}" - -# Note: We only mention patterns here since the error can only occur with references, and those -# are forbidden in const generics. -middle_invalid_const_in_valtree = constant {$global_const_id} cannot be used as pattern - .note = constants that reference mutable or external memory cannot be used as patterns - -middle_layout_cycle = - a cycle occurred during layout computation - -middle_layout_normalization_failure = - unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized - -middle_layout_references_error = - the type has an unknown layout - -middle_layout_simd_too_many = - the SIMD type `{$ty}` has more elements than the limit {$max_lanes} - -middle_layout_simd_zero_length = - the SIMD type `{$ty}` has zero elements - -middle_layout_size_overflow = - values of the type `{$ty}` are too big for the target architecture - -middle_layout_too_generic = the type `{$ty}` does not have a fixed layout - -middle_layout_unknown = - the type `{$ty}` has an unknown layout - -middle_max_num_nodes_in_valtree = maximum number of nodes exceeded in constant {$global_const_id} - -middle_opaque_hidden_type_mismatch = - concrete type differs from previous defining opaque type use - .label = expected `{$self_ty}`, got `{$other_ty}` - -middle_previous_use_here = - previous use here - -middle_recursion_limit_reached = - reached the recursion limit finding the struct tail for `{$ty}` - .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` - -middle_requires_lang_item = requires `{$name}` lang_item - -middle_strict_coherence_needs_negative_coherence = - to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled - .label = due to this attribute - -middle_type_length_limit = reached the type-length limit while instantiating `{$instance}` - -middle_unsupported_union = we don't support unions yet: '{$ty_name}' diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 3ff9eea8cc4b..a5d5978916eb 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -9,8 +9,8 @@ use rustc_span::{Span, Symbol}; use crate::ty::{Instance, Ty}; #[derive(Diagnostic)] -#[diag(middle_drop_check_overflow, code = E0320)] -#[note] +#[diag("overflow while adding drop-check rules for `{$ty}`", code = E0320)] +#[note("overflowed on `{$overflow_ty}`")] pub(crate) struct DropCheckOverflow<'tcx> { #[primary_span] pub span: Span, @@ -19,33 +19,33 @@ pub(crate) struct DropCheckOverflow<'tcx> { } #[derive(Diagnostic)] -#[diag(middle_failed_writing_file)] +#[diag("failed to write file {$path}: {$error}\"")] pub(crate) struct FailedWritingFile<'a> { pub path: &'a Path, pub error: io::Error, } #[derive(Diagnostic)] -#[diag(middle_opaque_hidden_type_mismatch)] +#[diag("concrete type differs from previous defining opaque type use")] pub(crate) struct OpaqueHiddenTypeMismatch<'tcx> { pub self_ty: Ty<'tcx>, pub other_ty: Ty<'tcx>, #[primary_span] - #[label] + #[label("expected `{$self_ty}`, got `{$other_ty}`")] pub other_span: Span, #[subdiagnostic] pub sub: TypeMismatchReason, } #[derive(Diagnostic)] -#[diag(middle_unsupported_union)] +#[diag("we don't support unions yet: '{$ty_name}'")] pub struct UnsupportedUnion { pub ty_name: String, } // FIXME(autodiff): I should get used somewhere #[derive(Diagnostic)] -#[diag(middle_autodiff_unsafe_inner_const_ref)] +#[diag("reading from a `Duplicated` const {$ty} is unsafe")] pub struct AutodiffUnsafeInnerConstRef<'tcx> { #[primary_span] pub span: Span, @@ -54,12 +54,12 @@ pub struct AutodiffUnsafeInnerConstRef<'tcx> { #[derive(Subdiagnostic)] pub enum TypeMismatchReason { - #[label(middle_conflict_types)] + #[label("this expression supplies two conflicting concrete types for the same opaque type")] ConflictType { #[primary_span] span: Span, }, - #[note(middle_previous_use_here)] + #[note("previous use here")] PreviousUse { #[primary_span] span: Span, @@ -67,8 +67,10 @@ pub enum TypeMismatchReason { } #[derive(Diagnostic)] -#[diag(middle_recursion_limit_reached)] -#[help] +#[diag("reached the recursion limit finding the struct tail for `{$ty}`")] +#[help( + "consider increasing the recursion limit by adding a `#![recursion_limit = \"{$suggested_limit}\"]`" +)] pub(crate) struct RecursionLimitReached<'tcx> { #[primary_span] pub span: Span, @@ -77,23 +79,25 @@ pub(crate) struct RecursionLimitReached<'tcx> { } #[derive(Diagnostic)] -#[diag(middle_const_eval_non_int)] +#[diag("constant evaluation of enum discriminant resulted in non-integer")] pub(crate) struct ConstEvalNonIntError { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(middle_strict_coherence_needs_negative_coherence)] +#[diag( + "to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled" +)] pub(crate) struct StrictCoherenceNeedsNegativeCoherence { #[primary_span] pub span: Span, - #[label] + #[label("due to this attribute")] pub attr_span: Option, } #[derive(Diagnostic)] -#[diag(middle_requires_lang_item)] +#[diag("requires `{$name}` lang_item")] pub(crate) struct RequiresLangItem { #[primary_span] pub span: Span, @@ -101,7 +105,9 @@ pub(crate) struct RequiresLangItem { } #[derive(Diagnostic)] -#[diag(middle_const_not_used_in_type_alias)] +#[diag( + "const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias" +)] pub(super) struct ConstNotUsedTraitAlias { pub ct: String, #[primary_span] @@ -133,41 +139,41 @@ impl fmt::Debug for CustomSubdiagnostic<'_> { #[derive(Diagnostic)] pub enum LayoutError<'tcx> { - #[diag(middle_layout_unknown)] + #[diag("the type `{$ty}` has an unknown layout")] Unknown { ty: Ty<'tcx> }, - #[diag(middle_layout_too_generic)] + #[diag("the type `{$ty}` does not have a fixed layout")] TooGeneric { ty: Ty<'tcx> }, - #[diag(middle_layout_size_overflow)] + #[diag("values of the type `{$ty}` are too big for the target architecture")] Overflow { ty: Ty<'tcx> }, - #[diag(middle_layout_simd_too_many)] + #[diag("the SIMD type `{$ty}` has more elements than the limit {$max_lanes}")] SimdTooManyLanes { ty: Ty<'tcx>, max_lanes: u64 }, - #[diag(middle_layout_simd_zero_length)] + #[diag("the SIMD type `{$ty}` has zero elements")] SimdZeroLength { ty: Ty<'tcx> }, - #[diag(middle_layout_normalization_failure)] + #[diag("unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized")] NormalizationFailure { ty: Ty<'tcx>, failure_ty: String }, - #[diag(middle_layout_cycle)] + #[diag("a cycle occurred during layout computation")] Cycle, - #[diag(middle_layout_references_error)] + #[diag("the type has an unknown layout")] ReferencesError, } #[derive(Diagnostic)] -#[diag(middle_erroneous_constant)] +#[diag("erroneous constant encountered")] pub(crate) struct ErroneousConstant { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(middle_type_length_limit)] -#[help(middle_consider_type_length_limit)] +#[diag("reached the type-length limit while instantiating `{$instance}`")] +#[help("consider adding a `#![type_length_limit=\"{$type_length}\"]` attribute to your crate")] pub(crate) struct TypeLengthLimit<'tcx> { #[primary_span] pub span: Span, @@ -176,7 +182,7 @@ pub(crate) struct TypeLengthLimit<'tcx> { } #[derive(Diagnostic)] -#[diag(middle_max_num_nodes_in_valtree)] +#[diag("maximum number of nodes exceeded in constant {$global_const_id}")] pub(crate) struct MaxNumNodesInValtree { #[primary_span] pub span: Span, @@ -184,8 +190,8 @@ pub(crate) struct MaxNumNodesInValtree { } #[derive(Diagnostic)] -#[diag(middle_invalid_const_in_valtree)] -#[note] +#[diag("constant {$global_const_id} cannot be used as pattern")] +#[note("constants that reference mutable or external memory cannot be used as patterns")] pub(crate) struct InvalidConstInValtree { #[primary_span] pub span: Span, diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 7d1b775cc4bc..5b32d4551a16 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -91,5 +91,3 @@ pub mod dep_graph; // Allows macros to refer to this crate as `::rustc_middle` extern crate self as rustc_middle; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index fe2d4b9130ed..fce0158aa511 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -4,7 +4,7 @@ use std::num::NonZero; use rustc_ast::NodeId; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, LintBuffer}; +use rustc_errors::{Applicability, Diag, EmissionGuarantee, LintBuffer, inline_fluent}; use rustc_feature::GateIssue; use rustc_hir::attrs::{DeprecatedSince, Deprecation}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -103,7 +103,7 @@ fn deprecation_lint(is_in_effect: bool) -> &'static Lint { #[derive(Subdiagnostic)] #[suggestion( - middle_deprecated_suggestion, + "replace the use of the deprecated {$kind}", code = "{suggestion}", style = "verbose", applicability = "machine-applicable" @@ -128,10 +128,19 @@ pub struct Deprecated { impl<'a, G: EmissionGuarantee> rustc_errors::LintDiagnostic<'a, G> for Deprecated { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) { diag.primary_message(match &self.since_kind { - DeprecatedSinceKind::InEffect => crate::fluent_generated::middle_deprecated, - DeprecatedSinceKind::InFuture => crate::fluent_generated::middle_deprecated_in_future, + DeprecatedSinceKind::InEffect => inline_fluent!("use of deprecated {$kind} `{$path}`{$has_note -> + [true] : {$note} + *[other] {\"\"} + }"), + DeprecatedSinceKind::InFuture => inline_fluent!("use of {$kind} `{$path}` that will be deprecated in a future Rust version{$has_note -> + [true] : {$note} + *[other] {\"\"} + }"), DeprecatedSinceKind::InVersion(_) => { - crate::fluent_generated::middle_deprecated_in_version + inline_fluent!("use of {$kind} `{$path}` that will be deprecated in future version {$version}{$has_note -> + [true] : {$note} + *[other] {\"\"} + }") } }); diag.arg("kind", self.kind); diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index cd447d4ed992..e212dd43fa7d 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -336,18 +336,26 @@ impl AssertKind { pub fn diagnostic_message(&self) -> DiagMessage { use AssertKind::*; - use crate::fluent_generated::*; - match self { - BoundsCheck { .. } => middle_bounds_check, - Overflow(BinOp::Shl, _, _) => middle_assert_shl_overflow, - Overflow(BinOp::Shr, _, _) => middle_assert_shr_overflow, - Overflow(_, _, _) => middle_assert_op_overflow, - OverflowNeg(_) => middle_assert_overflow_neg, - DivisionByZero(_) => middle_assert_divide_by_zero, - RemainderByZero(_) => middle_assert_remainder_by_zero, + BoundsCheck { .. } => inline_fluent!( + "index out of bounds: the length is {$len} but the index is {$index}" + ), + Overflow(BinOp::Shl, _, _) => { + inline_fluent!("attempt to shift left by `{$val}`, which would overflow") + } + Overflow(BinOp::Shr, _, _) => { + inline_fluent!("attempt to shift right by `{$val}`, which would overflow") + } + Overflow(_, _, _) => { + inline_fluent!("attempt to compute `{$left} {$op} {$right}`, which would overflow") + } + OverflowNeg(_) => inline_fluent!("attempt to negate `{$val}`, which would overflow"), + DivisionByZero(_) => inline_fluent!("attempt to divide `{$val}` by zero"), + RemainderByZero(_) => inline_fluent!( + "attempt to calculate the remainder of `{$val}` with a divisor of zero" + ), ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { - middle_assert_async_resume_after_return + inline_fluent!("`async fn` resumed after completion") } ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { todo!() @@ -356,36 +364,42 @@ impl AssertKind { bug!("gen blocks can be resumed after they return and will keep returning `None`") } ResumedAfterReturn(CoroutineKind::Coroutine(_)) => { - middle_assert_coroutine_resume_after_return + inline_fluent!("coroutine resumed after completion") } ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { - middle_assert_async_resume_after_panic + inline_fluent!("`async fn` resumed after panicking") } ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { todo!() } ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => { - middle_assert_gen_resume_after_panic + inline_fluent!("`gen` fn or block cannot be further iterated on after it panicked") } ResumedAfterPanic(CoroutineKind::Coroutine(_)) => { - middle_assert_coroutine_resume_after_panic + inline_fluent!("coroutine resumed after panicking") + } + NullPointerDereference => inline_fluent!("null pointer dereference occurred"), + InvalidEnumConstruction(_) => { + inline_fluent!("trying to construct an enum from an invalid value `{$source}`") } - NullPointerDereference => middle_assert_null_ptr_deref, - InvalidEnumConstruction(_) => middle_assert_invalid_enum_construction, ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { - middle_assert_async_resume_after_drop + inline_fluent!("`async fn` resumed after async drop") } ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { todo!() } ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => { - middle_assert_gen_resume_after_drop + inline_fluent!( + "`gen` fn or block cannot be further iterated on after it async dropped" + ) } ResumedAfterDrop(CoroutineKind::Coroutine(_)) => { - middle_assert_coroutine_resume_after_drop + inline_fluent!("coroutine resumed after async drop") } - MisalignedPointerDereference { .. } => middle_assert_misaligned_ptr_deref, + MisalignedPointerDereference { .. } => inline_fluent!( + "misaligned pointer dereference: address must be a multiple of {$required} but is {$found}" + ), } } @@ -498,6 +512,7 @@ impl<'tcx> TerminatorKind<'tcx> { } pub use helper::*; +use rustc_errors::inline_fluent; mod helper { use super::*; diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 14ebcc968f7a..d3b4654a8d79 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -9,6 +9,7 @@ use rustc_abi::{ use rustc_error_messages::DiagMessage; use rustc_errors::{ Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, + inline_fluent, }; use rustc_hir::LangItem; use rustc_hir::def_id::DefId; @@ -268,18 +269,25 @@ impl<'tcx> LayoutError<'tcx> { pub fn diagnostic_message(&self) -> DiagMessage { use LayoutError::*; - use crate::fluent_generated::*; match self { - Unknown(_) => middle_layout_unknown, - SizeOverflow(_) => middle_layout_size_overflow, - InvalidSimd { kind: SimdLayoutError::TooManyLanes(_), .. } => { - middle_layout_simd_too_many + Unknown(_) => inline_fluent!("the type `{$ty}` has an unknown layout"), + SizeOverflow(_) => { + inline_fluent!("values of the type `{$ty}` are too big for the target architecture") } - InvalidSimd { kind: SimdLayoutError::ZeroLength, .. } => middle_layout_simd_zero_length, - TooGeneric(_) => middle_layout_too_generic, - NormalizationFailure(_, _) => middle_layout_normalization_failure, - Cycle(_) => middle_layout_cycle, - ReferencesError(_) => middle_layout_references_error, + InvalidSimd { kind: SimdLayoutError::TooManyLanes(_), .. } => { + inline_fluent!( + "the SIMD type `{$ty}` has more elements than the limit {$max_lanes}" + ) + } + InvalidSimd { kind: SimdLayoutError::ZeroLength, .. } => { + inline_fluent!("the SIMD type `{$ty}` has zero elements") + } + TooGeneric(_) => inline_fluent!("the type `{$ty}` does not have a fixed layout"), + NormalizationFailure(_, _) => inline_fluent!( + "unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized" + ), + Cycle(_) => inline_fluent!("a cycle occurred during layout computation"), + ReferencesError(_) => inline_fluent!("the type has an unknown layout"), } } From 0da9476010e9ee65777638928bd38820c6d7dfc2 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 4 Feb 2026 15:53:02 +0100 Subject: [PATCH 566/978] Convert to inline diagnostics in `rustc_ast_passes` --- Cargo.lock | 2 - compiler/rustc_ast_passes/Cargo.toml | 1 - compiler/rustc_ast_passes/messages.ftl | 342 ----------- compiler/rustc_ast_passes/src/errors.rs | 531 +++++++++++------- compiler/rustc_ast_passes/src/feature_gate.rs | 3 +- compiler/rustc_ast_passes/src/lib.rs | 2 - compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - 8 files changed, 329 insertions(+), 554 deletions(-) delete mode 100644 compiler/rustc_ast_passes/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 9c98946c9d39..6103e787f107 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3514,7 +3514,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_macros", "rustc_session", "rustc_span", @@ -3772,7 +3771,6 @@ dependencies = [ "libc", "rustc_abi", "rustc_ast", - "rustc_ast_passes", "rustc_ast_pretty", "rustc_borrowck", "rustc_builtin_macros", diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index 3e04f8b11ec9..fdc735fa8d4f 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -13,7 +13,6 @@ rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_macros = { path = "../rustc_macros" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl deleted file mode 100644 index b9117c83ae2f..000000000000 --- a/compiler/rustc_ast_passes/messages.ftl +++ /dev/null @@ -1,342 +0,0 @@ -ast_passes_abi_cannot_be_coroutine = - functions with the {$abi} ABI cannot be `{$coroutine_kind_str}` - .suggestion = remove the `{$coroutine_kind_str}` keyword from this definition - -ast_passes_abi_custom_safe_foreign_function = - foreign functions with the "custom" ABI cannot be safe - .suggestion = remove the `safe` keyword from this definition - -ast_passes_abi_custom_safe_function = - functions with the "custom" ABI must be unsafe - .suggestion = add the `unsafe` keyword to this definition - -ast_passes_abi_must_not_have_parameters_or_return_type= - invalid signature for `extern {$abi}` function - .note = functions with the {$abi} ABI cannot have any parameters or return type - .suggestion = remove the parameters and return type - -ast_passes_abi_must_not_have_return_type= - invalid signature for `extern {$abi}` function - .note = functions with the {$abi} ABI cannot have a return type - .help = remove the return type - -ast_passes_abi_x86_interrupt = - invalid signature for `extern "x86-interrupt"` function - .note = functions with the "x86-interrupt" ABI must be have either 1 or 2 parameters (but found {$param_count}) - -ast_passes_assoc_const_without_body = - associated constant in `impl` without body - .suggestion = provide a definition for the constant - -ast_passes_assoc_fn_without_body = - associated function in `impl` without body - .suggestion = provide a definition for the function - -ast_passes_assoc_type_without_body = - associated type in `impl` without body - .suggestion = provide a definition for the type - -ast_passes_async_fn_in_const_trait_or_trait_impl = - async functions are not allowed in `const` {$context -> - [trait_impl] trait impls - [impl] impls - *[trait] traits - } - .label = associated functions of `const` cannot be declared `async` - -ast_passes_at_least_one_trait = at least one trait must be specified - -ast_passes_auto_generic = auto traits cannot have generic parameters - .label = auto trait cannot have generic parameters - .suggestion = remove the parameters - -ast_passes_auto_items = auto traits cannot have associated items - .label = {ast_passes_auto_items} - .suggestion = remove the associated items - -ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetime bounds - .label = {ast_passes_auto_super_lifetime} - .suggestion = remove the super traits or lifetime bounds - -ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block - .cannot_have = cannot have a body - .invalid = the invalid body - .existing = `extern` blocks define existing foreign {$kind}s and {$kind}s inside of them cannot have a body - -ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect - -ast_passes_c_variadic_bad_extern = `...` is not supported for `extern "{$abi}"` functions - .label = `extern "{$abi}"` because of this - .help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list - -ast_passes_c_variadic_bad_naked_extern = `...` is not supported for `extern "{$abi}"` naked functions - .label = `extern "{$abi}"` because of this - .help = C-variadic function must have a compatible calling convention - -ast_passes_c_variadic_must_be_unsafe = - functions with a C variable argument list must be unsafe - .suggestion = add the `unsafe` keyword to this definition - -ast_passes_c_variadic_no_extern = `...` is not supported for non-extern functions - .help = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list - -ast_passes_c_variadic_not_supported = the `{$target}` target does not support c-variadic functions - -ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic - .const = `const` because of this - .variadic = C-variadic because of this - -ast_passes_const_and_coroutine = functions cannot be both `const` and `{$coroutine_kind}` - .const = `const` because of this - .coroutine = `{$coroutine_kind}` because of this - .label = {""} - -ast_passes_const_auto_trait = auto traits cannot be const - .help = remove the `const` keyword - -ast_passes_const_bound_trait_object = const trait bounds are not allowed in trait object types - -ast_passes_const_without_body = - free constant item without body - .suggestion = provide a definition for the constant - -ast_passes_constraint_on_negative_bound = - associated type constraints not allowed on negative bounds - -ast_passes_coroutine_and_c_variadic = functions cannot be both `{$coroutine_kind}` and C-variadic - .const = `{$coroutine_kind}` because of this - .variadic = C-variadic because of this - -ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses - .label = not supported - .suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax - .suggestion_path = if `{$trait_segment}::{$potential_assoc}` is an associated type you're trying to set, use the associated type binding syntax - .note = see issue #20041 for more information - -ast_passes_extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block - -ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have `{$kw}` qualifier - .label = in this `extern` block - .suggestion = remove the `{$kw}` qualifier - -ast_passes_extern_invalid_safety = items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers - .suggestion = add `unsafe` to this `extern` block - -ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers - .label = in this `extern` block - .note = this limitation may be lifted in the future; see issue #83942 for more information - -ast_passes_extern_keyword_link = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html - -ast_passes_extern_types_cannot = `type`s inside `extern` blocks cannot have {$descr} - .suggestion = remove the {$remove_descr} - .label = `extern` block begins here - -ast_passes_extern_without_abi = `extern` declarations without an explicit ABI are disallowed - .suggestion = specify an ABI - .help = prior to Rust 2024, a default ABI was inferred - -ast_passes_extern_without_abi_sugg = `extern` declarations without an explicit ABI are deprecated - .label = ABI should be specified here - .suggestion = explicitly specify the {$default_abi} ABI - -ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$channel} release channel - .suggestion = remove the attribute - .stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable - -ast_passes_fieldless_union = unions cannot have zero fields - -ast_passes_fn_body_extern = incorrect function inside `extern` block - .cannot_have = cannot have a body - .suggestion = remove the invalid body - .help = you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block - .label = `extern` blocks define existing foreign functions and functions inside of them cannot have a body - -ast_passes_fn_param_c_var_args_not_last = - `...` must be the last argument of a C-variadic function - -ast_passes_fn_param_doc_comment = - documentation comments cannot be applied to function parameters - .label = doc comments are not allowed here - -ast_passes_fn_param_forbidden_attr = - allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - -ast_passes_fn_param_forbidden_self = - `self` parameter is only allowed in associated functions - .label = not semantically valid as function parameter - .note = associated functions are those in `impl` or `trait` definitions - -ast_passes_fn_param_too_many = - function can not have more than {$max_num_args} arguments - -ast_passes_fn_ptr_invalid_safety = function pointers cannot be declared with `safe` safety qualifier - .suggestion = remove safe from this item - -ast_passes_fn_without_body = - free function without a body - .suggestion = provide a definition for the function - -ast_passes_forbidden_bound = - bounds cannot be used in this context - -ast_passes_forbidden_const_param = - late-bound const parameters cannot be used currently - -ast_passes_forbidden_default = - `default` is only allowed on items in trait impls - .label = `default` because of this - -ast_passes_forbidden_non_lifetime_param = - only lifetime parameters can be used in this context - -ast_passes_generic_before_constraints = generic arguments must come before the first constraint - .constraints = {$constraint_len -> - [one] constraint - *[other] constraints - } - .args = generic {$args_len -> - [one] argument - *[other] arguments - } - .empty_string = {""}, - .suggestion = move the {$constraint_len -> - [one] constraint - *[other] constraints - } after the generic {$args_len -> - [one] argument - *[other] arguments - } - -ast_passes_generic_default_trailing = generic parameters with a default must be trailing - -ast_passes_impl_fn_const = - redundant `const` fn marker in const impl - .parent_constness = this declares all associated functions implicitly const - .label = remove the `const` - -ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed - .help = remove one of these features - -ast_passes_item_invalid_safety = items outside of `unsafe extern {"{ }"}` cannot be declared with `safe` safety qualifier - .suggestion = remove safe from this item - -ast_passes_item_underscore = `{$kind}` items in this context need a name - .label = `_` is not a valid name for this `{$kind}` item - -ast_passes_match_arm_with_no_body = - `match` arm with no body - .suggestion = add a body after the pattern - -ast_passes_missing_unsafe_on_extern = extern blocks must be unsafe - .suggestion = needs `unsafe` before the extern keyword - -ast_passes_missing_unsafe_on_extern_lint = extern blocks should be unsafe - .suggestion = needs `unsafe` before the extern keyword - -ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name - .help = consider using the `#[path]` attribute to specify filesystem path - -ast_passes_negative_bound_not_supported = - negative bounds are not supported - -ast_passes_negative_bound_with_parenthetical_notation = - parenthetical notation may not be used for negative bounds - -ast_passes_nested_impl_trait = nested `impl Trait` is not allowed - .outer = outer `impl Trait` - .inner = nested `impl Trait` here - -ast_passes_nested_lifetimes = nested quantification of lifetimes - -ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier - -ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax - .help = use `auto trait Trait {"{}"}` instead - -ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters - .suggestion = reorder the parameters: lifetimes, then consts and types - -ast_passes_pattern_in_bodiless = patterns aren't allowed in functions without bodies - .label = pattern not allowed in function without body - -ast_passes_pattern_in_fn_pointer = patterns aren't allowed in function pointer types - -ast_passes_pattern_in_foreign = patterns aren't allowed in foreign function declarations - .label = pattern not allowed in foreign function - -ast_passes_precise_capturing_duplicated = duplicate `use<...>` precise capturing syntax - .label = second `use<...>` here - -ast_passes_precise_capturing_not_allowed_here = `use<...>` precise capturing syntax not allowed in {$loc} - -ast_passes_scalable_vector_not_tuple_struct = scalable vectors must be tuple structs - -ast_passes_static_without_body = - free static item without body - .suggestion = provide a definition for the static - -ast_passes_tilde_const_disallowed = `[const]` is not allowed here - .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 `const`, so it cannot have `[const]` trait bounds - .trait_impl = this impl is not `const`, so it cannot have `[const]` trait bounds - .impl = inherent impls cannot have `[const]` trait bounds - .trait_assoc_ty = associated types in non-`const` traits cannot have `[const]` trait bounds - .trait_impl_assoc_ty = associated types in non-const impls cannot have `[const]` trait bounds - .inherent_assoc_ty = inherent associated types cannot have `[const]` trait bounds - .struct = structs cannot have `[const]` trait bounds - .enum = enums cannot have `[const]` trait bounds - .union = unions cannot have `[const]` trait bounds - .anon_const = anonymous constants 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 {$in_impl -> - [true] trait impls - *[false] traits - } cannot be declared const - .label = functions in {$in_impl -> - [true] trait impls - *[false] traits - } cannot be const - .const_context_label = this declares all associated functions implicitly const - .remove_const_sugg = remove the `const`{$requires_multiple_changes -> - [true] {" ..."} - *[false] {""} - } - .make_impl_const_sugg = ... and declare the impl to be const instead - .make_trait_const_sugg = ... and declare the trait to be const instead - -ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted - -ast_passes_ty_alias_without_body = - free type alias without body - .suggestion = provide a definition for the type - -ast_passes_unsafe_item = {$kind} cannot be declared unsafe - -ast_passes_unsafe_negative_impl = negative impls cannot be unsafe - .negative = negative because of this - .unsafe = unsafe because of this - -ast_passes_unsafe_static = - static items cannot be declared with `unsafe` safety qualifier outside of `extern` block - -ast_passes_visibility_not_permitted = - visibility qualifiers are not permitted here - .enum_variant = enum variants and their fields always share the visibility of the enum they are in - .trait_impl = trait items always share the visibility of their trait - .individual_impl_items = place qualifiers on individual impl items instead - .individual_foreign_items = place qualifiers on individual foreign items instead - .remove_qualifier_sugg = remove the qualifier - -ast_passes_where_clause_after_type_alias = where clauses are not allowed after the type for type aliases - .note = see issue #112792 for more information - .help = add `#![feature(lazy_type_alias)]` to the crate attributes to enable - -ast_passes_where_clause_before_type_alias = where clauses are not allowed before the type for type aliases - .note = see issue #89122 for more information - .remove_suggestion = remove this `where` - .move_suggestion = move it to the end of the type declaration diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 22adaae8c6f2..baf6f6beaeed 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -3,68 +3,76 @@ use rustc_abi::ExternAbi; use rustc_ast::ParamKindOrd; use rustc_errors::codes::*; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic}; +use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic, inline_fluent}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; -use crate::fluent_generated as fluent; - #[derive(Diagnostic)] -#[diag(ast_passes_visibility_not_permitted, code = E0449)] +#[diag("visibility qualifiers are not permitted here", code = E0449)] pub(crate) struct VisibilityNotPermitted { #[primary_span] pub span: Span, #[subdiagnostic] pub note: VisibilityNotPermittedNote, - #[suggestion( - ast_passes_remove_qualifier_sugg, - code = "", - applicability = "machine-applicable" - )] + #[suggestion("remove the qualifier", code = "", applicability = "machine-applicable")] pub remove_qualifier_sugg: Span, } #[derive(Subdiagnostic)] pub(crate) enum VisibilityNotPermittedNote { - #[note(ast_passes_enum_variant)] + #[note("enum variants and their fields always share the visibility of the enum they are in")] EnumVariant, - #[note(ast_passes_trait_impl)] + #[note("trait items always share the visibility of their trait")] TraitImpl, - #[note(ast_passes_individual_impl_items)] + #[note("place qualifiers on individual impl items instead")] IndividualImplItems, - #[note(ast_passes_individual_foreign_items)] + #[note("place qualifiers on individual foreign items instead")] IndividualForeignItems, } #[derive(Diagnostic)] -#[diag(ast_passes_impl_fn_const)] +#[diag("redundant `const` fn marker in const impl")] pub(crate) struct ImplFnConst { #[primary_span] - #[suggestion(ast_passes_label, code = "", applicability = "machine-applicable")] + #[suggestion("remove the `const`", code = "", applicability = "machine-applicable")] pub span: Span, - #[label(ast_passes_parent_constness)] + #[label("this declares all associated functions implicitly const")] pub parent_constness: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_trait_fn_const, code = E0379)] +#[diag("functions in {$in_impl -> + [true] trait impls + *[false] traits + } cannot be declared const", code = E0379)] pub(crate) struct TraitFnConst { #[primary_span] - #[label] + #[label( + "functions in {$in_impl -> + [true] trait impls + *[false] traits + } cannot be const" + )] pub span: Span, pub in_impl: bool, - #[label(ast_passes_const_context_label)] + #[label("this declares all associated functions implicitly const")] pub const_context_label: Option, - #[suggestion(ast_passes_remove_const_sugg, code = "")] + #[suggestion( + "remove the `const`{$requires_multiple_changes -> + [true] {\" ...\"} + *[false] {\"\"} + }", + code = "" + )] pub remove_const_sugg: (Span, Applicability), pub requires_multiple_changes: bool, #[suggestion( - ast_passes_make_impl_const_sugg, + "... and declare the impl to be const instead", code = "const ", applicability = "maybe-incorrect" )] pub make_impl_const_sugg: Option, #[suggestion( - ast_passes_make_trait_const_sugg, + "... and declare the trait to be const instead", code = "const ", applicability = "maybe-incorrect" )] @@ -72,31 +80,37 @@ pub(crate) struct TraitFnConst { } #[derive(Diagnostic)] -#[diag(ast_passes_async_fn_in_const_trait_or_trait_impl)] +#[diag( + "async functions are not allowed in `const` {$context -> + [trait_impl] trait impls + [impl] impls + *[trait] traits + }" +)] pub(crate) struct AsyncFnInConstTraitOrTraitImpl { #[primary_span] pub async_keyword: Span, pub context: &'static str, - #[label] + #[label("associated functions of `const` cannot be declared `async`")] pub const_keyword: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_forbidden_bound)] +#[diag("bounds cannot be used in this context")] pub(crate) struct ForbiddenBound { #[primary_span] pub spans: Vec, } #[derive(Diagnostic)] -#[diag(ast_passes_forbidden_const_param)] +#[diag("late-bound const parameters cannot be used currently")] pub(crate) struct ForbiddenConstParam { #[primary_span] pub const_param_spans: Vec, } #[derive(Diagnostic)] -#[diag(ast_passes_fn_param_too_many)] +#[diag("function can not have more than {$max_num_args} arguments")] pub(crate) struct FnParamTooMany { #[primary_span] pub span: Span, @@ -104,105 +118,135 @@ pub(crate) struct FnParamTooMany { } #[derive(Diagnostic)] -#[diag(ast_passes_fn_param_c_var_args_not_last)] +#[diag("`...` must be the last argument of a C-variadic function")] pub(crate) struct FnParamCVarArgsNotLast { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_fn_param_doc_comment)] +#[diag("documentation comments cannot be applied to function parameters")] pub(crate) struct FnParamDocComment { #[primary_span] - #[label] + #[label("doc comments are not allowed here")] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_fn_param_forbidden_attr)] +#[diag( + "allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters" +)] pub(crate) struct FnParamForbiddenAttr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_fn_param_forbidden_self)] -#[note] +#[diag("`self` parameter is only allowed in associated functions")] +#[note("associated functions are those in `impl` or `trait` definitions")] pub(crate) struct FnParamForbiddenSelf { #[primary_span] - #[label] + #[label("not semantically valid as function parameter")] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_forbidden_default)] +#[diag("`default` is only allowed on items in trait impls")] pub(crate) struct ForbiddenDefault { #[primary_span] pub span: Span, - #[label] + #[label("`default` because of this")] pub def_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_assoc_const_without_body)] +#[diag("associated constant in `impl` without body")] pub(crate) struct AssocConstWithoutBody { #[primary_span] pub span: Span, - #[suggestion(code = " = ;", applicability = "has-placeholders")] + #[suggestion( + "provide a definition for the constant", + code = " = ;", + applicability = "has-placeholders" + )] pub replace_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_assoc_fn_without_body)] +#[diag("associated function in `impl` without body")] pub(crate) struct AssocFnWithoutBody { #[primary_span] pub span: Span, - #[suggestion(code = " {{ }}", applicability = "has-placeholders")] + #[suggestion( + "provide a definition for the function", + code = " {{ }}", + applicability = "has-placeholders" + )] pub replace_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_assoc_type_without_body)] +#[diag("associated type in `impl` without body")] pub(crate) struct AssocTypeWithoutBody { #[primary_span] pub span: Span, - #[suggestion(code = " = ;", applicability = "has-placeholders")] + #[suggestion( + "provide a definition for the type", + code = " = ;", + applicability = "has-placeholders" + )] pub replace_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_const_without_body)] +#[diag("free constant item without body")] pub(crate) struct ConstWithoutBody { #[primary_span] pub span: Span, - #[suggestion(code = " = ;", applicability = "has-placeholders")] + #[suggestion( + "provide a definition for the constant", + code = " = ;", + applicability = "has-placeholders" + )] pub replace_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_static_without_body)] +#[diag("free static item without body")] pub(crate) struct StaticWithoutBody { #[primary_span] pub span: Span, - #[suggestion(code = " = ;", applicability = "has-placeholders")] + #[suggestion( + "provide a definition for the static", + code = " = ;", + applicability = "has-placeholders" + )] pub replace_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_ty_alias_without_body)] +#[diag("free type alias without body")] pub(crate) struct TyAliasWithoutBody { #[primary_span] pub span: Span, - #[suggestion(code = " = ;", applicability = "has-placeholders")] + #[suggestion( + "provide a definition for the type", + code = " = ;", + applicability = "has-placeholders" + )] pub replace_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_fn_without_body)] +#[diag("free function without a body")] pub(crate) struct FnWithoutBody { #[primary_span] pub span: Span, - #[suggestion(code = " {{ }}", applicability = "has-placeholders")] + #[suggestion( + "provide a definition for the function", + code = " {{ }}", + applicability = "has-placeholders" + )] pub replace_span: Span, #[subdiagnostic] pub extern_block_suggestion: Option, @@ -210,14 +254,20 @@ pub(crate) struct FnWithoutBody { #[derive(Subdiagnostic)] pub(crate) enum ExternBlockSuggestion { - #[multipart_suggestion(ast_passes_extern_block_suggestion, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "if you meant to declare an externally defined function, use an `extern` block", + applicability = "maybe-incorrect" + )] Implicit { #[suggestion_part(code = "extern {{")] start_span: Span, #[suggestion_part(code = " }}")] end_span: Span, }, - #[multipart_suggestion(ast_passes_extern_block_suggestion, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "if you meant to declare an externally defined function, use an `extern` block", + applicability = "maybe-incorrect" + )] Explicit { #[suggestion_part(code = "extern \"{abi}\" {{")] start_span: Span, @@ -228,37 +278,44 @@ pub(crate) enum ExternBlockSuggestion { } #[derive(Diagnostic)] -#[diag(ast_passes_extern_invalid_safety)] +#[diag("items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers")] pub(crate) struct InvalidSafetyOnExtern { #[primary_span] pub item_span: Span, - #[suggestion(code = "unsafe ", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "add `unsafe` to this `extern` block", + code = "unsafe ", + applicability = "machine-applicable", + style = "verbose" + )] pub block: Option, } #[derive(Diagnostic)] -#[diag(ast_passes_item_invalid_safety)] +#[diag( + "items outside of `unsafe extern {\"{ }\"}` cannot be declared with `safe` safety qualifier" +)] pub(crate) struct InvalidSafetyOnItem { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_fn_ptr_invalid_safety)] +#[diag("function pointers cannot be declared with `safe` safety qualifier")] pub(crate) struct InvalidSafetyOnFnPtr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_unsafe_static)] +#[diag("static items cannot be declared with `unsafe` safety qualifier outside of `extern` block")] pub(crate) struct UnsafeStatic { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_bound_in_context)] +#[diag("bounds on `type`s in {$ctx} have no effect")] pub(crate) struct BoundInContext<'a> { #[primary_span] pub span: Span, @@ -266,83 +323,93 @@ pub(crate) struct BoundInContext<'a> { } #[derive(Diagnostic)] -#[diag(ast_passes_extern_types_cannot)] -#[note(ast_passes_extern_keyword_link)] +#[diag("`type`s inside `extern` blocks cannot have {$descr}")] +#[note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html")] pub(crate) struct ExternTypesCannotHave<'a> { #[primary_span] - #[suggestion(code = "", applicability = "maybe-incorrect")] + #[suggestion("remove the {$remove_descr}", code = "", applicability = "maybe-incorrect")] pub span: Span, pub descr: &'a str, pub remove_descr: &'a str, - #[label] + #[label("`extern` block begins here")] pub block_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_body_in_extern)] -#[note(ast_passes_extern_keyword_link)] +#[diag("incorrect `{$kind}` inside `extern` block")] +#[note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html")] pub(crate) struct BodyInExtern<'a> { #[primary_span] - #[label(ast_passes_cannot_have)] + #[label("cannot have a body")] pub span: Span, - #[label(ast_passes_invalid)] + #[label("the invalid body")] pub body: Span, - #[label(ast_passes_existing)] + #[label( + "`extern` blocks define existing foreign {$kind}s and {$kind}s inside of them cannot have a body" + )] pub block: Span, pub kind: &'a str, } #[derive(Diagnostic)] -#[diag(ast_passes_fn_body_extern)] -#[help] -#[note(ast_passes_extern_keyword_link)] +#[diag("incorrect function inside `extern` block")] +#[help( + "you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block" +)] +#[note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html")] pub(crate) struct FnBodyInExtern { #[primary_span] - #[label(ast_passes_cannot_have)] + #[label("cannot have a body")] pub span: Span, - #[suggestion(code = ";", applicability = "maybe-incorrect")] + #[suggestion("remove the invalid body", code = ";", applicability = "maybe-incorrect")] pub body: Span, - #[label] + #[label( + "`extern` blocks define existing foreign functions and functions inside of them cannot have a body" + )] pub block: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_extern_fn_qualifiers)] +#[diag("functions in `extern` blocks cannot have `{$kw}` qualifier")] pub(crate) struct FnQualifierInExtern { #[primary_span] - #[suggestion(code = "", applicability = "maybe-incorrect")] + #[suggestion("remove the `{$kw}` qualifier", code = "", applicability = "maybe-incorrect")] pub span: Span, - #[label] + #[label("in this `extern` block")] pub block: Span, pub kw: &'static str, } #[derive(Diagnostic)] -#[diag(ast_passes_extern_item_ascii)] -#[note] +#[diag("items in `extern` blocks cannot use non-ascii identifiers")] +#[note( + "this limitation may be lifted in the future; see issue #83942 for more information" +)] pub(crate) struct ExternItemAscii { #[primary_span] pub span: Span, - #[label] + #[label("in this `extern` block")] pub block: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_c_variadic_no_extern)] -#[help] +#[diag("`...` is not supported for non-extern functions")] +#[help( + "only `extern \"C\"` and `extern \"C-unwind\"` functions may have a C variable argument list" +)] pub(crate) struct CVariadicNoExtern { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_c_variadic_must_be_unsafe)] +#[diag("functions with a C variable argument list must be unsafe")] pub(crate) struct CVariadicMustBeUnsafe { #[primary_span] pub span: Span, #[suggestion( - ast_passes_suggestion, + "add the `unsafe` keyword to this definition", applicability = "maybe-incorrect", code = "unsafe ", style = "verbose" @@ -351,46 +418,48 @@ pub(crate) struct CVariadicMustBeUnsafe { } #[derive(Diagnostic)] -#[diag(ast_passes_c_variadic_bad_extern)] -#[help] +#[diag("`...` is not supported for `extern \"{$abi}\"` functions")] +#[help( + "only `extern \"C\"` and `extern \"C-unwind\"` functions may have a C variable argument list" +)] pub(crate) struct CVariadicBadExtern { #[primary_span] pub span: Span, pub abi: &'static str, - #[label] + #[label("`extern \"{$abi}\"` because of this")] pub extern_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_c_variadic_bad_naked_extern)] -#[help] +#[diag("`...` is not supported for `extern \"{$abi}\"` naked functions")] +#[help("C-variadic function must have a compatible calling convention")] pub(crate) struct CVariadicBadNakedExtern { #[primary_span] pub span: Span, pub abi: &'static str, - #[label] + #[label("`extern \"{$abi}\"` because of this")] pub extern_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_item_underscore)] +#[diag("`{$kind}` items in this context need a name")] pub(crate) struct ItemUnderscore<'a> { #[primary_span] - #[label] + #[label("`_` is not a valid name for this `{$kind}` item")] pub span: Span, pub kind: &'a str, } #[derive(Diagnostic)] -#[diag(ast_passes_nomangle_ascii, code = E0754)] +#[diag("`#[no_mangle]` requires ASCII identifier", code = E0754)] pub(crate) struct NoMangleAscii { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_module_nonascii, code = E0754)] -#[help] +#[diag("trying to load file for module `{$name}` with non-ascii identifier name", code = E0754)] +#[help("consider using the `#[path]` attribute to specify filesystem path")] pub(crate) struct ModuleNonAscii { #[primary_span] pub span: Span, @@ -398,55 +467,91 @@ pub(crate) struct ModuleNonAscii { } #[derive(Diagnostic)] -#[diag(ast_passes_auto_generic, code = E0567)] +#[diag("auto traits cannot have generic parameters", code = E0567)] pub(crate) struct AutoTraitGeneric { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove the parameters", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub span: Span, - #[label] + #[label("auto trait cannot have generic parameters")] pub ident: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_auto_super_lifetime, code = E0568)] +#[diag("auto traits cannot have super traits or lifetime bounds", code = E0568)] pub(crate) struct AutoTraitBounds { #[primary_span] pub span: Vec, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove the super traits or lifetime bounds", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub removal: Span, - #[label] + #[label("auto traits cannot have super traits or lifetime bounds")] pub ident: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_auto_items, code = E0380)] +#[diag("auto traits cannot have associated items", code = E0380)] pub(crate) struct AutoTraitItems { #[primary_span] pub spans: Vec, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove the super traits or lifetime bounds", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub total: Span, - #[label] + #[label("auto traits cannot have associated items")] pub ident: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_const_auto_trait)] -#[help] +#[diag("auto traits cannot be const")] +#[help("remove the `const` keyword")] pub(crate) struct ConstAutoTrait { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_generic_before_constraints)] +#[diag("generic arguments must come before the first constraint")] pub(crate) struct ArgsBeforeConstraint { #[primary_span] pub arg_spans: Vec, - #[label(ast_passes_constraints)] + #[label( + "{$constraint_len -> + [one] constraint + *[other] constraints + }" + )] pub constraints: Span, - #[label(ast_passes_args)] + #[label( + "generic {$args_len -> + [one] argument + *[other] arguments + }" + )] pub args: Span, - #[suggestion(code = "{suggestion}", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "move the {$constraint_len -> + [one] constraint + *[other] constraints + } after the generic {$args_len -> + [one] argument + *[other] arguments + }", + code = "{suggestion}", + applicability = "machine-applicable", + style = "verbose" + )] pub data: Span, pub suggestion: String, pub constraint_len: usize, @@ -467,43 +572,47 @@ impl Subdiagnostic for EmptyLabelManySpans { } #[derive(Diagnostic)] -#[diag(ast_passes_pattern_in_fn_pointer, code = E0561)] +#[diag("patterns aren't allowed in function pointer types", code = E0561)] pub(crate) struct PatternFnPointer { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_trait_object_single_bound, code = E0226)] +#[diag("only a single explicit lifetime bound is permitted", code = E0226)] pub(crate) struct TraitObjectBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_nested_impl_trait, code = E0666)] +#[diag("nested `impl Trait` is not allowed", code = E0666)] pub(crate) struct NestedImplTrait { #[primary_span] pub span: Span, - #[label(ast_passes_outer)] + #[label("outer `impl Trait`")] pub outer: Span, - #[label(ast_passes_inner)] + #[label("nested `impl Trait` here")] pub inner: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_at_least_one_trait)] +#[diag("at least one trait must be specified")] pub(crate) struct AtLeastOneTrait { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_out_of_order_params)] +#[diag("{$param_ord} parameters must be declared prior to {$max_param} parameters")] pub(crate) struct OutOfOrderParams<'a> { #[primary_span] pub spans: Vec, - #[suggestion(code = "{ordered_params}", applicability = "machine-applicable")] + #[suggestion( + "reorder the parameters: lifetimes, then consts and types", + code = "{ordered_params}", + applicability = "machine-applicable" + )] pub sugg_span: Span, pub param_ord: &'a ParamKindOrd, pub max_param: &'a ParamKindOrd, @@ -511,26 +620,26 @@ pub(crate) struct OutOfOrderParams<'a> { } #[derive(Diagnostic)] -#[diag(ast_passes_obsolete_auto)] -#[help] +#[diag("`impl Trait for .. {\"{}\"}` is an obsolete syntax")] +#[help("use `auto trait Trait {\"{}\"}` instead")] pub(crate) struct ObsoleteAuto { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_unsafe_negative_impl, code = E0198)] +#[diag("negative impls cannot be unsafe", code = E0198)] pub(crate) struct UnsafeNegativeImpl { #[primary_span] pub span: Span, - #[label(ast_passes_negative)] + #[label("negative because of this")] pub negative: Span, - #[label(ast_passes_unsafe)] + #[label("unsafe because of this")] pub r#unsafe: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_unsafe_item)] +#[diag("{$kind} cannot be declared unsafe")] pub(crate) struct UnsafeItem { #[primary_span] pub span: Span, @@ -538,39 +647,43 @@ pub(crate) struct UnsafeItem { } #[derive(Diagnostic)] -#[diag(ast_passes_missing_unsafe_on_extern)] +#[diag("extern blocks must be unsafe")] pub(crate) struct MissingUnsafeOnExtern { #[primary_span] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(ast_passes_missing_unsafe_on_extern_lint)] +#[diag("extern blocks should be unsafe")] pub(crate) struct MissingUnsafeOnExternLint { - #[suggestion(code = "unsafe ", applicability = "machine-applicable")] + #[suggestion( + "needs `unsafe` before the extern keyword", + code = "unsafe ", + applicability = "machine-applicable" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_fieldless_union)] +#[diag("unions cannot have zero fields")] pub(crate) struct FieldlessUnion { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_where_clause_after_type_alias)] -#[note] +#[diag("where clauses are not allowed after the type for type aliases")] +#[note("see issue #112792 for more information")] pub(crate) struct WhereClauseAfterTypeAlias { #[primary_span] pub span: Span, - #[help] + #[help("add `#![feature(lazy_type_alias)]` to the crate attributes to enable")] pub help: bool, } #[derive(Diagnostic)] -#[diag(ast_passes_where_clause_before_type_alias)] -#[note] +#[diag("where clauses are not allowed before the type for type aliases")] +#[note("see issue #89122 for more information")] pub(crate) struct WhereClauseBeforeTypeAlias { #[primary_span] pub span: Span, @@ -580,13 +693,13 @@ pub(crate) struct WhereClauseBeforeTypeAlias { #[derive(Subdiagnostic)] pub(crate) enum WhereClauseBeforeTypeAliasSugg { - #[suggestion(ast_passes_remove_suggestion, applicability = "machine-applicable", code = "")] + #[suggestion("remove this `where`", applicability = "machine-applicable", code = "")] Remove { #[primary_span] span: Span, }, #[multipart_suggestion( - ast_passes_move_suggestion, + "move it to the end of the type declaration", applicability = "machine-applicable", style = "verbose" )] @@ -600,21 +713,21 @@ pub(crate) enum WhereClauseBeforeTypeAliasSugg { } #[derive(Diagnostic)] -#[diag(ast_passes_generic_default_trailing)] +#[diag("generic parameters with a default must be trailing")] pub(crate) struct GenericDefaultTrailing { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_nested_lifetimes, code = E0316)] +#[diag("nested quantification of lifetimes", code = E0316)] pub(crate) struct NestedLifetimes { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_const_bound_trait_object)] +#[diag("const trait bounds are not allowed in trait object types")] pub(crate) struct ConstBoundTraitObject { #[primary_span] pub span: Span, @@ -623,7 +736,7 @@ pub(crate) struct ConstBoundTraitObject { // FIXME(const_trait_impl): Consider making the note/reason the message of the diagnostic. // FIXME(const_trait_impl): Provide structured suggestions (e.g., add `const` here). #[derive(Diagnostic)] -#[diag(ast_passes_tilde_const_disallowed)] +#[diag("`[const]` is not allowed here")] pub(crate) struct TildeConstDisallowed { #[primary_span] pub span: Span, @@ -633,108 +746,108 @@ pub(crate) struct TildeConstDisallowed { #[derive(Subdiagnostic, Copy, Clone)] pub(crate) enum TildeConstReason { - #[note(ast_passes_closure)] + #[note("closures cannot have `[const]` trait bounds")] Closure, - #[note(ast_passes_function)] + #[note("this function is not `const`, so it cannot have `[const]` trait bounds")] Function { #[primary_span] ident: Span, }, - #[note(ast_passes_trait)] + #[note("this trait is not `const`, so it cannot have `[const]` trait bounds")] Trait { #[primary_span] span: Span, }, - #[note(ast_passes_trait_impl)] + #[note("this impl is not `const`, so it cannot have `[const]` trait bounds")] TraitImpl { #[primary_span] span: Span, }, - #[note(ast_passes_impl)] + #[note("inherent impls cannot have `[const]` trait bounds")] Impl { #[primary_span] span: Span, }, - #[note(ast_passes_trait_assoc_ty)] + #[note("associated types in non-`const` traits cannot have `[const]` trait bounds")] TraitAssocTy { #[primary_span] span: Span, }, - #[note(ast_passes_trait_impl_assoc_ty)] + #[note("associated types in non-const impls cannot have `[const]` trait bounds")] TraitImplAssocTy { #[primary_span] span: Span, }, - #[note(ast_passes_inherent_assoc_ty)] + #[note("inherent associated types cannot have `[const]` trait bounds")] InherentAssocTy { #[primary_span] span: Span, }, - #[note(ast_passes_struct)] + #[note("structs cannot have `[const]` trait bounds")] Struct { #[primary_span] span: Span, }, - #[note(ast_passes_enum)] + #[note("enums cannot have `[const]` trait bounds")] Enum { #[primary_span] span: Span, }, - #[note(ast_passes_union)] + #[note("unions cannot have `[const]` trait bounds")] Union { #[primary_span] span: Span, }, - #[note(ast_passes_anon_const)] + #[note("anonymous constants cannot have `[const]` trait bounds")] AnonConst { #[primary_span] span: Span, }, - #[note(ast_passes_object)] + #[note("trait objects cannot have `[const]` trait bounds")] TraitObject, - #[note(ast_passes_item)] + #[note("this item cannot have `[const]` trait bounds")] Item, } #[derive(Diagnostic)] -#[diag(ast_passes_const_and_coroutine)] +#[diag("functions cannot be both `const` and `{$coroutine_kind}`")] pub(crate) struct ConstAndCoroutine { #[primary_span] pub spans: Vec, - #[label(ast_passes_const)] + #[label("`const` because of this")] pub const_span: Span, - #[label(ast_passes_coroutine)] + #[label("`{$coroutine_kind}` because of this")] pub coroutine_span: Span, - #[label] + #[label("{\"\"}")] pub span: Span, pub coroutine_kind: &'static str, } #[derive(Diagnostic)] -#[diag(ast_passes_const_and_c_variadic)] +#[diag("functions cannot be both `const` and C-variadic")] pub(crate) struct ConstAndCVariadic { #[primary_span] pub spans: Vec, - #[label(ast_passes_const)] + #[label("`const` because of this")] pub const_span: Span, - #[label(ast_passes_variadic)] + #[label("C-variadic because of this")] pub variadic_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_coroutine_and_c_variadic)] +#[diag("functions cannot be both `{$coroutine_kind}` and C-variadic")] pub(crate) struct CoroutineAndCVariadic { #[primary_span] pub spans: Vec, pub coroutine_kind: &'static str, - #[label(ast_passes_const)] + #[label("`{$coroutine_kind}` because of this")] pub coroutine_span: Span, - #[label(ast_passes_variadic)] + #[label("C-variadic because of this")] pub variadic_span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_c_variadic_not_supported)] +#[diag("the `{$target}` target does not support c-variadic functions")] pub(crate) struct CVariadicNotSupported<'a> { #[primary_span] pub variadic_span: Span, @@ -742,29 +855,29 @@ pub(crate) struct CVariadicNotSupported<'a> { } #[derive(Diagnostic)] -#[diag(ast_passes_pattern_in_foreign, code = E0130)] +#[diag("patterns aren't allowed in foreign function declarations", code = E0130)] // FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`) pub(crate) struct PatternInForeign { #[primary_span] - #[label] + #[label("pattern not allowed in foreign function")] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_pattern_in_bodiless, code = E0642)] +#[diag("patterns aren't allowed in functions without bodies", code = E0642)] // FIXME: deduplicate with rustc_lint (`BuiltinLintDiag::PatternsInFnsWithoutBody`) pub(crate) struct PatternInBodiless { #[primary_span] - #[label] + #[label("pattern not allowed in function without body")] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_equality_in_where)] -#[note] +#[diag("equality constraints are not yet supported in `where` clauses")] +#[note("see issue #20041 for more information")] pub(crate) struct EqualityInWhere { #[primary_span] - #[label] + #[label("not supported")] pub span: Span, #[subdiagnostic] pub assoc: Option, @@ -774,7 +887,7 @@ pub(crate) struct EqualityInWhere { #[derive(Subdiagnostic)] #[suggestion( - ast_passes_suggestion, + "if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax", code = "{param}: {path}", style = "verbose", applicability = "maybe-incorrect" @@ -788,7 +901,10 @@ pub(crate) struct AssociatedSuggestion { } #[derive(Subdiagnostic)] -#[multipart_suggestion(ast_passes_suggestion_path, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "if `{$trait_segment}::{$potential_assoc}` is an associated type you're trying to set, use the associated type binding syntax", + applicability = "maybe-incorrect" +)] pub(crate) struct AssociatedSuggestion2 { #[suggestion_part(code = "{args}")] pub span: Span, @@ -800,14 +916,14 @@ pub(crate) struct AssociatedSuggestion2 { } #[derive(Diagnostic)] -#[diag(ast_passes_feature_on_non_nightly, code = E0554)] +#[diag("`#![feature]` may not be used on the {$channel} release channel", code = E0554)] pub(crate) struct FeatureOnNonNightly { #[primary_span] pub span: Span, pub channel: &'static str, #[subdiagnostic] pub stable_features: Vec, - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove the attribute", code = "", applicability = "machine-applicable")] pub sugg: Option, } @@ -820,13 +936,13 @@ impl Subdiagnostic for StableFeature { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("name", self.name); diag.arg("since", self.since); - diag.help(fluent::ast_passes_stable_since); + diag.help(inline_fluent!("the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable")); } } #[derive(Diagnostic)] -#[diag(ast_passes_incompatible_features)] -#[help] +#[diag("`{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed")] +#[help("remove one of these features")] pub(crate) struct IncompatibleFeatures { #[primary_span] pub spans: Vec, @@ -835,28 +951,28 @@ pub(crate) struct IncompatibleFeatures { } #[derive(Diagnostic)] -#[diag(ast_passes_negative_bound_not_supported)] +#[diag("negative bounds are not supported")] pub(crate) struct NegativeBoundUnsupported { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_constraint_on_negative_bound)] +#[diag("associated type constraints not allowed on negative bounds")] pub(crate) struct ConstraintOnNegativeBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_negative_bound_with_parenthetical_notation)] +#[diag("parenthetical notation may not be used for negative bounds")] pub(crate) struct NegativeBoundWithParentheticalNotation { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_match_arm_with_no_body)] +#[diag("`match` arm with no body")] pub(crate) struct MatchArmWithNoBody { #[primary_span] pub span: Span, @@ -864,6 +980,7 @@ pub(crate) struct MatchArmWithNoBody { // any logic looking at the arm being replaced if there was a comma already or not for the // resulting code to be correct. #[suggestion( + "add a body after the pattern", code = " => {{ todo!() }}", applicability = "has-placeholders", style = "verbose" @@ -872,7 +989,7 @@ pub(crate) struct MatchArmWithNoBody { } #[derive(Diagnostic)] -#[diag(ast_passes_precise_capturing_not_allowed_here)] +#[diag("`use<...>` precise capturing syntax not allowed in {$loc}")] pub(crate) struct PreciseCapturingNotAllowedHere { #[primary_span] pub span: Span, @@ -880,39 +997,43 @@ pub(crate) struct PreciseCapturingNotAllowedHere { } #[derive(Diagnostic)] -#[diag(ast_passes_precise_capturing_duplicated)] +#[diag("duplicate `use<...>` precise capturing syntax")] pub(crate) struct DuplicatePreciseCapturing { #[primary_span] pub bound1: Span, - #[label] + #[label("second `use<...>` here")] pub bound2: Span, } #[derive(Diagnostic)] -#[diag(ast_passes_extern_without_abi)] -#[help] +#[diag("`extern` declarations without an explicit ABI are disallowed")] +#[help("prior to Rust 2024, a default ABI was inferred")] pub(crate) struct MissingAbi { #[primary_span] - #[suggestion(code = "extern \"\"", applicability = "has-placeholders")] + #[suggestion("specify an ABI", code = "extern \"\"", applicability = "has-placeholders")] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(ast_passes_extern_without_abi_sugg)] +#[diag("`extern` declarations without an explicit ABI are deprecated")] pub(crate) struct MissingAbiSugg { - #[suggestion(code = "extern {default_abi}", applicability = "machine-applicable")] + #[suggestion( + "explicitly specify the {$default_abi} ABI", + code = "extern {default_abi}", + applicability = "machine-applicable" + )] pub span: Span, pub default_abi: ExternAbi, } #[derive(Diagnostic)] -#[diag(ast_passes_abi_custom_safe_foreign_function)] +#[diag("foreign functions with the \"custom\" ABI cannot be safe")] pub(crate) struct AbiCustomSafeForeignFunction { #[primary_span] pub span: Span, #[suggestion( - ast_passes_suggestion, + "remove the `safe` keyword from this definition", applicability = "maybe-incorrect", code = "", style = "verbose" @@ -921,14 +1042,14 @@ pub(crate) struct AbiCustomSafeForeignFunction { } #[derive(Diagnostic)] -#[diag(ast_passes_abi_custom_safe_function)] +#[diag("functions with the \"custom\" ABI must be unsafe")] pub(crate) struct AbiCustomSafeFunction { #[primary_span] pub span: Span, pub abi: ExternAbi, #[suggestion( - ast_passes_suggestion, + "add the `unsafe` keyword to this definition", applicability = "maybe-incorrect", code = "unsafe ", style = "verbose" @@ -937,14 +1058,14 @@ pub(crate) struct AbiCustomSafeFunction { } #[derive(Diagnostic)] -#[diag(ast_passes_abi_cannot_be_coroutine)] +#[diag("functions with the {$abi} ABI cannot be `{$coroutine_kind_str}`")] pub(crate) struct AbiCannotBeCoroutine { #[primary_span] pub span: Span, pub abi: ExternAbi, #[suggestion( - ast_passes_suggestion, + "remove the `{$coroutine_kind_str}` keyword from this definition", applicability = "maybe-incorrect", code = "", style = "verbose" @@ -954,15 +1075,15 @@ pub(crate) struct AbiCannotBeCoroutine { } #[derive(Diagnostic)] -#[diag(ast_passes_abi_must_not_have_parameters_or_return_type)] -#[note] +#[diag("invalid signature for `extern {$abi}` function")] +#[note("functions with the {$abi} ABI cannot have any parameters or return type")] pub(crate) struct AbiMustNotHaveParametersOrReturnType { #[primary_span] pub spans: Vec, pub abi: ExternAbi, #[suggestion( - ast_passes_suggestion, + "remove the parameters and return type", applicability = "maybe-incorrect", code = "{padding}fn {symbol}()", style = "verbose" @@ -973,18 +1094,20 @@ pub(crate) struct AbiMustNotHaveParametersOrReturnType { } #[derive(Diagnostic)] -#[diag(ast_passes_abi_must_not_have_return_type)] -#[note] +#[diag("invalid signature for `extern {$abi}` function")] +#[note("functions with the {$abi} ABI cannot have a return type")] pub(crate) struct AbiMustNotHaveReturnType { #[primary_span] - #[help] + #[help("remove the return type")] pub span: Span, pub abi: ExternAbi, } #[derive(Diagnostic)] -#[diag(ast_passes_abi_x86_interrupt)] -#[note] +#[diag("invalid signature for `extern \"x86-interrupt\"` function")] +#[note( + "functions with the \"x86-interrupt\" ABI must be have either 1 or 2 parameters (but found {$param_count})" +)] pub(crate) struct AbiX86Interrupt { #[primary_span] pub spans: Vec, @@ -992,7 +1115,7 @@ pub(crate) struct AbiX86Interrupt { } #[derive(Diagnostic)] -#[diag(ast_passes_scalable_vector_not_tuple_struct)] +#[diag("scalable vectors must be tuple structs")] pub(crate) struct ScalableVectorNotTupleStruct { #[primary_span] pub span: Span, diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 6376cab364db..1b1bbb1564c4 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -1,5 +1,6 @@ use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::{self as ast, AttrVec, NodeId, PatKind, attr, token}; +use rustc_errors::inline_fluent; use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features}; use rustc_session::Session; use rustc_session::parse::{feature_err, feature_warn}; @@ -124,7 +125,7 @@ impl<'a> PostExpansionVisitor<'a> { &self, non_lifetime_binders, non_lt_param_spans, - crate::fluent_generated::ast_passes_forbidden_non_lifetime_param + inline_fluent!("only lifetime parameters can be used in this context") ); // FIXME(non_lifetime_binders): Const bound params are pretty broken. diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 06795a6be81e..2630348c49c1 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -11,5 +11,3 @@ pub mod ast_validation; mod errors; pub mod feature_gate; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index c24a4ca53219..37e856cd6d50 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -9,7 +9,6 @@ anstyle = "1.0.13" jiff = { version = "0.2.5", default-features = false, features = ["std"] } rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } -rustc_ast_passes = { path = "../rustc_ast_passes" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_borrowck = { path = "../rustc_borrowck" } rustc_builtin_macros = { path = "../rustc_builtin_macros" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 02298dbf8267..0a6f57f72e5d 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -114,7 +114,6 @@ pub fn default_translator() -> Translator { pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ // tidy-alphabetical-start - rustc_ast_passes::DEFAULT_LOCALE_RESOURCE, rustc_borrowck::DEFAULT_LOCALE_RESOURCE, rustc_builtin_macros::DEFAULT_LOCALE_RESOURCE, rustc_const_eval::DEFAULT_LOCALE_RESOURCE, From 67c6cd99b721309b32c3d4f484da4a856f32bef5 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 3 Feb 2026 22:33:13 +0100 Subject: [PATCH 567/978] Convert to inline diagnostics in `rustc_pattern_analysis` --- Cargo.lock | 2 - compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_pattern_analysis/Cargo.toml | 2 - compiler/rustc_pattern_analysis/messages.ftl | 31 ---------- compiler/rustc_pattern_analysis/src/errors.rs | 61 +++++++++++++------ compiler/rustc_pattern_analysis/src/lib.rs | 3 - 7 files changed, 41 insertions(+), 60 deletions(-) delete mode 100644 compiler/rustc_pattern_analysis/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 9c98946c9d39..1c97ec790d4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3796,7 +3796,6 @@ dependencies = [ "rustc_mir_transform", "rustc_parse", "rustc_passes", - "rustc_pattern_analysis", "rustc_public", "rustc_resolve", "rustc_session", @@ -4451,7 +4450,6 @@ dependencies = [ "rustc_arena", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index c24a4ca53219..653bf3902a26 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -33,7 +33,6 @@ rustc_mir_build = { path = "../rustc_mir_build" } rustc_mir_transform = { path = "../rustc_mir_transform" } rustc_parse = { path = "../rustc_parse" } rustc_passes = { path = "../rustc_passes" } -rustc_pattern_analysis = { path = "../rustc_pattern_analysis" } rustc_public = { path = "../rustc_public", features = ["rustc_internal"] } rustc_resolve = { path = "../rustc_resolve" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 02298dbf8267..0ec8520217e1 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -125,7 +125,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_mir_build::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE, rustc_passes::DEFAULT_LOCALE_RESOURCE, - rustc_pattern_analysis::DEFAULT_LOCALE_RESOURCE, rustc_trait_selection::DEFAULT_LOCALE_RESOURCE, // tidy-alphabetical-end ]; diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml index a59f7bbeb9e5..a644c6a7c01a 100644 --- a/compiler/rustc_pattern_analysis/Cargo.toml +++ b/compiler/rustc_pattern_analysis/Cargo.toml @@ -11,7 +11,6 @@ rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena", optional = true } rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_errors = { path = "../rustc_errors", optional = true } -rustc_fluent_macro = { path = "../rustc_fluent_macro", optional = true } rustc_hir = { path = "../rustc_hir", optional = true } rustc_index = { path = "../rustc_index", default-features = false } rustc_macros = { path = "../rustc_macros", optional = true } @@ -36,7 +35,6 @@ rustc = [ "dep:rustc_arena", "dep:rustc_data_structures", "dep:rustc_errors", - "dep:rustc_fluent_macro", "dep:rustc_hir", "dep:rustc_macros", "dep:rustc_middle", diff --git a/compiler/rustc_pattern_analysis/messages.ftl b/compiler/rustc_pattern_analysis/messages.ftl deleted file mode 100644 index d3a3107f8e89..000000000000 --- a/compiler/rustc_pattern_analysis/messages.ftl +++ /dev/null @@ -1,31 +0,0 @@ -pattern_analysis_excluside_range_missing_gap = multiple ranges are one apart - .label = this range doesn't match `{$gap}` because `..` is an exclusive range - .suggestion = use an inclusive range instead - -pattern_analysis_excluside_range_missing_max = exclusive range missing `{$max}` - .label = this range doesn't match `{$max}` because `..` is an exclusive range - .suggestion = use an inclusive range instead - -pattern_analysis_mixed_deref_pattern_constructors = mix of deref patterns and normal constructors - .deref_pattern_label = matches on the result of dereferencing `{$smart_pointer_ty}` - .normal_constructor_label = matches directly on `{$smart_pointer_ty}` - -pattern_analysis_non_exhaustive_omitted_pattern = some variants are not matched explicitly - .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 - -pattern_analysis_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 - -pattern_analysis_overlapping_range_endpoints = multiple patterns overlap on their endpoints - .label = ... with this range - .note = you likely meant to write mutually exclusive ranges - -pattern_analysis_uncovered = {$count -> - [1] pattern `{$witness_1}` - [2] patterns `{$witness_1}` and `{$witness_2}` - [3] patterns `{$witness_1}`, `{$witness_2}` and `{$witness_3}` - *[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more - } not covered diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs index 156ba9737673..64d4ff422043 100644 --- a/compiler/rustc_pattern_analysis/src/errors.rs +++ b/compiler/rustc_pattern_analysis/src/errors.rs @@ -6,7 +6,14 @@ use rustc_span::Span; use crate::rustc::{RustcPatCtxt, WitnessPat}; #[derive(Subdiagnostic)] -#[label(pattern_analysis_uncovered)] +#[label( + "{$count -> + [1] pattern `{$witness_1}` + [2] patterns `{$witness_1}` and `{$witness_2}` + [3] patterns `{$witness_1}`, `{$witness_2}` and `{$witness_3}` + *[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more + } not covered" +)] pub struct Uncovered { #[primary_span] span: Span, @@ -40,10 +47,10 @@ impl Uncovered { } #[derive(LintDiagnostic)] -#[diag(pattern_analysis_overlapping_range_endpoints)] -#[note] +#[diag("multiple patterns overlap on their endpoints")] +#[note("you likely meant to write mutually exclusive ranges")] pub struct OverlappingRangeEndpoints { - #[label] + #[label("... with this range")] pub range: Span, #[subdiagnostic] pub overlap: Vec, @@ -66,10 +73,14 @@ impl Subdiagnostic for Overlap { } #[derive(LintDiagnostic)] -#[diag(pattern_analysis_excluside_range_missing_max)] +#[diag("exclusive range missing `{$max}`")] pub struct ExclusiveRangeMissingMax { - #[label] - #[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")] + #[label("this range doesn't match `{$max}` because `..` is an exclusive range")] + #[suggestion( + "use an inclusive range instead", + code = "{suggestion}", + applicability = "maybe-incorrect" + )] /// This is an exclusive range that looks like `lo..max` (i.e. doesn't match `max`). pub first_range: Span, /// Suggest `lo..=max` instead. @@ -78,10 +89,14 @@ pub struct ExclusiveRangeMissingMax { } #[derive(LintDiagnostic)] -#[diag(pattern_analysis_excluside_range_missing_gap)] +#[diag("multiple ranges are one apart")] pub struct ExclusiveRangeMissingGap { - #[label] - #[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")] + #[label("this range doesn't match `{$gap}` because `..` is an exclusive range")] + #[suggestion( + "use an inclusive range instead", + code = "{suggestion}", + applicability = "maybe-incorrect" + )] /// This is an exclusive range that looks like `lo..gap` (i.e. doesn't match `gap`). pub first_range: Span, pub gap: String, // a printed pattern @@ -113,9 +128,11 @@ impl Subdiagnostic for GappedRange { } #[derive(LintDiagnostic)] -#[diag(pattern_analysis_non_exhaustive_omitted_pattern)] -#[help] -#[note] +#[diag("some variants are not matched explicitly")] +#[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" +)] pub(crate) struct NonExhaustiveOmittedPattern<'tcx> { pub scrut_ty: Ty<'tcx>, #[subdiagnostic] @@ -123,25 +140,29 @@ pub(crate) struct NonExhaustiveOmittedPattern<'tcx> { } #[derive(LintDiagnostic)] -#[diag(pattern_analysis_non_exhaustive_omitted_pattern_lint_on_arm)] -#[help] +#[diag("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")] pub(crate) struct NonExhaustiveOmittedPatternLintOnArm { - #[label] + #[label("remove this attribute")] pub lint_span: Span, - #[suggestion(code = "#[{lint_level}({lint_name})]\n", applicability = "maybe-incorrect")] + #[suggestion( + "set the lint level on the whole match", + 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(Diagnostic)] -#[diag(pattern_analysis_mixed_deref_pattern_constructors)] +#[diag("mix of deref patterns and normal constructors")] pub(crate) struct MixedDerefPatternConstructors<'tcx> { #[primary_span] pub spans: Vec, pub smart_pointer_ty: Ty<'tcx>, - #[label(pattern_analysis_deref_pattern_label)] + #[label("matches on the result of dereferencing `{$smart_pointer_ty}`")] pub deref_pattern_label: Span, - #[label(pattern_analysis_normal_constructor_label)] + #[label("matches directly on `{$smart_pointer_ty}`")] pub normal_constructor_label: Span, } diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 265284086377..9ffc237c6329 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -19,9 +19,6 @@ pub mod pat_column; pub mod rustc; pub mod usefulness; -#[cfg(feature = "rustc")] -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - use std::fmt; pub use rustc_index::{Idx, IndexVec}; // re-exported to avoid rustc_index version issues From e55eb4566152bbed506f4916ddec3817c2a76f42 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 4 Feb 2026 16:27:09 +0100 Subject: [PATCH 568/978] Convert to inline diagnostics in `rustc_errors` --- Cargo.lock | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_errors/Cargo.toml | 1 - compiler/rustc_errors/messages.ftl | 48 ----------------- compiler/rustc_errors/src/diagnostic_impls.rs | 54 ++++++++++++------- compiler/rustc_errors/src/json/tests.rs | 3 +- compiler/rustc_errors/src/lib.rs | 13 +++-- compiler/rustc_session/src/session.rs | 3 +- 8 files changed, 45 insertions(+), 79 deletions(-) delete mode 100644 compiler/rustc_errors/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 9c98946c9d39..a5882a14faf9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3846,7 +3846,6 @@ dependencies = [ "rustc_data_structures", "rustc_error_codes", "rustc_error_messages", - "rustc_fluent_macro", "rustc_hashes", "rustc_index", "rustc_lint_defs", diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 02298dbf8267..085953bc4b84 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -118,7 +118,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_borrowck::DEFAULT_LOCALE_RESOURCE, rustc_builtin_macros::DEFAULT_LOCALE_RESOURCE, rustc_const_eval::DEFAULT_LOCALE_RESOURCE, - rustc_errors::DEFAULT_LOCALE_RESOURCE, rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE, rustc_lint::DEFAULT_LOCALE_RESOURCE, rustc_middle::DEFAULT_LOCALE_RESOURCE, diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index 81eecca3199f..a81fc496c828 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -14,7 +14,6 @@ rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_error_codes = { path = "../rustc_error_codes" } rustc_error_messages = { path = "../rustc_error_messages" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hashes = { path = "../rustc_hashes" } rustc_index = { path = "../rustc_index" } rustc_lint_defs = { path = "../rustc_lint_defs" } diff --git a/compiler/rustc_errors/messages.ftl b/compiler/rustc_errors/messages.ftl deleted file mode 100644 index ad2e206260d5..000000000000 --- a/compiler/rustc_errors/messages.ftl +++ /dev/null @@ -1,48 +0,0 @@ -errors_delayed_at_with_newline = - delayed at {$emitted_at} - {$note} - -errors_delayed_at_without_newline = - delayed at {$emitted_at} - {$note} - -errors_expected_lifetime_parameter = - expected lifetime {$count -> - [1] parameter - *[other] parameters - } - -errors_indicate_anonymous_lifetime = - indicate the anonymous {$count -> - [1] lifetime - *[other] lifetimes - } - -errors_invalid_flushed_delayed_diagnostic_level = - `flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug` - -errors_target_inconsistent_architecture = - inconsistent target specification: "data-layout" claims architecture is {$dl}-endian, while "target-endian" is `{$target}` - -errors_target_inconsistent_pointer_width = - inconsistent target specification: "data-layout" claims pointers are {$pointer_size}-bit, while "target-pointer-width" is `{$target}` - -errors_target_invalid_address_space = - invalid address space `{$addr_space}` for `{$cause}` in "data-layout": {$err} - -errors_target_invalid_alignment = - invalid alignment for `{$cause}` in "data-layout": `{$align}` is {$err_kind -> - [not_power_of_two] not a power of 2 - [too_large] too large - *[other] {""} - } - -errors_target_invalid_bits = - invalid {$kind} `{$bit}` for `{$cause}` in "data-layout": {$err} - -errors_target_invalid_bits_size = {$err} - -errors_target_invalid_datalayout_pointer_spec = - unknown pointer specification `{$err}` in datalayout string - -errors_target_missing_alignment = - missing alignment for `{$cause}` in "data-layout" diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 435d16a83806..c36afc6fc889 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -7,8 +7,7 @@ use rustc_span::{Span, Symbol}; use crate::diagnostic::DiagLocation; use crate::{ - Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, Subdiagnostic, - fluent_generated as fluent, + Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, Subdiagnostic, inline_fluent, }; impl IntoDiagArg for DiagLocation { @@ -44,43 +43,48 @@ impl Diagnostic<'_, G> for TargetDataLayoutErrors<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { match self { TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => { - Diag::new(dcx, level, fluent::errors_target_invalid_address_space) + Diag::new(dcx, level, inline_fluent!("invalid address space `{$addr_space}` for `{$cause}` in \"data-layout\": {$err}")) .with_arg("addr_space", addr_space) .with_arg("cause", cause) .with_arg("err", err) } TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => { - Diag::new(dcx, level, fluent::errors_target_invalid_bits) + Diag::new(dcx, level, inline_fluent!("invalid {$kind} `{$bit}` for `{$cause}` in \"data-layout\": {$err}")) .with_arg("kind", kind) .with_arg("bit", bit) .with_arg("cause", cause) .with_arg("err", err) } TargetDataLayoutErrors::MissingAlignment { cause } => { - Diag::new(dcx, level, fluent::errors_target_missing_alignment) + Diag::new(dcx, level, inline_fluent!("missing alignment for `{$cause}` in \"data-layout\"")) .with_arg("cause", cause) } TargetDataLayoutErrors::InvalidAlignment { cause, err } => { - Diag::new(dcx, level, fluent::errors_target_invalid_alignment) - .with_arg("cause", cause) - .with_arg("err_kind", err.diag_ident()) - .with_arg("align", err.align()) + Diag::new(dcx, level, inline_fluent!("invalid alignment for `{$cause}` in \"data-layout\": `{$align}` is {$err_kind -> + [not_power_of_two] not a power of 2 + [too_large] too large + *[other] {\"\"} + }")) + .with_arg("cause", cause) + .with_arg("err_kind", err.diag_ident()) + .with_arg("align", err.align()) } TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => { - Diag::new(dcx, level, fluent::errors_target_inconsistent_architecture) - .with_arg("dl", dl) - .with_arg("target", target) + Diag::new(dcx, level, inline_fluent!( + "inconsistent target specification: \"data-layout\" claims architecture is {$dl}-endian, while \"target-endian\" is `{$target}`" + )) + .with_arg("dl", dl).with_arg("target", target) } TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => { - Diag::new(dcx, level, fluent::errors_target_inconsistent_pointer_width) - .with_arg("pointer_size", pointer_size) - .with_arg("target", target) + Diag::new(dcx, level, inline_fluent!( + "inconsistent target specification: \"data-layout\" claims pointers are {$pointer_size}-bit, while \"target-pointer-width\" is `{$target}`" + )).with_arg("pointer_size", pointer_size).with_arg("target", target) } TargetDataLayoutErrors::InvalidBitsSize { err } => { - Diag::new(dcx, level, fluent::errors_target_invalid_bits_size).with_arg("err", err) + Diag::new(dcx, level, inline_fluent!("{$err}")).with_arg("err", err) } TargetDataLayoutErrors::UnknownPointerSpecification { err } => { - Diag::new(dcx, level, fluent::errors_target_invalid_datalayout_pointer_spec) + Diag::new(dcx, level, inline_fluent!("unknown pointer specification `{$err}` in datalayout string")) .with_arg("err", err) } } @@ -99,7 +103,12 @@ impl Subdiagnostic for SingleLabelManySpans { } #[derive(Subdiagnostic)] -#[label(errors_expected_lifetime_parameter)] +#[label( + "expected lifetime {$count -> + [1] parameter + *[other] parameters + }" +)] pub struct ExpectedLifetimeParameter { #[primary_span] pub span: Span, @@ -107,7 +116,14 @@ pub struct ExpectedLifetimeParameter { } #[derive(Subdiagnostic)] -#[suggestion(errors_indicate_anonymous_lifetime, code = "{suggestion}", style = "verbose")] +#[suggestion( + "indicate the anonymous {$count -> + [1] lifetime + *[other] lifetimes + }", + code = "{suggestion}", + style = "verbose" +)] pub struct IndicateAnonymousLifetime { #[primary_span] pub span: Span, diff --git a/compiler/rustc_errors/src/json/tests.rs b/compiler/rustc_errors/src/json/tests.rs index c1c9ecf7198f..6f99930c433b 100644 --- a/compiler/rustc_errors/src/json/tests.rs +++ b/compiler/rustc_errors/src/json/tests.rs @@ -45,8 +45,7 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) { rustc_span::create_default_session_globals_then(|| { let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); sm.new_source_file(filename(&sm, "test.rs"), code.to_owned()); - let translator = - Translator::with_fallback_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false); + let translator = Translator::with_fallback_bundle(vec![], false); let output = Arc::new(Mutex::new(Vec::new())); let je = JsonEmitter::new( diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 68d825a4514a..f89a2af71022 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -92,8 +92,6 @@ pub mod translation; pub type PResult<'a, T> = Result>; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - // `PResult` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_pointer_width = "64")] rustc_data_structures::static_assert_size!(PResult<'_, ()>, 24); @@ -1531,7 +1529,9 @@ impl DiagCtxtInner { // the usual `Diag`/`DiagCtxt` level, so we must augment `bug` // in a lower-level fashion. bug.arg("level", bug.level); - let msg = crate::fluent_generated::errors_invalid_flushed_delayed_diagnostic_level; + let msg = inline_fluent!( + "`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`" + ); let msg = self.eagerly_translate_for_subdiag(&bug, msg); // after the `arg` call bug.sub(Note, msg, bug.span.primary_span().unwrap().into()); } @@ -1573,10 +1573,13 @@ impl DelayedDiagInner { // lower-level fashion. let mut diag = self.inner; let msg = match self.note.status() { - BacktraceStatus::Captured => crate::fluent_generated::errors_delayed_at_with_newline, + BacktraceStatus::Captured => inline_fluent!( + "delayed at {$emitted_at} +{$note}" + ), // Avoid the needless newline when no backtrace has been captured, // the display impl should just be a single line. - _ => crate::fluent_generated::errors_delayed_at_without_newline, + _ => inline_fluent!("delayed at {$emitted_at} - {$note}"), }; diag.arg("emitted_at", diag.emitted_at.clone()); diag.arg("note", self.note); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 26efa03c898c..298b25088151 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1432,8 +1432,7 @@ impl EarlyDiagCtxt { fn mk_emitter(output: ErrorOutputType) -> Box { // FIXME(#100717): early errors aren't translated at the moment, so this is fine, but it will // need to reference every crate that might emit an early error for translation to work. - let translator = - Translator::with_fallback_bundle(vec![rustc_errors::DEFAULT_LOCALE_RESOURCE], false); + let translator = Translator::with_fallback_bundle(vec![], false); let emitter: Box = match output { config::ErrorOutputType::HumanReadable { kind, color_config } => match kind { HumanReadableErrorType { short, unicode } => Box::new( From 1a240d604cf8687320fd5e10b599a9688f3aabfe Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 5 Feb 2026 11:39:38 +0000 Subject: [PATCH 569/978] expand `define_reify_functions!` --- .../proc_macro/src/bridge/selfless_reify.rs | 64 +++++++------------ 1 file changed, 22 insertions(+), 42 deletions(-) diff --git a/library/proc_macro/src/bridge/selfless_reify.rs b/library/proc_macro/src/bridge/selfless_reify.rs index a53550e0b9e0..9d565485bbdd 100644 --- a/library/proc_macro/src/bridge/selfless_reify.rs +++ b/library/proc_macro/src/bridge/selfless_reify.rs @@ -38,47 +38,27 @@ use std::mem; -// FIXME(eddyb) this could be `trait` impls except for the `const fn` requirement. -macro_rules! define_reify_functions { - ($( - fn $name:ident $(<$($param:ident),*>)? - for $(extern $abi:tt)? fn($($arg:ident: $arg_ty:ty),*) -> $ret_ty:ty; - )+) => { - $(pub(super) const fn $name< - $($($param,)*)? - F: Fn($($arg_ty),*) -> $ret_ty + Copy - >(f: F) -> $(extern $abi)? fn($($arg_ty),*) -> $ret_ty { - // FIXME(eddyb) describe the `F` type (e.g. via `type_name::`) once panic - // formatting becomes possible in `const fn`. - const { assert!(size_of::() == 0, "selfless_reify: closure must be zero-sized"); } - - $(extern $abi)? fn wrapper< - $($($param,)*)? - F: Fn($($arg_ty),*) -> $ret_ty + Copy - >($($arg: $arg_ty),*) -> $ret_ty { - let f = unsafe { - // SAFETY: `F` satisfies all criteria for "out of thin air" - // reconstructability (see module-level doc comment). - mem::MaybeUninit::::uninit().assume_init() - }; - f($($arg),*) - } - let _f_proof = f; - wrapper::< - $($($param,)*)? - F - > - })+ +pub(super) const fn reify_to_extern_c_fn_hrt_bridge< + R, + F: Fn(super::BridgeConfig<'_>) -> R + Copy, +>( + f: F, +) -> extern "C" fn(super::BridgeConfig<'_>) -> R { + // FIXME(eddyb) describe the `F` type (e.g. via `type_name::`) once panic + // formatting becomes possible in `const fn`. + const { + assert!(size_of::() == 0, "selfless_reify: closure must be zero-sized"); } -} - -define_reify_functions! { - fn _reify_to_extern_c_fn_unary for extern "C" fn(arg: A) -> R; - - // HACK(eddyb) this abstraction is used with `for<'a> fn(BridgeConfig<'a>) - // -> T` but that doesn't work with just `reify_to_extern_c_fn_unary` - // because of the `fn` pointer type being "higher-ranked" (i.e. the - // `for<'a>` binder). - // FIXME(eddyb) try to remove the lifetime from `BridgeConfig`, that'd help. - fn reify_to_extern_c_fn_hrt_bridge for extern "C" fn(bridge: super::BridgeConfig<'_>) -> R; + extern "C" fn wrapper) -> R + Copy>( + bridge: super::BridgeConfig<'_>, + ) -> R { + let f = unsafe { + // SAFETY: `F` satisfies all criteria for "out of thin air" + // reconstructability (see module-level doc comment). + mem::MaybeUninit::::uninit().assume_init() + }; + f(bridge) + } + let _f_proof = f; + wrapper:: } From 749d62b26225c20d49e7276951062ab458c6aa63 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 5 Feb 2026 11:40:11 +0000 Subject: [PATCH 570/978] remove `Closure` generics --- library/proc_macro/src/bridge/client.rs | 2 +- library/proc_macro/src/bridge/closure.rs | 20 +++++++++++--------- library/proc_macro/src/bridge/mod.rs | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 8f4a79b389f6..ddc9e0d4dee0 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -129,7 +129,7 @@ struct Bridge<'a> { cached_buffer: Buffer, /// Server-side function that the client uses to make requests. - dispatch: closure::Closure<'a, Buffer, Buffer>, + dispatch: closure::Closure<'a>, /// Provided globals for this macro expansion. globals: ExpnGlobals, diff --git a/library/proc_macro/src/bridge/closure.rs b/library/proc_macro/src/bridge/closure.rs index e5133907854b..88c4dd6630b1 100644 --- a/library/proc_macro/src/bridge/closure.rs +++ b/library/proc_macro/src/bridge/closure.rs @@ -1,10 +1,12 @@ -//! Closure type (equivalent to `&mut dyn FnMut(A) -> R`) that's `repr(C)`. +//! Closure type (equivalent to `&mut dyn FnMut(Buffer) -> Buffer`) that's `repr(C)`. use std::marker::PhantomData; +use super::Buffer; + #[repr(C)] -pub(super) struct Closure<'a, A, R> { - call: unsafe extern "C" fn(*mut Env, A) -> R, +pub(super) struct Closure<'a> { + call: extern "C" fn(*mut Env, Buffer) -> Buffer, env: *mut Env, // Prevent Send and Sync impls. // @@ -14,17 +16,17 @@ pub(super) struct Closure<'a, A, R> { struct Env; -impl<'a, A, R, F: FnMut(A) -> R> From<&'a mut F> for Closure<'a, A, R> { +impl<'a, F: FnMut(Buffer) -> Buffer> From<&'a mut F> for Closure<'a> { fn from(f: &'a mut F) -> Self { - unsafe extern "C" fn call R>(env: *mut Env, arg: A) -> R { + extern "C" fn call Buffer>(env: *mut Env, arg: Buffer) -> Buffer { unsafe { (*(env as *mut _ as *mut F))(arg) } } - Closure { call: call::, env: f as *mut _ as *mut Env, _marker: PhantomData } + Closure { call: call::, env: f as *mut _ as *mut Env, _marker: PhantomData } } } -impl<'a, A, R> Closure<'a, A, R> { - pub(super) fn call(&mut self, arg: A) -> R { - unsafe { (self.call)(self.env, arg) } +impl<'a> Closure<'a> { + pub(super) fn call(&mut self, arg: Buffer) -> Buffer { + (self.call)(self.env, arg) } } diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 244ab7d81b02..d9529b63e8e4 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -126,7 +126,7 @@ pub struct BridgeConfig<'a> { input: Buffer, /// Server-side function that the client uses to make requests. - dispatch: closure::Closure<'a, Buffer, Buffer>, + dispatch: closure::Closure<'a>, /// If 'true', always invoke the default panic hook force_show_panics: bool, From aa7c785e8a273fb8ceb0a93e282e8b7c5a3072cd Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 5 Feb 2026 17:44:01 +0900 Subject: [PATCH 571/978] Add note for `?Sized` params in int-ptr casts diag --- compiler/rustc_hir_typeck/src/cast.rs | 12 ++++++++++++ compiler/rustc_hir_typeck/src/errors.rs | 8 ++++++++ tests/ui/cast/fat-ptr-cast.stderr | 2 ++ 3 files changed, 22 insertions(+) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 3f13a102684e..b5094d736dd5 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -572,6 +572,17 @@ impl<'a, 'tcx> CastCheck<'tcx> { let metadata = known_metadata.unwrap_or("type-specific metadata"); let known_wide = known_metadata.is_some(); let span = self.cast_span; + let param_note = (!known_wide) + .then(|| match cast_ty.kind() { + ty::RawPtr(pointee, _) => match pointee.kind() { + ty::Param(param) => { + Some(errors::IntToWideParamNote { param: param.name }) + } + _ => None, + }, + _ => None, + }) + .flatten(); fcx.dcx().emit_err(errors::IntToWide { span, metadata, @@ -579,6 +590,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { cast_ty, expr_if_nightly, known_wide, + param_note, }); } CastError::UnknownCastPtrKind | CastError::UnknownExprPtrKind => { diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 0f330c3021c0..60ac2acaec36 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -590,6 +590,14 @@ pub(crate) struct IntToWide<'tcx> { )] pub expr_if_nightly: Option, pub known_wide: bool, + #[subdiagnostic] + pub param_note: Option, +} + +#[derive(Subdiagnostic)] +#[note("the type parameter `{$param}` is not known to be `Sized`, so this pointer may be wide")] +pub(crate) struct IntToWideParamNote { + pub param: Symbol, } #[derive(Subdiagnostic)] diff --git a/tests/ui/cast/fat-ptr-cast.stderr b/tests/ui/cast/fat-ptr-cast.stderr index 2b0bceebf15c..c6354122f568 100644 --- a/tests/ui/cast/fat-ptr-cast.stderr +++ b/tests/ui/cast/fat-ptr-cast.stderr @@ -81,6 +81,8 @@ LL | let s = 0 as *const T; | - ^^^^^^^^ creating a `*const T` requires both an address and type-specific metadata | | | consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` + | + = note: the type parameter `T` is not known to be `Sized`, so this pointer may be wide error: aborting due to 11 previous errors From edeb02f3828aedb3dac3c32553842e6a4d01d422 Mon Sep 17 00:00:00 2001 From: "Eddy (Eduard) Stefes" Date: Thu, 5 Feb 2026 13:36:18 +0100 Subject: [PATCH 572/978] disable s390x vector intrinsics if softfloat is enabled we will add an explicit incompatibility of softfloat and vector feature in rutsc s390x-unknown-none-softfloat target specification. Therefore we need to disable vector intrinsics here to be able to compile core for this target. --- library/stdarch/crates/core_arch/src/s390x/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/stdarch/crates/core_arch/src/s390x/mod.rs b/library/stdarch/crates/core_arch/src/s390x/mod.rs index 7d3b3f2d99aa..5b85020072d8 100644 --- a/library/stdarch/crates/core_arch/src/s390x/mod.rs +++ b/library/stdarch/crates/core_arch/src/s390x/mod.rs @@ -2,6 +2,11 @@ pub(crate) mod macros; +/// the float and vector registers overlap therefore we cannot use any vector +/// extensions if softfloat is enabled. + +#[cfg(not(target_abi = "softfloat"))] mod vector; +#[cfg(not(target_abi = "softfloat"))] #[unstable(feature = "stdarch_s390x", issue = "130869")] pub use self::vector::*; From 911203936b799451029b91526eba6b7dbf842559 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Thu, 5 Feb 2026 14:34:01 +0100 Subject: [PATCH 573/978] Port rustc_effective_visibility to the new attribute parser --- .../src/attributes/rustc_internal.rs | 39 +++++++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + .../rustc_hir/src/attrs/data_structures.rs | 3 ++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 2 +- 6 files changed, 46 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 348882dc59fc..bde4904e9655 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -721,3 +721,42 @@ impl CombineAttributeParser for RustcThenThisWouldNeedParser { Some(ident) } } + +pub(crate) struct RustcEffectiveVisibilityParser; + +impl NoArgsAttributeParser for RustcEffectiveVisibilityParser { + const PATH: &'static [Symbol] = &[sym::rustc_effective_visibility]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Use), + Allow(Target::Static), + Allow(Target::Const), + Allow(Target::Fn), + Allow(Target::Closure), + Allow(Target::Mod), + Allow(Target::ForeignMod), + Allow(Target::TyAlias), + Allow(Target::Enum), + Allow(Target::Variant), + Allow(Target::Struct), + Allow(Target::Field), + Allow(Target::Union), + Allow(Target::Trait), + Allow(Target::TraitAlias), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Impl { of_trait: true }), + Allow(Target::AssocConst), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::AssocTy), + Allow(Target::ForeignFn), + Allow(Target::ForeignStatic), + Allow(Target::ForeignTy), + Allow(Target::MacroDef), + Allow(Target::PatField), + Allow(Target::Crate), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEffectiveVisibility; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 5abf299ec618..eb9ae158abb7 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -258,6 +258,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index a444b5e4badf..e4d93b2e0c29 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1094,6 +1094,9 @@ pub enum AttributeKind { /// Represents `#[rustc_dyn_incompatible_trait]`. RustcDynIncompatibleTrait(Span), + /// Represents `#[rustc_effective_visibility]`. + RustcEffectiveVisibility, + /// Represents `#[rustc_has_incoherent_inherent_impls]` RustcHasIncoherentInherentImpls, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index b6249e1e2ec2..2a214fe58220 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -112,6 +112,7 @@ impl AttributeKind { RustcDumpUserArgs => No, RustcDumpVtable(..) => No, RustcDynIncompatibleTrait(..) => No, + RustcEffectiveVisibility => Yes, RustcHasIncoherentInherentImpls => Yes, RustcHiddenTypeOfOpaques => No, RustcIfThisChanged(..) => No, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 0d64e30d9c79..acc7abe19167 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -307,6 +307,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcDumpUserArgs | AttributeKind::RustcDumpVtable(..) | AttributeKind::RustcDynIncompatibleTrait(..) + | AttributeKind::RustcEffectiveVisibility | AttributeKind::RustcHasIncoherentInherentImpls | AttributeKind::RustcHiddenTypeOfOpaques | AttributeKind::RustcIfThisChanged(..) @@ -401,7 +402,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_regions | sym::rustc_strict_coherence | sym::rustc_mir - | sym::rustc_effective_visibility | sym::rustc_outlives | sym::rustc_symbol_name | sym::rustc_evaluate_where_clauses diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 4a88ea0cc445..f69f8777ef42 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -876,7 +876,7 @@ pub struct TestReachabilityVisitor<'a, 'tcx> { impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> { fn effective_visibility_diagnostic(&self, def_id: LocalDefId) { - if self.tcx.has_attr(def_id, sym::rustc_effective_visibility) { + if find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::RustcEffectiveVisibility) { let mut error_msg = String::new(); let span = self.tcx.def_span(def_id.to_def_id()); if let Some(effective_vis) = self.effective_visibilities.effective_vis(def_id) { From 2495d07fc7f15fa88dce5d566d1a30377f886a3e Mon Sep 17 00:00:00 2001 From: Redddy Date: Thu, 5 Feb 2026 23:46:34 +0900 Subject: [PATCH 574/978] Updated link to the Rust CI successful workflow runs page --- src/doc/rustc-dev-guide/src/tests/ci.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md index 723926f2241f..c04e3da8b2c2 100644 --- a/src/doc/rustc-dev-guide/src/tests/ci.md +++ b/src/doc/rustc-dev-guide/src/tests/ci.md @@ -447,7 +447,7 @@ If you want to determine which `bootstrap.toml` settings are used in CI for a particular job, it is probably easiest to just look at the build log. To do this: -1. Go to +1. Go to [the Rust CI successful workflow runs page][workflow runs] to find the most recently successful build, and click on it. 2. Choose the job you are interested in on the left-hand side. 3. Click on the gear icon and choose "View raw logs" @@ -462,3 +462,4 @@ To do this: [merge queue]: https://bors.rust-lang.org/queue/rust [dist-x86_64-linux]: https://github.com/rust-lang/rust/blob/HEAD/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile [the GitHub Actions workflows page]: https://github.com/rust-lang/rust/actions +[workflow runs]: https://github.com/rust-lang/rust/actions?query=branch%3Aautomation%2Fbors%2Fauto+is%3Asuccess From f85323666d032469fde09063d3bab55a09b6de43 Mon Sep 17 00:00:00 2001 From: Redddy Date: Fri, 6 Feb 2026 00:20:10 +0900 Subject: [PATCH 575/978] Update CI documentation for branch names --- src/doc/rustc-dev-guide/src/tests/ci.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md index c04e3da8b2c2..45cb10cfcb02 100644 --- a/src/doc/rustc-dev-guide/src/tests/ci.md +++ b/src/doc/rustc-dev-guide/src/tests/ci.md @@ -102,7 +102,7 @@ Most platforms only run the build steps, some run a restricted set of tests; only a subset run the full suite of tests (see Rust's [platform tiers]). Auto jobs are defined in the `auto` section of [`jobs.yml`]. -They are executed on the `auto` branch under the `rust-lang/rust` repository, +They are executed on the [`automation/bors/auto`][auto] branch under the `rust-lang/rust` repository, and the final result will be reported via a comment made by bors on the corresponding PR. The live results can be seen on [the GitHub Actions workflows page]. @@ -110,6 +110,7 @@ At any given time, at most a single `auto` build is being executed. Find out more in [Merging PRs serially with bors](#merging-prs-serially-with-bors). [platform tiers]: https://forge.rust-lang.org/release/platform-support.html#rust-platform-support +[auto]: https://github.com/rust-lang/rust/tree/automation/bors/auto ### Try builds @@ -204,7 +205,7 @@ to help make the perf comparison as fair as possible. > However, it can be less flexible because you cannot adjust the set of tests > that are exercised this way. -Try builds are executed on the `try` branch under the `rust-lang/rust` repository and +Try builds are executed on the [`automation/bors/try`][try] branch under the `rust-lang/rust` repository and their results can be seen on [the GitHub Actions workflows page], although usually you will be notified of the result by a comment made by bors on the corresponding PR. @@ -213,6 +214,7 @@ Multiple try builds can execute concurrently across different PRs, but there can a single try build running on a single PR at any given time. [rustc-perf]: https://github.com/rust-lang/rustc-perf +[try]: https://github.com/rust-lang/rust/tree/automation/bors/try ### Modifying CI jobs @@ -284,8 +286,8 @@ If all the builders are green, the PR is merged, otherwise the failure is recorded and the PR will have to be re-approved again. Bors doesn’t interact with CI services directly, but it works by pushing the -merge commit it wants to test to specific branches (like `auto` or `try`), which -are configured to execute CI checks. +merge commit it wants to test to specific branches (like `automation/bors/auto` or `automation/bors/try`), +which are configured to execute CI checks. Bors then detects the outcome of the build by listening for either Commit Statuses or Check Runs. Since the merge commit is based on the latest `main` and only one can be tested at the same time, when From 3fd4ab427a0b3c94d9c198730e4609736e479745 Mon Sep 17 00:00:00 2001 From: Redddy Date: Fri, 6 Feb 2026 00:31:37 +0900 Subject: [PATCH 576/978] Simplify redundant description --- src/doc/rustc-dev-guide/src/tests/ci.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md index 45cb10cfcb02..6b63f68b29ee 100644 --- a/src/doc/rustc-dev-guide/src/tests/ci.md +++ b/src/doc/rustc-dev-guide/src/tests/ci.md @@ -450,7 +450,7 @@ particular job, it is probably easiest to just look at the build log. To do this: 1. Go to [the Rust CI successful workflow runs page][workflow runs] - to find the most recently successful build, and click on it. + and click on the most recent one. 2. Choose the job you are interested in on the left-hand side. 3. Click on the gear icon and choose "View raw logs" 4. Search for the string "Configure the build" From dd61998e74e1cc4bcec9b6f92026d218b34d262e Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 4 Feb 2026 16:00:30 +0100 Subject: [PATCH 577/978] Convert to inline diagnostics in `rustc_borrowck` --- Cargo.lock | 2 - compiler/rustc_borrowck/Cargo.toml | 1 - compiler/rustc_borrowck/messages.ftl | 296 ------------------ .../rustc_borrowck/src/diagnostics/mod.rs | 22 +- .../src/diagnostics/region_errors.rs | 28 +- compiler/rustc_borrowck/src/lib.rs | 2 - .../rustc_borrowck/src/session_diagnostics.rs | 275 +++++++++++----- compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - 9 files changed, 233 insertions(+), 395 deletions(-) delete mode 100644 compiler/rustc_borrowck/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 23abc6626aab..4d67ea5b8180 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3571,7 +3571,6 @@ dependencies = [ "rustc_abi", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_graphviz", "rustc_hir", "rustc_index", @@ -3771,7 +3770,6 @@ dependencies = [ "rustc_abi", "rustc_ast", "rustc_ast_pretty", - "rustc_borrowck", "rustc_codegen_ssa", "rustc_const_eval", "rustc_data_structures", diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index 9e7d55180a23..55a09dbf1d72 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -11,7 +11,6 @@ polonius-engine = "0.13.0" rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_graphviz = { path = "../rustc_graphviz" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl deleted file mode 100644 index f59e106c7ac3..000000000000 --- a/compiler/rustc_borrowck/messages.ftl +++ /dev/null @@ -1,296 +0,0 @@ -borrowck_assign_due_to_use_closure = - assignment occurs due to use in closure - -borrowck_assign_due_to_use_coroutine = - assign occurs due to use in coroutine - -borrowck_assign_part_due_to_use_closure = - assignment to part occurs due to use in closure - -borrowck_assign_part_due_to_use_coroutine = - assign to part occurs due to use in coroutine - -borrowck_borrow_due_to_use_closure = - borrow occurs due to use in closure - -borrowck_borrow_due_to_use_coroutine = - borrow occurs due to use in coroutine - -borrowck_calling_operator_moves = - calling this operator moves the value - -borrowck_calling_operator_moves_lhs = - calling this operator moves the left-hand side - -borrowck_cannot_move_when_borrowed = - cannot move out of {$place -> - [value] value - *[other] {$place} - } because it is borrowed - .label = borrow of {$borrow_place -> - [value] value - *[other] {$borrow_place} - } occurs here - .move_label = move out of {$value_place -> - [value] value - *[other] {$value_place} - } occurs here - -borrowck_capture_immute = - capture is immutable because of use here - -borrowck_capture_move = - capture is moved because of use here - -borrowck_capture_mut = - capture is mutable because of use here - -borrowck_closure_inferred_mut = inferred to be a `FnMut` closure - -borrowck_closure_invoked_twice = - closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment - -borrowck_closure_moved_twice = - closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment - -borrowck_consider_borrow_type_contents = - help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents - -borrowck_could_not_normalize = - could not normalize `{$value}` - -borrowck_could_not_prove = - could not prove `{$predicate}` - -borrowck_dereference_suggestion = - dereference the return value - -borrowck_func_take_self_moved_place = - `{$func}` takes ownership of the receiver `self`, which moves {$place_name} - -borrowck_generic_does_not_live_long_enough = - `{$kind}` does not live long enough - -borrowck_higher_ranked_lifetime_error = - higher-ranked lifetime error - -borrowck_higher_ranked_subtype_error = - higher-ranked subtype error - -borrowck_implicit_static = - this has an implicit `'static` lifetime requirement - -borrowck_implicit_static_introduced = - calling this method introduces the `impl`'s `'static` requirement - -borrowck_implicit_static_relax = - consider relaxing the implicit `'static` requirement - -borrowck_lifetime_constraints_error = - lifetime may not live long enough - -borrowck_limitations_implies_static = - due to a current limitation of the type system, this implies a `'static` lifetime - -borrowck_move_closure_suggestion = - consider adding 'move' keyword before the nested closure - -borrowck_move_out_place_here = - {$place} is moved here - -borrowck_move_unsized = - cannot move a value of type `{$ty}` - .label = the size of `{$ty}` cannot be statically determined - -borrowck_moved_a_fn_once_in_call = - this value implements `FnOnce`, which causes it to be moved when called - -borrowck_moved_a_fn_once_in_call_call = - `FnOnce` closures can only be called once - -borrowck_moved_a_fn_once_in_call_def = - `{$ty}` is made to be an `FnOnce` closure here - -borrowck_moved_due_to_await = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this {$is_loop_message -> - [true] await, in previous iteration of loop - *[false] await - } - -borrowck_moved_due_to_call = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this {$is_loop_message -> - [true] call, in previous iteration of loop - *[false] call - } - -borrowck_moved_due_to_implicit_into_iter_call = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this implicit call to {$is_loop_message -> - [true] `.into_iter()`, in previous iteration of loop - *[false] `.into_iter()` - } - -borrowck_moved_due_to_method_call = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this method {$is_loop_message -> - [true] call, in previous iteration of loop - *[false] call - } - -borrowck_moved_due_to_usage_in_operator = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to usage in {$is_loop_message -> - [true] operator, in previous iteration of loop - *[false] operator - } - -borrowck_opaque_type_lifetime_mismatch = - opaque type used twice with different lifetimes - .label = lifetime `{$arg}` used here - .prev_lifetime_label = lifetime `{$prev}` previously used here - .note = if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - -borrowck_partial_var_move_by_use_in_closure = - variable {$is_partial -> - [true] partially moved - *[false] moved - } due to use in closure - -borrowck_partial_var_move_by_use_in_coroutine = - variable {$is_partial -> - [true] partially moved - *[false] moved - } due to use in coroutine - -borrowck_restrict_to_static = - consider restricting the type parameter to the `'static` lifetime - -borrowck_returned_async_block_escaped = - returns an `async` block that contains a reference to a captured variable, which then escapes the closure body - -borrowck_returned_closure_escaped = - returns a closure that contains a reference to a captured variable, which then escapes the closure body - -borrowck_returned_lifetime_short = - {$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}` - -borrowck_returned_lifetime_wrong = - {$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}` - -borrowck_returned_ref_escaped = - returns a reference to a captured variable which escapes the closure body - -borrowck_simd_intrinsic_arg_const = - {$arg -> - [1] 1st - [2] 2nd - [3] 3rd - *[other] {$arg}th - } argument of `{$intrinsic}` is required to be a `const` item - -borrowck_suggest_create_fresh_reborrow = - consider reborrowing the `Pin` instead of moving it - -borrowck_suggest_iterate_over_slice = - consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop - -borrowck_tail_expr_drop_order = relative drop order changing in Rust 2024 - .label = this temporary value will be dropped at the end of the block - .note = consider using a `let` binding to ensure the value will live long enough - -borrowck_ty_no_impl_copy = - {$is_partial_move -> - [true] partial move - *[false] move - } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait - -borrowck_use_due_to_use_closure = - use occurs due to use in closure - -borrowck_use_due_to_use_coroutine = - use occurs due to use in coroutine - -borrowck_used_impl_require_static = - the used `impl` has a `'static` requirement - -borrowck_value_capture_here = - value captured {$is_within -> - [true] here by coroutine - *[false] here - } - -borrowck_value_moved_here = - value {$is_partial -> - [true] partially moved - *[false] moved - } {$is_move_msg -> - [true] into closure here - *[false] here - }{$is_loop_message -> - [true] , in previous iteration of loop - *[false] {""} - } - -borrowck_var_borrow_by_use_in_closure = - borrow occurs due to use in closure - -borrowck_var_borrow_by_use_in_coroutine = - borrow occurs due to use in coroutine - -borrowck_var_borrow_by_use_place_in_closure = - {$is_single_var -> - *[true] borrow occurs - [false] borrows occur - } due to use of {$place} in closure - -borrowck_var_borrow_by_use_place_in_coroutine = - {$is_single_var -> - *[true] borrow occurs - [false] borrows occur - } due to use of {$place} in coroutine - -borrowck_var_cannot_escape_closure = - captured variable cannot escape `FnMut` closure body - .note = `FnMut` closures only have access to their captured variables while they are executing... - .cannot_escape = ...therefore, they cannot allow references to captured variables to escape - -borrowck_var_does_not_need_mut = - variable does not need to be mutable - .suggestion = remove this `mut` - -borrowck_var_first_borrow_by_use_place_in_closure = - first borrow occurs due to use of {$place} in closure - -borrowck_var_first_borrow_by_use_place_in_coroutine = - first borrow occurs due to use of {$place} in coroutine - -borrowck_var_here_captured = variable captured here - -borrowck_var_here_defined = variable defined here - -borrowck_var_move_by_use_in_closure = - move occurs due to use in closure - -borrowck_var_move_by_use_in_coroutine = - move occurs due to use in coroutine - -borrowck_var_mutable_borrow_by_use_place_in_closure = - mutable borrow occurs due to use of {$place} in closure - -borrowck_var_second_borrow_by_use_place_in_closure = - second borrow occurs due to use of {$place} in closure - -borrowck_var_second_borrow_by_use_place_in_coroutine = - second borrow occurs due to use of {$place} in coroutine diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index c15e7041c94d..04bacd049bc9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -4,7 +4,9 @@ use std::collections::BTreeMap; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan, listify}; +use rustc_errors::{ + Applicability, Diag, DiagMessage, EmissionGuarantee, MultiSpan, inline_fluent, listify, +}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::{ self as hir, CoroutineKind, GenericBound, LangItem, WhereBoundPredicate, WherePredicateKind, @@ -35,7 +37,6 @@ use tracing::debug; use super::MirBorrowckCtxt; use super::borrow_set::BorrowData; use crate::constraints::OutlivesConstraint; -use crate::fluent_generated as fluent; use crate::nll::ConstraintDescription; use crate::session_diagnostics::{ CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause, @@ -700,7 +701,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { .rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id) .is_some() { - diag.span_note(pred.span, fluent::borrowck_limitations_implies_static); + diag.span_note(pred.span, LIMITATION_NOTE); return; } for bound in bounds.iter() { @@ -711,7 +712,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { .rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id) .is_some() { - diag.span_note(bound.span, fluent::borrowck_limitations_implies_static); + diag.span_note(bound.span, LIMITATION_NOTE); return; } } @@ -1312,7 +1313,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let mut span: MultiSpan = spans.clone().into(); err.arg("ty", param_ty.to_string()); let msg = err.dcx.eagerly_translate_to_string( - fluent::borrowck_moved_a_fn_once_in_call_def, + inline_fluent!("`{$ty}` is made to be an `FnOnce` closure here"), err.args.iter(), ); err.remove_arg("ty"); @@ -1321,9 +1322,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } span.push_span_label( fn_call_span, - fluent::borrowck_moved_a_fn_once_in_call, + inline_fluent!("this value implements `FnOnce`, which causes it to be moved when called"), + ); + err.span_note( + span, + inline_fluent!("`FnOnce` closures can only be called once"), ); - err.span_note(span, fluent::borrowck_moved_a_fn_once_in_call_call); } else { err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span }); } @@ -1568,3 +1572,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.local_name(index).is_none_or(|name| name.as_str().starts_with('_')) } } + +const LIMITATION_NOTE: DiagMessage = inline_fluent!( + "due to a current limitation of the type system, this implies a `'static` lifetime" +); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 17f1988a17c4..ae389d1a6e10 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1,7 +1,7 @@ //! Error reporting machinery for lifetime errors. use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, inline_fluent}; use rustc_hir as hir; use rustc_hir::GenericBound::Trait; use rustc_hir::QPath::Resolved; @@ -27,7 +27,7 @@ use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{Obligation, ObligationCtxt}; use tracing::{debug, instrument, trace}; -use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource}; +use super::{LIMITATION_NOTE, OutlivesSuggestionBuilder, RegionName, RegionNameSource}; use crate::nll::ConstraintDescription; use crate::region_infer::values::RegionElement; use crate::region_infer::{BlameConstraint, TypeTest}; @@ -36,7 +36,7 @@ use crate::session_diagnostics::{ LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote, }; use crate::universal_regions::DefiningTy; -use crate::{MirBorrowckCtxt, borrowck_errors, fluent_generated as fluent}; +use crate::{MirBorrowckCtxt, borrowck_errors}; impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { fn description(&self) -> &'static str { @@ -265,7 +265,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }) = bound else { return; }; - diag.span_note(*trait_span, fluent::borrowck_limitations_implies_static); + diag.span_note(*trait_span, LIMITATION_NOTE); let Some(generics_fn) = tcx.hir_get_generics(self.body.source.def_id().expect_local()) else { return; @@ -298,7 +298,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if suggestions.len() > 0 { suggestions.dedup(); diag.multipart_suggestion_verbose( - fluent::borrowck_restrict_to_static, + inline_fluent!("consider restricting the type parameter to the `'static` lifetime"), suggestions, Applicability::MaybeIncorrect, ); @@ -966,12 +966,20 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { debug!("trait spans found: {:?}", traits); for span in &traits { let mut multi_span: MultiSpan = vec![*span].into(); - multi_span.push_span_label(*span, fluent::borrowck_implicit_static); - multi_span.push_span_label(ident.span, fluent::borrowck_implicit_static_introduced); + multi_span.push_span_label( + *span, + inline_fluent!("this has an implicit `'static` lifetime requirement"), + ); + multi_span.push_span_label( + ident.span, + inline_fluent!( + "calling this method introduces the `impl`'s `'static` requirement" + ), + ); err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span }); err.span_suggestion_verbose( span.shrink_to_hi(), - fluent::borrowck_implicit_static_relax, + inline_fluent!("consider relaxing the implicit `'static` requirement"), " + '_", Applicability::MaybeIncorrect, ); @@ -1134,7 +1142,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if ocx.evaluate_obligations_error_on_ambiguity().is_empty() && count > 0 { diag.span_suggestion_verbose( tcx.hir_body(*body).value.peel_blocks().span.shrink_to_lo(), - fluent::borrowck_dereference_suggestion, + inline_fluent!("dereference the return value"), "*".repeat(count), Applicability::MachineApplicable, ); @@ -1178,7 +1186,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let Some(closure_span) = closure_span { diag.span_suggestion_verbose( closure_span, - fluent::borrowck_move_closure_suggestion, + inline_fluent!("consider adding 'move' keyword before the nested closure"), "move ", Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 7c5cbc58e25c..9186d82974d7 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -99,8 +99,6 @@ mod used_muts; /// A public API provided for the Rust compiler consumers. pub mod consumers; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - /// Associate some local constants with the `'tcx` lifetime struct TyCtxtConsts<'tcx>(PhantomData<&'tcx ()>); diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 5143b2fa2059..7bde534dafd2 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -7,16 +7,16 @@ use rustc_span::Span; use crate::diagnostics::RegionName; #[derive(Diagnostic)] -#[diag(borrowck_move_unsized, code = E0161)] +#[diag("cannot move a value of type `{$ty}`", code = E0161)] pub(crate) struct MoveUnsized<'tcx> { pub ty: Ty<'tcx>, #[primary_span] - #[label] + #[label("the size of `{$ty}` cannot be statically determined")] pub span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_higher_ranked_lifetime_error)] +#[diag("higher-ranked lifetime error")] pub(crate) struct HigherRankedLifetimeError { #[subdiagnostic] pub cause: Option, @@ -26,21 +26,21 @@ pub(crate) struct HigherRankedLifetimeError { #[derive(Subdiagnostic)] pub(crate) enum HigherRankedErrorCause { - #[note(borrowck_could_not_prove)] + #[note("could not prove `{$predicate}`")] CouldNotProve { predicate: String }, - #[note(borrowck_could_not_normalize)] + #[note("could not normalize `{$value}`")] CouldNotNormalize { value: String }, } #[derive(Diagnostic)] -#[diag(borrowck_higher_ranked_subtype_error)] +#[diag("higher-ranked subtype error")] pub(crate) struct HigherRankedSubtypeError { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_generic_does_not_live_long_enough)] +#[diag("`{$kind}` does not live long enough")] pub(crate) struct GenericDoesNotLiveLongEnough { pub kind: String, #[primary_span] @@ -48,15 +48,20 @@ pub(crate) struct GenericDoesNotLiveLongEnough { } #[derive(LintDiagnostic)] -#[diag(borrowck_var_does_not_need_mut)] +#[diag("variable does not need to be mutable")] pub(crate) struct VarNeedNotMut { - #[suggestion(style = "short", applicability = "machine-applicable", code = "")] + #[suggestion( + "remove this `mut`", + style = "short", + applicability = "machine-applicable", + code = "" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_var_cannot_escape_closure)] -#[note] -#[note(borrowck_cannot_escape)] +#[diag("captured variable cannot escape `FnMut` closure body")] +#[note("`FnMut` closures only have access to their captured variables while they are executing...")] +#[note("...therefore, they cannot allow references to captured variables to escape")] pub(crate) struct FnMutError { #[primary_span] pub span: Span, @@ -66,17 +71,17 @@ pub(crate) struct FnMutError { #[derive(Subdiagnostic)] pub(crate) enum VarHereDenote { - #[label(borrowck_var_here_captured)] + #[label("variable captured here")] Captured { #[primary_span] span: Span, }, - #[label(borrowck_var_here_defined)] + #[label("variable defined here")] Defined { #[primary_span] span: Span, }, - #[label(borrowck_closure_inferred_mut)] + #[label("inferred to be a `FnMut` closure")] FnMutInferred { #[primary_span] span: Span, @@ -85,17 +90,21 @@ pub(crate) enum VarHereDenote { #[derive(Subdiagnostic)] pub(crate) enum FnMutReturnTypeErr { - #[label(borrowck_returned_closure_escaped)] + #[label( + "returns a closure that contains a reference to a captured variable, which then escapes the closure body" + )] ReturnClosure { #[primary_span] span: Span, }, - #[label(borrowck_returned_async_block_escaped)] + #[label( + "returns an `async` block that contains a reference to a captured variable, which then escapes the closure body" + )] ReturnAsyncBlock { #[primary_span] span: Span, }, - #[label(borrowck_returned_ref_escaped)] + #[label("returns a reference to a captured variable which escapes the closure body")] ReturnRef { #[primary_span] span: Span, @@ -103,7 +112,7 @@ pub(crate) enum FnMutReturnTypeErr { } #[derive(Diagnostic)] -#[diag(borrowck_lifetime_constraints_error)] +#[diag("lifetime may not live long enough")] pub(crate) struct LifetimeOutliveErr { #[primary_span] pub span: Span, @@ -111,7 +120,9 @@ pub(crate) struct LifetimeOutliveErr { #[derive(Subdiagnostic)] pub(crate) enum LifetimeReturnCategoryErr<'a> { - #[label(borrowck_returned_lifetime_wrong)] + #[label( + "{$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}`" + )] WrongReturn { #[primary_span] span: Span, @@ -119,7 +130,9 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> { outlived_fr_name: RegionName, fr_name: &'a RegionName, }, - #[label(borrowck_returned_lifetime_short)] + #[label( + "{$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}`" + )] ShortReturn { #[primary_span] span: Span, @@ -131,7 +144,7 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> { #[derive(Subdiagnostic)] pub(crate) enum RequireStaticErr { - #[note(borrowck_used_impl_require_static)] + #[note("the used `impl` has a `'static` requirement")] UsedImpl { #[primary_span] multi_span: MultiSpan, @@ -140,42 +153,42 @@ pub(crate) enum RequireStaticErr { #[derive(Subdiagnostic)] pub(crate) enum CaptureVarPathUseCause { - #[label(borrowck_borrow_due_to_use_coroutine)] + #[label("borrow occurs due to use in coroutine")] BorrowInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_use_due_to_use_coroutine)] + #[label("use occurs due to use in coroutine")] UseInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_due_to_use_coroutine)] + #[label("assign occurs due to use in coroutine")] AssignInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_part_due_to_use_coroutine)] + #[label("assign to part occurs due to use in coroutine")] AssignPartInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_borrow_due_to_use_closure)] + #[label("borrow occurs due to use in closure")] BorrowInClosure { #[primary_span] path_span: Span, }, - #[label(borrowck_use_due_to_use_closure)] + #[label("use occurs due to use in closure")] UseInClosure { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_due_to_use_closure)] + #[label("assignment occurs due to use in closure")] AssignInClosure { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_part_due_to_use_closure)] + #[label("assignment to part occurs due to use in closure")] AssignPartInClosure { #[primary_span] path_span: Span, @@ -184,17 +197,17 @@ pub(crate) enum CaptureVarPathUseCause { #[derive(Subdiagnostic)] pub(crate) enum CaptureVarKind { - #[label(borrowck_capture_immute)] + #[label("capture is immutable because of use here")] Immut { #[primary_span] kind_span: Span, }, - #[label(borrowck_capture_mut)] + #[label("capture is mutable because of use here")] Mut { #[primary_span] kind_span: Span, }, - #[label(borrowck_capture_move)] + #[label("capture is moved because of use here")] Move { #[primary_span] kind_span: Span, @@ -203,77 +216,97 @@ pub(crate) enum CaptureVarKind { #[derive(Subdiagnostic)] pub(crate) enum CaptureVarCause { - #[label(borrowck_var_borrow_by_use_place_in_coroutine)] + #[label( + "{$is_single_var -> + *[true] borrow occurs + [false] borrows occur + } due to use of {$place} in coroutine" + )] BorrowUsePlaceCoroutine { is_single_var: bool, place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_borrow_by_use_place_in_closure)] + #[label( + "{$is_single_var -> + *[true] borrow occurs + [false] borrows occur + } due to use of {$place} in closure" + )] BorrowUsePlaceClosure { is_single_var: bool, place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_borrow_by_use_in_coroutine)] + #[label("borrow occurs due to use in coroutine")] BorrowUseInCoroutine { #[primary_span] var_span: Span, }, - #[label(borrowck_var_borrow_by_use_in_closure)] + #[label("borrow occurs due to use in closure")] BorrowUseInClosure { #[primary_span] var_span: Span, }, - #[label(borrowck_var_move_by_use_in_coroutine)] + #[label("move occurs due to use in coroutine")] MoveUseInCoroutine { #[primary_span] var_span: Span, }, - #[label(borrowck_var_move_by_use_in_closure)] + #[label("move occurs due to use in closure")] MoveUseInClosure { #[primary_span] var_span: Span, }, - #[label(borrowck_var_first_borrow_by_use_place_in_coroutine)] + #[label("first borrow occurs due to use of {$place} in coroutine")] FirstBorrowUsePlaceCoroutine { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_first_borrow_by_use_place_in_closure)] + #[label("first borrow occurs due to use of {$place} in closure")] FirstBorrowUsePlaceClosure { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_second_borrow_by_use_place_in_coroutine)] + #[label("second borrow occurs due to use of {$place} in coroutine")] SecondBorrowUsePlaceCoroutine { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_second_borrow_by_use_place_in_closure)] + #[label("second borrow occurs due to use of {$place} in closure")] SecondBorrowUsePlaceClosure { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_mutable_borrow_by_use_place_in_closure)] + #[label("mutable borrow occurs due to use of {$place} in closure")] MutableBorrowUsePlaceClosure { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_partial_var_move_by_use_in_coroutine)] + #[label( + "variable {$is_partial -> + [true] partially moved + *[false] moved + } due to use in coroutine" + )] PartialMoveUseInCoroutine { #[primary_span] var_span: Span, is_partial: bool, }, - #[label(borrowck_partial_var_move_by_use_in_closure)] + #[label( + "variable {$is_partial -> + [true] partially moved + *[false] moved + } due to use in closure" + )] PartialMoveUseInClosure { #[primary_span] var_span: Span, @@ -282,34 +315,57 @@ pub(crate) enum CaptureVarCause { } #[derive(Diagnostic)] -#[diag(borrowck_cannot_move_when_borrowed, code = E0505)] +#[diag("cannot move out of {$place -> + [value] value + *[other] {$place} +} because it is borrowed", code = E0505)] pub(crate) struct MoveBorrow<'a> { pub place: &'a str, pub borrow_place: &'a str, pub value_place: &'a str, #[primary_span] - #[label(borrowck_move_label)] + #[label( + "move out of {$value_place -> + [value] value + *[other] {$value_place} + } occurs here" + )] pub span: Span, - #[label] + #[label( + "borrow of {$borrow_place -> + [value] value + *[other] {$borrow_place} + } occurs here" + )] pub borrow_span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_opaque_type_lifetime_mismatch)] +#[diag("opaque type used twice with different lifetimes")] pub(crate) struct LifetimeMismatchOpaqueParam<'tcx> { pub arg: GenericArg<'tcx>, pub prev: GenericArg<'tcx>, #[primary_span] - #[label] - #[note] + #[label("lifetime `{$arg}` used here")] + #[note( + "if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types" + )] pub span: Span, - #[label(borrowck_prev_lifetime_label)] + #[label("lifetime `{$prev}` previously used here")] pub prev_span: Span, } #[derive(Subdiagnostic)] pub(crate) enum CaptureReasonLabel<'a> { - #[label(borrowck_moved_due_to_call)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this {$is_loop_message -> + [true] call, in previous iteration of loop + *[false] call + }" + )] Call { #[primary_span] fn_call_span: Span, @@ -317,7 +373,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_usage_in_operator)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to usage in {$is_loop_message -> + [true] operator, in previous iteration of loop + *[false] operator + }" + )] OperatorUse { #[primary_span] fn_call_span: Span, @@ -325,7 +389,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_implicit_into_iter_call)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this implicit call to {$is_loop_message -> + [true] `.into_iter()`, in previous iteration of loop + *[false] `.into_iter()` + }" + )] ImplicitCall { #[primary_span] fn_call_span: Span, @@ -333,7 +405,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_method_call)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this method {$is_loop_message -> + [true] call, in previous iteration of loop + *[false] call + }" + )] MethodCall { #[primary_span] fn_call_span: Span, @@ -341,7 +421,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_await)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this {$is_loop_message -> + [true] await, in previous iteration of loop + *[false] await + }" + )] Await { #[primary_span] fn_call_span: Span, @@ -349,7 +437,18 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_value_moved_here)] + #[label( + "value {$is_partial -> + [true] partially moved + *[false] moved + } {$is_move_msg -> + [true] into closure here + *[false] here + }{$is_loop_message -> + [true] , in previous iteration of loop + *[false] {\"\"} + }" + )] MovedHere { #[primary_span] move_span: Span, @@ -357,7 +456,7 @@ pub(crate) enum CaptureReasonLabel<'a> { is_move_msg: bool, is_loop_message: bool, }, - #[label(borrowck_consider_borrow_type_contents)] + #[label("help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents")] BorrowContent { #[primary_span] var_span: Span, @@ -366,22 +465,22 @@ pub(crate) enum CaptureReasonLabel<'a> { #[derive(Subdiagnostic)] pub(crate) enum CaptureReasonNote { - #[note(borrowck_moved_a_fn_once_in_call)] + #[note("this value implements `FnOnce`, which causes it to be moved when called")] FnOnceMoveInCall { #[primary_span] var_span: Span, }, - #[note(borrowck_calling_operator_moves)] + #[note("calling this operator moves the value")] UnOpMoveByOperator { #[primary_span] span: Span, }, - #[note(borrowck_calling_operator_moves_lhs)] + #[note("calling this operator moves the left-hand side")] LhsMoveByOperator { #[primary_span] span: Span, }, - #[note(borrowck_func_take_self_moved_place)] + #[note("`{$func}` takes ownership of the receiver `self`, which moves {$place_name}")] FuncTakeSelf { func: String, place_name: String, @@ -393,7 +492,7 @@ pub(crate) enum CaptureReasonNote { #[derive(Subdiagnostic)] pub(crate) enum CaptureReasonSuggest<'tcx> { #[suggestion( - borrowck_suggest_iterate_over_slice, + "consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop", applicability = "maybe-incorrect", code = "&", style = "verbose" @@ -404,7 +503,7 @@ pub(crate) enum CaptureReasonSuggest<'tcx> { span: Span, }, #[suggestion( - borrowck_suggest_create_fresh_reborrow, + "consider reborrowing the `Pin` instead of moving it", applicability = "maybe-incorrect", code = ".as_mut()", style = "verbose" @@ -417,13 +516,18 @@ pub(crate) enum CaptureReasonSuggest<'tcx> { #[derive(Subdiagnostic)] pub(crate) enum CaptureArgLabel { - #[label(borrowck_value_capture_here)] + #[label( + "value captured {$is_within -> + [true] here by coroutine + *[false] here + }" + )] Capture { is_within: bool, #[primary_span] args_span: Span, }, - #[label(borrowck_move_out_place_here)] + #[label("{$place} is moved here")] MoveOutPlace { place: String, #[primary_span] @@ -433,13 +537,17 @@ pub(crate) enum CaptureArgLabel { #[derive(Subdiagnostic)] pub(crate) enum OnClosureNote<'a> { - #[note(borrowck_closure_invoked_twice)] + #[note( + "closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment" + )] InvokedTwice { place_name: &'a str, #[primary_span] span: Span, }, - #[note(borrowck_closure_moved_twice)] + #[note( + "closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment" + )] MovedTwice { place_name: &'a str, #[primary_span] @@ -449,7 +557,12 @@ pub(crate) enum OnClosureNote<'a> { #[derive(Subdiagnostic)] pub(crate) enum TypeNoCopy<'a, 'tcx> { - #[label(borrowck_ty_no_impl_copy)] + #[label( + "{$is_partial_move -> + [true] partial move + *[false] move + } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait" + )] Label { is_partial_move: bool, ty: Ty<'tcx>, @@ -457,12 +570,24 @@ pub(crate) enum TypeNoCopy<'a, 'tcx> { #[primary_span] span: Span, }, - #[note(borrowck_ty_no_impl_copy)] + #[note( + "{$is_partial_move -> + [true] partial move + *[false] move + } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait" + )] Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str }, } #[derive(Diagnostic)] -#[diag(borrowck_simd_intrinsic_arg_const)] +#[diag( + "{$arg -> + [1] 1st + [2] 2nd + [3] 3rd + *[other] {$arg}th + } argument of `{$intrinsic}` is required to be a `const` item" +)] pub(crate) struct SimdIntrinsicArgConst { #[primary_span] pub span: Span, @@ -471,8 +596,8 @@ pub(crate) struct SimdIntrinsicArgConst { } #[derive(LintDiagnostic)] -#[diag(borrowck_tail_expr_drop_order)] +#[diag("relative drop order changing in Rust 2024")] pub(crate) struct TailExprDropOrder { - #[label] + #[label("this temporary value will be dropped at the end of the block")] pub borrowed: Span, } diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 39e512be6820..be77b879757c 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -10,7 +10,6 @@ jiff = { version = "0.2.5", default-features = false, features = ["std"] } rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } -rustc_borrowck = { path = "../rustc_borrowck" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_const_eval = { path = "../rustc_const_eval" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 2e97b4fed245..3b19ee3c672c 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -114,7 +114,6 @@ pub fn default_translator() -> Translator { pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ // tidy-alphabetical-start - rustc_borrowck::DEFAULT_LOCALE_RESOURCE, rustc_const_eval::DEFAULT_LOCALE_RESOURCE, rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE, rustc_lint::DEFAULT_LOCALE_RESOURCE, From 6782a190f22df03d1106f4d4c1aa907c016ddebb Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 4 Feb 2026 17:17:45 +0100 Subject: [PATCH 578/978] Register functions in translation --- compiler/rustc_error_messages/src/lib.rs | 2 +- compiler/rustc_errors/src/translation.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index c9e887061305..641defd1eabf 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -192,7 +192,7 @@ pub fn fluent_bundle( Ok(Some(bundle)) } -fn register_functions(bundle: &mut FluentBundle) { +pub fn register_functions(bundle: &mut fluent_bundle::bundle::FluentBundle) { bundle .add_function("STREQ", |positional, _named| match positional { [FluentValue::String(a), FluentValue::String(b)] => format!("{}", (a == b)).into(), diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index aba79c30f3a3..ed3f9a405342 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -3,8 +3,8 @@ use std::env; use std::error::Report; use std::sync::Arc; -use rustc_error_messages::langid; pub use rustc_error_messages::{FluentArgs, LazyFallbackBundle}; +use rustc_error_messages::{langid, register_functions}; use tracing::{debug, trace}; use crate::error::{TranslateError, TranslateErrorKind}; @@ -91,6 +91,7 @@ impl Translator { let mut bundle = fluent_bundle::FluentBundle::new(vec![langid!("en-US")]); bundle.set_use_isolating(false); bundle.add_resource(resource).unwrap(); + register_functions(&mut bundle); let message = bundle.get_message(GENERATED_MSG_ID).unwrap(); let value = message.value().unwrap(); From 55d1ba12d9df062e4ee6543f06657716028b5bbd Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 4 Feb 2026 17:17:54 +0100 Subject: [PATCH 579/978] Convert to inline diagnostics in `rustc_trait_selection` --- Cargo.lock | 2 - compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_trait_selection/Cargo.toml | 1 - compiler/rustc_trait_selection/messages.ftl | 470 ------------ .../src/error_reporting/infer/region.rs | 37 +- .../traits/fulfillment_errors.rs | 4 +- .../traits/on_unimplemented.rs | 18 +- .../traits/on_unimplemented_format.rs | 18 +- compiler/rustc_trait_selection/src/errors.rs | 704 +++++++++++++----- .../src/errors/note_and_explain.rs | 38 +- compiler/rustc_trait_selection/src/lib.rs | 2 - .../src/traits/normalize.rs | 3 +- 13 files changed, 586 insertions(+), 713 deletions(-) delete mode 100644 compiler/rustc_trait_selection/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 23abc6626aab..a2a475b8011c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3797,7 +3797,6 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "rustc_trait_selection", "serde_json", "shlex", "tracing", @@ -4724,7 +4723,6 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_infer", "rustc_macros", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 39e512be6820..4fdac2b3da4e 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -36,7 +36,6 @@ rustc_resolve = { path = "../rustc_resolve" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -rustc_trait_selection = { path = "../rustc_trait_selection" } serde_json = "1.0.59" shlex = "1.0" tracing = { version = "0.1.35" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 2e97b4fed245..83f502cf72d5 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -121,7 +121,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_mir_build::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE, rustc_passes::DEFAULT_LOCALE_RESOURCE, - rustc_trait_selection::DEFAULT_LOCALE_RESOURCE, // tidy-alphabetical-end ]; diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 1071105522d1..cd61a8f65473 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -10,7 +10,6 @@ rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_infer = { path = "../rustc_infer" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl deleted file mode 100644 index fcb250250871..000000000000 --- a/compiler/rustc_trait_selection/messages.ftl +++ /dev/null @@ -1,470 +0,0 @@ -trait_selection_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime -> - [true] , for some specific lifetime `'{$lifetime}` - *[false] {""} -} -trait_selection_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime -> - [true] , for some specific lifetime `'{$lifetime}` - *[false] {""} -} -trait_selection_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime -> - [true] , for some specific lifetime `'{$lifetime}` - *[false] {""} -} - -trait_selection_actual_impl_expl_expected_other_any = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_other_nothing = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}` - -trait_selection_actual_impl_expl_expected_other_some = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_other_two = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... -trait_selection_actual_impl_expl_expected_passive_any = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}` -trait_selection_actual_impl_expl_expected_passive_some = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_passive_two = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... -trait_selection_actual_impl_expl_expected_signature_any = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}` -trait_selection_actual_impl_expl_expected_signature_some = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_signature_two = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... -trait_selection_adjust_signature_borrow = consider adjusting the signature so it borrows its {$len -> - [one] argument - *[other] arguments - } - -trait_selection_adjust_signature_remove_borrow = consider adjusting the signature so it does not borrow its {$len -> - [one] argument - *[other] arguments - } - -trait_selection_ascribe_user_type_prove_predicate = ...so that the where clause holds - -trait_selection_await_both_futures = consider `await`ing on both `Future`s -trait_selection_await_future = consider `await`ing on the `Future` -trait_selection_await_note = calling an async function returns a future - -trait_selection_but_calling_introduces = {$has_param_name -> - [true] `{$param_name}` - *[false] `fn` parameter -} has {$lifetime_kind -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` -} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement - .label1 = {$has_lifetime -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` - } - .label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path -> - [true] `impl` of `{$impl_path}` - *[false] inherent `impl` - } - -trait_selection_but_needs_to_satisfy = {$has_param_name -> - [true] `{$param_name}` - *[false] `fn` parameter -} has {$has_lifetime -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` -} but it needs to satisfy a `'static` lifetime requirement - .influencer = this data with {$has_lifetime -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` - }... - .require = {$spans_empty -> - *[true] ...is used and required to live as long as `'static` here - [false] ...and is required to live as long as `'static` here - } - .used_here = ...is used here... - .introduced_by_bound = `'static` lifetime requirement introduced by this bound - -trait_selection_closure_fn_mut_label = closure is `{$trait_prefix}FnMut` because it mutates the variable `{$place}` here - -trait_selection_closure_fn_once_label = closure is `{$trait_prefix}FnOnce` because it moves the variable `{$place}` out of its environment - -trait_selection_closure_kind_mismatch = expected a closure that implements the `{$trait_prefix}{$expected}` trait, but this closure only implements `{$trait_prefix}{$found}` - .label = this closure implements `{$trait_prefix}{$found}`, not `{$trait_prefix}{$expected}` - -trait_selection_closure_kind_requirement = the requirement to implement `{$trait_prefix}{$expected}` derives from here - -trait_selection_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait -trait_selection_consider_specifying_length = consider specifying the actual array length -trait_selection_coro_closure_not_fn = {$coro_kind}closure does not implement `{$kind}` because it captures state from its environment - -trait_selection_data_flows = ...but data{$label_var1_exists -> - [true] {" "}from `{$label_var1}` - *[false] {""} -} flows{$label_var2_exists -> - [true] {" "}into `{$label_var2}` - *[false] {""} -} here - -trait_selection_data_lifetime_flow = ...but data with one lifetime flows into the other here -trait_selection_data_returned = ...but data{$label_var1_exists -> - [true] {" "}from `{$label_var1}` - *[false] {""} -} is returned here - -trait_selection_declared_different = this parameter and the return type are declared with different lifetimes... -trait_selection_declared_multiple = this type is declared with multiple lifetimes... -trait_selection_disallowed_positional_argument = positional format arguments are not allowed here - .help = only named format arguments with the name of one of the generic types are allowed in this context - -trait_selection_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl` -trait_selection_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement -trait_selection_dtcs_has_req_note = the used `impl` has a `'static` requirement -trait_selection_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement -trait_selection_dtcs_suggestion = consider relaxing the implicit `'static` requirement - -trait_selection_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}` - -trait_selection_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type - -trait_selection_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}` - .label = lifetime `{$named}` required - -trait_selection_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type - .label = lifetime `{$named}` required - -trait_selection_fn_consider_casting = consider casting the fn item to a fn pointer: `{$casting}` - -trait_selection_fn_consider_casting_both = consider casting both fn items to fn pointers using `as {$sig}` - -trait_selection_fn_uniq_types = different fn items have unique types, even if their signatures are the same -trait_selection_fps_cast = consider casting to a fn pointer -trait_selection_fps_cast_both = consider casting both fn items to fn pointers using `as {$expected_sig}` - -trait_selection_fps_items_are_distinct = fn items are distinct from fn pointers -trait_selection_fps_remove_ref = consider removing the reference -trait_selection_fps_use_ref = consider using a reference -trait_selection_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime - -trait_selection_ignored_diagnostic_option = `{$option_name}` is ignored due to previous definition of `{$option_name}` - .other_label = `{$option_name}` is first declared here - .label = `{$option_name}` is already declared here - -trait_selection_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement -trait_selection_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement -trait_selection_inherent_projection_normalization_overflow = overflow evaluating associated type `{$ty}` - -trait_selection_invalid_format_specifier = invalid format specifier - .help = no format specifier are supported in this position - -trait_selection_label_bad = {$bad_kind -> - *[other] cannot infer type - [more_info] cannot infer {$prefix_kind -> - *[type] type for {$prefix} - [const_with_param] the value of const parameter - [const] the value of the constant - } `{$name}`{$has_parent -> - [true] {" "}declared on the {$parent_prefix} `{$parent_name}` - *[false] {""} - } -} - -trait_selection_lf_bound_not_satisfied = lifetime bound not satisfied -trait_selection_lifetime_mismatch = lifetime mismatch - -trait_selection_lifetime_param_suggestion = consider {$is_reuse -> - [true] reusing - *[false] introducing -} a named lifetime parameter{$is_impl -> - [true] {" "}and update trait if needed - *[false] {""} -} -trait_selection_lifetime_param_suggestion_elided = each elided lifetime in input position becomes a distinct lifetime - -trait_selection_malformed_on_unimplemented_attr = malformed `on_unimplemented` attribute - .help = only `message`, `note` and `label` are allowed as options - .label = invalid option found here - -trait_selection_meant_byte_literal = if you meant to write a byte literal, prefix with `b` -trait_selection_meant_char_literal = if you meant to write a `char` literal, use single quotes -trait_selection_meant_str_literal = if you meant to write a string literal, use double quotes -trait_selection_mismatched_static_lifetime = incompatible lifetime on type -trait_selection_missing_options_for_on_unimplemented_attr = missing options for `on_unimplemented` attribute - .help = at least one of the `message`, `note` and `label` options are expected - -trait_selection_msl_introduces_static = introduces a `'static` lifetime requirement -trait_selection_msl_unmet_req = because this has an unmet lifetime requirement - -trait_selection_negative_positive_conflict = found both positive and negative implementation of trait `{$trait_desc}`{$self_desc -> - [none] {""} - *[default] {" "}for type `{$self_desc}` - }: - .negative_implementation_here = negative implementation here - .negative_implementation_in_crate = negative implementation in crate `{$negative_impl_cname}` - .positive_implementation_here = positive implementation here - .positive_implementation_in_crate = positive implementation in crate `{$positive_impl_cname}` - -trait_selection_nothing = {""} - -trait_selection_oc_cant_coerce_force_inline = - cannot coerce functions which must be inlined to function pointers -trait_selection_oc_cant_coerce_intrinsic = cannot coerce intrinsics to function pointers -trait_selection_oc_closure_selfref = closure/coroutine type that references itself -trait_selection_oc_const_compat = const not compatible with trait -trait_selection_oc_fn_lang_correct_type = {$lang_item_name -> - [panic_impl] `#[panic_handler]` - *[lang_item_name] lang item `{$lang_item_name}` - } function has wrong type -trait_selection_oc_fn_main_correct_type = `main` function has wrong type -trait_selection_oc_generic = mismatched types - -trait_selection_oc_if_else_different = `if` and `else` have incompatible types -trait_selection_oc_intrinsic_correct_type = intrinsic has wrong type -trait_selection_oc_match_compat = `match` arms have incompatible types -trait_selection_oc_method_compat = method not compatible with trait -trait_selection_oc_method_correct_type = mismatched `self` parameter type -trait_selection_oc_no_diverge = `else` clause of `let...else` does not diverge -trait_selection_oc_no_else = `if` may be missing an `else` clause -trait_selection_oc_try_compat = `?` operator has incompatible types -trait_selection_oc_type_compat = type not compatible with trait - -trait_selection_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds - .label = opaque type defined here -trait_selection_opaque_type_non_generic_param = - expected generic {$kind} parameter, found `{$arg}` - .label = {STREQ($arg, "'static") -> - [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type - *[other] this generic parameter must be used with a generic {$kind} parameter - } - -trait_selection_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type -trait_selection_outlives_content = lifetime of reference outlives lifetime of borrowed content... - -trait_selection_precise_capturing_existing = add `{$new_lifetime}` to the `use<...>` bound to explicitly capture it -trait_selection_precise_capturing_new = add a `use<...>` bound to explicitly capture `{$new_lifetime}` - -trait_selection_precise_capturing_new_but_apit = add a `use<...>` bound to explicitly capture `{$new_lifetime}` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate - -trait_selection_precise_capturing_overcaptures = use the precise capturing `use<...>` syntax to make the captures explicit - -trait_selection_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here... -trait_selection_prlf_defined_without_sub = the lifetime defined here... -trait_selection_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 for more information) - -trait_selection_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here -trait_selection_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here -trait_selection_reborrow = ...so that reference does not outlive borrowed content -trait_selection_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references - -trait_selection_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at -trait_selection_region_explanation = {$pref_kind -> - *[should_not_happen] [{$pref_kind}] - [ref_valid_for] ...the reference is valid for - [content_valid_for] ...but the borrowed content is only valid for - [type_obj_valid_for] object type is valid for - [source_pointer_valid_for] source pointer is only valid for - [type_satisfy] type must satisfy - [type_outlive] type must outlive - [lf_param_instantiated_with] lifetime parameter instantiated with - [lf_param_must_outlive] but lifetime parameter must outlive - [lf_instantiated_with] lifetime instantiated with - [lf_must_outlive] but lifetime must outlive - [pointer_valid_for] the pointer is valid for - [data_valid_for] but the referenced data is only valid for - [empty] {""} -}{$pref_kind -> - [empty] {""} - *[other] {" "} -}{$desc_kind -> - *[should_not_happen] [{$desc_kind}] - [restatic] the static lifetime - [revar] lifetime {$desc_arg} - [as_defined] the lifetime `{$desc_arg}` as defined here - [as_defined_anon] the anonymous lifetime as defined here - [defined_here] the anonymous lifetime defined here - [defined_here_reg] the lifetime `{$desc_arg}` as defined here -}{$suff_kind -> - *[should_not_happen] [{$suff_kind}] - [empty]{""} - [continues] ... - [req_by_binding] {" "}as required by this binding -} - -trait_selection_relate_object_bound = ...so that it can be closed over into an object -trait_selection_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues -> - [true] ... - *[false] {""} -} -trait_selection_relate_param_bound_2 = ...that is required by this bound -trait_selection_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied -trait_selection_ril_because_of = because of this returned expression -trait_selection_ril_introduced_by = requirement introduced by this return type -trait_selection_ril_introduced_here = `'static` requirement introduced here -trait_selection_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type - -trait_selection_rustc_on_unimplemented_empty_on_clause = empty `on`-clause in `#[rustc_on_unimplemented]` - .label = empty `on`-clause here -trait_selection_rustc_on_unimplemented_expected_identifier = expected an identifier inside this `on`-clause - .label = expected an identifier here, not `{$path}` -trait_selection_rustc_on_unimplemented_expected_one_predicate_in_not = expected a single predicate in `not(..)` - .label = unexpected quantity of predicates here -trait_selection_rustc_on_unimplemented_invalid_flag = invalid flag in `on`-clause - .label = expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}` -trait_selection_rustc_on_unimplemented_invalid_name = invalid name in `on`-clause - .label = expected one of `cause`, `from_desugaring`, `Self` or any generic parameter of the trait, not `{$invalid_name}` -trait_selection_rustc_on_unimplemented_invalid_predicate = this predicate is invalid - .label = expected one of `any`, `all` or `not` here, not `{$invalid_pred}` -trait_selection_rustc_on_unimplemented_missing_value = this attribute must have a value - .label = expected value here - .note = e.g. `#[rustc_on_unimplemented(message="foo")]` -trait_selection_rustc_on_unimplemented_unsupported_literal_in_on = literals inside `on`-clauses are not supported - .label = unexpected literal here - -trait_selection_source_kind_closure_return = - try giving this closure an explicit return type - -# coroutine_kind may need to be translated -trait_selection_source_kind_fully_qualified = - try using a fully qualified path to specify the expected types - -trait_selection_source_kind_subdiag_generic_label = - cannot infer {$is_type -> - [true] type - *[false] the value - } of the {$is_type -> - [true] type - *[false] const - } {$parent_exists -> - [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}` - *[false] parameter {$param_name} - } - -trait_selection_source_kind_subdiag_generic_suggestion = - consider specifying the generic {$arg_count -> - [one] argument - *[other] arguments - } - -trait_selection_source_kind_subdiag_let = {$kind -> - [with_pattern] consider giving `{$name}` an explicit type - [closure] consider giving this closure parameter an explicit type - *[other] consider giving this pattern a type -}{$x_kind -> - [has_name] , where the {$prefix_kind -> - *[type] type for {$prefix} - [const_with_param] value of const parameter - [const] value of the constant - } `{$arg_name}` is specified - [underscore] , where the placeholders `_` are specified - *[empty] {""} -} - -trait_selection_srs_add = consider returning the local binding `{$ident}` -trait_selection_srs_add_one = consider returning one of these bindings - -trait_selection_srs_remove = consider removing this semicolon -trait_selection_srs_remove_and_box = consider removing this semicolon and boxing the expressions -trait_selection_stp_wrap_many = try wrapping the pattern in a variant of `{$path}` - -trait_selection_stp_wrap_one = try wrapping the pattern in `{$variant}` -trait_selection_subtype = ...so that the {$requirement -> - [method_compat] method type is compatible with trait - [type_compat] associated type is compatible with trait - [const_compat] const is compatible with trait - [expr_assignable] expression is assignable - [if_else_different] `if` and `else` have incompatible types - [no_else] `if` missing an `else` returns `()` - [fn_main_correct_type] `main` function has the correct type - [fn_lang_correct_type] lang item function has the correct type - [intrinsic_correct_type] intrinsic has the correct type - [method_correct_type] method receiver has the correct type - *[other] types are compatible -} -trait_selection_subtype_2 = ...so that {$requirement -> - [method_compat] method type is compatible with trait - [type_compat] associated type is compatible with trait - [const_compat] const is compatible with trait - [expr_assignable] expression is assignable - [if_else_different] `if` and `else` have incompatible types - [no_else] `if` missing an `else` returns `()` - [fn_main_correct_type] `main` function has the correct type - [fn_lang_correct_type] lang item function has the correct type - [intrinsic_correct_type] intrinsic has the correct type - [method_correct_type] method receiver has the correct type - *[other] types are compatible -} - -trait_selection_suggest_accessing_field = you might have meant to use field `{$name}` whose type is `{$ty}` - -trait_selection_suggest_add_let_for_letchains = consider adding `let` - -trait_selection_tid_consider_borrowing = consider borrowing this type parameter in the trait -trait_selection_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` - -trait_selection_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output -trait_selection_trait_has_no_impls = this trait has no implementations, consider adding one - -trait_selection_trait_impl_diff = `impl` item signature doesn't match `trait` item signature - .found = found `{$found}` - .expected = expected `{$expected}` - .expected_found = expected signature `{$expected}` - {" "}found signature `{$found}` - -trait_selection_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough - .label_satisfy = doesn't satisfy where-clause - .label_where = due to a where-clause on `{$def_id}`... - .label_dup = implementation of `{$trait_def_id}` is not general enough - -trait_selection_try_cannot_convert = `?` operator cannot convert from `{$found}` to `{$expected}` - -trait_selection_tuple_trailing_comma = use a trailing comma to create a tuple with one element - -trait_selection_ty_alias_overflow = in case this is a recursive type alias, consider using a struct, enum, or union instead -trait_selection_type_annotations_needed = {$source_kind -> - [closure] type annotations needed for the closure `{$source_name}` - [normal] type annotations needed for `{$source_name}` - *[other] type annotations needed -} - .label = type must be known at this point - -trait_selection_types_declared_different = these two types are declared with different lifetimes... - -trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated} - -trait_selection_unknown_format_parameter_for_on_unimplemented_attr = there is no parameter `{$argument_name}` on trait `{$trait_name}` - .help = expect either a generic argument name or {"`{Self}`"} as format argument - -trait_selection_warn_removing_apit_params_for_overcapture = you could use a `use<...>` bound to explicitly specify captures, but argument-position `impl Trait`s are not nameable - -trait_selection_warn_removing_apit_params_for_undercapture = you could use a `use<...>` bound to explicitly capture `{$new_lifetime}`, but argument-position `impl Trait`s are not nameable - -trait_selection_where_copy_predicates = copy the `where` clause predicates from the trait - -trait_selection_where_remove = remove the `where` clause -trait_selection_wrapped_parser_error = {$description} - .label = {$label} diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index b11461cd0e32..d15fb40dd1cb 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -2,7 +2,8 @@ use std::iter; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ - Applicability, Diag, E0309, E0310, E0311, E0803, Subdiagnostic, struct_span_code_err, + Applicability, Diag, E0309, E0310, E0311, E0803, Subdiagnostic, inline_fluent, + struct_span_code_err, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -25,7 +26,6 @@ use crate::errors::{ self, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent, RefLongerThanData, RegionOriginNote, WhereClauseSuggestions, note_and_explain, }; -use crate::fluent_generated as fluent; use crate::infer::region_constraints::GenericKind; use crate::infer::{ BoundRegionConversionTime, InferCtxt, RegionResolutionError, RegionVariableOrigin, @@ -228,18 +228,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { expected_found: self.values_str(trace.values, &trace.cause, err.long_ty_path()), } .add_to_diag(err), - SubregionOrigin::Reborrow(span) => { - RegionOriginNote::Plain { span, msg: fluent::trait_selection_reborrow } - .add_to_diag(err) + SubregionOrigin::Reborrow(span) => RegionOriginNote::Plain { + span, + msg: inline_fluent!("...so that reference does not outlive borrowed content"), } + .add_to_diag(err), SubregionOrigin::RelateObjectBound(span) => { - RegionOriginNote::Plain { span, msg: fluent::trait_selection_relate_object_bound } - .add_to_diag(err); + RegionOriginNote::Plain { + span, + msg: inline_fluent!("...so that it can be closed over into an object"), + } + .add_to_diag(err); } SubregionOrigin::ReferenceOutlivesReferent(ty, span) => { RegionOriginNote::WithName { span, - msg: fluent::trait_selection_reference_outlives_referent, + msg: inline_fluent!("...so that the reference type `{$name}` does not outlive the data it points at"), name: &self.ty_to_string(ty), continues: false, } @@ -248,7 +252,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::RelateParamBound(span, ty, opt_span) => { RegionOriginNote::WithName { span, - msg: fluent::trait_selection_relate_param_bound, + msg: inline_fluent!("...so that the type `{$name}` will meet its required lifetime bounds{$continues -> +[true] ... +*[false] {\"\"} +}"), name: &self.ty_to_string(ty), continues: opt_span.is_some(), } @@ -256,7 +263,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(span) = opt_span { RegionOriginNote::Plain { span, - msg: fluent::trait_selection_relate_param_bound_2, + msg: inline_fluent!("...that is required by this bound"), } .add_to_diag(err); } @@ -264,14 +271,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::RelateRegionParamBound(span, _) => { RegionOriginNote::Plain { span, - msg: fluent::trait_selection_relate_region_param_bound, + msg: inline_fluent!( + "...so that the declared lifetime parameter bounds are satisfied" + ), } .add_to_diag(err); } SubregionOrigin::CompareImplItemObligation { span, .. } => { RegionOriginNote::Plain { span, - msg: fluent::trait_selection_compare_impl_item_obligation, + msg: inline_fluent!( + "...so that the definition in impl matches the definition from the trait" + ), } .add_to_diag(err); } @@ -281,7 +292,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::AscribeUserTypeProvePredicate(span) => { RegionOriginNote::Plain { span, - msg: fluent::trait_selection_ascribe_user_type_prove_predicate, + msg: inline_fluent!("...so that the where clause holds"), } .add_to_diag(err); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 45e4f5fe23a6..3cb3224302b6 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -12,7 +12,7 @@ use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions, - pluralize, struct_span_code_err, + inline_fluent, pluralize, struct_span_code_err, }; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::intravisit::Visitor; @@ -3003,7 +3003,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { err.span_help( self.tcx.def_span(trait_def_id), - crate::fluent_generated::trait_selection_trait_has_no_impls, + inline_fluent!("this trait has no implementations, consider adding one"), ); } else if !suggested && trait_predicate.polarity() == ty::PredicatePolarity::Positive { // Can't show anything else useful, try to find similar impls. diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 0a6af42e122b..5eff7bba7c63 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -360,10 +360,10 @@ pub enum AppendConstMessage { } #[derive(LintDiagnostic)] -#[diag(trait_selection_malformed_on_unimplemented_attr)] -#[help] +#[diag("malformed `on_unimplemented` attribute")] +#[help("only `message`, `note` and `label` are allowed as options")] pub struct MalformedOnUnimplementedAttrLint { - #[label] + #[label("invalid option found here")] pub span: Span, } @@ -374,17 +374,17 @@ impl MalformedOnUnimplementedAttrLint { } #[derive(LintDiagnostic)] -#[diag(trait_selection_missing_options_for_on_unimplemented_attr)] -#[help] +#[diag("missing options for `on_unimplemented` attribute")] +#[help("at least one of the `message`, `note` and `label` options are expected")] pub struct MissingOptionsForOnUnimplementedAttr; #[derive(LintDiagnostic)] -#[diag(trait_selection_ignored_diagnostic_option)] +#[diag("`{$option_name}` is ignored due to previous definition of `{$option_name}`")] pub struct IgnoredDiagnosticOption { pub option_name: &'static str, - #[label] + #[label("`{$option_name}` is already declared here")] pub span: Span, - #[label(trait_selection_other_label)] + #[label("`{$option_name}` is first declared here")] pub prev_span: Span, } @@ -410,7 +410,7 @@ impl IgnoredDiagnosticOption { } #[derive(LintDiagnostic)] -#[diag(trait_selection_wrapped_parser_error)] +#[diag("{$description}")] pub struct WrappedParserError { pub description: String, pub label: String, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs index 1954f8a1f639..8488d76e2c77 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs @@ -310,25 +310,27 @@ pub mod errors { use super::*; #[derive(LintDiagnostic)] - #[diag(trait_selection_unknown_format_parameter_for_on_unimplemented_attr)] - #[help] + #[diag("there is no parameter `{$argument_name}` on trait `{$trait_name}`")] + #[help("expect either a generic argument name or {\"`{Self}`\"} as format argument")] pub struct UnknownFormatParameterForOnUnimplementedAttr { pub argument_name: Symbol, pub trait_name: Ident, } #[derive(LintDiagnostic)] - #[diag(trait_selection_disallowed_positional_argument)] - #[help] + #[diag("positional format arguments are not allowed here")] + #[help( + "only named format arguments with the name of one of the generic types are allowed in this context" + )] pub struct DisallowedPositionalArgument; #[derive(LintDiagnostic)] - #[diag(trait_selection_invalid_format_specifier)] - #[help] + #[diag("invalid format specifier")] + #[help("no format specifier are supported in this position")] pub struct InvalidFormatSpecifier; #[derive(LintDiagnostic)] - #[diag(trait_selection_missing_options_for_on_unimplemented_attr)] - #[help] + #[diag("missing options for `on_unimplemented` attribute")] + #[help("at least one of the `message`, `note` and `label` options are expected")] pub struct MissingOptionsForOnUnimplementedAttr; } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index af241099c014..e0690b8a6245 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -3,7 +3,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, - EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, + EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, inline_fluent, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -17,12 +17,11 @@ use rustc_span::{BytePos, Ident, Span, Symbol, kw}; use crate::error_reporting::infer::ObligationCauseAsDiagArg; use crate::error_reporting::infer::need_type_info::UnderspecifiedArgKind; use crate::error_reporting::infer::nice_region_error::placeholder_error::Highlighted; -use crate::fluent_generated as fluent; pub mod note_and_explain; #[derive(Diagnostic)] -#[diag(trait_selection_unable_to_construct_constant_value)] +#[diag("unable to construct a constant value for the unevaluated constant {$unevaluated}")] pub struct UnableToConstructConstantValue<'a> { #[primary_span] pub span: Span, @@ -31,60 +30,64 @@ pub struct UnableToConstructConstantValue<'a> { #[derive(Diagnostic)] pub enum InvalidOnClause { - #[diag(trait_selection_rustc_on_unimplemented_empty_on_clause, code = E0232)] + #[diag("empty `on`-clause in `#[rustc_on_unimplemented]`", code = E0232)] Empty { #[primary_span] - #[label] + #[label("empty `on`-clause here")] span: Span, }, - #[diag(trait_selection_rustc_on_unimplemented_expected_one_predicate_in_not, code = E0232)] + #[diag("expected a single predicate in `not(..)`", code = E0232)] ExpectedOnePredInNot { #[primary_span] - #[label] + #[label("unexpected quantity of predicates here")] span: Span, }, - #[diag(trait_selection_rustc_on_unimplemented_unsupported_literal_in_on, code = E0232)] + #[diag("literals inside `on`-clauses are not supported", code = E0232)] UnsupportedLiteral { #[primary_span] - #[label] + #[label("unexpected literal here")] span: Span, }, - #[diag(trait_selection_rustc_on_unimplemented_expected_identifier, code = E0232)] + #[diag("expected an identifier inside this `on`-clause", code = E0232)] ExpectedIdentifier { #[primary_span] - #[label] + #[label("expected an identifier here, not `{$path}`")] span: Span, path: Path, }, - #[diag(trait_selection_rustc_on_unimplemented_invalid_predicate, code = E0232)] + #[diag("this predicate is invalid", code = E0232)] InvalidPredicate { #[primary_span] - #[label] + #[label("expected one of `any`, `all` or `not` here, not `{$invalid_pred}`")] span: Span, invalid_pred: Symbol, }, - #[diag(trait_selection_rustc_on_unimplemented_invalid_flag, code = E0232)] + #[diag("invalid flag in `on`-clause", code = E0232)] InvalidFlag { #[primary_span] - #[label] + #[label( + "expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}`" + )] span: Span, invalid_flag: Symbol, }, - #[diag(trait_selection_rustc_on_unimplemented_invalid_name, code = E0232)] + #[diag("invalid name in `on`-clause", code = E0232)] InvalidName { #[primary_span] - #[label] + #[label( + "expected one of `cause`, `from_desugaring`, `Self` or any generic parameter of the trait, not `{$invalid_name}`" + )] span: Span, invalid_name: Symbol, }, } #[derive(Diagnostic)] -#[diag(trait_selection_rustc_on_unimplemented_missing_value, code = E0232)] -#[note] +#[diag("this attribute must have a value", code = E0232)] +#[note("e.g. `#[rustc_on_unimplemented(message=\"foo\")]`")] pub struct NoValueInOnUnimplemented { #[primary_span] - #[label] + #[label("expected value here")] pub span: Span, } @@ -99,26 +102,33 @@ pub struct NegativePositiveConflict<'tcx> { impl Diagnostic<'_, G> for NegativePositiveConflict<'_> { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::trait_selection_negative_positive_conflict); + let mut diag = Diag::new(dcx, level, inline_fluent!("found both positive and negative implementation of trait `{$trait_desc}`{$self_desc -> +[none] {\"\"} +*[default] {\" \"}for type `{$self_desc}` +}:")); diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string()); diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string())); diag.span(self.impl_span); diag.code(E0751); match self.negative_impl_span { Ok(span) => { - diag.span_label(span, fluent::trait_selection_negative_implementation_here); + diag.span_label(span, inline_fluent!("negative implementation here")); } Err(cname) => { - diag.note(fluent::trait_selection_negative_implementation_in_crate); + diag.note(inline_fluent!( + "negative implementation in crate `{$negative_impl_cname}`" + )); diag.arg("negative_impl_cname", cname.to_string()); } } match self.positive_impl_span { Ok(span) => { - diag.span_label(span, fluent::trait_selection_positive_implementation_here); + diag.span_label(span, inline_fluent!("positive implementation here")); } Err(cname) => { - diag.note(fluent::trait_selection_positive_implementation_in_crate); + diag.note(inline_fluent!( + "positive implementation in crate `{$positive_impl_cname}`" + )); diag.arg("positive_impl_cname", cname.to_string()); } } @@ -127,7 +137,7 @@ impl Diagnostic<'_, G> for NegativePositiveConflict<'_> { } #[derive(Diagnostic)] -#[diag(trait_selection_inherent_projection_normalization_overflow)] +#[diag("overflow evaluating associated type `{$ty}`")] pub struct InherentProjectionNormalizationOverflow { #[primary_span] pub span: Span, @@ -145,7 +155,12 @@ impl Subdiagnostic for AdjustSignatureBorrow { AdjustSignatureBorrow::Borrow { to_borrow } => { diag.arg("len", to_borrow.len()); diag.multipart_suggestion_verbose( - fluent::trait_selection_adjust_signature_borrow, + inline_fluent!( + "consider adjusting the signature so it borrows its {$len -> +[one] argument +*[other] arguments +}" + ), to_borrow, Applicability::MaybeIncorrect, ); @@ -153,7 +168,12 @@ impl Subdiagnostic for AdjustSignatureBorrow { AdjustSignatureBorrow::RemoveBorrow { remove_borrow } => { diag.arg("len", remove_borrow.len()); diag.multipart_suggestion_verbose( - fluent::trait_selection_adjust_signature_remove_borrow, + inline_fluent!( + "consider adjusting the signature so it does not borrow its {$len -> +[one] argument +*[other] arguments +}" + ), remove_borrow, Applicability::MaybeIncorrect, ); @@ -163,14 +183,14 @@ impl Subdiagnostic for AdjustSignatureBorrow { } #[derive(Diagnostic)] -#[diag(trait_selection_closure_kind_mismatch, code = E0525)] +#[diag("expected a closure that implements the `{$trait_prefix}{$expected}` trait, but this closure only implements `{$trait_prefix}{$found}`", code = E0525)] pub struct ClosureKindMismatch { #[primary_span] - #[label] + #[label("this closure implements `{$trait_prefix}{$found}`, not `{$trait_prefix}{$expected}`")] pub closure_span: Span, pub expected: ClosureKind, pub found: ClosureKind, - #[label(trait_selection_closure_kind_requirement)] + #[label("the requirement to implement `{$trait_prefix}{$expected}` derives from here")] pub cause_span: Span, pub trait_prefix: &'static str, @@ -183,7 +203,9 @@ pub struct ClosureKindMismatch { } #[derive(Subdiagnostic)] -#[label(trait_selection_closure_fn_once_label)] +#[label( + "closure is `{$trait_prefix}FnOnce` because it moves the variable `{$place}` out of its environment" +)] pub struct ClosureFnOnceLabel { #[primary_span] pub span: Span, @@ -191,7 +213,7 @@ pub struct ClosureFnOnceLabel { } #[derive(Subdiagnostic)] -#[label(trait_selection_closure_fn_mut_label)] +#[label("closure is `{$trait_prefix}FnMut` because it mutates the variable `{$place}` here")] pub struct ClosureFnMutLabel { #[primary_span] pub span: Span, @@ -199,7 +221,9 @@ pub struct ClosureFnMutLabel { } #[derive(Diagnostic)] -#[diag(trait_selection_coro_closure_not_fn)] +#[diag( + "{$coro_kind}closure does not implement `{$kind}` because it captures state from its environment" +)] pub(crate) struct CoroClosureNotFn { #[primary_span] pub span: Span, @@ -208,13 +232,17 @@ pub(crate) struct CoroClosureNotFn { } #[derive(Diagnostic)] -#[diag(trait_selection_type_annotations_needed, code = E0282)] +#[diag("{$source_kind -> +[closure] type annotations needed for the closure `{$source_name}` +[normal] type annotations needed for `{$source_name}` +*[other] type annotations needed +}", code = E0282)] pub struct AnnotationRequired<'a> { #[primary_span] pub span: Span, pub source_kind: &'static str, pub source_name: &'a str, - #[label] + #[label("type must be known at this point")] pub failure_span: Option, #[subdiagnostic] pub bad_label: Option>, @@ -226,13 +254,17 @@ pub struct AnnotationRequired<'a> { // Copy of `AnnotationRequired` for E0283 #[derive(Diagnostic)] -#[diag(trait_selection_type_annotations_needed, code = E0283)] +#[diag("{$source_kind -> +[closure] type annotations needed for the closure `{$source_name}` +[normal] type annotations needed for `{$source_name}` +*[other] type annotations needed +}", code = E0283)] pub struct AmbiguousImpl<'a> { #[primary_span] pub span: Span, pub source_kind: &'static str, pub source_name: &'a str, - #[label] + #[label("type must be known at this point")] pub failure_span: Option, #[subdiagnostic] pub bad_label: Option>, @@ -244,13 +276,17 @@ pub struct AmbiguousImpl<'a> { // Copy of `AnnotationRequired` for E0284 #[derive(Diagnostic)] -#[diag(trait_selection_type_annotations_needed, code = E0284)] +#[diag("{$source_kind -> +[closure] type annotations needed for the closure `{$source_name}` +[normal] type annotations needed for `{$source_name}` +*[other] type annotations needed +}", code = E0284)] pub struct AmbiguousReturn<'a> { #[primary_span] pub span: Span, pub source_kind: &'static str, pub source_name: &'a str, - #[label] + #[label("type must be known at this point")] pub failure_span: Option, #[subdiagnostic] pub bad_label: Option>, @@ -262,7 +298,19 @@ pub struct AmbiguousReturn<'a> { // Used when a better one isn't available #[derive(Subdiagnostic)] -#[label(trait_selection_label_bad)] +#[label( + "{$bad_kind -> +*[other] cannot infer type +[more_info] cannot infer {$prefix_kind -> +*[type] type for {$prefix} +[const_with_param] the value of const parameter +[const] the value of the constant +} `{$name}`{$has_parent -> +[true] {\" \"}declared on the {$parent_prefix} `{$parent_name}` +*[false] {\"\"} +} +}" +)] pub struct InferenceBadError<'a> { #[primary_span] pub span: Span, @@ -278,7 +326,19 @@ pub struct InferenceBadError<'a> { #[derive(Subdiagnostic)] pub enum SourceKindSubdiag<'a> { #[suggestion( - trait_selection_source_kind_subdiag_let, + "{$kind -> +[with_pattern] consider giving `{$name}` an explicit type +[closure] consider giving this closure parameter an explicit type +*[other] consider giving this pattern a type +}{$x_kind -> +[has_name] , where the {$prefix_kind -> +*[type] type for {$prefix} +[const_with_param] value of const parameter +[const] value of the constant +} `{$arg_name}` is specified +[underscore] , where the placeholders `_` are specified +*[empty] {\"\"} +}", style = "verbose", code = ": {type_name}", applicability = "has-placeholders" @@ -294,7 +354,18 @@ pub enum SourceKindSubdiag<'a> { prefix: &'a str, arg_name: String, }, - #[label(trait_selection_source_kind_subdiag_generic_label)] + #[label( + "cannot infer {$is_type -> +[true] type +*[false] the value +} of the {$is_type -> +[true] type +*[false] const +} {$parent_exists -> +[true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}` +*[false] parameter {$param_name} +}" + )] GenericLabel { #[primary_span] span: Span, @@ -305,7 +376,10 @@ pub enum SourceKindSubdiag<'a> { parent_name: String, }, #[suggestion( - trait_selection_source_kind_subdiag_generic_suggestion, + "consider specifying the generic {$arg_count -> +[one] argument +*[other] arguments +}", style = "verbose", code = "::<{args}>", applicability = "has-placeholders" @@ -321,7 +395,7 @@ pub enum SourceKindSubdiag<'a> { #[derive(Subdiagnostic)] pub enum SourceKindMultiSuggestion<'a> { #[multipart_suggestion( - trait_selection_source_kind_fully_qualified, + "try using a fully qualified path to specify the expected types", style = "verbose", applicability = "has-placeholders" )] @@ -335,7 +409,7 @@ pub enum SourceKindMultiSuggestion<'a> { successor_pos: &'a str, }, #[multipart_suggestion( - trait_selection_source_kind_closure_return, + "try giving this closure an explicit return type", style = "verbose", applicability = "has-placeholders" )] @@ -427,7 +501,24 @@ impl Subdiagnostic for RegionOriginNote<'_> { requirement, expected_found: Some((expected, found)), } => { - label_or_note(span, fluent::trait_selection_subtype); + label_or_note( + span, + inline_fluent!( + "...so that the {$requirement -> +[method_compat] method type is compatible with trait +[type_compat] associated type is compatible with trait +[const_compat] const is compatible with trait +[expr_assignable] expression is assignable +[if_else_different] `if` and `else` have incompatible types +[no_else] `if` missing an `else` returns `()` +[fn_main_correct_type] `main` function has the correct type +[fn_lang_correct_type] lang item function has the correct type +[intrinsic_correct_type] intrinsic has the correct type +[method_correct_type] method receiver has the correct type +*[other] types are compatible +}" + ), + ); diag.arg("requirement", requirement); diag.note_expected_found("", expected, "", found); @@ -436,7 +527,24 @@ impl Subdiagnostic for RegionOriginNote<'_> { // FIXME: this really should be handled at some earlier stage. Our // handling of region checking when type errors are present is // *terrible*. - label_or_note(span, fluent::trait_selection_subtype_2); + label_or_note( + span, + inline_fluent!( + "...so that {$requirement -> +[method_compat] method type is compatible with trait +[type_compat] associated type is compatible with trait +[const_compat] const is compatible with trait +[expr_assignable] expression is assignable +[if_else_different] `if` and `else` have incompatible types +[no_else] `if` missing an `else` returns `()` +[fn_main_correct_type] `main` function has the correct type +[fn_lang_correct_type] lang item function has the correct type +[intrinsic_correct_type] intrinsic has the correct type +[method_correct_type] method receiver has the correct type +*[other] types are compatible +}" + ), + ); diag.arg("requirement", requirement); } }; @@ -464,9 +572,17 @@ impl Subdiagnostic for LifetimeMismatchLabels { fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => { - diag.span_label(param_span, fluent::trait_selection_declared_different); - diag.span_label(ret_span, fluent::trait_selection_nothing); - diag.span_label(span, fluent::trait_selection_data_returned); + diag.span_label(param_span, inline_fluent!("this parameter and the return type are declared with different lifetimes...")); + diag.span_label(ret_span, inline_fluent!("{\"\"}")); + diag.span_label( + span, + inline_fluent!( + "...but data{$label_var1_exists -> +[true] {\" \"}from `{$label_var1}` +*[false] {\"\"} +} is returned here" + ), + ); diag.arg("label_var1_exists", label_var1.is_some()); diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); } @@ -479,13 +595,33 @@ impl Subdiagnostic for LifetimeMismatchLabels { sub: label_var2, } => { if hir_equal { - diag.span_label(ty_sup, fluent::trait_selection_declared_multiple); - diag.span_label(ty_sub, fluent::trait_selection_nothing); - diag.span_label(span, fluent::trait_selection_data_lifetime_flow); + diag.span_label( + ty_sup, + inline_fluent!("this type is declared with multiple lifetimes..."), + ); + diag.span_label(ty_sub, inline_fluent!("{\"\"}")); + diag.span_label( + span, + inline_fluent!("...but data with one lifetime flows into the other here"), + ); } else { - diag.span_label(ty_sup, fluent::trait_selection_types_declared_different); - diag.span_label(ty_sub, fluent::trait_selection_nothing); - diag.span_label(span, fluent::trait_selection_data_flows); + diag.span_label( + ty_sup, + inline_fluent!("these two types are declared with different lifetimes..."), + ); + diag.span_label(ty_sub, inline_fluent!("{\"\"}")); + diag.span_label( + span, + inline_fluent!( + "...but data{$label_var1_exists -> +[true] {\" \"}from `{$label_var1}` +*[false] {\"\"} +} flows{$label_var2_exists -> +[true] {\" \"}into `{$label_var2}` +*[false] {\"\"} +} here" + ), + ); diag.arg("label_var1_exists", label_var1.is_some()); diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); diag.arg("label_var2_exists", label_var2.is_some()); @@ -651,7 +787,15 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { visitor.suggestions.push(new_param_suggestion); } diag.multipart_suggestion_verbose( - fluent::trait_selection_lifetime_param_suggestion, + inline_fluent!( + "consider {$is_reuse -> +[true] reusing +*[false] introducing +} a named lifetime parameter{$is_impl -> +[true] {\" \"}and update trait if needed +*[false] {\"\"} +}" + ), visitor.suggestions, Applicability::MaybeIncorrect, ); @@ -661,13 +805,15 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { true }; if mk_suggestion() && self.add_note { - diag.note(fluent::trait_selection_lifetime_param_suggestion_elided); + diag.note(inline_fluent!( + "each elided lifetime in input position becomes a distinct lifetime" + )); } } } #[derive(Diagnostic)] -#[diag(trait_selection_lifetime_mismatch, code = E0623)] +#[diag("lifetime mismatch", code = E0623)] pub struct LifetimeMismatch<'a> { #[primary_span] pub span: Span, @@ -684,33 +830,42 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq { impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { fn add_to_diag(mut self, diag: &mut Diag<'_, G>) { - self.unmet_requirements - .push_span_label(self.binding_span, fluent::trait_selection_msl_introduces_static); - diag.span_note(self.unmet_requirements, fluent::trait_selection_msl_unmet_req); + self.unmet_requirements.push_span_label( + self.binding_span, + inline_fluent!("introduces a `'static` lifetime requirement"), + ); + diag.span_note( + self.unmet_requirements, + inline_fluent!("because this has an unmet lifetime requirement"), + ); } } // FIXME(#100717): replace with a `Option` when subdiagnostic supports that #[derive(Subdiagnostic)] pub enum DoesNotOutliveStaticFromImpl { - #[note(trait_selection_does_not_outlive_static_from_impl)] + #[note( + "...does not necessarily outlive the static lifetime introduced by the compatible `impl`" + )] Spanned { #[primary_span] span: Span, }, - #[note(trait_selection_does_not_outlive_static_from_impl)] + #[note( + "...does not necessarily outlive the static lifetime introduced by the compatible `impl`" + )] Unspanned, } #[derive(Subdiagnostic)] pub enum ImplicitStaticLifetimeSubdiag { - #[note(trait_selection_implicit_static_lifetime_note)] + #[note("this has an implicit `'static` lifetime requirement")] Note { #[primary_span] span: Span, }, #[suggestion( - trait_selection_implicit_static_lifetime_suggestion, + "consider relaxing the implicit `'static` requirement", style = "verbose", code = " + '_", applicability = "maybe-incorrect" @@ -722,7 +877,7 @@ pub enum ImplicitStaticLifetimeSubdiag { } #[derive(Diagnostic)] -#[diag(trait_selection_mismatched_static_lifetime)] +#[diag("incompatible lifetime on type")] pub struct MismatchedStaticLifetime<'a> { #[primary_span] pub cause_span: Span, @@ -738,15 +893,15 @@ pub struct MismatchedStaticLifetime<'a> { #[derive(Diagnostic)] pub enum ExplicitLifetimeRequired<'a> { - #[diag(trait_selection_explicit_lifetime_required_with_ident, code = E0621)] + #[diag("explicit lifetime required in the type of `{$simple_ident}`", code = E0621)] WithIdent { #[primary_span] - #[label] + #[label("lifetime `{$named}` required")] span: Span, simple_ident: Ident, named: String, #[suggestion( - trait_selection_explicit_lifetime_required_sugg_with_ident, + "add explicit lifetime `{$named}` to the type of `{$simple_ident}`", code = "{new_ty}", applicability = "unspecified", style = "verbose" @@ -755,14 +910,14 @@ pub enum ExplicitLifetimeRequired<'a> { #[skip_arg] new_ty: Ty<'a>, }, - #[diag(trait_selection_explicit_lifetime_required_with_param_type, code = E0621)] + #[diag("explicit lifetime required in parameter type", code = E0621)] WithParamType { #[primary_span] - #[label] + #[label("lifetime `{$named}` required")] span: Span, named: String, #[suggestion( - trait_selection_explicit_lifetime_required_sugg_with_param_type, + "add explicit lifetime `{$named}` to type", code = "{new_ty}", applicability = "unspecified", style = "verbose" @@ -789,7 +944,10 @@ impl IntoDiagArg for TyOrSig<'_> { #[derive(Subdiagnostic)] pub enum ActualImplExplNotes<'tcx> { - #[note(trait_selection_actual_impl_expl_expected_signature_two)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedSignatureTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -797,27 +955,41 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, lifetime_2: usize, }, - #[note(trait_selection_actual_impl_expl_expected_signature_any)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...")] ExpectedSignatureAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_signature_some)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...")] ExpectedSignatureSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_signature_nothing)] + #[note( + "{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`" + )] ExpectedSignatureNothing { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note(trait_selection_actual_impl_expl_expected_passive_two)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedPassiveTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -825,27 +997,41 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, lifetime_2: usize, }, - #[note(trait_selection_actual_impl_expl_expected_passive_any)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...")] ExpectedPassiveAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_passive_some)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...")] ExpectedPassiveSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_passive_nothing)] + #[note( + "{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`" + )] ExpectedPassiveNothing { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note(trait_selection_actual_impl_expl_expected_other_two)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedOtherTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -853,40 +1039,70 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, lifetime_2: usize, }, - #[note(trait_selection_actual_impl_expl_expected_other_any)] + #[note( + "{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`..." + )] ExpectedOtherAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_other_some)] + #[note( + "{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`..." + )] ExpectedOtherSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_other_nothing)] + #[note( + "{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$ty_or_sig}` must implement `{$trait_path}`" + )] ExpectedOtherNothing { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note(trait_selection_actual_impl_expl_but_actually_implements_trait)] + #[note( + "...but it actually implements `{$trait_path}`{$has_lifetime -> +[true] , for some specific lifetime `'{$lifetime}` +*[false] {\"\"} +}" + )] ButActuallyImplementsTrait { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, lifetime: usize, }, - #[note(trait_selection_actual_impl_expl_but_actually_implemented_for_ty)] + #[note( + "...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime -> +[true] , for some specific lifetime `'{$lifetime}` +*[false] {\"\"} +}" + )] ButActuallyImplementedForTy { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, lifetime: usize, ty: String, }, - #[note(trait_selection_actual_impl_expl_but_actually_ty_implements)] + #[note( + "...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime -> +[true] , for some specific lifetime `'{$lifetime}` +*[false] {\"\"} +}" + )] ButActuallyTyImplements { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, @@ -978,15 +1194,15 @@ impl<'tcx> ActualImplExplNotes<'tcx> { } #[derive(Diagnostic)] -#[diag(trait_selection_trait_placeholder_mismatch)] +#[diag("implementation of `{$trait_def_id}` is not general enough")] pub struct TraitPlaceholderMismatch<'tcx> { #[primary_span] pub span: Span, - #[label(trait_selection_label_satisfy)] + #[label("doesn't satisfy where-clause")] pub satisfy_span: Option, - #[label(trait_selection_label_where)] + #[label("due to a where-clause on `{$def_id}`...")] pub where_span: Option, - #[label(trait_selection_label_dup)] + #[label("implementation of `{$trait_def_id}` is not general enough")] pub dup_span: Option, pub def_id: String, pub trait_def_id: String, @@ -1004,26 +1220,34 @@ impl Subdiagnostic for ConsiderBorrowingParamHelp { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { // Seems like we can't call f() here as Into is required - type_param_span.push_span_label(span, fluent::trait_selection_tid_consider_borrowing); + type_param_span.push_span_label( + span, + inline_fluent!("consider borrowing this type parameter in the trait"), + ); } - let msg = diag.eagerly_translate(fluent::trait_selection_tid_param_help); + let msg = diag.eagerly_translate(inline_fluent!("the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`")); diag.span_help(type_param_span, msg); } } #[derive(Subdiagnostic)] -#[help(trait_selection_tid_rel_help)] +#[help( + "verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output" +)] pub struct RelationshipHelp; #[derive(Diagnostic)] -#[diag(trait_selection_trait_impl_diff)] +#[diag("`impl` item signature doesn't match `trait` item signature")] pub struct TraitImplDiff { #[primary_span] - #[label(trait_selection_found)] + #[label("found `{$found}`")] pub sp: Span, - #[label(trait_selection_expected)] + #[label("expected `{$expected}`")] pub trait_sp: Span, - #[note(trait_selection_expected_found)] + #[note( + "expected signature `{$expected}` + {\" \"}found signature `{$found}`" + )] pub note: (), #[subdiagnostic] pub param_help: ConsiderBorrowingParamHelp, @@ -1043,12 +1267,20 @@ pub struct DynTraitConstraintSuggestion { impl Subdiagnostic for DynTraitConstraintSuggestion { fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut multi_span: MultiSpan = vec![self.span].into(); - multi_span.push_span_label(self.span, fluent::trait_selection_dtcs_has_lifetime_req_label); - multi_span - .push_span_label(self.ident.span, fluent::trait_selection_dtcs_introduces_requirement); - let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_has_req_note); + multi_span.push_span_label( + self.span, + inline_fluent!("this has an implicit `'static` lifetime requirement"), + ); + multi_span.push_span_label( + self.ident.span, + inline_fluent!("calling this method introduces the `impl`'s `'static` requirement"), + ); + let msg = + diag.eagerly_translate(inline_fluent!("the used `impl` has a `'static` requirement")); diag.span_note(multi_span, msg); - let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_suggestion); + let msg = diag.eagerly_translate(inline_fluent!( + "consider relaxing the implicit `'static` requirement" + )); diag.span_suggestion_verbose( self.span.shrink_to_hi(), msg, @@ -1059,12 +1291,26 @@ impl Subdiagnostic for DynTraitConstraintSuggestion { } #[derive(Diagnostic)] -#[diag(trait_selection_but_calling_introduces, code = E0772)] +#[diag("{$has_param_name -> + [true] `{$param_name}` + *[false] `fn` parameter +} has {$lifetime_kind -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` +} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement", code = E0772)] pub struct ButCallingIntroduces { - #[label(trait_selection_label1)] + #[label( + "{$has_lifetime -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` + }" + )] pub param_ty_span: Span, #[primary_span] - #[label(trait_selection_label2)] + #[label("...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path -> + [true] `impl` of `{$impl_path}` + *[false] inherent `impl` + }")] pub cause_span: Span, pub has_param_name: bool, @@ -1087,32 +1333,61 @@ pub struct ReqIntroducedLocations { impl Subdiagnostic for ReqIntroducedLocations { fn add_to_diag(mut self, diag: &mut Diag<'_, G>) { for sp in self.spans { - self.span.push_span_label(sp, fluent::trait_selection_ril_introduced_here); + self.span.push_span_label(sp, inline_fluent!("`'static` requirement introduced here")); } if self.add_label { - self.span.push_span_label(self.fn_decl_span, fluent::trait_selection_ril_introduced_by); + self.span.push_span_label( + self.fn_decl_span, + inline_fluent!("requirement introduced by this return type"), + ); } - self.span.push_span_label(self.cause_span, fluent::trait_selection_ril_because_of); - let msg = diag.eagerly_translate(fluent::trait_selection_ril_static_introduced_by); + self.span.push_span_label( + self.cause_span, + inline_fluent!("because of this returned expression"), + ); + let msg = diag.eagerly_translate(inline_fluent!( + "\"`'static` lifetime requirement introduced by the return type" + )); diag.span_note(self.span, msg); } } #[derive(Diagnostic)] -#[diag(trait_selection_but_needs_to_satisfy, code = E0759)] +#[diag("{$has_param_name -> + [true] `{$param_name}` + *[false] `fn` parameter +} has {$has_lifetime -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` +} but it needs to satisfy a `'static` lifetime requirement", code = E0759)] pub struct ButNeedsToSatisfy { #[primary_span] pub sp: Span, - #[label(trait_selection_influencer)] + #[label( + "this data with {$has_lifetime -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` + }..." + )] pub influencer_point: Span, - #[label(trait_selection_used_here)] + #[label("...is used here...")] pub spans: Vec, - #[label(trait_selection_require)] + #[label( + "{$spans_empty -> + *[true] ...is used and required to live as long as `'static` here + [false] ...and is required to live as long as `'static` here + }" + )] pub require_span_as_label: Option, - #[note(trait_selection_require)] + #[note( + "{$spans_empty -> + *[true] ...is used and required to live as long as `'static` here + [false] ...and is required to live as long as `'static` here + }" + )] pub require_span_as_note: Option, - #[note(trait_selection_introduced_by_bound)] + #[note("`'static` lifetime requirement introduced by this bound")] pub bound: Option, pub has_param_name: bool, @@ -1123,7 +1398,7 @@ pub struct ButNeedsToSatisfy { } #[derive(Diagnostic)] -#[diag(trait_selection_outlives_content, code = E0312)] +#[diag("lifetime of reference outlives lifetime of borrowed content...", code = E0312)] pub struct OutlivesContent<'a> { #[primary_span] pub span: Span, @@ -1132,7 +1407,7 @@ pub struct OutlivesContent<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_outlives_bound, code = E0476)] +#[diag("lifetime of the source pointer does not outlive lifetime bound of the object type", code = E0476)] pub struct OutlivesBound<'a> { #[primary_span] pub span: Span, @@ -1141,7 +1416,7 @@ pub struct OutlivesBound<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_fulfill_req_lifetime, code = E0477)] +#[diag("the type `{$ty}` does not fulfill the required lifetime", code = E0477)] pub struct FulfillReqLifetime<'a> { #[primary_span] pub span: Span, @@ -1151,7 +1426,7 @@ pub struct FulfillReqLifetime<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_lf_bound_not_satisfied, code = E0478)] +#[diag("lifetime bound not satisfied", code = E0478)] pub struct LfBoundNotSatisfied<'a> { #[primary_span] pub span: Span, @@ -1160,7 +1435,7 @@ pub struct LfBoundNotSatisfied<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_ref_longer_than_data, code = E0491)] +#[diag("in type `{$ty}`, reference has a longer lifetime than the data it references", code = E0491)] pub struct RefLongerThanData<'a> { #[primary_span] pub span: Span, @@ -1172,7 +1447,7 @@ pub struct RefLongerThanData<'a> { #[derive(Subdiagnostic)] pub enum WhereClauseSuggestions { #[suggestion( - trait_selection_where_remove, + "remove the `where` clause", code = "", applicability = "machine-applicable", style = "verbose" @@ -1182,7 +1457,7 @@ pub enum WhereClauseSuggestions { span: Span, }, #[suggestion( - trait_selection_where_copy_predicates, + "copy the `where` clause predicates from the trait", code = "{space}where {trait_predicates}", applicability = "machine-applicable", style = "verbose" @@ -1198,7 +1473,7 @@ pub enum WhereClauseSuggestions { #[derive(Subdiagnostic)] pub enum SuggestRemoveSemiOrReturnBinding { #[multipart_suggestion( - trait_selection_srs_remove_and_box, + "consider removing this semicolon and boxing the expressions", applicability = "machine-applicable" )] RemoveAndBox { @@ -1214,7 +1489,7 @@ pub enum SuggestRemoveSemiOrReturnBinding { sp: Span, }, #[suggestion( - trait_selection_srs_remove, + "consider removing this semicolon", style = "short", code = "", applicability = "machine-applicable" @@ -1224,7 +1499,7 @@ pub enum SuggestRemoveSemiOrReturnBinding { sp: Span, }, #[suggestion( - trait_selection_srs_add, + "consider returning the local binding `{$ident}`", style = "verbose", code = "{code}", applicability = "maybe-incorrect" @@ -1235,7 +1510,7 @@ pub enum SuggestRemoveSemiOrReturnBinding { code: String, ident: Ident, }, - #[note(trait_selection_srs_add_one)] + #[note("consider returning one of these bindings")] AddOne { #[primary_span] spans: MultiSpan, @@ -1244,9 +1519,12 @@ pub enum SuggestRemoveSemiOrReturnBinding { #[derive(Subdiagnostic)] pub enum ConsiderAddingAwait { - #[help(trait_selection_await_both_futures)] + #[help("consider `await`ing on both `Future`s")] BothFuturesHelp, - #[multipart_suggestion(trait_selection_await_both_futures, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "consider `await`ing on both `Future`s", + applicability = "maybe-incorrect" + )] BothFuturesSugg { #[suggestion_part(code = ".await")] first: Span, @@ -1254,7 +1532,7 @@ pub enum ConsiderAddingAwait { second: Span, }, #[suggestion( - trait_selection_await_future, + "consider `await`ing on the `Future`", code = ".await", style = "verbose", applicability = "maybe-incorrect" @@ -1263,13 +1541,13 @@ pub enum ConsiderAddingAwait { #[primary_span] span: Span, }, - #[note(trait_selection_await_note)] + #[note("calling an async function returns a future")] FutureSuggNote { #[primary_span] span: Span, }, #[multipart_suggestion( - trait_selection_await_future, + "consider `await`ing on the `Future`", style = "verbose", applicability = "maybe-incorrect" )] @@ -1281,69 +1559,79 @@ pub enum ConsiderAddingAwait { #[derive(Diagnostic)] pub enum PlaceholderRelationLfNotSatisfied { - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasBoth { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_with_sub)] + #[note("the lifetime `{$sub_symbol}` defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_with_sup)] + #[note("...must outlive the lifetime `{$sup_symbol}` defined here")] sup_span: Span, sub_symbol: Symbol, sup_symbol: Symbol, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasSub { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_with_sub)] + #[note("the lifetime `{$sub_symbol}` defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_without_sup)] + #[note("...must outlive the lifetime defined here")] sup_span: Span, sub_symbol: Symbol, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasSup { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_without_sub)] + #[note("the lifetime defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_with_sup)] + #[note("...must outlive the lifetime `{$sup_symbol}` defined here")] sup_span: Span, sup_symbol: Symbol, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasNone { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_without_sub)] + #[note("the lifetime defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_without_sup)] + #[note("...must outlive the lifetime defined here")] sup_span: Span, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] OnlyPrimarySpan { #[primary_span] span: Span, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, } #[derive(Diagnostic)] -#[diag(trait_selection_opaque_captures_lifetime, code = E0700)] +#[diag("hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds", code = E0700)] pub struct OpaqueCapturesLifetime<'tcx> { #[primary_span] pub span: Span, - #[label] + #[label("opaque type defined here")] pub opaque_ty_span: Span, pub opaque_ty: Ty<'tcx>, } @@ -1351,7 +1639,7 @@ pub struct OpaqueCapturesLifetime<'tcx> { #[derive(Subdiagnostic)] pub enum FunctionPointerSuggestion<'a> { #[suggestion( - trait_selection_fps_use_ref, + "consider using a reference", code = "&", style = "verbose", applicability = "maybe-incorrect" @@ -1361,7 +1649,7 @@ pub enum FunctionPointerSuggestion<'a> { span: Span, }, #[suggestion( - trait_selection_fps_remove_ref, + "consider removing the reference", code = "{fn_name}", style = "verbose", applicability = "maybe-incorrect" @@ -1373,7 +1661,7 @@ pub enum FunctionPointerSuggestion<'a> { fn_name: String, }, #[suggestion( - trait_selection_fps_cast, + "consider casting to a fn pointer", code = "&({fn_name} as {sig})", style = "verbose", applicability = "maybe-incorrect" @@ -1387,7 +1675,7 @@ pub enum FunctionPointerSuggestion<'a> { sig: Binder<'a, FnSig<'a>>, }, #[suggestion( - trait_selection_fps_cast, + "consider casting to a fn pointer", code = " as {sig}", style = "verbose", applicability = "maybe-incorrect" @@ -1399,7 +1687,7 @@ pub enum FunctionPointerSuggestion<'a> { sig: Binder<'a, FnSig<'a>>, }, #[suggestion( - trait_selection_fps_cast_both, + "consider casting both fn items to fn pointers using `as {$expected_sig}`", code = " as {found_sig}", style = "hidden", applicability = "maybe-incorrect" @@ -1412,7 +1700,7 @@ pub enum FunctionPointerSuggestion<'a> { expected_sig: Binder<'a, FnSig<'a>>, }, #[suggestion( - trait_selection_fps_cast_both, + "consider casting both fn items to fn pointers using `as {$expected_sig}`", code = "&({fn_name} as {found_sig})", style = "hidden", applicability = "maybe-incorrect" @@ -1429,21 +1717,21 @@ pub enum FunctionPointerSuggestion<'a> { } #[derive(Subdiagnostic)] -#[note(trait_selection_fps_items_are_distinct)] +#[note("fn items are distinct from fn pointers")] pub struct FnItemsAreDistinct; #[derive(Subdiagnostic)] -#[note(trait_selection_fn_uniq_types)] +#[note("different fn items have unique types, even if their signatures are the same")] pub struct FnUniqTypes; #[derive(Subdiagnostic)] -#[help(trait_selection_fn_consider_casting)] +#[help("consider casting the fn item to a fn pointer: `{$casting}`")] pub struct FnConsiderCasting { pub casting: String, } #[derive(Subdiagnostic)] -#[help(trait_selection_fn_consider_casting_both)] +#[help("consider casting both fn items to fn pointers using `as {$sig}`")] pub struct FnConsiderCastingBoth<'a> { pub sig: Binder<'a, FnSig<'a>>, } @@ -1451,7 +1739,7 @@ pub struct FnConsiderCastingBoth<'a> { #[derive(Subdiagnostic)] pub enum SuggestAccessingField<'a> { #[suggestion( - trait_selection_suggest_accessing_field, + "you might have meant to use field `{$name}` whose type is `{$ty}`", code = "{snippet}.{name}", applicability = "maybe-incorrect", style = "verbose" @@ -1464,7 +1752,7 @@ pub enum SuggestAccessingField<'a> { ty: Ty<'a>, }, #[suggestion( - trait_selection_suggest_accessing_field, + "you might have meant to use field `{$name}` whose type is `{$ty}`", code = "unsafe {{ {snippet}.{name} }}", applicability = "maybe-incorrect", style = "verbose" @@ -1479,7 +1767,10 @@ pub enum SuggestAccessingField<'a> { } #[derive(Subdiagnostic)] -#[multipart_suggestion(trait_selection_stp_wrap_one, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "try wrapping the pattern in `{$variant}`", + applicability = "maybe-incorrect" +)] pub struct SuggestTuplePatternOne { pub variant: String, #[suggestion_part(code = "{variant}(")] @@ -1497,7 +1788,9 @@ pub struct SuggestTuplePatternMany { impl Subdiagnostic for SuggestTuplePatternMany { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("path", self.path); - let message = diag.eagerly_translate(fluent::trait_selection_stp_wrap_many); + let message = diag.eagerly_translate(inline_fluent!( + "try wrapping the pattern in a variant of `{$path}`" + )); diag.multipart_suggestions( message, self.compatible_variants.into_iter().map(|variant| { @@ -1514,7 +1807,7 @@ impl Subdiagnostic for SuggestTuplePatternMany { #[derive(Subdiagnostic)] pub enum TypeErrorAdditionalDiags { #[suggestion( - trait_selection_meant_byte_literal, + "if you meant to write a byte literal, prefix with `b`", code = "b'{code}'", applicability = "machine-applicable" )] @@ -1524,7 +1817,7 @@ pub enum TypeErrorAdditionalDiags { code: String, }, #[suggestion( - trait_selection_meant_char_literal, + "if you meant to write a `char` literal, use single quotes", code = "'{code}'", applicability = "machine-applicable" )] @@ -1533,7 +1826,10 @@ pub enum TypeErrorAdditionalDiags { span: Span, code: String, }, - #[multipart_suggestion(trait_selection_meant_str_literal, applicability = "machine-applicable")] + #[multipart_suggestion( + "if you meant to write a string literal, use double quotes", + applicability = "machine-applicable" + )] MeantStrLiteral { #[suggestion_part(code = "\"")] start: Span, @@ -1541,7 +1837,7 @@ pub enum TypeErrorAdditionalDiags { end: Span, }, #[suggestion( - trait_selection_consider_specifying_length, + "consider specifying the actual array length", code = "{length}", applicability = "maybe-incorrect" )] @@ -1550,10 +1846,10 @@ pub enum TypeErrorAdditionalDiags { span: Span, length: u64, }, - #[note(trait_selection_try_cannot_convert)] + #[note("`?` operator cannot convert from `{$found}` to `{$expected}`")] TryCannotConvert { found: String, expected: String }, #[suggestion( - trait_selection_tuple_trailing_comma, + "use a trailing comma to create a tuple with one element", code = ",", applicability = "machine-applicable" )] @@ -1562,7 +1858,7 @@ pub enum TypeErrorAdditionalDiags { span: Span, }, #[multipart_suggestion( - trait_selection_tuple_trailing_comma, + "use a trailing comma to create a tuple with one element", applicability = "machine-applicable" )] TupleAlsoParentheses { @@ -1572,7 +1868,7 @@ pub enum TypeErrorAdditionalDiags { span_high: Span, }, #[suggestion( - trait_selection_suggest_add_let_for_letchains, + "consider adding `let`", style = "verbose", applicability = "machine-applicable", code = "let " @@ -1585,66 +1881,69 @@ pub enum TypeErrorAdditionalDiags { #[derive(Diagnostic)] pub enum ObligationCauseFailureCode { - #[diag(trait_selection_oc_method_compat, code = E0308)] + #[diag("method not compatible with trait", code = E0308)] MethodCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_type_compat, code = E0308)] + #[diag("type not compatible with trait", code = E0308)] TypeCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_const_compat, code = E0308)] + #[diag("const not compatible with trait", code = E0308)] ConstCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_try_compat, code = E0308)] + #[diag("`?` operator has incompatible types", code = E0308)] TryCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_match_compat, code = E0308)] + #[diag("`match` arms have incompatible types", code = E0308)] MatchCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_if_else_different, code = E0308)] + #[diag("`if` and `else` have incompatible types", code = E0308)] IfElseDifferent { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_no_else, code = E0317)] + #[diag("`if` may be missing an `else` clause", code = E0317)] NoElse { #[primary_span] span: Span, }, - #[diag(trait_selection_oc_no_diverge, code = E0308)] + #[diag("`else` clause of `let...else` does not diverge", code = E0308)] NoDiverge { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_fn_main_correct_type, code = E0580)] + #[diag("`main` function has wrong type", code = E0580)] FnMainCorrectType { #[primary_span] span: Span, }, - #[diag(trait_selection_oc_fn_lang_correct_type, code = E0308)] + #[diag("{$lang_item_name -> +[panic_impl] `#[panic_handler]` +*[lang_item_name] lang item `{$lang_item_name}` +} function has wrong type", code = E0308)] FnLangCorrectType { #[primary_span] span: Span, @@ -1652,40 +1951,40 @@ pub enum ObligationCauseFailureCode { subdiags: Vec, lang_item_name: Symbol, }, - #[diag(trait_selection_oc_intrinsic_correct_type, code = E0308)] + #[diag("intrinsic has wrong type", code = E0308)] IntrinsicCorrectType { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_method_correct_type, code = E0308)] + #[diag("mismatched `self` parameter type", code = E0308)] MethodCorrectType { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_closure_selfref, code = E0644)] + #[diag("closure/coroutine type that references itself", code = E0644)] ClosureSelfref { #[primary_span] span: Span, }, - #[diag(trait_selection_oc_cant_coerce_force_inline, code = E0308)] + #[diag("cannot coerce functions which must be inlined to function pointers", code = E0308)] CantCoerceForceInline { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_cant_coerce_intrinsic, code = E0308)] + #[diag("cannot coerce intrinsics to function pointers", code = E0308)] CantCoerceIntrinsic { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_generic, code = E0308)] + #[diag("mismatched types", code = E0308)] Generic { #[primary_span] span: Span, @@ -1697,7 +1996,7 @@ pub enum ObligationCauseFailureCode { #[derive(Subdiagnostic)] pub enum AddPreciseCapturing { #[suggestion( - trait_selection_precise_capturing_new, + "add a `use<...>` bound to explicitly capture `{$new_lifetime}`", style = "verbose", code = " + use<{concatenated_bounds}>", applicability = "machine-applicable" @@ -1709,7 +2008,7 @@ pub enum AddPreciseCapturing { concatenated_bounds: String, }, #[suggestion( - trait_selection_precise_capturing_existing, + "add `{$new_lifetime}` to the `use<...>` bound to explicitly capture it", style = "verbose", code = "{pre}{new_lifetime}{post}", applicability = "machine-applicable" @@ -1733,13 +2032,13 @@ impl Subdiagnostic for AddPreciseCapturingAndParams { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("new_lifetime", self.new_lifetime); diag.multipart_suggestion_verbose( - fluent::trait_selection_precise_capturing_new_but_apit, + inline_fluent!("add a `use<...>` bound to explicitly capture `{$new_lifetime}` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate"), self.suggs, Applicability::MaybeIncorrect, ); diag.span_note( self.apit_spans, - fluent::trait_selection_warn_removing_apit_params_for_undercapture, + inline_fluent!("you could use a `use<...>` bound to explicitly capture `{$new_lifetime}`, but argument-position `impl Trait`s are not nameable"), ); } } @@ -1880,26 +2179,31 @@ impl Subdiagnostic for AddPreciseCapturingForOvercapture { Applicability::MaybeIncorrect }; diag.multipart_suggestion_verbose( - fluent::trait_selection_precise_capturing_overcaptures, + inline_fluent!( + "use the precise capturing `use<...>` syntax to make the captures explicit" + ), self.suggs, applicability, ); if !self.apit_spans.is_empty() { diag.span_note( self.apit_spans, - fluent::trait_selection_warn_removing_apit_params_for_overcapture, + inline_fluent!("you could use a `use<...>` bound to explicitly specify captures, but argument-position `impl Trait`s are not nameable"), ); } } } #[derive(Diagnostic)] -#[diag(trait_selection_opaque_type_non_generic_param, code = E0792)] +#[diag("expected generic {$kind} parameter, found `{$arg}`", code = E0792)] pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> { pub arg: GenericArg<'tcx>, pub kind: &'a str, #[primary_span] pub span: Span, - #[label] + #[label("{STREQ($arg, \"'static\") -> + [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type + *[other] this generic parameter must be used with a generic {$kind} parameter + }")] pub param_span: Span, } diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs index 3471036256db..8e86b8fae157 100644 --- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs @@ -1,11 +1,10 @@ -use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, Subdiagnostic}; +use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, Subdiagnostic, inline_fluent}; use rustc_hir::def_id::LocalDefId; use rustc_middle::bug; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{Span, kw}; use crate::error_reporting::infer::nice_region_error::find_anon_type; -use crate::fluent_generated as fluent; struct DescriptionCtx<'a> { span: Option, @@ -170,7 +169,40 @@ impl Subdiagnostic for RegionExplanation<'_> { diag.arg("desc_kind", self.desc.kind); diag.arg("desc_arg", self.desc.arg); - let msg = diag.eagerly_translate(fluent::trait_selection_region_explanation); + let msg = diag.eagerly_translate(inline_fluent!( + "{$pref_kind -> +*[should_not_happen] [{$pref_kind}] +[ref_valid_for] ...the reference is valid for +[content_valid_for] ...but the borrowed content is only valid for +[type_obj_valid_for] object type is valid for +[source_pointer_valid_for] source pointer is only valid for +[type_satisfy] type must satisfy +[type_outlive] type must outlive +[lf_param_instantiated_with] lifetime parameter instantiated with +[lf_param_must_outlive] but lifetime parameter must outlive +[lf_instantiated_with] lifetime instantiated with +[lf_must_outlive] but lifetime must outlive +[pointer_valid_for] the pointer is valid for +[data_valid_for] but the referenced data is only valid for +[empty] {\"\"} +}{$pref_kind -> +[empty] {\"\"} +*[other] {\" \"} +}{$desc_kind -> +*[should_not_happen] [{$desc_kind}] +[restatic] the static lifetime +[revar] lifetime {$desc_arg} +[as_defined] the lifetime `{$desc_arg}` as defined here +[as_defined_anon] the anonymous lifetime as defined here +[defined_here] the anonymous lifetime defined here +[defined_here_reg] the lifetime `{$desc_arg}` as defined here +}{$suff_kind -> +*[should_not_happen] [{$suff_kind}] +[empty]{\"\"} +[continues] ... +[req_by_binding] {\" \"}as required by this binding +}" + )); diag.restore_args(); if let Some(span) = self.desc.span { diag.span_note(span, msg); diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 561a95bad50c..645fd17ac709 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -34,5 +34,3 @@ pub mod opaque_types; pub mod regions; pub mod solve; pub mod traits; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 24854990fe71..46d95fdfabfe 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -1,6 +1,7 @@ //! Deeply normalize types using the old trait solver. use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_errors::inline_fluent; use rustc_hir::def::DefKind; use rustc_infer::infer::at::At; use rustc_infer::infer::{InferCtxt, InferOk}; @@ -294,7 +295,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { self.cause.span, false, |diag| { - diag.note(crate::fluent_generated::trait_selection_ty_alias_overflow); + diag.note(inline_fluent!("in case this is a recursive type alias, consider using a struct, enum, or union instead")); }, ); } From 623c9cd1432c8e53e7217e65925234e2f633f2ea Mon Sep 17 00:00:00 2001 From: apiraino Date: Thu, 5 Feb 2026 18:24:30 +0100 Subject: [PATCH 580/978] update compiler stable backport zulip msg --- triagebot.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index eb25d6e1b201..6a540b2f9aac 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -795,7 +795,8 @@ zulip_stream = 474880 # #t-compiler/backports topic = "#{number}: stable-nominated" message_on_add = [ """\ -@**channel** PR #{number} "{title}" has been nominated for stable backport. +PR #{number} "{title}" fixes a regression and has been nominated for backport. +{recipients}, what do you think about it? """, """\ /poll Approve stable backport of #{number}? From 43ee28aa1668f2b6b6beffa7548184e1183c9bf5 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 24 Jan 2026 13:57:49 +0100 Subject: [PATCH 581/978] cmse: don't use `BackendRepr` when checking return type --- .../src/hir_ty_lowering/cmse.rs | 36 ++++++++----- .../cmse-nonsecure-call/return-via-stack.rs | 12 +++-- .../return-via-stack.stderr | 51 +++++++++++-------- 3 files changed, 60 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 81bdfc1705a1..6b8c2e4d0610 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -1,8 +1,8 @@ -use rustc_abi::{BackendRepr, ExternAbi, Float, Integer, Primitive, Scalar}; +use rustc_abi::ExternAbi; use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err}; use rustc_hir::{self as hir, HirId}; use rustc_middle::bug; -use rustc_middle::ty::layout::{LayoutError, TyAndLayout}; +use rustc_middle::ty::layout::{LayoutCx, LayoutError, TyAndLayout}; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_span::Span; @@ -150,8 +150,9 @@ fn is_valid_cmse_output<'tcx>( let typing_env = ty::TypingEnv::fully_monomorphized(); let layout = tcx.layout_of(typing_env.as_query_input(return_type))?; + let layout_cx = LayoutCx::new(tcx, typing_env); - if !is_valid_cmse_output_layout(layout) { + if !is_valid_cmse_output_layout(layout_cx, layout) { dcx.emit_err(errors::CmseOutputStackSpill { span: fn_decl.output.span(), abi }); } @@ -159,25 +160,32 @@ fn is_valid_cmse_output<'tcx>( } /// Returns whether the output will fit into the available registers -fn is_valid_cmse_output_layout<'tcx>(layout: TyAndLayout<'tcx>) -> bool { +fn is_valid_cmse_output_layout<'tcx>(cx: LayoutCx<'tcx>, mut layout: TyAndLayout<'tcx>) -> bool { let size = layout.layout.size().bytes(); if size <= 4 { return true; - } else if size > 8 { + } else if size != 8 { return false; } - // Accept scalar 64-bit types. - let BackendRepr::Scalar(scalar) = layout.layout.backend_repr else { - return false; - }; + // Find the wrapped inner type of a transparent wrapper. + loop { + match layout.ty.kind() { + ty::Adt(adt_def, _) if adt_def.repr().transparent() => { + // Find the non-1-ZST field, and recurse. + (_, layout) = layout.non_1zst_field(&cx).unwrap(); + } + // Not a transparent type, no further unfolding. + _ => break, + } + } - let Scalar::Initialized { value, .. } = scalar else { - return false; - }; - - matches!(value, Primitive::Int(Integer::I64, _) | Primitive::Float(Float::F64)) + // Accept (transparently wrapped) scalar 64-bit primitives. + matches!( + layout.ty.kind(), + ty::Int(ty::IntTy::I64) | ty::Uint(ty::UintTy::U64) | ty::Float(ty::FloatTy::F64) + ) } fn should_emit_layout_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError<'tcx>) -> bool { diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs index 4565d89f0dc8..55160f7a0f00 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.rs @@ -13,6 +13,9 @@ use minicore::*; #[repr(C)] pub struct ReprCU64(u64); +#[repr(Rust)] +pub struct ReprRustU64(u64); + #[repr(C)] pub struct ReprCBytes(u8, u8, u8, u8, u8); @@ -25,10 +28,11 @@ pub struct ReprCAlign16(u16); #[no_mangle] pub fn test( f1: extern "cmse-nonsecure-call" fn() -> ReprCU64, //~ ERROR [E0798] - f2: extern "cmse-nonsecure-call" fn() -> ReprCBytes, //~ ERROR [E0798] - f3: extern "cmse-nonsecure-call" fn() -> U64Compound, //~ ERROR [E0798] - f4: extern "cmse-nonsecure-call" fn() -> ReprCAlign16, //~ ERROR [E0798] - f5: extern "cmse-nonsecure-call" fn() -> [u8; 5], //~ ERROR [E0798] + f2: extern "cmse-nonsecure-call" fn() -> ReprRustU64, //~ ERROR [E0798] + f3: extern "cmse-nonsecure-call" fn() -> ReprCBytes, //~ ERROR [E0798] + f4: extern "cmse-nonsecure-call" fn() -> U64Compound, //~ ERROR [E0798] + f5: extern "cmse-nonsecure-call" fn() -> ReprCAlign16, //~ ERROR [E0798] + f6: extern "cmse-nonsecure-call" fn() -> [u8; 5], //~ ERROR [E0798] ) { } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr index 4351444225b5..6b7446abc8eb 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr @@ -1,5 +1,5 @@ error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:37:48 + --> $DIR/return-via-stack.rs:41:48 | LL | u128: extern "cmse-nonsecure-call" fn() -> u128, | ^^^^ this type doesn't fit in the available registers @@ -8,7 +8,7 @@ LL | u128: extern "cmse-nonsecure-call" fn() -> u128, = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:38:48 + --> $DIR/return-via-stack.rs:42:48 | LL | i128: extern "cmse-nonsecure-call" fn() -> i128, | ^^^^ this type doesn't fit in the available registers @@ -17,7 +17,7 @@ LL | i128: extern "cmse-nonsecure-call" fn() -> i128, = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:27:46 + --> $DIR/return-via-stack.rs:30:46 | LL | f1: extern "cmse-nonsecure-call" fn() -> ReprCU64, | ^^^^^^^^ this type doesn't fit in the available registers @@ -26,43 +26,52 @@ LL | f1: extern "cmse-nonsecure-call" fn() -> ReprCU64, = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:28:46 + --> $DIR/return-via-stack.rs:31:46 | -LL | f2: extern "cmse-nonsecure-call" fn() -> ReprCBytes, - | ^^^^^^^^^^ this type doesn't fit in the available registers - | - = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers - = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size - -error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:29:46 - | -LL | f3: extern "cmse-nonsecure-call" fn() -> U64Compound, +LL | f2: extern "cmse-nonsecure-call" fn() -> ReprRustU64, | ^^^^^^^^^^^ this type doesn't fit in the available registers | = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:30:46 + --> $DIR/return-via-stack.rs:32:46 | -LL | f4: extern "cmse-nonsecure-call" fn() -> ReprCAlign16, +LL | f3: extern "cmse-nonsecure-call" fn() -> ReprCBytes, + | ^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:33:46 + | +LL | f4: extern "cmse-nonsecure-call" fn() -> U64Compound, + | ^^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:34:46 + | +LL | f5: extern "cmse-nonsecure-call" fn() -> ReprCAlign16, | ^^^^^^^^^^^^ this type doesn't fit in the available registers | = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:31:46 + --> $DIR/return-via-stack.rs:35:46 | -LL | f5: extern "cmse-nonsecure-call" fn() -> [u8; 5], +LL | f6: extern "cmse-nonsecure-call" fn() -> [u8; 5], | ^^^^^^^ this type doesn't fit in the available registers | = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:53:46 + --> $DIR/return-via-stack.rs:57:46 | LL | f1: extern "cmse-nonsecure-call" fn() -> ReprRustUnionU64, | ^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers @@ -71,7 +80,7 @@ LL | f1: extern "cmse-nonsecure-call" fn() -> ReprRustUnionU64, = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:54:46 + --> $DIR/return-via-stack.rs:58:46 | LL | f2: extern "cmse-nonsecure-call" fn() -> ReprCUnionU64, | ^^^^^^^^^^^^^ this type doesn't fit in the available registers @@ -79,6 +88,6 @@ LL | f2: extern "cmse-nonsecure-call" fn() -> ReprCUnionU64, = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0798`. From df0bdea5455ee0a0a67770f479b1c34003076655 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 28 Jan 2026 13:50:54 +0100 Subject: [PATCH 582/978] cmse: additional argument passing tests --- .../cmse-nonsecure-entry/params-via-stack.rs | 21 +++++++++++++++++++ .../params-via-stack.stderr | 10 ++++++++- .../cmse-nonsecure-entry/via-registers.rs | 12 ++++++++--- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs index 53e98d2eb1bc..2e73ef8c32f5 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.rs @@ -24,3 +24,24 @@ pub extern "cmse-nonsecure-entry" fn f4(_: AlignRelevant, _: u32) {} //~ ERROR [ #[no_mangle] #[allow(improper_ctypes_definitions)] pub extern "cmse-nonsecure-entry" fn f5(_: [u32; 5]) {} //~ ERROR [E0798] + +struct Four { + a: u32, + b: u32, + c: u32, + d: u32, +} + +struct Five { + a: u32, + b: u32, + c: u32, + d: u32, + e: u32, +} + +#[no_mangle] +pub extern "cmse-nonsecure-entry" fn four(_: Four) {} + +#[no_mangle] +pub extern "cmse-nonsecure-entry" fn five(_: Five) {} //~ ERROR [E0798] diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr index af8277d314ba..c17cf50a6139 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-via-stack.stderr @@ -40,6 +40,14 @@ LL | pub extern "cmse-nonsecure-entry" fn f5(_: [u32; 5]) {} | = note: functions with the `"cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit argument registers -error: aborting due to 5 previous errors +error[E0798]: arguments for `"cmse-nonsecure-entry"` function too large to pass via registers + --> $DIR/params-via-stack.rs:47:46 + | +LL | pub extern "cmse-nonsecure-entry" fn five(_: Five) {} + | ^^^^ does not fit in the available registers + | + = note: functions with the `"cmse-nonsecure-entry"` ABI must pass all their arguments via the 4 32-bit argument registers + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0798`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs index 0a6565e37fc7..756cc6816acd 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/via-registers.rs @@ -40,9 +40,15 @@ pub extern "cmse-nonsecure-entry" fn inputs5(_: f64, _: f32, _: f32) {} #[no_mangle] pub extern "cmse-nonsecure-entry" fn inputs6(_: ReprTransparentStruct, _: U32Compound) {} #[no_mangle] -#[allow(improper_ctypes_definitions)] +#[expect(improper_ctypes_definitions)] pub extern "cmse-nonsecure-entry" fn inputs7(_: [u32; 4]) {} +// With zero-sized types we can actually have more than 4 arguments. +#[expect(improper_ctypes_definitions)] +pub extern "cmse-nonsecure-entry" fn inputs8(_: (), _: (), _: (), _: (), _: ()) {} +#[expect(improper_ctypes_definitions)] +pub extern "cmse-nonsecure-entry" fn inputs9(_: (), _: (), _: (), _: (), _: ()) {} + #[no_mangle] pub extern "cmse-nonsecure-entry" fn outputs1() -> u32 { 0 @@ -69,8 +75,8 @@ pub extern "cmse-nonsecure-entry" fn outputs6() -> ReprTransparentStruct { ReprTransparentStruct { _marker1: (), _marker2: (), field: 0xAA, _marker3: () } } #[no_mangle] -pub extern "cmse-nonsecure-entry" fn outputs7( -) -> ReprTransparentStruct> { +pub extern "cmse-nonsecure-entry" fn outputs7() -> ReprTransparentStruct> +{ ReprTransparentStruct { _marker1: (), _marker2: (), From a2f9dec29cfd8a0fc1b76f5ffbf7803a904c1017 Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Thu, 5 Feb 2026 19:04:44 +0000 Subject: [PATCH 583/978] Parse #[rustc_abi(..)] --- .../src/attributes/test_attrs.rs | 50 +++++ compiler/rustc_attr_parsing/src/context.rs | 1 + .../rustc_hir/src/attrs/data_structures.rs | 11 + .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_passes/src/abi_test.rs | 193 +++++++++--------- compiler/rustc_passes/src/check_attr.rs | 2 +- tests/ui/abi/debug.generic.stderr | 44 +++- tests/ui/abi/debug.loongarch64.stderr | 44 +++- tests/ui/abi/debug.riscv64.stderr | 44 +++- tests/ui/abi/debug.rs | 10 +- 10 files changed, 276 insertions(+), 124 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 236d10d77b92..908941c2b335 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -1,3 +1,4 @@ +use rustc_hir::attrs::RustcAbiAttrKind; use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; use super::prelude::*; @@ -140,3 +141,52 @@ impl SingleAttributeParser for ReexportTestHarnessMainParser { Some(AttributeKind::ReexportTestHarnessMain(name)) } } + +pub(crate) struct RustcAbiParser; + +impl SingleAttributeParser for RustcAbiParser { + const PATH: &[Symbol] = &[sym::rustc_abi]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::debug, sym::assert_eq]); + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::TyAlias), + Allow(Target::Fn), + Allow(Target::ForeignFn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(args) = args.list() else { + cx.expected_specific_argument_and_list(cx.attr_span, &[sym::assert_eq, sym::debug]); + return None; + }; + + let Some(arg) = args.single() else { + cx.expected_single_argument(cx.attr_span); + return None; + }; + + let fail_incorrect_argument = + |span| cx.expected_specific_argument(span, &[sym::assert_eq, sym::debug]); + + let Some(arg) = arg.meta_item() else { + fail_incorrect_argument(args.span); + return None; + }; + + let kind: RustcAbiAttrKind = match arg.path().word_sym() { + Some(sym::assert_eq) => RustcAbiAttrKind::AssertEq, + Some(sym::debug) => RustcAbiAttrKind::Debug, + None | Some(_) => { + fail_incorrect_argument(arg.span()); + return None; + } + }; + + Some(AttributeKind::RustcAbi { attr_span: cx.attr_span, kind }) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 5abf299ec618..6259a90ea3f3 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -191,6 +191,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index a444b5e4badf..2a3adbd77e6e 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -167,6 +167,14 @@ pub enum CoverageAttrKind { Off, } +/// Successfully-parsed value of a `#[rustc_abi(..)]` attribute. +#[derive(Copy, Debug, Eq, PartialEq, Encodable, Decodable, Clone)] +#[derive(HashStable_Generic, PrintAttribute)] +pub enum RustcAbiAttrKind { + Debug, + AssertEq, +} + impl Deprecation { /// Whether an item marked with #[deprecated(since = "X")] is currently /// deprecated (i.e., whether X is not greater than the current rustc @@ -1015,6 +1023,9 @@ pub enum AttributeKind { /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations). Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span }, + /// Represents `#[rustc_abi(..)]` + RustcAbi { attr_span: Span, kind: RustcAbiAttrKind }, + /// Represents `#[rustc_allocator]` RustcAllocator, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index b6249e1e2ec2..6a529cae5f19 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -89,6 +89,7 @@ impl AttributeKind { RecursionLimit { .. } => No, ReexportTestHarnessMain(..) => No, Repr { .. } => No, + RustcAbi { .. } => No, RustcAllocator => No, RustcAllocatorZeroed => No, RustcAllocatorZeroedVariant { .. } => Yes, diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs index 0ac42f03eb2f..c3e80208e2d5 100644 --- a/compiler/rustc_passes/src/abi_test.rs +++ b/compiler/rustc_passes/src/abi_test.rs @@ -1,11 +1,12 @@ -use rustc_hir::Attribute; +use rustc_hir::attrs::{AttributeKind, RustcAbiAttrKind}; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; +use rustc_hir::find_attr; use rustc_middle::span_bug; use rustc_middle::ty::layout::{FnAbiError, LayoutError}; use rustc_middle::ty::{self, GenericArgs, Instance, Ty, TyCtxt}; +use rustc_span::Span; use rustc_span::source_map::Spanned; -use rustc_span::sym; use rustc_target::callconv::FnAbi; use super::layout_test::ensure_wf; @@ -17,17 +18,19 @@ pub fn test_abi(tcx: TyCtxt<'_>) { return; } for id in tcx.hir_crate_items(()).definitions() { - for attr in tcx.get_attrs(id, sym::rustc_abi) { - match tcx.def_kind(id) { - DefKind::Fn | DefKind::AssocFn => { - dump_abi_of_fn_item(tcx, id, attr); - } - DefKind::TyAlias => { - dump_abi_of_fn_type(tcx, id, attr); - } - _ => { - tcx.dcx().emit_err(AbiInvalidAttribute { span: tcx.def_span(id) }); - } + let Some((attr_span, attr_kind)) = find_attr!(tcx.get_all_attrs(id), AttributeKind::RustcAbi{ attr_span, kind } => (*attr_span, *kind)) + else { + continue; + }; + match tcx.def_kind(id) { + DefKind::Fn | DefKind::AssocFn => { + dump_abi_of_fn_item(tcx, id, attr_span, attr_kind); + } + DefKind::TyAlias => { + dump_abi_of_fn_type(tcx, id, attr_span, attr_kind); + } + _ => { + tcx.dcx().emit_err(AbiInvalidAttribute { span: tcx.def_span(id) }); } } } @@ -49,7 +52,12 @@ fn unwrap_fn_abi<'tcx>( } } -fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { +fn dump_abi_of_fn_item( + tcx: TyCtxt<'_>, + item_def_id: LocalDefId, + attr_span: Span, + attr_kind: RustcAbiAttrKind, +) { let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id); let args = GenericArgs::identity_for_item(tcx, item_def_id); let instance = match Instance::try_resolve(tcx, typing_env, item_def_id.into(), args) { @@ -75,22 +83,18 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut // Check out the `#[rustc_abi(..)]` attribute to tell what to dump. // The `..` are the names of fields to dump. - let meta_items = attr.meta_item_list().unwrap_or_default(); - for meta_item in meta_items { - match meta_item.name() { - Some(sym::debug) => { - let fn_name = tcx.item_name(item_def_id); - tcx.dcx().emit_err(AbiOf { - span: tcx.def_span(item_def_id), - fn_name, - // FIXME: using the `Debug` impl here isn't ideal. - fn_abi: format!("{:#?}", abi), - }); - } - - _ => { - tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() }); - } + match attr_kind { + RustcAbiAttrKind::Debug => { + let fn_name = tcx.item_name(item_def_id); + tcx.dcx().emit_err(AbiOf { + span: tcx.def_span(item_def_id), + fn_name, + // FIXME: using the `Debug` impl here isn't ideal. + fn_abi: format!("{:#?}", abi), + }); + } + _ => { + tcx.dcx().emit_err(UnrecognizedArgument { span: attr_span }); } } } @@ -109,24 +113,29 @@ fn test_abi_eq<'tcx>(abi1: &'tcx FnAbi<'tcx, Ty<'tcx>>, abi2: &'tcx FnAbi<'tcx, && abi1.args.iter().zip(abi2.args.iter()).all(|(arg1, arg2)| arg1.eq_abi(arg2)) } -fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { +fn dump_abi_of_fn_type( + tcx: TyCtxt<'_>, + item_def_id: LocalDefId, + attr_span: Span, + attr_kind: RustcAbiAttrKind, +) { let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id); let ty = tcx.type_of(item_def_id).instantiate_identity(); let span = tcx.def_span(item_def_id); if !ensure_wf(tcx, typing_env, ty, item_def_id, span) { return; } - let meta_items = attr.meta_item_list().unwrap_or_default(); - for meta_item in meta_items { - match meta_item.name() { - Some(sym::debug) => { - let ty::FnPtr(sig_tys, hdr) = ty.kind() else { - span_bug!( - meta_item.span(), - "`#[rustc_abi(debug)]` on a type alias requires function pointer type" - ); - }; - let abi = unwrap_fn_abi( + + match attr_kind { + RustcAbiAttrKind::Debug => { + let ty::FnPtr(sig_tys, hdr) = ty.kind() else { + span_bug!( + attr_span, + "`#[rustc_abi(debug)]` on a type alias requires function pointer type" + ); + }; + let abi = + unwrap_fn_abi( tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( sig_tys.with(*hdr), /* extra_args */ ty::List::empty(), @@ -135,61 +144,57 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut item_def_id, ); - let fn_name = tcx.item_name(item_def_id); - tcx.dcx().emit_err(AbiOf { span, fn_name, fn_abi: format!("{:#?}", abi) }); - } - Some(sym::assert_eq) => { - let ty::Tuple(fields) = ty.kind() else { - span_bug!( - meta_item.span(), - "`#[rustc_abi(assert_eq)]` on a type alias requires pair type" - ); - }; - let [field1, field2] = ***fields else { - span_bug!( - meta_item.span(), - "`#[rustc_abi(assert_eq)]` on a type alias requires pair type" - ); - }; - let ty::FnPtr(sig_tys1, hdr1) = field1.kind() else { - span_bug!( - meta_item.span(), - "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types" - ); - }; - let abi1 = unwrap_fn_abi( - tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( - sig_tys1.with(*hdr1), - /* extra_args */ ty::List::empty(), - ))), - tcx, - item_def_id, + let fn_name = tcx.item_name(item_def_id); + tcx.dcx().emit_err(AbiOf { span, fn_name, fn_abi: format!("{:#?}", abi) }); + } + RustcAbiAttrKind::AssertEq => { + let ty::Tuple(fields) = ty.kind() else { + span_bug!( + attr_span, + "`#[rustc_abi(assert_eq)]` on a type alias requires pair type" ); - let ty::FnPtr(sig_tys2, hdr2) = field2.kind() else { - span_bug!( - meta_item.span(), - "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types" - ); - }; - let abi2 = unwrap_fn_abi( - tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( - sig_tys2.with(*hdr2), - /* extra_args */ ty::List::empty(), - ))), - tcx, - item_def_id, + }; + let [field1, field2] = ***fields else { + span_bug!( + attr_span, + "`#[rustc_abi(assert_eq)]` on a type alias requires pair type" ); + }; + let ty::FnPtr(sig_tys1, hdr1) = field1.kind() else { + span_bug!( + attr_span, + "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types" + ); + }; + let abi1 = unwrap_fn_abi( + tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( + sig_tys1.with(*hdr1), + /* extra_args */ ty::List::empty(), + ))), + tcx, + item_def_id, + ); + let ty::FnPtr(sig_tys2, hdr2) = field2.kind() else { + span_bug!( + attr_span, + "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types" + ); + }; + let abi2 = unwrap_fn_abi( + tcx.fn_abi_of_fn_ptr(typing_env.as_query_input(( + sig_tys2.with(*hdr2), + /* extra_args */ ty::List::empty(), + ))), + tcx, + item_def_id, + ); - if !test_abi_eq(abi1, abi2) { - tcx.dcx().emit_err(AbiNe { - span, - left: format!("{:#?}", abi1), - right: format!("{:#?}", abi2), - }); - } - } - _ => { - tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() }); + if !test_abi_eq(abi1, abi2) { + tcx.dcx().emit_err(AbiNe { + span, + left: format!("{:#?}", abi1), + right: format!("{:#?}", abi2), + }); } } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 0d64e30d9c79..27398d4a9ac4 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -287,6 +287,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::ReexportTestHarnessMain(..) // handled below this loop and elsewhere | AttributeKind::Repr { .. } + | AttributeKind::RustcAbi { .. } | AttributeKind::RustcAllocator | AttributeKind::RustcAllocatorZeroed | AttributeKind::RustcAllocatorZeroedVariant { .. } @@ -392,7 +393,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_conversion_suggestion | sym::rustc_deprecated_safe_2024 | sym::rustc_test_marker - | sym::rustc_abi | sym::rustc_layout | sym::rustc_proc_macro_decls | sym::rustc_never_type_options diff --git a/tests/ui/abi/debug.generic.stderr b/tests/ui/abi/debug.generic.stderr index 8a031b79780a..b154c3fa201e 100644 --- a/tests/ui/abi/debug.generic.stderr +++ b/tests/ui/abi/debug.generic.stderr @@ -1,3 +1,36 @@ +error: `#[rustc_abi]` attribute cannot be used on constants + --> $DIR/debug.rs:42:1 + | +LL | #[rustc_abi(debug)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_abi]` can be applied to functions and type aliases + +error: `#[rustc_abi]` attribute cannot be used on associated consts + --> $DIR/debug.rs:46:5 + | +LL | #[rustc_abi(debug)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_abi]` can be applied to functions and type aliases + +error[E0539]: malformed `rustc_abi` attribute input + --> $DIR/debug.rs:74:1 + | +LL | #[rustc_abi("assert_eq")] + | ^^^^^^^^^^^-------------^ + | | + | valid arguments are `assert_eq` or `debug` + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[rustc_abi("assert_eq")] +LL + #[rustc_abi(assert_eq)] + | +LL - #[rustc_abi("assert_eq")] +LL + #[rustc_abi(debug)] + | + error: fn_abi_of(test) = FnAbi { args: [ ArgAbi { @@ -884,12 +917,6 @@ LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); = help: the trait `Sized` is not implemented for `str` = note: only the last element of a tuple may have a dynamically sized type -error: unrecognized argument - --> $DIR/debug.rs:74:13 - | -LL | #[rustc_abi("assert_eq")] - | ^^^^^^^^^^^ - error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions --> $DIR/debug.rs:47:5 | @@ -986,6 +1013,7 @@ error: fn_abi_of(assoc_test) = FnAbi { LL | fn assoc_test(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 14 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0539. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/abi/debug.loongarch64.stderr b/tests/ui/abi/debug.loongarch64.stderr index 00bd3febde4e..68bcd736e47c 100644 --- a/tests/ui/abi/debug.loongarch64.stderr +++ b/tests/ui/abi/debug.loongarch64.stderr @@ -1,3 +1,36 @@ +error: `#[rustc_abi]` attribute cannot be used on constants + --> $DIR/debug.rs:42:1 + | +LL | #[rustc_abi(debug)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_abi]` can be applied to functions and type aliases + +error: `#[rustc_abi]` attribute cannot be used on associated consts + --> $DIR/debug.rs:46:5 + | +LL | #[rustc_abi(debug)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_abi]` can be applied to functions and type aliases + +error[E0539]: malformed `rustc_abi` attribute input + --> $DIR/debug.rs:74:1 + | +LL | #[rustc_abi("assert_eq")] + | ^^^^^^^^^^^-------------^ + | | + | valid arguments are `assert_eq` or `debug` + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[rustc_abi("assert_eq")] +LL + #[rustc_abi(assert_eq)] + | +LL - #[rustc_abi("assert_eq")] +LL + #[rustc_abi(debug)] + | + error: fn_abi_of(test) = FnAbi { args: [ ArgAbi { @@ -884,12 +917,6 @@ LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); = help: the trait `Sized` is not implemented for `str` = note: only the last element of a tuple may have a dynamically sized type -error: unrecognized argument - --> $DIR/debug.rs:74:13 - | -LL | #[rustc_abi("assert_eq")] - | ^^^^^^^^^^^ - error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions --> $DIR/debug.rs:47:5 | @@ -986,6 +1013,7 @@ error: fn_abi_of(assoc_test) = FnAbi { LL | fn assoc_test(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 14 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0539. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/abi/debug.riscv64.stderr b/tests/ui/abi/debug.riscv64.stderr index 00bd3febde4e..68bcd736e47c 100644 --- a/tests/ui/abi/debug.riscv64.stderr +++ b/tests/ui/abi/debug.riscv64.stderr @@ -1,3 +1,36 @@ +error: `#[rustc_abi]` attribute cannot be used on constants + --> $DIR/debug.rs:42:1 + | +LL | #[rustc_abi(debug)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_abi]` can be applied to functions and type aliases + +error: `#[rustc_abi]` attribute cannot be used on associated consts + --> $DIR/debug.rs:46:5 + | +LL | #[rustc_abi(debug)] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_abi]` can be applied to functions and type aliases + +error[E0539]: malformed `rustc_abi` attribute input + --> $DIR/debug.rs:74:1 + | +LL | #[rustc_abi("assert_eq")] + | ^^^^^^^^^^^-------------^ + | | + | valid arguments are `assert_eq` or `debug` + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[rustc_abi("assert_eq")] +LL + #[rustc_abi(assert_eq)] + | +LL - #[rustc_abi("assert_eq")] +LL + #[rustc_abi(debug)] + | + error: fn_abi_of(test) = FnAbi { args: [ ArgAbi { @@ -884,12 +917,6 @@ LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); = help: the trait `Sized` is not implemented for `str` = note: only the last element of a tuple may have a dynamically sized type -error: unrecognized argument - --> $DIR/debug.rs:74:13 - | -LL | #[rustc_abi("assert_eq")] - | ^^^^^^^^^^^ - error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions --> $DIR/debug.rs:47:5 | @@ -986,6 +1013,7 @@ error: fn_abi_of(assoc_test) = FnAbi { LL | fn assoc_test(&self) {} | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 14 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0539. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/abi/debug.rs b/tests/ui/abi/debug.rs index 2e34fa5d7df4..42ea14ec51d0 100644 --- a/tests/ui/abi/debug.rs +++ b/tests/ui/abi/debug.rs @@ -39,12 +39,12 @@ type TestFnPtr = fn(bool) -> u8; //~ ERROR: fn_abi #[rustc_abi(debug)] fn test_generic(_x: *const T) {} //~ ERROR: fn_abi -#[rustc_abi(debug)] -const C: () = (); //~ ERROR: can only be applied to +#[rustc_abi(debug)] //~ ERROR: `#[rustc_abi]` attribute cannot be used on constants +const C: () = (); //~ ERROR: `#[rustc_abi]` can only be applied to impl S { - #[rustc_abi(debug)] - const C: () = (); //~ ERROR: can only be applied to + #[rustc_abi(debug)] //~ ERROR: `#[rustc_abi]` attribute cannot be used on assoc + const C: () = (); //~ ERROR: `#[rustc_abi]` can only be applied to } impl S { @@ -71,5 +71,5 @@ type TestAbiNeSign = (fn(i32), fn(u32)); //~ ERROR: ABIs are not compatible #[rustc_abi(assert_eq)] type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); //~ ERROR: cannot be known at compilation time -#[rustc_abi("assert_eq")] //~ ERROR unrecognized argument +#[rustc_abi("assert_eq")] //~ ERROR malformed `rustc_abi` attribute input type Bad = u32; From 0061a2232de5b23a703380e8f90926c5335aecad Mon Sep 17 00:00:00 2001 From: Usman Akinyemi Date: Wed, 14 Jan 2026 11:03:45 +0530 Subject: [PATCH 584/978] rustc_parse_format: improve diagnostics for unsupported debug `=` syntax Detect Python-style f-string debug syntax in format strings and emit a clear diagnostic explaining that it is not supported in Rust. When the intended operation can be inferred, suggest the corresponding Rust alternative e.g from `println!("{=}", x)` to `dbg!({x})`. Signed-off-by: Usman Akinyemi --- compiler/rustc_builtin_macros/src/errors.rs | 12 ++++++++++ compiler/rustc_builtin_macros/src/format.rs | 20 ++++++++++++++++- compiler/rustc_parse_format/src/lib.rs | 25 +++++++++++++++++++++ tests/ui/fmt/format-string-error-2.rs | 3 +++ tests/ui/fmt/format-string-error-2.stderr | 12 +++++++++- tests/ui/fmt/format-string-error-3.fixed | 5 +++++ tests/ui/fmt/format-string-error-3.rs | 5 +++++ tests/ui/fmt/format-string-error-3.stderr | 17 ++++++++++++++ 8 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 tests/ui/fmt/format-string-error-3.fixed create mode 100644 tests/ui/fmt/format-string-error-3.rs create mode 100644 tests/ui/fmt/format-string-error-3.stderr diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index d3f7e1c5d8e3..898deaadf2f6 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -678,6 +678,18 @@ pub(crate) enum InvalidFormatStringSuggestion { #[primary_span] span: Span, }, + + #[suggestion( + "use rust debug printing macro", + code = "{replacement}", + style = "verbose", + applicability = "machine-applicable" + )] + UseRustDebugPrintingMacro { + #[primary_span] + macro_span: Span, + replacement: String, + }, } #[derive(Diagnostic)] diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 12cb2cd00694..f47dae5eba00 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -160,6 +160,7 @@ fn make_format_args( ecx: &mut ExtCtxt<'_>, input: MacroInput, append_newline: bool, + macro_span: Span, ) -> ExpandResult, ()> { let msg = "format argument must be a string literal"; let unexpanded_fmt_span = input.fmtstr.span; @@ -333,6 +334,23 @@ fn make_format_args( let span = fmt_span.from_inner(InnerSpan::new(span.start, span.end)); e.sugg_ = Some(errors::InvalidFormatStringSuggestion::AddMissingColon { span }); } + parse::Suggestion::UseRustDebugPrintingMacro => { + // This targets `println!("{=}", x);` and `println!("{0=}", x);` + if let [arg] = args.all_args() { + let expr_span = arg.expr.span; + if let Ok(expr_snippet) = ecx.source_map().span_to_snippet(expr_span) { + let replacement = format!("{}!({})", "dbg", expr_snippet); + + let call_span = macro_span.source_callsite(); + e.sugg_ = Some( + errors::InvalidFormatStringSuggestion::UseRustDebugPrintingMacro { + macro_span: call_span, + replacement, + }, + ); + } + } + } } let guar = ecx.dcx().emit_err(e); return ExpandResult::Ready(Err(guar)); @@ -1048,7 +1066,7 @@ fn expand_format_args_impl<'cx>( sp = ecx.with_def_site_ctxt(sp); ExpandResult::Ready(match parse_args(ecx, sp, tts) { Ok(input) => { - let ExpandResult::Ready(mac) = make_format_args(ecx, input, nl) else { + let ExpandResult::Ready(mac) = make_format_args(ecx, input, nl, sp) else { return ExpandResult::Retry(()); }; match mac { diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 3d8b97b2fde3..2338268a874f 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -187,6 +187,9 @@ pub enum Suggestion { /// Add missing colon: /// `format!("{foo?}")` -> `format!("{foo:?}")` AddMissingColon(Range), + /// Use Rust format string: + /// `format!("{x=}")` -> `dbg!(x)` + UseRustDebugPrintingMacro, } /// The parser structure for interpreting the input format string. This is @@ -462,6 +465,7 @@ impl<'input> Parser<'input> { ('?', _) => self.suggest_format_debug(), ('<' | '^' | '>', _) => self.suggest_format_align(c), (',', _) => self.suggest_unsupported_python_numeric_grouping(), + ('=', '}') => self.suggest_rust_debug_printing_macro(), _ => self.suggest_positional_arg_instead_of_captured_arg(arg), } } @@ -871,6 +875,27 @@ impl<'input> Parser<'input> { } } + fn suggest_rust_debug_printing_macro(&mut self) { + if let Some((range, _)) = self.consume_pos('=') { + self.errors.insert( + 0, + ParseError { + description: + "python's f-string debug `=` is not supported in rust, use `dbg(x)` instead" + .to_owned(), + note: Some(format!("to print `{{`, you can escape it using `{{{{`",)), + label: "expected `}`".to_owned(), + span: range, + secondary_label: self + .last_open_brace + .clone() + .map(|sp| ("because of this opening brace".to_owned(), sp)), + suggestion: Suggestion::UseRustDebugPrintingMacro, + }, + ); + } + } + fn suggest_format_align(&mut self, alignment: char) { if let Some((range, _)) = self.consume_pos(alignment) { self.errors.insert( diff --git a/tests/ui/fmt/format-string-error-2.rs b/tests/ui/fmt/format-string-error-2.rs index 63d65023eb78..c1d228bfbc9c 100644 --- a/tests/ui/fmt/format-string-error-2.rs +++ b/tests/ui/fmt/format-string-error-2.rs @@ -88,4 +88,7 @@ raw { \n //~^ ERROR invalid format string: expected `}`, found `?` println!("{x,}, world!",); //~^ ERROR invalid format string: python's numeric grouping `,` is not supported in rust format strings + + println!("{x=}"); + //~^ ERROR invalid format string: python's f-string debug `=` is not supported in rust, use `dbg(x)` instead } diff --git a/tests/ui/fmt/format-string-error-2.stderr b/tests/ui/fmt/format-string-error-2.stderr index e7fbc2e81fc6..b12e827853f8 100644 --- a/tests/ui/fmt/format-string-error-2.stderr +++ b/tests/ui/fmt/format-string-error-2.stderr @@ -198,5 +198,15 @@ LL | println!("{x,}, world!",); | = note: to print `{`, you can escape it using `{{` -error: aborting due to 20 previous errors +error: invalid format string: python's f-string debug `=` is not supported in rust, use `dbg(x)` instead + --> $DIR/format-string-error-2.rs:92:17 + | +LL | println!("{x=}"); + | - ^ expected `}` in format string + | | + | because of this opening brace + | + = note: to print `{`, you can escape it using `{{` + +error: aborting due to 21 previous errors diff --git a/tests/ui/fmt/format-string-error-3.fixed b/tests/ui/fmt/format-string-error-3.fixed new file mode 100644 index 000000000000..16a169db1147 --- /dev/null +++ b/tests/ui/fmt/format-string-error-3.fixed @@ -0,0 +1,5 @@ +//@ run-rustfix +fn main() { + let x = 32; + dbg!(x); //~ ERROR invalid format string: python's f-string debug +} diff --git a/tests/ui/fmt/format-string-error-3.rs b/tests/ui/fmt/format-string-error-3.rs new file mode 100644 index 000000000000..bd61233a475e --- /dev/null +++ b/tests/ui/fmt/format-string-error-3.rs @@ -0,0 +1,5 @@ +//@ run-rustfix +fn main() { + let x = 32; + println!("{=}", x); //~ ERROR invalid format string: python's f-string debug +} diff --git a/tests/ui/fmt/format-string-error-3.stderr b/tests/ui/fmt/format-string-error-3.stderr new file mode 100644 index 000000000000..e07f47cff5a6 --- /dev/null +++ b/tests/ui/fmt/format-string-error-3.stderr @@ -0,0 +1,17 @@ +error: invalid format string: python's f-string debug `=` is not supported in rust, use `dbg(x)` instead + --> $DIR/format-string-error-3.rs:4:16 + | +LL | println!("{=}", x); + | -^ expected `}` in format string + | | + | because of this opening brace + | + = note: to print `{`, you can escape it using `{{` +help: use rust debug printing macro + | +LL - println!("{=}", x); +LL + dbg!(x); + | + +error: aborting due to 1 previous error + From ec3de4bac51689656c904cfa66dee3593854a9e7 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 5 Feb 2026 11:30:41 -0800 Subject: [PATCH 585/978] Replace `stdarch` version placeholders with 1.94 (cherry picked from commit b90149755ad030e74bc3c198f8c4b90e08be8065) --- .../core_arch/src/aarch64/neon/generated.rs | 210 +- .../src/arm_shared/neon/generated.rs | 404 ++-- .../core_arch/src/arm_shared/neon/mod.rs | 14 +- .../crates/core_arch/src/x86/avx512fp16.rs | 1762 ++++++++--------- .../crates/core_arch/src/x86/avxneconvert.rs | 8 +- .../stdarch/crates/core_arch/src/x86/mod.rs | 4 +- .../crates/core_arch/src/x86_64/avx512fp16.rs | 24 +- .../crates/core_arch/src/x86_64/mod.rs | 2 +- .../spec/neon/aarch64.spec.yml | 4 +- .../spec/neon/arm_shared.spec.yml | 8 +- 10 files changed, 1220 insertions(+), 1220 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index 9507b71106dd..ed50bff5ae31 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -1565,7 +1565,7 @@ pub fn vceqh_f16(a: f16, b: f16) -> u16 { #[inline(always)] #[cfg_attr(test, assert_instr(fcmeq))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vceqz_f16(a: float16x4_t) -> uint16x4_t { let b: f16x4 = f16x4::new(0.0, 0.0, 0.0, 0.0); @@ -1576,7 +1576,7 @@ pub fn vceqz_f16(a: float16x4_t) -> uint16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcmeq))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vceqzq_f16(a: float16x8_t) -> uint16x8_t { let b: f16x8 = f16x8::new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); @@ -7283,7 +7283,7 @@ pub fn vcvtq_f64_u64(a: uint64x2_t) -> float64x2_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtn2))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvt_high_f16_f32(a: float16x4_t, b: float32x4_t) -> float16x8_t { vcombine_f16(a, vcvt_f16_f32(b)) @@ -7293,7 +7293,7 @@ pub fn vcvt_high_f16_f32(a: float16x4_t, b: float32x4_t) -> float16x8_t { #[inline(always)] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtl2))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvt_high_f32_f16(a: float16x8_t) -> float32x4_t { vcvt_f32_f16(vget_high_f16(a)) @@ -7532,7 +7532,7 @@ pub fn vcvtq_u64_f64(a: float64x2_t) -> uint64x2_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtas))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvta_s16_f16(a: float16x4_t) -> int16x4_t { unsafe extern "unadjusted" { @@ -7549,7 +7549,7 @@ pub fn vcvta_s16_f16(a: float16x4_t) -> int16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtas))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtaq_s16_f16(a: float16x8_t) -> int16x8_t { unsafe extern "unadjusted" { @@ -7630,7 +7630,7 @@ pub fn vcvtaq_s64_f64(a: float64x2_t) -> int64x2_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtau))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvta_u16_f16(a: float16x4_t) -> uint16x4_t { unsafe extern "unadjusted" { @@ -7647,7 +7647,7 @@ pub fn vcvta_u16_f16(a: float16x4_t) -> uint16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtau))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtaq_u16_f16(a: float16x8_t) -> uint16x8_t { unsafe extern "unadjusted" { @@ -8218,7 +8218,7 @@ pub fn vcvth_u64_f16(a: f16) -> u64 { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtms))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtm_s16_f16(a: float16x4_t) -> int16x4_t { unsafe extern "unadjusted" { @@ -8235,7 +8235,7 @@ pub fn vcvtm_s16_f16(a: float16x4_t) -> int16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtms))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtmq_s16_f16(a: float16x8_t) -> int16x8_t { unsafe extern "unadjusted" { @@ -8316,7 +8316,7 @@ pub fn vcvtmq_s64_f64(a: float64x2_t) -> int64x2_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtmu))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtm_u16_f16(a: float16x4_t) -> uint16x4_t { unsafe extern "unadjusted" { @@ -8333,7 +8333,7 @@ pub fn vcvtm_u16_f16(a: float16x4_t) -> uint16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtmu))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtmq_u16_f16(a: float16x8_t) -> uint16x8_t { unsafe extern "unadjusted" { @@ -8566,7 +8566,7 @@ pub fn vcvtmd_u64_f64(a: f64) -> u64 { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtns))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtn_s16_f16(a: float16x4_t) -> int16x4_t { unsafe extern "unadjusted" { @@ -8583,7 +8583,7 @@ pub fn vcvtn_s16_f16(a: float16x4_t) -> int16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtns))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtnq_s16_f16(a: float16x8_t) -> int16x8_t { unsafe extern "unadjusted" { @@ -8664,7 +8664,7 @@ pub fn vcvtnq_s64_f64(a: float64x2_t) -> int64x2_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtnu))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtn_u16_f16(a: float16x4_t) -> uint16x4_t { unsafe extern "unadjusted" { @@ -8681,7 +8681,7 @@ pub fn vcvtn_u16_f16(a: float16x4_t) -> uint16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtnu))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtnq_u16_f16(a: float16x8_t) -> uint16x8_t { unsafe extern "unadjusted" { @@ -8914,7 +8914,7 @@ pub fn vcvtnd_u64_f64(a: f64) -> u64 { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtps))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtp_s16_f16(a: float16x4_t) -> int16x4_t { unsafe extern "unadjusted" { @@ -8931,7 +8931,7 @@ pub fn vcvtp_s16_f16(a: float16x4_t) -> int16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtps))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtpq_s16_f16(a: float16x8_t) -> int16x8_t { unsafe extern "unadjusted" { @@ -9012,7 +9012,7 @@ pub fn vcvtpq_s64_f64(a: float64x2_t) -> int64x2_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtpu))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtp_u16_f16(a: float16x4_t) -> uint16x4_t { unsafe extern "unadjusted" { @@ -9029,7 +9029,7 @@ pub fn vcvtp_u16_f16(a: float16x4_t) -> uint16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fcvtpu))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vcvtpq_u16_f16(a: float16x8_t) -> uint16x8_t { unsafe extern "unadjusted" { @@ -9493,7 +9493,7 @@ pub fn vcvtxd_f32_f64(a: f64) -> f32 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vdiv_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fdiv))] pub fn vdiv_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -9503,7 +9503,7 @@ pub fn vdiv_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vdivq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fdiv))] pub fn vdivq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -10108,7 +10108,7 @@ pub fn vfma_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfma_lane_f16( a: float16x4_t, @@ -10124,7 +10124,7 @@ pub fn vfma_lane_f16( #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfma_laneq_f16( a: float16x4_t, @@ -10140,7 +10140,7 @@ pub fn vfma_laneq_f16( #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmaq_lane_f16( a: float16x8_t, @@ -10156,7 +10156,7 @@ pub fn vfmaq_lane_f16( #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmaq_laneq_f16( a: float16x8_t, @@ -10434,7 +10434,7 @@ pub fn vfmad_laneq_f64(a: f64, b: f64, c: float64x2_t) -> f64 { #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlal2))] pub fn vfmlal_high_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float32x2_t { @@ -10452,7 +10452,7 @@ pub fn vfmlal_high_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float3 #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlal2))] pub fn vfmlalq_high_f16(r: float32x4_t, a: float16x8_t, b: float16x8_t) -> float32x4_t { @@ -10472,7 +10472,7 @@ pub fn vfmlalq_high_f16(r: float32x4_t, a: float16x8_t, b: float16x8_t) -> float #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlal_lane_high_f16( r: float32x2_t, @@ -10489,7 +10489,7 @@ pub fn vfmlal_lane_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlal_laneq_high_f16( r: float32x2_t, @@ -10506,7 +10506,7 @@ pub fn vfmlal_laneq_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlalq_lane_high_f16( r: float32x4_t, @@ -10523,7 +10523,7 @@ pub fn vfmlalq_lane_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlalq_laneq_high_f16( r: float32x4_t, @@ -10540,7 +10540,7 @@ pub fn vfmlalq_laneq_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlal_lane_low_f16( r: float32x2_t, @@ -10557,7 +10557,7 @@ pub fn vfmlal_lane_low_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlal_laneq_low_f16( r: float32x2_t, @@ -10574,7 +10574,7 @@ pub fn vfmlal_laneq_low_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlalq_lane_low_f16( r: float32x4_t, @@ -10591,7 +10591,7 @@ pub fn vfmlalq_lane_low_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlalq_laneq_low_f16( r: float32x4_t, @@ -10606,7 +10606,7 @@ pub fn vfmlalq_laneq_low_f16( #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlal))] pub fn vfmlal_low_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float32x2_t { @@ -10624,7 +10624,7 @@ pub fn vfmlal_low_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float32 #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlal))] pub fn vfmlalq_low_f16(r: float32x4_t, a: float16x8_t, b: float16x8_t) -> float32x4_t { @@ -10642,7 +10642,7 @@ pub fn vfmlalq_low_f16(r: float32x4_t, a: float16x8_t, b: float16x8_t) -> float3 #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlsl2))] pub fn vfmlsl_high_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float32x2_t { @@ -10660,7 +10660,7 @@ pub fn vfmlsl_high_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float3 #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlsl2))] pub fn vfmlslq_high_f16(r: float32x4_t, a: float16x8_t, b: float16x8_t) -> float32x4_t { @@ -10680,7 +10680,7 @@ pub fn vfmlslq_high_f16(r: float32x4_t, a: float16x8_t, b: float16x8_t) -> float #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlsl_lane_high_f16( r: float32x2_t, @@ -10697,7 +10697,7 @@ pub fn vfmlsl_lane_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlsl_laneq_high_f16( r: float32x2_t, @@ -10714,7 +10714,7 @@ pub fn vfmlsl_laneq_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlslq_lane_high_f16( r: float32x4_t, @@ -10731,7 +10731,7 @@ pub fn vfmlslq_lane_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlslq_laneq_high_f16( r: float32x4_t, @@ -10748,7 +10748,7 @@ pub fn vfmlslq_laneq_high_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlsl_lane_low_f16( r: float32x2_t, @@ -10765,7 +10765,7 @@ pub fn vfmlsl_lane_low_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlsl_laneq_low_f16( r: float32x2_t, @@ -10782,7 +10782,7 @@ pub fn vfmlsl_laneq_low_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlslq_lane_low_f16( r: float32x4_t, @@ -10799,7 +10799,7 @@ pub fn vfmlslq_lane_low_f16( #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmlslq_laneq_low_f16( r: float32x4_t, @@ -10814,7 +10814,7 @@ pub fn vfmlslq_laneq_low_f16( #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlsl))] pub fn vfmlsl_low_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float32x2_t { @@ -10832,7 +10832,7 @@ pub fn vfmlsl_low_f16(r: float32x2_t, a: float16x4_t, b: float16x4_t) -> float32 #[inline(always)] #[target_feature(enable = "neon,fp16")] #[cfg_attr(not(target_arch = "arm"), target_feature(enable = "fhm"))] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmlsl))] pub fn vfmlslq_low_f16(r: float32x4_t, a: float16x8_t, b: float16x8_t) -> float32x4_t { @@ -10863,7 +10863,7 @@ pub fn vfms_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfms_lane_f16( a: float16x4_t, @@ -10879,7 +10879,7 @@ pub fn vfms_lane_f16( #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfms_laneq_f16( a: float16x4_t, @@ -10895,7 +10895,7 @@ pub fn vfms_laneq_f16( #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmsq_lane_f16( a: float16x8_t, @@ -10911,7 +10911,7 @@ pub fn vfmsq_lane_f16( #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vfmsq_laneq_f16( a: float16x8_t, @@ -15078,7 +15078,7 @@ pub fn vmul_lane_f64(a: float64x1_t, b: float64x1_t) -> float64 #[cfg_attr(test, assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vmul_laneq_f16(a: float16x4_t, b: float16x8_t) -> float16x4_t { static_assert_uimm_bits!(LANE, 3); @@ -15095,7 +15095,7 @@ pub fn vmul_laneq_f16(a: float16x4_t, b: float16x8_t) -> float1 #[cfg_attr(test, assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vmulq_laneq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { static_assert_uimm_bits!(LANE, 3); @@ -15602,7 +15602,7 @@ pub fn vmuld_laneq_f64(a: f64, b: float64x2_t) -> f64 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vmulx_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmulx))] pub fn vmulx_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -15619,7 +15619,7 @@ pub fn vmulx_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vmulxq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmulx))] pub fn vmulxq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -15702,7 +15702,7 @@ pub fn vmulxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vmulx_lane_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { static_assert_uimm_bits!(LANE, 2); @@ -15719,7 +15719,7 @@ pub fn vmulx_lane_f16(a: float16x4_t, b: float16x4_t) -> float1 #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vmulx_laneq_f16(a: float16x4_t, b: float16x8_t) -> float16x4_t { static_assert_uimm_bits!(LANE, 3); @@ -15736,7 +15736,7 @@ pub fn vmulx_laneq_f16(a: float16x4_t, b: float16x8_t) -> float #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vmulxq_lane_f16(a: float16x8_t, b: float16x4_t) -> float16x8_t { static_assert_uimm_bits!(LANE, 2); @@ -15766,7 +15766,7 @@ pub fn vmulxq_lane_f16(a: float16x8_t, b: float16x4_t) -> float #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vmulxq_laneq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { static_assert_uimm_bits!(LANE, 3); @@ -16128,7 +16128,7 @@ pub fn vpaddd_u64(a: uint64x2_t) -> u64 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpaddq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(faddp))] pub fn vpaddq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -16347,7 +16347,7 @@ pub fn vpaddq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpmax_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmaxp))] pub fn vpmax_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -16364,7 +16364,7 @@ pub fn vpmax_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpmaxq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmaxp))] pub fn vpmaxq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -16381,7 +16381,7 @@ pub fn vpmaxq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpmaxnm_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmaxnmp))] pub fn vpmaxnm_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -16398,7 +16398,7 @@ pub fn vpmaxnm_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpmaxnmq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fmaxnmp))] pub fn vpmaxnmq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -16655,7 +16655,7 @@ pub fn vpmaxs_f32(a: float32x2_t) -> f32 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpmin_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fminp))] pub fn vpmin_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -16672,7 +16672,7 @@ pub fn vpmin_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpminq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fminp))] pub fn vpminq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -16689,7 +16689,7 @@ pub fn vpminq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpminnm_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fminnmp))] pub fn vpminnm_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -16706,7 +16706,7 @@ pub fn vpminnm_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vpminnmq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(fminnmp))] pub fn vpminnmq_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -21832,7 +21832,7 @@ pub fn vrecpxh_f16(a: f16) -> f16 { #[inline(always)] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpret_f64_f16(a: float16x4_t) -> float64x1_t { @@ -21843,7 +21843,7 @@ pub fn vreinterpret_f64_f16(a: float16x4_t) -> float64x1_t { #[inline(always)] #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpret_f64_f16(a: float16x4_t) -> float64x1_t { @@ -21855,7 +21855,7 @@ pub fn vreinterpret_f64_f16(a: float16x4_t) -> float64x1_t { #[inline(always)] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpretq_f64_f16(a: float16x8_t) -> float64x2_t { @@ -21866,7 +21866,7 @@ pub fn vreinterpretq_f64_f16(a: float16x8_t) -> float64x2_t { #[inline(always)] #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpretq_f64_f16(a: float16x8_t) -> float64x2_t { @@ -21881,7 +21881,7 @@ pub fn vreinterpretq_f64_f16(a: float16x8_t) -> float64x2_t { #[inline(always)] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpret_f16_f64(a: float64x1_t) -> float16x4_t { @@ -21892,7 +21892,7 @@ pub fn vreinterpret_f16_f64(a: float64x1_t) -> float16x4_t { #[inline(always)] #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpret_f16_f64(a: float64x1_t) -> float16x4_t { @@ -21906,7 +21906,7 @@ pub fn vreinterpret_f16_f64(a: float64x1_t) -> float16x4_t { #[inline(always)] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpretq_f16_f64(a: float64x2_t) -> float16x8_t { @@ -21917,7 +21917,7 @@ pub fn vreinterpretq_f16_f64(a: float64x2_t) -> float16x8_t { #[inline(always)] #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(nop))] pub fn vreinterpretq_f16_f64(a: float64x2_t) -> float16x8_t { @@ -23496,7 +23496,7 @@ pub fn vrnd64z_f64(a: float64x1_t) -> float64x1_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrnd_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintz))] pub fn vrnd_f16(a: float16x4_t) -> float16x4_t { @@ -23506,7 +23506,7 @@ pub fn vrnd_f16(a: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintz))] pub fn vrndq_f16(a: float16x8_t) -> float16x8_t { @@ -23552,7 +23552,7 @@ pub fn vrndq_f64(a: float64x2_t) -> float64x2_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrnda_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frinta))] pub fn vrnda_f16(a: float16x4_t) -> float16x4_t { @@ -23562,7 +23562,7 @@ pub fn vrnda_f16(a: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndaq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frinta))] pub fn vrndaq_f16(a: float16x8_t) -> float16x8_t { @@ -23628,7 +23628,7 @@ pub fn vrndh_f16(a: f16) -> f16 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndi_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frinti))] pub fn vrndi_f16(a: float16x4_t) -> float16x4_t { @@ -23645,7 +23645,7 @@ pub fn vrndi_f16(a: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndiq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frinti))] pub fn vrndiq_f16(a: float16x8_t) -> float16x8_t { @@ -23743,7 +23743,7 @@ pub fn vrndih_f16(a: f16) -> f16 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndm_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintm))] pub fn vrndm_f16(a: float16x4_t) -> float16x4_t { @@ -23753,7 +23753,7 @@ pub fn vrndm_f16(a: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndmq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintm))] pub fn vrndmq_f16(a: float16x8_t) -> float16x8_t { @@ -23874,7 +23874,7 @@ pub fn vrndns_f32(a: f32) -> f32 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndp_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintp))] pub fn vrndp_f16(a: float16x4_t) -> float16x4_t { @@ -23884,7 +23884,7 @@ pub fn vrndp_f16(a: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndpq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintp))] pub fn vrndpq_f16(a: float16x8_t) -> float16x8_t { @@ -23940,7 +23940,7 @@ pub fn vrndph_f16(a: f16) -> f16 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndx_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintx))] pub fn vrndx_f16(a: float16x4_t) -> float16x4_t { @@ -23950,7 +23950,7 @@ pub fn vrndx_f16(a: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vrndxq_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(test, assert_instr(frintx))] pub fn vrndxq_f16(a: float16x8_t) -> float16x8_t { @@ -25453,7 +25453,7 @@ pub fn vsqadds_u32(a: u32, b: i32) -> u32 { #[inline(always)] #[cfg_attr(test, assert_instr(fsqrt))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vsqrt_f16(a: float16x4_t) -> float16x4_t { unsafe { simd_fsqrt(a) } @@ -25463,7 +25463,7 @@ pub fn vsqrt_f16(a: float16x4_t) -> float16x4_t { #[inline(always)] #[cfg_attr(test, assert_instr(fsqrt))] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] pub fn vsqrtq_f16(a: float16x8_t) -> float16x8_t { unsafe { simd_fsqrt(a) } @@ -28016,7 +28016,7 @@ pub fn vtbx4_p8(a: poly8x8_t, b: poly8x8x4_t, c: uint8x8_t) -> poly8x8_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vtrn1_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(trn1))] pub fn vtrn1_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -28026,7 +28026,7 @@ pub fn vtrn1_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vtrn1q_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(trn1))] pub fn vtrn1q_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -28252,7 +28252,7 @@ pub fn vtrn1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vtrn2_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(trn2))] pub fn vtrn2_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -28262,7 +28262,7 @@ pub fn vtrn2_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vtrn2q_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(trn2))] pub fn vtrn2q_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -28762,7 +28762,7 @@ pub fn vuqadds_s32(a: i32, b: u32) -> i32 { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vuzp1_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(uzp1))] pub fn vuzp1_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -28772,7 +28772,7 @@ pub fn vuzp1_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vuzp1q_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(uzp1))] pub fn vuzp1q_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -28998,7 +28998,7 @@ pub fn vuzp1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vuzp2_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(uzp2))] pub fn vuzp2_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -29008,7 +29008,7 @@ pub fn vuzp2_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vuzp2q_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(uzp2))] pub fn vuzp2q_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -29252,7 +29252,7 @@ pub fn vxarq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vzip1_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(zip1))] pub fn vzip1_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -29262,7 +29262,7 @@ pub fn vzip1_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vzip1q_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(zip1))] pub fn vzip1q_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { @@ -29488,7 +29488,7 @@ pub fn vzip1q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vzip2_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(zip2))] pub fn vzip2_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { @@ -29498,7 +29498,7 @@ pub fn vzip2_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vzip2q_f16)"] #[inline(always)] #[target_feature(enable = "neon,fp16")] -#[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] #[cfg(not(target_arch = "arm64ec"))] #[cfg_attr(all(test, not(target_env = "msvc")), assert_instr(zip2))] pub fn vzip2q_f16(a: float16x8_t, b: float16x8_t) -> float16x8_t { diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs index 3b67208182cb..c2faf44681b1 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs @@ -821,7 +821,7 @@ pub fn vabaq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -851,7 +851,7 @@ pub fn vabd_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -1422,7 +1422,7 @@ pub fn vabdl_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -1444,7 +1444,7 @@ pub fn vabs_f16(a: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -1673,7 +1673,7 @@ pub fn vabsh_f16(a: f16) -> f16 { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -1695,7 +1695,7 @@ pub fn vadd_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -3879,7 +3879,7 @@ pub fn vbicq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -3907,7 +3907,7 @@ pub fn vbsl_f16(a: uint16x4_t, b: float16x4_t, c: float16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4529,7 +4529,7 @@ pub fn vbslq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4559,7 +4559,7 @@ pub fn vcage_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4647,7 +4647,7 @@ pub fn vcageq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4677,7 +4677,7 @@ pub fn vcagt_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4765,7 +4765,7 @@ pub fn vcagtq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4787,7 +4787,7 @@ pub fn vcale_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4851,7 +4851,7 @@ pub fn vcaleq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4873,7 +4873,7 @@ pub fn vcalt_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4937,7 +4937,7 @@ pub fn vcaltq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -4959,7 +4959,7 @@ pub fn vceq_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -5317,7 +5317,7 @@ pub fn vceqq_p8(a: poly8x16_t, b: poly8x16_t) -> uint8x16_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -5339,7 +5339,7 @@ pub fn vcge_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -5655,7 +5655,7 @@ pub fn vcgeq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -5678,7 +5678,7 @@ pub fn vcgez_f16(a: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -5701,7 +5701,7 @@ pub fn vcgezq_f16(a: float16x8_t) -> uint16x8_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -5723,7 +5723,7 @@ pub fn vcgt_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6039,7 +6039,7 @@ pub fn vcgtq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6062,7 +6062,7 @@ pub fn vcgtz_f16(a: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6085,7 +6085,7 @@ pub fn vcgtzq_f16(a: float16x8_t) -> uint16x8_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6107,7 +6107,7 @@ pub fn vcle_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6423,7 +6423,7 @@ pub fn vcleq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6446,7 +6446,7 @@ pub fn vclez_f16(a: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6769,7 +6769,7 @@ pub fn vclsq_u32(a: uint32x4_t) -> int32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -6791,7 +6791,7 @@ pub fn vclt_f16(a: float16x4_t, b: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -7107,7 +7107,7 @@ pub fn vcltq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -7130,7 +7130,7 @@ pub fn vcltz_f16(a: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -7812,7 +7812,7 @@ pub fn vcntq_p8(a: poly8x16_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8041,7 +8041,7 @@ pub fn vcombine_p64(a: poly64x1_t, b: poly64x1_t) -> poly64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8065,7 +8065,7 @@ pub fn vcreate_f16(a: u64) -> float16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8577,7 +8577,7 @@ pub fn vcreate_p64(a: u64) -> poly64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8599,7 +8599,7 @@ pub fn vcvt_f16_f32(a: float32x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8621,7 +8621,7 @@ pub fn vcvt_f16_s16(a: int16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8643,7 +8643,7 @@ pub fn vcvtq_f16_s16(a: int16x8_t) -> float16x8_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8665,7 +8665,7 @@ pub fn vcvt_f16_u16(a: uint16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8688,7 +8688,7 @@ pub fn vcvtq_f16_u16(a: uint16x8_t) -> float16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8795,7 +8795,7 @@ pub fn vcvtq_f32_u32(a: uint32x4_t) -> float32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8830,7 +8830,7 @@ pub fn vcvt_n_f16_s16(a: int16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8865,7 +8865,7 @@ pub fn vcvtq_n_f16_s16(a: int16x8_t) -> float16x8_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -8900,7 +8900,7 @@ pub fn vcvt_n_f16_u16(a: uint16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9087,7 +9087,7 @@ pub fn vcvtq_n_f32_u32(a: uint32x4_t) -> float32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9122,7 +9122,7 @@ pub fn vcvt_n_s16_f16(a: float16x4_t) -> int16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9233,7 +9233,7 @@ pub fn vcvtq_n_s32_f32(a: float32x4_t) -> int32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9268,7 +9268,7 @@ pub fn vcvt_n_u16_f16(a: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9378,7 +9378,7 @@ pub fn vcvtq_n_u32_f32(a: float32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9400,7 +9400,7 @@ pub fn vcvt_s16_f16(a: float16x4_t) -> int16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9480,7 +9480,7 @@ pub fn vcvtq_s32_f32(a: float32x4_t) -> int32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -9502,7 +9502,7 @@ pub fn vcvt_u16_f16(a: float16x4_t) -> uint16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -10140,7 +10140,7 @@ pub fn vdotq_u32(a: uint32x4_t, b: uint8x16_t, c: uint8x16_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -10165,7 +10165,7 @@ pub fn vdup_lane_f16(a: float16x4_t) -> float16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -10719,7 +10719,7 @@ pub fn vdup_lane_u64(a: uint64x1_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -10744,7 +10744,7 @@ pub fn vdup_laneq_f16(a: float16x8_t) -> float16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -12261,7 +12261,7 @@ pub fn veorq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -12640,7 +12640,7 @@ pub fn vextq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -13228,7 +13228,7 @@ pub fn vextq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -13250,7 +13250,7 @@ pub fn vfma_f16(a: float16x4_t, b: float16x4_t, c: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -13357,7 +13357,7 @@ pub fn vfmaq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -13383,7 +13383,7 @@ pub fn vfms_f16(a: float16x4_t, b: float16x4_t, c: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -13494,7 +13494,7 @@ pub fn vfmsq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -13513,7 +13513,7 @@ pub fn vget_high_f16(a: float16x8_t) -> float16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "fp16"))] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -28187,7 +28187,7 @@ pub unsafe fn vldrq_p128(a: *const p128) -> p128 { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -28217,7 +28217,7 @@ pub fn vmax_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -28593,7 +28593,7 @@ pub fn vmaxq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -28615,7 +28615,7 @@ pub fn vmaxnm_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -28679,7 +28679,7 @@ pub fn vmaxnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -28709,7 +28709,7 @@ pub fn vmin_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -29085,7 +29085,7 @@ pub fn vminq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -29107,7 +29107,7 @@ pub fn vminnm_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -33043,7 +33043,7 @@ pub fn vmovn_u64(a: uint64x2_t) -> uint32x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -33065,7 +33065,7 @@ pub fn vmul_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -33130,7 +33130,7 @@ pub fn vmulq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -33159,7 +33159,7 @@ pub fn vmul_lane_f16(a: float16x4_t, v: float16x4_t) -> float16 #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -35131,7 +35131,7 @@ pub fn vmvnq_u8(a: uint8x16_t) -> uint8x16_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -35153,7 +35153,7 @@ pub fn vneg_f16(a: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -36391,7 +36391,7 @@ pub fn vpadalq_u32(a: uint64x2_t, b: uint32x4_t) -> uint64x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42473,7 +42473,7 @@ pub fn vraddhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42503,7 +42503,7 @@ pub fn vrecpe_f16(a: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42649,7 +42649,7 @@ pub fn vrecpeq_u32(a: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42679,7 +42679,7 @@ pub fn vrecps_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42768,7 +42768,7 @@ pub fn vrecpsq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42791,7 +42791,7 @@ pub fn vreinterpret_f32_f16(a: float16x4_t) -> float32x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42818,7 +42818,7 @@ pub fn vreinterpret_f32_f16(a: float16x4_t) -> float32x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42841,7 +42841,7 @@ pub fn vreinterpret_s8_f16(a: float16x4_t) -> int8x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42868,7 +42868,7 @@ pub fn vreinterpret_s8_f16(a: float16x4_t) -> int8x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42891,7 +42891,7 @@ pub fn vreinterpret_s16_f16(a: float16x4_t) -> int16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42918,7 +42918,7 @@ pub fn vreinterpret_s16_f16(a: float16x4_t) -> int16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42941,7 +42941,7 @@ pub fn vreinterpret_s32_f16(a: float16x4_t) -> int32x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42968,7 +42968,7 @@ pub fn vreinterpret_s32_f16(a: float16x4_t) -> int32x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -42991,7 +42991,7 @@ pub fn vreinterpret_s64_f16(a: float16x4_t) -> int64x1_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43015,7 +43015,7 @@ pub fn vreinterpret_s64_f16(a: float16x4_t) -> int64x1_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43038,7 +43038,7 @@ pub fn vreinterpret_u8_f16(a: float16x4_t) -> uint8x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43065,7 +43065,7 @@ pub fn vreinterpret_u8_f16(a: float16x4_t) -> uint8x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43088,7 +43088,7 @@ pub fn vreinterpret_u16_f16(a: float16x4_t) -> uint16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43115,7 +43115,7 @@ pub fn vreinterpret_u16_f16(a: float16x4_t) -> uint16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43138,7 +43138,7 @@ pub fn vreinterpret_u32_f16(a: float16x4_t) -> uint32x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43165,7 +43165,7 @@ pub fn vreinterpret_u32_f16(a: float16x4_t) -> uint32x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43188,7 +43188,7 @@ pub fn vreinterpret_u64_f16(a: float16x4_t) -> uint64x1_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43212,7 +43212,7 @@ pub fn vreinterpret_u64_f16(a: float16x4_t) -> uint64x1_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43235,7 +43235,7 @@ pub fn vreinterpret_p8_f16(a: float16x4_t) -> poly8x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43262,7 +43262,7 @@ pub fn vreinterpret_p8_f16(a: float16x4_t) -> poly8x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43285,7 +43285,7 @@ pub fn vreinterpret_p16_f16(a: float16x4_t) -> poly16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43312,7 +43312,7 @@ pub fn vreinterpret_p16_f16(a: float16x4_t) -> poly16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43335,7 +43335,7 @@ pub fn vreinterpretq_f32_f16(a: float16x8_t) -> float32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43362,7 +43362,7 @@ pub fn vreinterpretq_f32_f16(a: float16x8_t) -> float32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43385,7 +43385,7 @@ pub fn vreinterpretq_s8_f16(a: float16x8_t) -> int8x16_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43416,7 +43416,7 @@ pub fn vreinterpretq_s8_f16(a: float16x8_t) -> int8x16_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43439,7 +43439,7 @@ pub fn vreinterpretq_s16_f16(a: float16x8_t) -> int16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43466,7 +43466,7 @@ pub fn vreinterpretq_s16_f16(a: float16x8_t) -> int16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43489,7 +43489,7 @@ pub fn vreinterpretq_s32_f16(a: float16x8_t) -> int32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43516,7 +43516,7 @@ pub fn vreinterpretq_s32_f16(a: float16x8_t) -> int32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43539,7 +43539,7 @@ pub fn vreinterpretq_s64_f16(a: float16x8_t) -> int64x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43566,7 +43566,7 @@ pub fn vreinterpretq_s64_f16(a: float16x8_t) -> int64x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43589,7 +43589,7 @@ pub fn vreinterpretq_u8_f16(a: float16x8_t) -> uint8x16_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43620,7 +43620,7 @@ pub fn vreinterpretq_u8_f16(a: float16x8_t) -> uint8x16_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43643,7 +43643,7 @@ pub fn vreinterpretq_u16_f16(a: float16x8_t) -> uint16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43670,7 +43670,7 @@ pub fn vreinterpretq_u16_f16(a: float16x8_t) -> uint16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43693,7 +43693,7 @@ pub fn vreinterpretq_u32_f16(a: float16x8_t) -> uint32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43720,7 +43720,7 @@ pub fn vreinterpretq_u32_f16(a: float16x8_t) -> uint32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43743,7 +43743,7 @@ pub fn vreinterpretq_u64_f16(a: float16x8_t) -> uint64x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43770,7 +43770,7 @@ pub fn vreinterpretq_u64_f16(a: float16x8_t) -> uint64x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43793,7 +43793,7 @@ pub fn vreinterpretq_p8_f16(a: float16x8_t) -> poly8x16_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43824,7 +43824,7 @@ pub fn vreinterpretq_p8_f16(a: float16x8_t) -> poly8x16_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43847,7 +43847,7 @@ pub fn vreinterpretq_p16_f16(a: float16x8_t) -> poly16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43874,7 +43874,7 @@ pub fn vreinterpretq_p16_f16(a: float16x8_t) -> poly16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43897,7 +43897,7 @@ pub fn vreinterpret_f16_f32(a: float32x2_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43924,7 +43924,7 @@ pub fn vreinterpret_f16_f32(a: float32x2_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43947,7 +43947,7 @@ pub fn vreinterpretq_f16_f32(a: float32x4_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43974,7 +43974,7 @@ pub fn vreinterpretq_f16_f32(a: float32x4_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -43997,7 +43997,7 @@ pub fn vreinterpret_f16_s8(a: int8x8_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44024,7 +44024,7 @@ pub fn vreinterpret_f16_s8(a: int8x8_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44047,7 +44047,7 @@ pub fn vreinterpretq_f16_s8(a: int8x16_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44075,7 +44075,7 @@ pub fn vreinterpretq_f16_s8(a: int8x16_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44098,7 +44098,7 @@ pub fn vreinterpret_f16_s16(a: int16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44125,7 +44125,7 @@ pub fn vreinterpret_f16_s16(a: int16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44148,7 +44148,7 @@ pub fn vreinterpretq_f16_s16(a: int16x8_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44175,7 +44175,7 @@ pub fn vreinterpretq_f16_s16(a: int16x8_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44198,7 +44198,7 @@ pub fn vreinterpret_f16_s32(a: int32x2_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44225,7 +44225,7 @@ pub fn vreinterpret_f16_s32(a: int32x2_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44248,7 +44248,7 @@ pub fn vreinterpretq_f16_s32(a: int32x4_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44275,7 +44275,7 @@ pub fn vreinterpretq_f16_s32(a: int32x4_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44298,7 +44298,7 @@ pub fn vreinterpret_f16_s64(a: int64x1_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44324,7 +44324,7 @@ pub fn vreinterpret_f16_s64(a: int64x1_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44347,7 +44347,7 @@ pub fn vreinterpretq_f16_s64(a: int64x2_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44374,7 +44374,7 @@ pub fn vreinterpretq_f16_s64(a: int64x2_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44397,7 +44397,7 @@ pub fn vreinterpret_f16_u8(a: uint8x8_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44424,7 +44424,7 @@ pub fn vreinterpret_f16_u8(a: uint8x8_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44447,7 +44447,7 @@ pub fn vreinterpretq_f16_u8(a: uint8x16_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44475,7 +44475,7 @@ pub fn vreinterpretq_f16_u8(a: uint8x16_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44498,7 +44498,7 @@ pub fn vreinterpret_f16_u16(a: uint16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44525,7 +44525,7 @@ pub fn vreinterpret_f16_u16(a: uint16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44548,7 +44548,7 @@ pub fn vreinterpretq_f16_u16(a: uint16x8_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44575,7 +44575,7 @@ pub fn vreinterpretq_f16_u16(a: uint16x8_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44598,7 +44598,7 @@ pub fn vreinterpret_f16_u32(a: uint32x2_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44625,7 +44625,7 @@ pub fn vreinterpret_f16_u32(a: uint32x2_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44648,7 +44648,7 @@ pub fn vreinterpretq_f16_u32(a: uint32x4_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44675,7 +44675,7 @@ pub fn vreinterpretq_f16_u32(a: uint32x4_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44698,7 +44698,7 @@ pub fn vreinterpret_f16_u64(a: uint64x1_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44724,7 +44724,7 @@ pub fn vreinterpret_f16_u64(a: uint64x1_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44747,7 +44747,7 @@ pub fn vreinterpretq_f16_u64(a: uint64x2_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44774,7 +44774,7 @@ pub fn vreinterpretq_f16_u64(a: uint64x2_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44797,7 +44797,7 @@ pub fn vreinterpret_f16_p8(a: poly8x8_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44824,7 +44824,7 @@ pub fn vreinterpret_f16_p8(a: poly8x8_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44847,7 +44847,7 @@ pub fn vreinterpretq_f16_p8(a: poly8x16_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44875,7 +44875,7 @@ pub fn vreinterpretq_f16_p8(a: poly8x16_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44898,7 +44898,7 @@ pub fn vreinterpret_f16_p16(a: poly16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44925,7 +44925,7 @@ pub fn vreinterpret_f16_p16(a: poly16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44948,7 +44948,7 @@ pub fn vreinterpretq_f16_p16(a: poly16x8_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44975,7 +44975,7 @@ pub fn vreinterpretq_f16_p16(a: poly16x8_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -44998,7 +44998,7 @@ pub fn vreinterpretq_f16_p128(a: p128) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45024,7 +45024,7 @@ pub fn vreinterpretq_f16_p128(a: p128) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45047,7 +45047,7 @@ pub fn vreinterpret_p64_f16(a: float16x4_t) -> poly64x1_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45071,7 +45071,7 @@ pub fn vreinterpret_p64_f16(a: float16x4_t) -> poly64x1_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45094,7 +45094,7 @@ pub fn vreinterpretq_p128_f16(a: float16x8_t) -> p128 { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45118,7 +45118,7 @@ pub fn vreinterpretq_p128_f16(a: float16x8_t) -> p128 { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45141,7 +45141,7 @@ pub fn vreinterpretq_p64_f16(a: float16x8_t) -> poly64x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45168,7 +45168,7 @@ pub fn vreinterpretq_p64_f16(a: float16x8_t) -> poly64x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45191,7 +45191,7 @@ pub fn vreinterpret_f16_p64(a: poly64x1_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45217,7 +45217,7 @@ pub fn vreinterpret_f16_p64(a: poly64x1_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -45240,7 +45240,7 @@ pub fn vreinterpretq_f16_p64(a: poly64x2_t) -> float16x8_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -59244,7 +59244,7 @@ pub fn vrev64q_u8(a: uint8x16_t) -> uint8x16_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -59266,7 +59266,7 @@ pub fn vrev64_f16(a: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -59636,7 +59636,7 @@ pub fn vrhaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -59665,7 +59665,7 @@ pub fn vrndn_f16(a: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -60756,7 +60756,7 @@ pub fn vrshrn_n_u64(a: uint64x2_t) -> uint32x2_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -60786,7 +60786,7 @@ pub fn vrsqrte_f16(a: float16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -60932,7 +60932,7 @@ pub fn vrsqrteq_u32(a: uint32x4_t) -> uint32x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -60962,7 +60962,7 @@ pub fn vrsqrts_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { )] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -72516,7 +72516,7 @@ pub unsafe fn vstrq_p128(a: *mut p128, b: p128) { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -72538,7 +72538,7 @@ pub fn vsub_f16(a: float16x4_t, b: float16x4_t) -> float16x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -74519,7 +74519,7 @@ pub fn vtbx4_p8(a: poly8x8_t, b: poly8x8x4_t, c: uint8x8_t) -> poly8x8_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -74549,7 +74549,7 @@ pub fn vtrn_f16(a: float16x4_t, b: float16x4_t) -> float16x4x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -75832,7 +75832,7 @@ pub fn vusmmlaq_s32(a: int32x4_t, b: uint8x16_t, c: int8x16_t) -> int32x4_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -75862,7 +75862,7 @@ pub fn vuzp_f16(a: float16x4_t, b: float16x4_t) -> float16x4x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -76438,7 +76438,7 @@ pub fn vuzpq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -76468,7 +76468,7 @@ pub fn vzip_f16(a: float16x4_t, b: float16x4_t) -> float16x4x2_t { #[target_feature(enable = "neon,fp16")] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs index 1ca8ce2b1395..8a4a6e922822 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs @@ -104,7 +104,7 @@ types! { } types! { - #![cfg_attr(not(target_arch = "arm"), stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION"))] + #![cfg_attr(not(target_arch = "arm"), stable(feature = "stdarch_neon_fp16", since = "1.94.0"))] #![cfg_attr(target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800"))] /// Arm-specific 64-bit wide vector of four packed `f16`. @@ -750,7 +750,7 @@ pub struct uint32x4x4_t( #[derive(Copy, Clone, Debug)] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -763,7 +763,7 @@ pub struct float16x4x2_t(pub float16x4_t, pub float16x4_t); #[derive(Copy, Clone, Debug)] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -776,7 +776,7 @@ pub struct float16x4x3_t(pub float16x4_t, pub float16x4_t, pub float16x4_t); #[derive(Copy, Clone, Debug)] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -794,7 +794,7 @@ pub struct float16x4x4_t( #[derive(Copy, Clone, Debug)] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -807,7 +807,7 @@ pub struct float16x8x2_t(pub float16x8_t, pub float16x8_t); #[derive(Copy, Clone, Debug)] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", @@ -820,7 +820,7 @@ pub struct float16x8x3_t(pub float16x8_t, pub float16x8_t, pub float16x8_t); #[derive(Copy, Clone, Debug)] #[cfg_attr( not(target_arch = "arm"), - stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION") + stable(feature = "stdarch_neon_fp16", since = "1.94.0") )] #[cfg_attr( target_arch = "arm", diff --git a/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs b/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs index 27f06691c550..8ddc3d29a3a1 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs @@ -247,7 +247,7 @@ pub const fn _mm512_setr_ph( /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setzero_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_setzero_ph() -> __m128h { unsafe { transmute(f16x8::ZERO) } @@ -258,7 +258,7 @@ pub const fn _mm_setzero_ph() -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_setzero_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_setzero_ph() -> __m256h { f16x16::ZERO.as_m256h() @@ -269,7 +269,7 @@ pub const fn _mm256_setzero_ph() -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setzero_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_setzero_ph() -> __m512h { f16x32::ZERO.as_m512h() @@ -283,7 +283,7 @@ pub const fn _mm512_setzero_ph() -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_undefined_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_undefined_ph() -> __m128h { f16x8::ZERO.as_m128h() @@ -297,7 +297,7 @@ pub const fn _mm_undefined_ph() -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_undefined_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_undefined_ph() -> __m256h { f16x16::ZERO.as_m256h() @@ -311,7 +311,7 @@ pub const fn _mm256_undefined_ph() -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_undefined_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_undefined_ph() -> __m512h { f16x32::ZERO.as_m512h() @@ -323,7 +323,7 @@ pub const fn _mm512_undefined_ph() -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castpd_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_castpd_ph(a: __m128d) -> __m128h { unsafe { transmute(a) } @@ -335,7 +335,7 @@ pub const fn _mm_castpd_ph(a: __m128d) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castpd_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castpd_ph(a: __m256d) -> __m256h { unsafe { transmute(a) } @@ -347,7 +347,7 @@ pub const fn _mm256_castpd_ph(a: __m256d) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castpd_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castpd_ph(a: __m512d) -> __m512h { unsafe { transmute(a) } @@ -359,7 +359,7 @@ pub const fn _mm512_castpd_ph(a: __m512d) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castph_pd) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_castph_pd(a: __m128h) -> __m128d { unsafe { transmute(a) } @@ -371,7 +371,7 @@ pub const fn _mm_castph_pd(a: __m128h) -> __m128d { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castph_pd) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castph_pd(a: __m256h) -> __m256d { unsafe { transmute(a) } @@ -383,7 +383,7 @@ pub const fn _mm256_castph_pd(a: __m256h) -> __m256d { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castph_pd) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castph_pd(a: __m512h) -> __m512d { unsafe { transmute(a) } @@ -395,7 +395,7 @@ pub const fn _mm512_castph_pd(a: __m512h) -> __m512d { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castps_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_castps_ph(a: __m128) -> __m128h { unsafe { transmute(a) } @@ -407,7 +407,7 @@ pub const fn _mm_castps_ph(a: __m128) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castps_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castps_ph(a: __m256) -> __m256h { unsafe { transmute(a) } @@ -419,7 +419,7 @@ pub const fn _mm256_castps_ph(a: __m256) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castps_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castps_ph(a: __m512) -> __m512h { unsafe { transmute(a) } @@ -431,7 +431,7 @@ pub const fn _mm512_castps_ph(a: __m512) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castph_ps) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_castph_ps(a: __m128h) -> __m128 { unsafe { transmute(a) } @@ -443,7 +443,7 @@ pub const fn _mm_castph_ps(a: __m128h) -> __m128 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castph_ps) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castph_ps(a: __m256h) -> __m256 { unsafe { transmute(a) } @@ -455,7 +455,7 @@ pub const fn _mm256_castph_ps(a: __m256h) -> __m256 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castph_ps) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castph_ps(a: __m512h) -> __m512 { unsafe { transmute(a) } @@ -467,7 +467,7 @@ pub const fn _mm512_castph_ps(a: __m512h) -> __m512 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castsi128_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_castsi128_ph(a: __m128i) -> __m128h { unsafe { transmute(a) } @@ -479,7 +479,7 @@ pub const fn _mm_castsi128_ph(a: __m128i) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castsi256_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castsi256_ph(a: __m256i) -> __m256h { unsafe { transmute(a) } @@ -491,7 +491,7 @@ pub const fn _mm256_castsi256_ph(a: __m256i) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castsi512_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castsi512_ph(a: __m512i) -> __m512h { unsafe { transmute(a) } @@ -503,7 +503,7 @@ pub const fn _mm512_castsi512_ph(a: __m512i) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castph_si128) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_castph_si128(a: __m128h) -> __m128i { unsafe { transmute(a) } @@ -515,7 +515,7 @@ pub const fn _mm_castph_si128(a: __m128h) -> __m128i { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castph_si256) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castph_si256(a: __m256h) -> __m256i { unsafe { transmute(a) } @@ -527,7 +527,7 @@ pub const fn _mm256_castph_si256(a: __m256h) -> __m256i { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castph_si512) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castph_si512(a: __m512h) -> __m512i { unsafe { transmute(a) } @@ -539,7 +539,7 @@ pub const fn _mm512_castph_si512(a: __m512h) -> __m512i { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castph256_ph128) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castph256_ph128(a: __m256h) -> __m128h { unsafe { simd_shuffle!(a, a, [0, 1, 2, 3, 4, 5, 6, 7]) } @@ -551,7 +551,7 @@ pub const fn _mm256_castph256_ph128(a: __m256h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castph512_ph128) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castph512_ph128(a: __m512h) -> __m128h { unsafe { simd_shuffle!(a, a, [0, 1, 2, 3, 4, 5, 6, 7]) } @@ -563,7 +563,7 @@ pub const fn _mm512_castph512_ph128(a: __m512h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castph512_ph256) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castph512_ph256(a: __m512h) -> __m256h { unsafe { simd_shuffle!(a, a, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } @@ -576,7 +576,7 @@ pub const fn _mm512_castph512_ph256(a: __m512h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_castph128_ph256) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_castph128_ph256(a: __m128h) -> __m256h { unsafe { @@ -595,7 +595,7 @@ pub const fn _mm256_castph128_ph256(a: __m128h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castph128_ph512) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castph128_ph512(a: __m128h) -> __m512h { unsafe { @@ -617,7 +617,7 @@ pub const fn _mm512_castph128_ph512(a: __m128h) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_castph256_ph512) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_castph256_ph512(a: __m256h) -> __m512h { unsafe { @@ -639,7 +639,7 @@ pub const fn _mm512_castph256_ph512(a: __m256h) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_zextph128_ph256) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_zextph128_ph256(a: __m128h) -> __m256h { unsafe { @@ -658,7 +658,7 @@ pub const fn _mm256_zextph128_ph256(a: __m128h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_zextph256_ph512) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_zextph256_ph512(a: __m256h) -> __m512h { unsafe { @@ -680,7 +680,7 @@ pub const fn _mm512_zextph256_ph512(a: __m256h) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_zextph128_ph512) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_zextph128_ph512(a: __m128h) -> __m512h { unsafe { @@ -730,7 +730,7 @@ macro_rules! cmp_asm { // FIXME: use LLVM intrinsics #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cmp_ph_mask(a: __m128h, b: __m128h) -> __mmask8 { unsafe { static_assert_uimm_bits!(IMM5, 5); @@ -746,7 +746,7 @@ pub fn _mm_cmp_ph_mask(a: __m128h, b: __m128h) -> __mmask8 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cmp_ph_mask(k1: __mmask8, a: __m128h, b: __m128h) -> __mmask8 { unsafe { static_assert_uimm_bits!(IMM5, 5); @@ -761,7 +761,7 @@ pub fn _mm_mask_cmp_ph_mask(k1: __mmask8, a: __m128h, b: __m128 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cmp_ph_mask(a: __m256h, b: __m256h) -> __mmask16 { unsafe { static_assert_uimm_bits!(IMM5, 5); @@ -777,7 +777,7 @@ pub fn _mm256_cmp_ph_mask(a: __m256h, b: __m256h) -> __mmask16 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cmp_ph_mask( k1: __mmask16, a: __m256h, @@ -796,7 +796,7 @@ pub fn _mm256_mask_cmp_ph_mask( #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cmp_ph_mask(a: __m512h, b: __m512h) -> __mmask32 { unsafe { static_assert_uimm_bits!(IMM5, 5); @@ -812,7 +812,7 @@ pub fn _mm512_cmp_ph_mask(a: __m512h, b: __m512h) -> __mmask32 #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cmp_ph_mask( k1: __mmask32, a: __m512h, @@ -833,7 +833,7 @@ pub fn _mm512_mask_cmp_ph_mask( #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(2, 3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cmp_round_ph_mask( a: __m512h, b: __m512h, @@ -868,7 +868,7 @@ pub fn _mm512_cmp_round_ph_mask( #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(3, 4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cmp_round_ph_mask( k1: __mmask32, a: __m512h, @@ -903,7 +903,7 @@ pub fn _mm512_mask_cmp_round_ph_mask( #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(2, 3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cmp_round_sh_mask(a: __m128h, b: __m128h) -> __mmask8 { static_assert_uimm_bits!(IMM5, 5); static_assert_sae!(SAE); @@ -918,7 +918,7 @@ pub fn _mm_cmp_round_sh_mask(a: __m128h, b: __m #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(3, 4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cmp_round_sh_mask( k1: __mmask8, a: __m128h, @@ -938,7 +938,7 @@ pub fn _mm_mask_cmp_round_sh_mask( #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cmp_sh_mask(a: __m128h, b: __m128h) -> __mmask8 { static_assert_uimm_bits!(IMM5, 5); _mm_cmp_round_sh_mask::(a, b) @@ -951,7 +951,7 @@ pub fn _mm_cmp_sh_mask(a: __m128h, b: __m128h) -> __mmask8 { #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cmp_sh_mask(k1: __mmask8, a: __m128h, b: __m128h) -> __mmask8 { static_assert_uimm_bits!(IMM5, 5); _mm_mask_cmp_round_sh_mask::(k1, a, b) @@ -965,7 +965,7 @@ pub fn _mm_mask_cmp_sh_mask(k1: __mmask8, a: __m128h, b: __m128 #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(2, 3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comi_round_sh(a: __m128h, b: __m128h) -> i32 { unsafe { static_assert_uimm_bits!(IMM5, 5); @@ -981,7 +981,7 @@ pub fn _mm_comi_round_sh(a: __m128h, b: __m128h #[inline] #[target_feature(enable = "avx512fp16")] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comi_sh(a: __m128h, b: __m128h) -> i32 { static_assert_uimm_bits!(IMM5, 5); _mm_comi_round_sh::(a, b) @@ -993,7 +993,7 @@ pub fn _mm_comi_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comieq_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comieq_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_EQ_OS>(a, b) } @@ -1004,7 +1004,7 @@ pub fn _mm_comieq_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comige_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comige_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_GE_OS>(a, b) } @@ -1015,7 +1015,7 @@ pub fn _mm_comige_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comigt_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comigt_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_GT_OS>(a, b) } @@ -1026,7 +1026,7 @@ pub fn _mm_comigt_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comile_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comile_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_LE_OS>(a, b) } @@ -1037,7 +1037,7 @@ pub fn _mm_comile_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comilt_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comilt_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_LT_OS>(a, b) } @@ -1048,7 +1048,7 @@ pub fn _mm_comilt_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_comineq_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_comineq_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_NEQ_US>(a, b) } @@ -1059,7 +1059,7 @@ pub fn _mm_comineq_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ucomieq_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_ucomieq_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_EQ_OQ>(a, b) } @@ -1070,7 +1070,7 @@ pub fn _mm_ucomieq_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ucomige_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_ucomige_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_GE_OQ>(a, b) } @@ -1081,7 +1081,7 @@ pub fn _mm_ucomige_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ucomigt_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_ucomigt_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_GT_OQ>(a, b) } @@ -1092,7 +1092,7 @@ pub fn _mm_ucomigt_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ucomile_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_ucomile_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_LE_OQ>(a, b) } @@ -1103,7 +1103,7 @@ pub fn _mm_ucomile_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ucomilt_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_ucomilt_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_LT_OQ>(a, b) } @@ -1114,7 +1114,7 @@ pub fn _mm_ucomilt_sh(a: __m128h, b: __m128h) -> i32 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ucomineq_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_ucomineq_sh(a: __m128h, b: __m128h) -> i32 { _mm_comi_sh::<_CMP_NEQ_UQ>(a, b) } @@ -1248,7 +1248,7 @@ pub const unsafe fn _mm512_loadu_ph(mem_addr: *const f16) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_move_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_move_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1267,7 +1267,7 @@ pub const fn _mm_mask_move_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_move_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_move_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1285,7 +1285,7 @@ pub const fn _mm_maskz_move_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_move_sh) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_move_sh(a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1399,7 +1399,7 @@ pub const unsafe fn _mm512_storeu_ph(mem_addr: *mut f16, a: __m512h) { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_add_ph(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_add(a, b) } @@ -1412,7 +1412,7 @@ pub const fn _mm_add_ph(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_add_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1428,7 +1428,7 @@ pub const fn _mm_mask_add_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_add_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1443,7 +1443,7 @@ pub const fn _mm_maskz_add_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_add_ph(a: __m256h, b: __m256h) -> __m256h { unsafe { simd_add(a, b) } @@ -1456,7 +1456,7 @@ pub const fn _mm256_add_ph(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_add_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -1472,7 +1472,7 @@ pub const fn _mm256_mask_add_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_add_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -1487,7 +1487,7 @@ pub const fn _mm256_maskz_add_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_add_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { simd_add(a, b) } @@ -1500,7 +1500,7 @@ pub const fn _mm512_add_ph(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_add_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -1516,7 +1516,7 @@ pub const fn _mm512_mask_add_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_add_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -1539,7 +1539,7 @@ pub const fn _mm512_maskz_add_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_add_round_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -1562,7 +1562,7 @@ pub fn _mm512_add_round_ph(a: __m512h, b: __m512h) -> __m51 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_add_round_ph( src: __m512h, k: __mmask32, @@ -1590,7 +1590,7 @@ pub fn _mm512_mask_add_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_add_round_ph( k: __mmask32, a: __m512h, @@ -1618,7 +1618,7 @@ pub fn _mm512_maskz_add_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_add_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_add_round_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -1640,7 +1640,7 @@ pub fn _mm_add_round_sh(a: __m128h, b: __m128h) -> __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_add_round_sh( src: __m128h, k: __mmask8, @@ -1669,7 +1669,7 @@ pub fn _mm_mask_add_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_add_round_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_add_round_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -1682,7 +1682,7 @@ pub fn _mm_maskz_add_round_sh(k: __mmask8, a: __m128h, b: _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_add_sh(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_insert!(a, 0, _mm_cvtsh_h(a) + _mm_cvtsh_h(b)) } @@ -1696,7 +1696,7 @@ pub const fn _mm_add_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_add_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1719,7 +1719,7 @@ pub const fn _mm_mask_add_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vaddsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_add_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1739,7 +1739,7 @@ pub const fn _mm_maskz_add_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_sub_ph(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_sub(a, b) } @@ -1752,7 +1752,7 @@ pub const fn _mm_sub_ph(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_sub_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1768,7 +1768,7 @@ pub const fn _mm_mask_sub_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_sub_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -1783,7 +1783,7 @@ pub const fn _mm_maskz_sub_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_sub_ph(a: __m256h, b: __m256h) -> __m256h { unsafe { simd_sub(a, b) } @@ -1796,7 +1796,7 @@ pub const fn _mm256_sub_ph(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_sub_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -1812,7 +1812,7 @@ pub const fn _mm256_mask_sub_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_sub_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -1827,7 +1827,7 @@ pub const fn _mm256_maskz_sub_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_sub_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { simd_sub(a, b) } @@ -1840,7 +1840,7 @@ pub const fn _mm512_sub_ph(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_sub_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -1856,7 +1856,7 @@ pub const fn _mm512_mask_sub_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_sub_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -1879,7 +1879,7 @@ pub const fn _mm512_maskz_sub_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_sub_round_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -1902,7 +1902,7 @@ pub fn _mm512_sub_round_ph(a: __m512h, b: __m512h) -> __m51 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_sub_round_ph( src: __m512h, k: __mmask32, @@ -1931,7 +1931,7 @@ pub fn _mm512_mask_sub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_sub_round_ph( k: __mmask32, a: __m512h, @@ -1959,7 +1959,7 @@ pub fn _mm512_maskz_sub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_sub_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_sub_round_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -1981,7 +1981,7 @@ pub fn _mm_sub_round_sh(a: __m128h, b: __m128h) -> __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_sub_round_sh( src: __m128h, k: __mmask8, @@ -2010,7 +2010,7 @@ pub fn _mm_mask_sub_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_sub_round_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_sub_round_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -2023,7 +2023,7 @@ pub fn _mm_maskz_sub_round_sh(k: __mmask8, a: __m128h, b: _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_sub_sh(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_insert!(a, 0, _mm_cvtsh_h(a) - _mm_cvtsh_h(b)) } @@ -2037,7 +2037,7 @@ pub const fn _mm_sub_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_sub_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2060,7 +2060,7 @@ pub const fn _mm_mask_sub_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsubsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_sub_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2080,7 +2080,7 @@ pub const fn _mm_maskz_sub_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mul_ph(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_mul(a, b) } @@ -2093,7 +2093,7 @@ pub const fn _mm_mul_ph(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_mul_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2109,7 +2109,7 @@ pub const fn _mm_mask_mul_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_mul_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2124,7 +2124,7 @@ pub const fn _mm_maskz_mul_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mul_ph(a: __m256h, b: __m256h) -> __m256h { unsafe { simd_mul(a, b) } @@ -2137,7 +2137,7 @@ pub const fn _mm256_mul_ph(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_mul_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -2153,7 +2153,7 @@ pub const fn _mm256_mask_mul_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_mul_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -2168,7 +2168,7 @@ pub const fn _mm256_maskz_mul_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mul_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { simd_mul(a, b) } @@ -2181,7 +2181,7 @@ pub const fn _mm512_mul_ph(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_mul_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -2197,7 +2197,7 @@ pub const fn _mm512_mask_mul_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_mul_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -2220,7 +2220,7 @@ pub const fn _mm512_maskz_mul_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mul_round_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -2243,7 +2243,7 @@ pub fn _mm512_mul_round_ph(a: __m512h, b: __m512h) -> __m51 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_mul_round_ph( src: __m512h, k: __mmask32, @@ -2272,7 +2272,7 @@ pub fn _mm512_mask_mul_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_mul_round_ph( k: __mmask32, a: __m512h, @@ -2300,7 +2300,7 @@ pub fn _mm512_maskz_mul_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mul_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_mul_round_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -2322,7 +2322,7 @@ pub fn _mm_mul_round_sh(a: __m128h, b: __m128h) -> __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_mul_round_sh( src: __m128h, k: __mmask8, @@ -2351,7 +2351,7 @@ pub fn _mm_mask_mul_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_mul_round_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_mul_round_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -2364,7 +2364,7 @@ pub fn _mm_maskz_mul_round_sh(k: __mmask8, a: __m128h, b: _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mul_sh(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_insert!(a, 0, _mm_cvtsh_h(a) * _mm_cvtsh_h(b)) } @@ -2378,7 +2378,7 @@ pub const fn _mm_mul_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_mul_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2401,7 +2401,7 @@ pub const fn _mm_mask_mul_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmulsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_mul_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2421,7 +2421,7 @@ pub const fn _mm_maskz_mul_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_div_ph(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_div(a, b) } @@ -2434,7 +2434,7 @@ pub const fn _mm_div_ph(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_div_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2450,7 +2450,7 @@ pub const fn _mm_mask_div_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_div_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2465,7 +2465,7 @@ pub const fn _mm_maskz_div_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_div_ph(a: __m256h, b: __m256h) -> __m256h { unsafe { simd_div(a, b) } @@ -2478,7 +2478,7 @@ pub const fn _mm256_div_ph(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_div_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -2494,7 +2494,7 @@ pub const fn _mm256_mask_div_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_div_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { @@ -2509,7 +2509,7 @@ pub const fn _mm256_maskz_div_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_div_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { simd_div(a, b) } @@ -2522,7 +2522,7 @@ pub const fn _mm512_div_ph(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_div_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -2538,7 +2538,7 @@ pub const fn _mm512_mask_div_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_div_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { @@ -2561,7 +2561,7 @@ pub const fn _mm512_maskz_div_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_div_round_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -2584,7 +2584,7 @@ pub fn _mm512_div_round_ph(a: __m512h, b: __m512h) -> __m51 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_div_round_ph( src: __m512h, k: __mmask32, @@ -2613,7 +2613,7 @@ pub fn _mm512_mask_div_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_div_round_ph( k: __mmask32, a: __m512h, @@ -2641,7 +2641,7 @@ pub fn _mm512_maskz_div_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_div_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_div_round_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -2663,7 +2663,7 @@ pub fn _mm_div_round_sh(a: __m128h, b: __m128h) -> __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_div_round_sh( src: __m128h, k: __mmask8, @@ -2692,7 +2692,7 @@ pub fn _mm_mask_div_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_div_round_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_div_round_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -2705,7 +2705,7 @@ pub fn _mm_maskz_div_round_sh(k: __mmask8, a: __m128h, b: _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_div_sh(a: __m128h, b: __m128h) -> __m128h { unsafe { simd_insert!(a, 0, _mm_cvtsh_h(a) / _mm_cvtsh_h(b)) } @@ -2719,7 +2719,7 @@ pub const fn _mm_div_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_div_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2742,7 +2742,7 @@ pub const fn _mm_mask_div_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vdivsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_div_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { @@ -2764,7 +2764,7 @@ pub const fn _mm_maskz_div_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mul_pch(a: __m128h, b: __m128h) -> __m128h { _mm_mask_mul_pch(_mm_undefined_ph(), 0xff, a, b) } @@ -2777,7 +2777,7 @@ pub fn _mm_mul_pch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_mul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { transmute(vfmulcph_128(transmute(a), transmute(b), transmute(src), k)) } } @@ -2790,7 +2790,7 @@ pub fn _mm_mask_mul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_mul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_mul_pch(_mm_setzero_ph(), k, a, b) } @@ -2803,7 +2803,7 @@ pub fn _mm_maskz_mul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mul_pch(a: __m256h, b: __m256h) -> __m256h { _mm256_mask_mul_pch(_mm256_undefined_ph(), 0xff, a, b) } @@ -2816,7 +2816,7 @@ pub fn _mm256_mul_pch(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_mul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) -> __m256h { unsafe { transmute(vfmulcph_256(transmute(a), transmute(b), transmute(src), k)) } } @@ -2829,7 +2829,7 @@ pub fn _mm256_mask_mul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_mul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { _mm256_mask_mul_pch(_mm256_setzero_ph(), k, a, b) } @@ -2842,7 +2842,7 @@ pub fn _mm256_maskz_mul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mul_pch(a: __m512h, b: __m512h) -> __m512h { _mm512_mask_mul_pch(_mm512_undefined_ph(), 0xffff, a, b) } @@ -2855,7 +2855,7 @@ pub fn _mm512_mul_pch(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_mul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_mul_round_pch::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -2868,7 +2868,7 @@ pub fn _mm512_mask_mul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) - #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_mul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_mul_pch(_mm512_setzero_ph(), k, a, b) } @@ -2890,7 +2890,7 @@ pub fn _mm512_maskz_mul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mul_round_pch(a: __m512h, b: __m512h) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mask_mul_round_pch::(_mm512_undefined_ph(), 0xffff, a, b) @@ -2913,7 +2913,7 @@ pub fn _mm512_mul_round_pch(a: __m512h, b: __m512h) -> __m5 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_mul_round_pch( src: __m512h, k: __mmask16, @@ -2949,7 +2949,7 @@ pub fn _mm512_mask_mul_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_mul_round_pch( k: __mmask16, a: __m512h, @@ -2968,7 +2968,7 @@ pub fn _mm512_maskz_mul_round_pch( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mul_sch(a: __m128h, b: __m128h) -> __m128h { _mm_mask_mul_sch(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -2982,7 +2982,7 @@ pub fn _mm_mul_sch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_mul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_mul_round_sch::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -2996,7 +2996,7 @@ pub fn _mm_mask_mul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_mul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_mul_sch(f16x8::ZERO.as_m128h(), k, a, b) } @@ -3019,7 +3019,7 @@ pub fn _mm_maskz_mul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mul_round_sch(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_mul_round_sch::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -3043,7 +3043,7 @@ pub fn _mm_mul_round_sch(a: __m128h, b: __m128h) -> __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_mul_round_sch( src: __m128h, k: __mmask8, @@ -3080,7 +3080,7 @@ pub fn _mm_mask_mul_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_mul_round_sch( k: __mmask8, a: __m128h, @@ -3098,7 +3098,7 @@ pub fn _mm_maskz_mul_round_sch( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmul_pch(a: __m128h, b: __m128h) -> __m128h { _mm_mul_pch(a, b) } @@ -3111,7 +3111,7 @@ pub fn _mm_fmul_pch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_mul_pch(src, k, a, b) } @@ -3124,7 +3124,7 @@ pub fn _mm_mask_fmul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_maskz_mul_pch(k, a, b) } @@ -3137,7 +3137,7 @@ pub fn _mm_maskz_fmul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_fmul_pch(a: __m256h, b: __m256h) -> __m256h { _mm256_mul_pch(a, b) } @@ -3150,7 +3150,7 @@ pub fn _mm256_fmul_pch(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_fmul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) -> __m256h { _mm256_mask_mul_pch(src, k, a, b) } @@ -3163,7 +3163,7 @@ pub fn _mm256_mask_fmul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) - #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_fmul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { _mm256_maskz_mul_pch(k, a, b) } @@ -3175,7 +3175,7 @@ pub fn _mm256_maskz_fmul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmul_pch(a: __m512h, b: __m512h) -> __m512h { _mm512_mul_pch(a, b) } @@ -3188,7 +3188,7 @@ pub fn _mm512_fmul_pch(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_mul_pch(src, k, a, b) } @@ -3201,7 +3201,7 @@ pub fn _mm512_mask_fmul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_maskz_mul_pch(k, a, b) } @@ -3221,7 +3221,7 @@ pub fn _mm512_maskz_fmul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmul_round_pch(a: __m512h, b: __m512h) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mul_round_pch::(a, b) @@ -3243,7 +3243,7 @@ pub fn _mm512_fmul_round_pch(a: __m512h, b: __m512h) -> __m #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmul_round_pch( src: __m512h, k: __mmask16, @@ -3270,7 +3270,7 @@ pub fn _mm512_mask_fmul_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmul_round_pch( k: __mmask16, a: __m512h, @@ -3288,7 +3288,7 @@ pub fn _mm512_maskz_fmul_round_pch( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmul_sch(a: __m128h, b: __m128h) -> __m128h { _mm_mul_sch(a, b) } @@ -3301,7 +3301,7 @@ pub fn _mm_fmul_sch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_mul_sch(src, k, a, b) } @@ -3314,7 +3314,7 @@ pub fn _mm_mask_fmul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_maskz_mul_sch(k, a, b) } @@ -3335,7 +3335,7 @@ pub fn _mm_maskz_fmul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmul_round_sch(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mul_round_sch::(a, b) @@ -3358,7 +3358,7 @@ pub fn _mm_fmul_round_sch(a: __m128h, b: __m128h) -> __m128 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmul_round_sch( src: __m128h, k: __mmask8, @@ -3386,7 +3386,7 @@ pub fn _mm_mask_fmul_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmul_round_sch( k: __mmask8, a: __m128h, @@ -3405,7 +3405,7 @@ pub fn _mm_maskz_fmul_round_sch( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cmul_pch(a: __m128h, b: __m128h) -> __m128h { _mm_mask_cmul_pch(_mm_undefined_ph(), 0xff, a, b) } @@ -3419,7 +3419,7 @@ pub fn _mm_cmul_pch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cmul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { transmute(vfcmulcph_128(transmute(a), transmute(b), transmute(src), k)) } } @@ -3433,7 +3433,7 @@ pub fn _mm_mask_cmul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cmul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_cmul_pch(_mm_setzero_ph(), k, a, b) } @@ -3447,7 +3447,7 @@ pub fn _mm_maskz_cmul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cmul_pch(a: __m256h, b: __m256h) -> __m256h { _mm256_mask_cmul_pch(_mm256_undefined_ph(), 0xff, a, b) } @@ -3461,7 +3461,7 @@ pub fn _mm256_cmul_pch(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cmul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) -> __m256h { unsafe { transmute(vfcmulcph_256(transmute(a), transmute(b), transmute(src), k)) } } @@ -3475,7 +3475,7 @@ pub fn _mm256_mask_cmul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) - #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cmul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { _mm256_mask_cmul_pch(_mm256_setzero_ph(), k, a, b) } @@ -3489,7 +3489,7 @@ pub fn _mm256_maskz_cmul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cmul_pch(a: __m512h, b: __m512h) -> __m512h { _mm512_mask_cmul_pch(_mm512_undefined_ph(), 0xffff, a, b) } @@ -3503,7 +3503,7 @@ pub fn _mm512_cmul_pch(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cmul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_cmul_round_pch::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -3517,7 +3517,7 @@ pub fn _mm512_mask_cmul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cmul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_cmul_pch(_mm512_setzero_ph(), k, a, b) } @@ -3540,7 +3540,7 @@ pub fn _mm512_maskz_cmul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cmul_round_pch(a: __m512h, b: __m512h) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mask_cmul_round_pch::(_mm512_undefined_ph(), 0xffff, a, b) @@ -3564,7 +3564,7 @@ pub fn _mm512_cmul_round_pch(a: __m512h, b: __m512h) -> __m #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cmul_round_pch( src: __m512h, k: __mmask16, @@ -3601,7 +3601,7 @@ pub fn _mm512_mask_cmul_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cmul_round_pch( k: __mmask16, a: __m512h, @@ -3619,7 +3619,7 @@ pub fn _mm512_maskz_cmul_round_pch( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cmul_sch(a: __m128h, b: __m128h) -> __m128h { _mm_mask_cmul_sch(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -3633,7 +3633,7 @@ pub fn _mm_cmul_sch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cmul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_cmul_round_sch::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -3647,7 +3647,7 @@ pub fn _mm_mask_cmul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cmul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_cmul_sch(f16x8::ZERO.as_m128h(), k, a, b) } @@ -3669,7 +3669,7 @@ pub fn _mm_maskz_cmul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cmul_round_sch(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_cmul_round_sch::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -3693,7 +3693,7 @@ pub fn _mm_cmul_round_sch(a: __m128h, b: __m128h) -> __m128 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cmul_round_sch( src: __m128h, k: __mmask8, @@ -3730,7 +3730,7 @@ pub fn _mm_mask_cmul_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cmul_round_sch( k: __mmask8, a: __m128h, @@ -3749,7 +3749,7 @@ pub fn _mm_maskz_cmul_round_sch( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fcmul_pch(a: __m128h, b: __m128h) -> __m128h { _mm_cmul_pch(a, b) } @@ -3763,7 +3763,7 @@ pub fn _mm_fcmul_pch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fcmul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_cmul_pch(src, k, a, b) } @@ -3777,7 +3777,7 @@ pub fn _mm_mask_fcmul_pch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fcmul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_maskz_cmul_pch(k, a, b) } @@ -3791,7 +3791,7 @@ pub fn _mm_maskz_fcmul_pch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_fcmul_pch(a: __m256h, b: __m256h) -> __m256h { _mm256_cmul_pch(a, b) } @@ -3805,7 +3805,7 @@ pub fn _mm256_fcmul_pch(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_fcmul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) -> __m256h { _mm256_mask_cmul_pch(src, k, a, b) } @@ -3819,7 +3819,7 @@ pub fn _mm256_mask_fcmul_pch(src: __m256h, k: __mmask8, a: __m256h, b: __m256h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_fcmul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { _mm256_maskz_cmul_pch(k, a, b) } @@ -3833,7 +3833,7 @@ pub fn _mm256_maskz_fcmul_pch(k: __mmask8, a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fcmul_pch(a: __m512h, b: __m512h) -> __m512h { _mm512_cmul_pch(a, b) } @@ -3847,7 +3847,7 @@ pub fn _mm512_fcmul_pch(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fcmul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_cmul_pch(src, k, a, b) } @@ -3861,7 +3861,7 @@ pub fn _mm512_mask_fcmul_pch(src: __m512h, k: __mmask16, a: __m512h, b: __m512h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fcmul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { _mm512_maskz_cmul_pch(k, a, b) } @@ -3883,7 +3883,7 @@ pub fn _mm512_maskz_fcmul_pch(k: __mmask16, a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fcmul_round_pch(a: __m512h, b: __m512h) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_cmul_round_pch::(a, b) @@ -3907,7 +3907,7 @@ pub fn _mm512_fcmul_round_pch(a: __m512h, b: __m512h) -> __ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fcmul_round_pch( src: __m512h, k: __mmask16, @@ -3936,7 +3936,7 @@ pub fn _mm512_mask_fcmul_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fcmul_round_pch( k: __mmask16, a: __m512h, @@ -3955,7 +3955,7 @@ pub fn _mm512_maskz_fcmul_round_pch( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fcmul_sch(a: __m128h, b: __m128h) -> __m128h { _mm_cmul_sch(a, b) } @@ -3969,7 +3969,7 @@ pub fn _mm_fcmul_sch(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fcmul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_cmul_sch(src, k, a, b) } @@ -3983,7 +3983,7 @@ pub fn _mm_mask_fcmul_sch(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fcmul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_maskz_cmul_sch(k, a, b) } @@ -4005,7 +4005,7 @@ pub fn _mm_maskz_fcmul_sch(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fcmul_round_sch(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_cmul_round_sch::(a, b) @@ -4029,7 +4029,7 @@ pub fn _mm_fcmul_round_sch(a: __m128h, b: __m128h) -> __m12 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fcmul_round_sch( src: __m128h, k: __mmask8, @@ -4058,7 +4058,7 @@ pub fn _mm_mask_fcmul_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmulcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fcmul_round_sch( k: __mmask8, a: __m128h, @@ -4074,7 +4074,7 @@ pub fn _mm_maskz_fcmul_round_sch( /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_abs_ph(v2: __m128h) -> __m128h { unsafe { transmute(_mm_and_si128(transmute(v2), _mm_set1_epi16(i16::MAX))) } @@ -4086,7 +4086,7 @@ pub const fn _mm_abs_ph(v2: __m128h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_abs_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_abs_ph(v2: __m256h) -> __m256h { unsafe { transmute(_mm256_and_si256(transmute(v2), _mm256_set1_epi16(i16::MAX))) } @@ -4098,7 +4098,7 @@ pub const fn _mm256_abs_ph(v2: __m256h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_abs_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_abs_ph(v2: __m512h) -> __m512h { unsafe { transmute(_mm512_and_si512(transmute(v2), _mm512_set1_epi16(i16::MAX))) } @@ -4112,7 +4112,7 @@ pub const fn _mm512_abs_ph(v2: __m512h) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_conj_pch) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_conj_pch(a: __m128h) -> __m128h { unsafe { transmute(_mm_xor_si128(transmute(a), _mm_set1_epi32(i32::MIN))) } @@ -4126,7 +4126,7 @@ pub const fn _mm_conj_pch(a: __m128h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_conj_pch) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_conj_pch(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { unsafe { @@ -4143,7 +4143,7 @@ pub const fn _mm_mask_conj_pch(src: __m128h, k: __mmask8, a: __m128h) -> __m128h /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_conj_pch) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_conj_pch(k: __mmask8, a: __m128h) -> __m128h { _mm_mask_conj_pch(_mm_setzero_ph(), k, a) @@ -4156,7 +4156,7 @@ pub const fn _mm_maskz_conj_pch(k: __mmask8, a: __m128h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_conj_pch) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_conj_pch(a: __m256h) -> __m256h { unsafe { transmute(_mm256_xor_si256(transmute(a), _mm256_set1_epi32(i32::MIN))) } @@ -4170,7 +4170,7 @@ pub const fn _mm256_conj_pch(a: __m256h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_conj_pch) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_conj_pch(src: __m256h, k: __mmask8, a: __m256h) -> __m256h { unsafe { @@ -4187,7 +4187,7 @@ pub const fn _mm256_mask_conj_pch(src: __m256h, k: __mmask8, a: __m256h) -> __m2 /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_conj_pch) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_conj_pch(k: __mmask8, a: __m256h) -> __m256h { _mm256_mask_conj_pch(_mm256_setzero_ph(), k, a) @@ -4200,7 +4200,7 @@ pub const fn _mm256_maskz_conj_pch(k: __mmask8, a: __m256h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_conj_pch) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_conj_pch(a: __m512h) -> __m512h { unsafe { transmute(_mm512_xor_si512(transmute(a), _mm512_set1_epi32(i32::MIN))) } @@ -4214,7 +4214,7 @@ pub const fn _mm512_conj_pch(a: __m512h) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_conj_pch) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_conj_pch(src: __m512h, k: __mmask16, a: __m512h) -> __m512h { unsafe { @@ -4231,7 +4231,7 @@ pub const fn _mm512_mask_conj_pch(src: __m512h, k: __mmask16, a: __m512h) -> __m /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_conj_pch) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_conj_pch(k: __mmask16, a: __m512h) -> __m512h { _mm512_mask_conj_pch(_mm512_setzero_ph(), k, a) @@ -4245,7 +4245,7 @@ pub const fn _mm512_maskz_conj_pch(k: __mmask16, a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmadd_pch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { _mm_mask3_fmadd_pch(a, b, c, 0xff) } @@ -4259,7 +4259,7 @@ pub fn _mm_fmadd_pch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmadd_pch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { let r: __m128 = transmute(_mm_mask3_fmadd_pch(a, b, c, k)); // using `0xff` would have been fine here, but this is what CLang does @@ -4276,7 +4276,7 @@ pub fn _mm_mask_fmadd_pch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fmadd_pch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { transmute(vfmaddcph_mask3_128( @@ -4297,7 +4297,7 @@ pub fn _mm_mask3_fmadd_pch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> _ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmadd_pch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { transmute(vfmaddcph_maskz_128( @@ -4317,7 +4317,7 @@ pub fn _mm_maskz_fmadd_pch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_fmadd_pch(a: __m256h, b: __m256h, c: __m256h) -> __m256h { _mm256_mask3_fmadd_pch(a, b, c, 0xff) } @@ -4331,7 +4331,7 @@ pub fn _mm256_fmadd_pch(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_fmadd_pch(a: __m256h, k: __mmask8, b: __m256h, c: __m256h) -> __m256h { unsafe { let r: __m256 = transmute(_mm256_mask3_fmadd_pch(a, b, c, k)); // using `0xff` would have been fine here, but this is what CLang does @@ -4348,7 +4348,7 @@ pub fn _mm256_mask_fmadd_pch(a: __m256h, k: __mmask8, b: __m256h, c: __m256h) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask3_fmadd_pch(a: __m256h, b: __m256h, c: __m256h, k: __mmask8) -> __m256h { unsafe { transmute(vfmaddcph_mask3_256( @@ -4369,7 +4369,7 @@ pub fn _mm256_mask3_fmadd_pch(a: __m256h, b: __m256h, c: __m256h, k: __mmask8) - #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_fmadd_pch(k: __mmask8, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { transmute(vfmaddcph_maskz_256( @@ -4389,7 +4389,7 @@ pub fn _mm256_maskz_fmadd_pch(k: __mmask8, a: __m256h, b: __m256h, c: __m256h) - #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmadd_pch(a: __m512h, b: __m512h, c: __m512h) -> __m512h { _mm512_fmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(a, b, c) } @@ -4403,7 +4403,7 @@ pub fn _mm512_fmadd_pch(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmadd_pch(a: __m512h, k: __mmask16, b: __m512h, c: __m512h) -> __m512h { _mm512_mask_fmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(a, k, b, c) } @@ -4417,7 +4417,7 @@ pub fn _mm512_mask_fmadd_pch(a: __m512h, k: __mmask16, b: __m512h, c: __m512h) - #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fmadd_pch(a: __m512h, b: __m512h, c: __m512h, k: __mmask16) -> __m512h { _mm512_mask3_fmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(a, b, c, k) } @@ -4431,7 +4431,7 @@ pub fn _mm512_mask3_fmadd_pch(a: __m512h, b: __m512h, c: __m512h, k: __mmask16) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmadd_pch(k: __mmask16, a: __m512h, b: __m512h, c: __m512h) -> __m512h { _mm512_maskz_fmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(k, a, b, c) } @@ -4453,7 +4453,7 @@ pub fn _mm512_maskz_fmadd_pch(k: __mmask16, a: __m512h, b: __m512h, c: __m512h) #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmadd_round_pch(a: __m512h, b: __m512h, c: __m512h) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mask3_fmadd_round_pch::(a, b, c, 0xffff) @@ -4477,7 +4477,7 @@ pub fn _mm512_fmadd_round_pch(a: __m512h, b: __m512h, c: __ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmadd_round_pch( a: __m512h, k: __mmask16, @@ -4509,7 +4509,7 @@ pub fn _mm512_mask_fmadd_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fmadd_round_pch( a: __m512h, b: __m512h, @@ -4546,7 +4546,7 @@ pub fn _mm512_mask3_fmadd_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmadd_round_pch( k: __mmask16, a: __m512h, @@ -4574,7 +4574,7 @@ pub fn _mm512_maskz_fmadd_round_pch( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmadd_sch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { _mm_fmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(a, b, c) } @@ -4589,7 +4589,7 @@ pub fn _mm_fmadd_sch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmadd_sch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { _mm_mask_fmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(a, k, b, c) } @@ -4604,7 +4604,7 @@ pub fn _mm_mask_fmadd_sch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fmadd_sch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { _mm_mask3_fmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(a, b, c, k) } @@ -4619,7 +4619,7 @@ pub fn _mm_mask3_fmadd_sch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmadd_sch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { _mm_maskz_fmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(k, a, b, c) } @@ -4641,7 +4641,7 @@ pub fn _mm_maskz_fmadd_sch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> _ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmadd_round_sch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -4674,7 +4674,7 @@ pub fn _mm_fmadd_round_sch(a: __m128h, b: __m128h, c: __m12 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmadd_round_sch( a: __m128h, k: __mmask8, @@ -4708,7 +4708,7 @@ pub fn _mm_mask_fmadd_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fmadd_round_sch( a: __m128h, b: __m128h, @@ -4742,7 +4742,7 @@ pub fn _mm_mask3_fmadd_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmadd_round_sch( k: __mmask8, a: __m128h, @@ -4770,7 +4770,7 @@ pub fn _mm_maskz_fmadd_round_sch( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fcmadd_pch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { _mm_mask3_fcmadd_pch(a, b, c, 0xff) } @@ -4785,7 +4785,7 @@ pub fn _mm_fcmadd_pch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fcmadd_pch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { let r: __m128 = transmute(_mm_mask3_fcmadd_pch(a, b, c, k)); // using `0xff` would have been fine here, but this is what CLang does @@ -4803,7 +4803,7 @@ pub fn _mm_mask_fcmadd_pch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fcmadd_pch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { transmute(vfcmaddcph_mask3_128( @@ -4825,7 +4825,7 @@ pub fn _mm_mask3_fcmadd_pch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fcmadd_pch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { transmute(vfcmaddcph_maskz_128( @@ -4846,7 +4846,7 @@ pub fn _mm_maskz_fcmadd_pch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_fcmadd_pch(a: __m256h, b: __m256h, c: __m256h) -> __m256h { _mm256_mask3_fcmadd_pch(a, b, c, 0xff) } @@ -4861,7 +4861,7 @@ pub fn _mm256_fcmadd_pch(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_fcmadd_pch(a: __m256h, k: __mmask8, b: __m256h, c: __m256h) -> __m256h { unsafe { let r: __m256 = transmute(_mm256_mask3_fcmadd_pch(a, b, c, k)); // using `0xff` would have been fine here, but this is what CLang does @@ -4879,7 +4879,7 @@ pub fn _mm256_mask_fcmadd_pch(a: __m256h, k: __mmask8, b: __m256h, c: __m256h) - #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask3_fcmadd_pch(a: __m256h, b: __m256h, c: __m256h, k: __mmask8) -> __m256h { unsafe { transmute(vfcmaddcph_mask3_256( @@ -4901,7 +4901,7 @@ pub fn _mm256_mask3_fcmadd_pch(a: __m256h, b: __m256h, c: __m256h, k: __mmask8) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_fcmadd_pch(k: __mmask8, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { transmute(vfcmaddcph_maskz_256( @@ -4922,7 +4922,7 @@ pub fn _mm256_maskz_fcmadd_pch(k: __mmask8, a: __m256h, b: __m256h, c: __m256h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fcmadd_pch(a: __m512h, b: __m512h, c: __m512h) -> __m512h { _mm512_fcmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(a, b, c) } @@ -4937,7 +4937,7 @@ pub fn _mm512_fcmadd_pch(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fcmadd_pch(a: __m512h, k: __mmask16, b: __m512h, c: __m512h) -> __m512h { _mm512_mask_fcmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(a, k, b, c) } @@ -4952,7 +4952,7 @@ pub fn _mm512_mask_fcmadd_pch(a: __m512h, k: __mmask16, b: __m512h, c: __m512h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fcmadd_pch(a: __m512h, b: __m512h, c: __m512h, k: __mmask16) -> __m512h { _mm512_mask3_fcmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(a, b, c, k) } @@ -4967,7 +4967,7 @@ pub fn _mm512_mask3_fcmadd_pch(a: __m512h, b: __m512h, c: __m512h, k: __mmask16) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fcmadd_pch(k: __mmask16, a: __m512h, b: __m512h, c: __m512h) -> __m512h { _mm512_maskz_fcmadd_round_pch::<_MM_FROUND_CUR_DIRECTION>(k, a, b, c) } @@ -4990,7 +4990,7 @@ pub fn _mm512_maskz_fcmadd_pch(k: __mmask16, a: __m512h, b: __m512h, c: __m512h) #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fcmadd_round_pch(a: __m512h, b: __m512h, c: __m512h) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mask3_fcmadd_round_pch::(a, b, c, 0xffff) @@ -5015,7 +5015,7 @@ pub fn _mm512_fcmadd_round_pch(a: __m512h, b: __m512h, c: _ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fcmadd_round_pch( a: __m512h, k: __mmask16, @@ -5048,7 +5048,7 @@ pub fn _mm512_mask_fcmadd_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fcmadd_round_pch( a: __m512h, b: __m512h, @@ -5086,7 +5086,7 @@ pub fn _mm512_mask3_fcmadd_round_pch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fcmadd_round_pch( k: __mmask16, a: __m512h, @@ -5115,7 +5115,7 @@ pub fn _mm512_maskz_fcmadd_round_pch( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fcmadd_sch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { _mm_fcmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(a, b, c) } @@ -5131,7 +5131,7 @@ pub fn _mm_fcmadd_sch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fcmadd_sch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { _mm_mask_fcmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(a, k, b, c) } @@ -5147,7 +5147,7 @@ pub fn _mm_mask_fcmadd_sch(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fcmadd_sch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { _mm_mask3_fcmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(a, b, c, k) } @@ -5163,7 +5163,7 @@ pub fn _mm_mask3_fcmadd_sch(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fcmadd_sch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { _mm_maskz_fcmadd_round_sch::<_MM_FROUND_CUR_DIRECTION>(k, a, b, c) } @@ -5187,7 +5187,7 @@ pub fn _mm_maskz_fcmadd_sch(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fcmadd_round_sch(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -5221,7 +5221,7 @@ pub fn _mm_fcmadd_round_sch(a: __m128h, b: __m128h, c: __m1 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fcmadd_round_sch( a: __m128h, k: __mmask8, @@ -5256,7 +5256,7 @@ pub fn _mm_mask_fcmadd_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fcmadd_round_sch( a: __m128h, b: __m128h, @@ -5291,7 +5291,7 @@ pub fn _mm_mask3_fcmadd_round_sch( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfcmaddcsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fcmadd_round_sch( k: __mmask8, a: __m128h, @@ -5317,7 +5317,7 @@ pub fn _mm_maskz_fcmadd_round_sch( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fmadd_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_fma(a, b, c) } @@ -5331,7 +5331,7 @@ pub const fn _mm_fmadd_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fmadd_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmadd_ph(a, b, c), a) } @@ -5345,7 +5345,7 @@ pub const fn _mm_mask_fmadd_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fmadd_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmadd_ph(a, b, c), c) } @@ -5359,7 +5359,7 @@ pub const fn _mm_mask3_fmadd_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fmadd_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmadd_ph(a, b, c), _mm_setzero_ph()) } @@ -5372,7 +5372,7 @@ pub const fn _mm_maskz_fmadd_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_fmadd_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_fma(a, b, c) } @@ -5386,7 +5386,7 @@ pub const fn _mm256_fmadd_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_fmadd_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmadd_ph(a, b, c), a) } @@ -5400,7 +5400,7 @@ pub const fn _mm256_mask_fmadd_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask3_fmadd_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmask16) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmadd_ph(a, b, c), c) } @@ -5414,7 +5414,7 @@ pub const fn _mm256_mask3_fmadd_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmas #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_fmadd_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmadd_ph(a, b, c), _mm256_setzero_ph()) } @@ -5427,7 +5427,7 @@ pub const fn _mm256_maskz_fmadd_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m2 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_fmadd_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_fma(a, b, c) } @@ -5441,7 +5441,7 @@ pub const fn _mm512_fmadd_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_fmadd_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmadd_ph(a, b, c), a) } @@ -5455,7 +5455,7 @@ pub const fn _mm512_mask_fmadd_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask3_fmadd_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmask32) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmadd_ph(a, b, c), c) } @@ -5469,7 +5469,7 @@ pub const fn _mm512_mask3_fmadd_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmas #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_fmadd_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmadd_ph(a, b, c), _mm512_setzero_ph()) } @@ -5491,7 +5491,7 @@ pub const fn _mm512_maskz_fmadd_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m5 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmadd_round_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -5516,7 +5516,7 @@ pub fn _mm512_fmadd_round_ph(a: __m512h, b: __m512h, c: __m #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmadd_round_ph( a: __m512h, k: __mmask32, @@ -5546,7 +5546,7 @@ pub fn _mm512_mask_fmadd_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fmadd_round_ph( a: __m512h, b: __m512h, @@ -5576,7 +5576,7 @@ pub fn _mm512_mask3_fmadd_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmadd_round_ph( k: __mmask32, a: __m512h, @@ -5601,7 +5601,7 @@ pub fn _mm512_maskz_fmadd_round_ph( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fmadd_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -5622,7 +5622,7 @@ pub const fn _mm_fmadd_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fmadd_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -5645,7 +5645,7 @@ pub const fn _mm_mask_fmadd_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fmadd_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { @@ -5668,7 +5668,7 @@ pub const fn _mm_mask3_fmadd_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fmadd_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -5700,7 +5700,7 @@ pub const fn _mm_maskz_fmadd_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmadd_round_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -5730,7 +5730,7 @@ pub fn _mm_fmadd_round_sh(a: __m128h, b: __m128h, c: __m128 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmadd_round_sh( a: __m128h, k: __mmask8, @@ -5767,7 +5767,7 @@ pub fn _mm_mask_fmadd_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fmadd_round_sh( a: __m128h, b: __m128h, @@ -5804,7 +5804,7 @@ pub fn _mm_mask3_fmadd_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmadd_round_sh( k: __mmask8, a: __m128h, @@ -5832,7 +5832,7 @@ pub fn _mm_maskz_fmadd_round_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fmsub_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_fma(a, b, simd_neg(c)) } @@ -5846,7 +5846,7 @@ pub const fn _mm_fmsub_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fmsub_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmsub_ph(a, b, c), a) } @@ -5860,7 +5860,7 @@ pub const fn _mm_mask_fmsub_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fmsub_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmsub_ph(a, b, c), c) } @@ -5874,7 +5874,7 @@ pub const fn _mm_mask3_fmsub_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fmsub_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmsub_ph(a, b, c), _mm_setzero_ph()) } @@ -5887,7 +5887,7 @@ pub const fn _mm_maskz_fmsub_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_fmsub_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_fma(a, b, simd_neg(c)) } @@ -5901,7 +5901,7 @@ pub const fn _mm256_fmsub_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_fmsub_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmsub_ph(a, b, c), a) } @@ -5915,7 +5915,7 @@ pub const fn _mm256_mask_fmsub_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask3_fmsub_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmask16) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmsub_ph(a, b, c), c) } @@ -5929,7 +5929,7 @@ pub const fn _mm256_mask3_fmsub_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmas #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_fmsub_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmsub_ph(a, b, c), _mm256_setzero_ph()) } @@ -5942,7 +5942,7 @@ pub const fn _mm256_maskz_fmsub_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m2 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_fmsub_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_fma(a, b, simd_neg(c)) } @@ -5956,7 +5956,7 @@ pub const fn _mm512_fmsub_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_fmsub_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmsub_ph(a, b, c), a) } @@ -5970,7 +5970,7 @@ pub const fn _mm512_mask_fmsub_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask3_fmsub_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmask32) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmsub_ph(a, b, c), c) } @@ -5984,7 +5984,7 @@ pub const fn _mm512_mask3_fmsub_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmas #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_fmsub_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmsub_ph(a, b, c), _mm512_setzero_ph()) } @@ -6006,7 +6006,7 @@ pub const fn _mm512_maskz_fmsub_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m5 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmsub_round_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -6031,7 +6031,7 @@ pub fn _mm512_fmsub_round_ph(a: __m512h, b: __m512h, c: __m #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmsub_round_ph( a: __m512h, k: __mmask32, @@ -6061,7 +6061,7 @@ pub fn _mm512_mask_fmsub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fmsub_round_ph( a: __m512h, b: __m512h, @@ -6091,7 +6091,7 @@ pub fn _mm512_mask3_fmsub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmsub_round_ph( k: __mmask32, a: __m512h, @@ -6116,7 +6116,7 @@ pub fn _mm512_maskz_fmsub_round_ph( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fmsub_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -6137,7 +6137,7 @@ pub const fn _mm_fmsub_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fmsub_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -6160,7 +6160,7 @@ pub const fn _mm_mask_fmsub_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fmsub_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { @@ -6183,7 +6183,7 @@ pub const fn _mm_mask3_fmsub_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fmsub_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -6215,7 +6215,7 @@ pub const fn _mm_maskz_fmsub_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fmsub_round_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -6245,7 +6245,7 @@ pub fn _mm_fmsub_round_sh(a: __m128h, b: __m128h, c: __m128 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fmsub_round_sh( a: __m128h, k: __mmask8, @@ -6282,7 +6282,7 @@ pub fn _mm_mask_fmsub_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fmsub_round_sh( a: __m128h, b: __m128h, @@ -6311,7 +6311,7 @@ pub fn _mm_mask3_fmsub_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fmsub_round_sh( k: __mmask8, a: __m128h, @@ -6338,7 +6338,7 @@ pub fn _mm_maskz_fmsub_round_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fnmadd_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_fma(simd_neg(a), b, c) } @@ -6352,7 +6352,7 @@ pub const fn _mm_fnmadd_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fnmadd_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fnmadd_ph(a, b, c), a) } @@ -6366,7 +6366,7 @@ pub const fn _mm_mask_fnmadd_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fnmadd_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fnmadd_ph(a, b, c), c) } @@ -6380,7 +6380,7 @@ pub const fn _mm_mask3_fnmadd_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fnmadd_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fnmadd_ph(a, b, c), _mm_setzero_ph()) } @@ -6393,7 +6393,7 @@ pub const fn _mm_maskz_fnmadd_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_fnmadd_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_fma(simd_neg(a), b, c) } @@ -6407,7 +6407,7 @@ pub const fn _mm256_fnmadd_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_fnmadd_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fnmadd_ph(a, b, c), a) } @@ -6421,7 +6421,7 @@ pub const fn _mm256_mask_fnmadd_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m2 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask3_fnmadd_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmask16) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fnmadd_ph(a, b, c), c) } @@ -6435,7 +6435,7 @@ pub const fn _mm256_mask3_fnmadd_ph(a: __m256h, b: __m256h, c: __m256h, k: __mma #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_fnmadd_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fnmadd_ph(a, b, c), _mm256_setzero_ph()) } @@ -6448,7 +6448,7 @@ pub const fn _mm256_maskz_fnmadd_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_fnmadd_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_fma(simd_neg(a), b, c) } @@ -6462,7 +6462,7 @@ pub const fn _mm512_fnmadd_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_fnmadd_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fnmadd_ph(a, b, c), a) } @@ -6476,7 +6476,7 @@ pub const fn _mm512_mask_fnmadd_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m5 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask3_fnmadd_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmask32) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fnmadd_ph(a, b, c), c) } @@ -6490,7 +6490,7 @@ pub const fn _mm512_mask3_fnmadd_ph(a: __m512h, b: __m512h, c: __m512h, k: __mma #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_fnmadd_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fnmadd_ph(a, b, c), _mm512_setzero_ph()) } @@ -6512,7 +6512,7 @@ pub const fn _mm512_maskz_fnmadd_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fnmadd_round_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -6537,7 +6537,7 @@ pub fn _mm512_fnmadd_round_ph(a: __m512h, b: __m512h, c: __ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fnmadd_round_ph( a: __m512h, k: __mmask32, @@ -6567,7 +6567,7 @@ pub fn _mm512_mask_fnmadd_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fnmadd_round_ph( a: __m512h, b: __m512h, @@ -6597,7 +6597,7 @@ pub fn _mm512_mask3_fnmadd_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fnmadd_round_ph( k: __mmask32, a: __m512h, @@ -6622,7 +6622,7 @@ pub fn _mm512_maskz_fnmadd_round_ph( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fnmadd_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -6643,7 +6643,7 @@ pub const fn _mm_fnmadd_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fnmadd_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -6666,7 +6666,7 @@ pub const fn _mm_mask_fnmadd_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fnmadd_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { @@ -6689,7 +6689,7 @@ pub const fn _mm_mask3_fnmadd_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fnmadd_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -6721,7 +6721,7 @@ pub const fn _mm_maskz_fnmadd_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fnmadd_round_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -6751,7 +6751,7 @@ pub fn _mm_fnmadd_round_sh(a: __m128h, b: __m128h, c: __m12 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fnmadd_round_sh( a: __m128h, k: __mmask8, @@ -6788,7 +6788,7 @@ pub fn _mm_mask_fnmadd_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fnmadd_round_sh( a: __m128h, b: __m128h, @@ -6825,7 +6825,7 @@ pub fn _mm_mask3_fnmadd_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fnmadd_round_sh( k: __mmask8, a: __m128h, @@ -6852,7 +6852,7 @@ pub fn _mm_maskz_fnmadd_round_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fnmsub_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_fma(simd_neg(a), b, simd_neg(c)) } @@ -6866,7 +6866,7 @@ pub const fn _mm_fnmsub_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fnmsub_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fnmsub_ph(a, b, c), a) } @@ -6880,7 +6880,7 @@ pub const fn _mm_mask_fnmsub_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fnmsub_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fnmsub_ph(a, b, c), c) } @@ -6894,7 +6894,7 @@ pub const fn _mm_mask3_fnmsub_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fnmsub_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fnmsub_ph(a, b, c), _mm_setzero_ph()) } @@ -6907,7 +6907,7 @@ pub const fn _mm_maskz_fnmsub_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_fnmsub_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_fma(simd_neg(a), b, simd_neg(c)) } @@ -6921,7 +6921,7 @@ pub const fn _mm256_fnmsub_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_fnmsub_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fnmsub_ph(a, b, c), a) } @@ -6935,7 +6935,7 @@ pub const fn _mm256_mask_fnmsub_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m2 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask3_fnmsub_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmask16) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fnmsub_ph(a, b, c), c) } @@ -6949,7 +6949,7 @@ pub const fn _mm256_mask3_fnmsub_ph(a: __m256h, b: __m256h, c: __m256h, k: __mma #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_fnmsub_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fnmsub_ph(a, b, c), _mm256_setzero_ph()) } @@ -6962,7 +6962,7 @@ pub const fn _mm256_maskz_fnmsub_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_fnmsub_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_fma(simd_neg(a), b, simd_neg(c)) } @@ -6976,7 +6976,7 @@ pub const fn _mm512_fnmsub_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_fnmsub_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fnmsub_ph(a, b, c), a) } @@ -6990,7 +6990,7 @@ pub const fn _mm512_mask_fnmsub_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m5 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask3_fnmsub_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmask32) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fnmsub_ph(a, b, c), c) } @@ -7004,7 +7004,7 @@ pub const fn _mm512_mask3_fnmsub_ph(a: __m512h, b: __m512h, c: __m512h, k: __mma #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_fnmsub_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fnmsub_ph(a, b, c), _mm512_setzero_ph()) } @@ -7026,7 +7026,7 @@ pub const fn _mm512_maskz_fnmsub_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fnmsub_round_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -7051,7 +7051,7 @@ pub fn _mm512_fnmsub_round_ph(a: __m512h, b: __m512h, c: __ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fnmsub_round_ph( a: __m512h, k: __mmask32, @@ -7081,7 +7081,7 @@ pub fn _mm512_mask_fnmsub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fnmsub_round_ph( a: __m512h, b: __m512h, @@ -7111,7 +7111,7 @@ pub fn _mm512_mask3_fnmsub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fnmsub_round_ph( k: __mmask32, a: __m512h, @@ -7136,7 +7136,7 @@ pub fn _mm512_maskz_fnmsub_round_ph( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fnmsub_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -7157,7 +7157,7 @@ pub const fn _mm_fnmsub_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fnmsub_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -7180,7 +7180,7 @@ pub const fn _mm_mask_fnmsub_sh(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fnmsub_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { @@ -7203,7 +7203,7 @@ pub const fn _mm_mask3_fnmsub_sh(a: __m128h, b: __m128h, c: __m128h, k: __mmask8 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fnmsub_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -7235,7 +7235,7 @@ pub const fn _mm_maskz_fnmsub_sh(k: __mmask8, a: __m128h, b: __m128h, c: __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fnmsub_round_sh(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -7265,7 +7265,7 @@ pub fn _mm_fnmsub_round_sh(a: __m128h, b: __m128h, c: __m12 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fnmsub_round_sh( a: __m128h, k: __mmask8, @@ -7302,7 +7302,7 @@ pub fn _mm_mask_fnmsub_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask3_fnmsub_round_sh( a: __m128h, b: __m128h, @@ -7339,7 +7339,7 @@ pub fn _mm_mask3_fnmsub_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfnmsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_fnmsub_round_sh( k: __mmask8, a: __m128h, @@ -7366,7 +7366,7 @@ pub fn _mm_maskz_fnmsub_round_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fmaddsub_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { @@ -7384,7 +7384,7 @@ pub const fn _mm_fmaddsub_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fmaddsub_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmaddsub_ph(a, b, c), a) } @@ -7398,7 +7398,7 @@ pub const fn _mm_mask_fmaddsub_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fmaddsub_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmaddsub_ph(a, b, c), c) } @@ -7412,7 +7412,7 @@ pub const fn _mm_mask3_fmaddsub_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmas #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fmaddsub_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmaddsub_ph(a, b, c), _mm_setzero_ph()) } @@ -7425,7 +7425,7 @@ pub const fn _mm_maskz_fmaddsub_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m12 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_fmaddsub_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { @@ -7447,7 +7447,7 @@ pub const fn _mm256_fmaddsub_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_fmaddsub_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmaddsub_ph(a, b, c), a) } @@ -7461,7 +7461,7 @@ pub const fn _mm256_mask_fmaddsub_ph(a: __m256h, k: __mmask16, b: __m256h, c: __ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask3_fmaddsub_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmask16) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmaddsub_ph(a, b, c), c) } @@ -7475,7 +7475,7 @@ pub const fn _mm256_mask3_fmaddsub_ph(a: __m256h, b: __m256h, c: __m256h, k: __m #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_fmaddsub_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmaddsub_ph(a, b, c), _mm256_setzero_ph()) } @@ -7488,7 +7488,7 @@ pub const fn _mm256_maskz_fmaddsub_ph(k: __mmask16, a: __m256h, b: __m256h, c: _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_fmaddsub_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { @@ -7513,7 +7513,7 @@ pub const fn _mm512_fmaddsub_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_fmaddsub_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmaddsub_ph(a, b, c), a) } @@ -7527,7 +7527,7 @@ pub const fn _mm512_mask_fmaddsub_ph(a: __m512h, k: __mmask32, b: __m512h, c: __ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask3_fmaddsub_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmask32) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmaddsub_ph(a, b, c), c) } @@ -7541,7 +7541,7 @@ pub const fn _mm512_mask3_fmaddsub_ph(a: __m512h, b: __m512h, c: __m512h, k: __m #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_fmaddsub_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmaddsub_ph(a, b, c), _mm512_setzero_ph()) } @@ -7563,7 +7563,7 @@ pub const fn _mm512_maskz_fmaddsub_ph(k: __mmask32, a: __m512h, b: __m512h, c: _ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmaddsub_round_ph( a: __m512h, b: __m512h, @@ -7592,7 +7592,7 @@ pub fn _mm512_fmaddsub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmaddsub_round_ph( a: __m512h, k: __mmask32, @@ -7622,7 +7622,7 @@ pub fn _mm512_mask_fmaddsub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fmaddsub_round_ph( a: __m512h, b: __m512h, @@ -7652,7 +7652,7 @@ pub fn _mm512_mask3_fmaddsub_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmaddsub, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmaddsub_round_ph( k: __mmask32, a: __m512h, @@ -7676,7 +7676,7 @@ pub fn _mm512_maskz_fmaddsub_round_ph( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_fmsubadd_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { _mm_fmaddsub_ph(a, b, unsafe { simd_neg(c) }) @@ -7690,7 +7690,7 @@ pub const fn _mm_fmsubadd_ph(a: __m128h, b: __m128h, c: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_fmsubadd_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmsubadd_ph(a, b, c), a) } @@ -7704,7 +7704,7 @@ pub const fn _mm_mask_fmsubadd_ph(a: __m128h, k: __mmask8, b: __m128h, c: __m128 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask3_fmsubadd_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmask8) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmsubadd_ph(a, b, c), c) } @@ -7718,7 +7718,7 @@ pub const fn _mm_mask3_fmsubadd_ph(a: __m128h, b: __m128h, c: __m128h, k: __mmas #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_fmsubadd_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_fmsubadd_ph(a, b, c), _mm_setzero_ph()) } @@ -7731,7 +7731,7 @@ pub const fn _mm_maskz_fmsubadd_ph(k: __mmask8, a: __m128h, b: __m128h, c: __m12 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_fmsubadd_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { _mm256_fmaddsub_ph(a, b, unsafe { simd_neg(c) }) @@ -7745,7 +7745,7 @@ pub const fn _mm256_fmsubadd_ph(a: __m256h, b: __m256h, c: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_fmsubadd_ph(a: __m256h, k: __mmask16, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmsubadd_ph(a, b, c), a) } @@ -7759,7 +7759,7 @@ pub const fn _mm256_mask_fmsubadd_ph(a: __m256h, k: __mmask16, b: __m256h, c: __ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask3_fmsubadd_ph(a: __m256h, b: __m256h, c: __m256h, k: __mmask16) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmsubadd_ph(a, b, c), c) } @@ -7773,7 +7773,7 @@ pub const fn _mm256_mask3_fmsubadd_ph(a: __m256h, b: __m256h, c: __m256h, k: __m #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_fmsubadd_ph(k: __mmask16, a: __m256h, b: __m256h, c: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_fmsubadd_ph(a, b, c), _mm256_setzero_ph()) } @@ -7786,7 +7786,7 @@ pub const fn _mm256_maskz_fmsubadd_ph(k: __mmask16, a: __m256h, b: __m256h, c: _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_fmsubadd_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { _mm512_fmaddsub_ph(a, b, unsafe { simd_neg(c) }) @@ -7800,7 +7800,7 @@ pub const fn _mm512_fmsubadd_ph(a: __m512h, b: __m512h, c: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_fmsubadd_ph(a: __m512h, k: __mmask32, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmsubadd_ph(a, b, c), a) } @@ -7814,7 +7814,7 @@ pub const fn _mm512_mask_fmsubadd_ph(a: __m512h, k: __mmask32, b: __m512h, c: __ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask3_fmsubadd_ph(a: __m512h, b: __m512h, c: __m512h, k: __mmask32) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmsubadd_ph(a, b, c), c) } @@ -7828,7 +7828,7 @@ pub const fn _mm512_mask3_fmsubadd_ph(a: __m512h, b: __m512h, c: __m512h, k: __m #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_maskz_fmsubadd_ph(k: __mmask32, a: __m512h, b: __m512h, c: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_fmsubadd_ph(a, b, c), _mm512_setzero_ph()) } @@ -7850,7 +7850,7 @@ pub const fn _mm512_maskz_fmsubadd_ph(k: __mmask32, a: __m512h, b: __m512h, c: _ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fmsubadd_round_ph( a: __m512h, b: __m512h, @@ -7879,7 +7879,7 @@ pub fn _mm512_fmsubadd_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fmsubadd_round_ph( a: __m512h, k: __mmask32, @@ -7909,7 +7909,7 @@ pub fn _mm512_mask_fmsubadd_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask3_fmsubadd_round_ph( a: __m512h, b: __m512h, @@ -7939,7 +7939,7 @@ pub fn _mm512_mask3_fmsubadd_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfmsubadd, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_fmsubadd_round_ph( k: __mmask32, a: __m512h, @@ -7963,7 +7963,7 @@ pub fn _mm512_maskz_fmsubadd_round_ph( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_rcp_ph(a: __m128h) -> __m128h { _mm_mask_rcp_ph(_mm_undefined_ph(), 0xff, a) } @@ -7976,7 +7976,7 @@ pub fn _mm_rcp_ph(a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_rcp_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { unsafe { vrcpph_128(a, src, k) } } @@ -7989,7 +7989,7 @@ pub fn _mm_mask_rcp_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_rcp_ph(k: __mmask8, a: __m128h) -> __m128h { _mm_mask_rcp_ph(_mm_setzero_ph(), k, a) } @@ -8001,7 +8001,7 @@ pub fn _mm_maskz_rcp_ph(k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_rcp_ph(a: __m256h) -> __m256h { _mm256_mask_rcp_ph(_mm256_undefined_ph(), 0xffff, a) } @@ -8014,7 +8014,7 @@ pub fn _mm256_rcp_ph(a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_rcp_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { unsafe { vrcpph_256(a, src, k) } } @@ -8027,7 +8027,7 @@ pub fn _mm256_mask_rcp_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_rcp_ph(k: __mmask16, a: __m256h) -> __m256h { _mm256_mask_rcp_ph(_mm256_setzero_ph(), k, a) } @@ -8039,7 +8039,7 @@ pub fn _mm256_maskz_rcp_ph(k: __mmask16, a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_rcp_ph(a: __m512h) -> __m512h { _mm512_mask_rcp_ph(_mm512_undefined_ph(), 0xffffffff, a) } @@ -8052,7 +8052,7 @@ pub fn _mm512_rcp_ph(a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_rcp_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { unsafe { vrcpph_512(a, src, k) } } @@ -8065,7 +8065,7 @@ pub fn _mm512_mask_rcp_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrcpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_rcp_ph(k: __mmask32, a: __m512h) -> __m512h { _mm512_mask_rcp_ph(_mm512_setzero_ph(), k, a) } @@ -8079,7 +8079,7 @@ pub fn _mm512_maskz_rcp_ph(k: __mmask32, a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrcpsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_rcp_sh(a: __m128h, b: __m128h) -> __m128h { _mm_mask_rcp_sh(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -8093,7 +8093,7 @@ pub fn _mm_rcp_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrcpsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_rcp_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { vrcpsh(a, b, src, k) } } @@ -8107,7 +8107,7 @@ pub fn _mm_mask_rcp_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrcpsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_rcp_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_rcp_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -8120,7 +8120,7 @@ pub fn _mm_maskz_rcp_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_rsqrt_ph(a: __m128h) -> __m128h { _mm_mask_rsqrt_ph(_mm_undefined_ph(), 0xff, a) } @@ -8134,7 +8134,7 @@ pub fn _mm_rsqrt_ph(a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_rsqrt_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { unsafe { vrsqrtph_128(a, src, k) } } @@ -8148,7 +8148,7 @@ pub fn _mm_mask_rsqrt_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_rsqrt_ph(k: __mmask8, a: __m128h) -> __m128h { _mm_mask_rsqrt_ph(_mm_setzero_ph(), k, a) } @@ -8161,7 +8161,7 @@ pub fn _mm_maskz_rsqrt_ph(k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_rsqrt_ph(a: __m256h) -> __m256h { _mm256_mask_rsqrt_ph(_mm256_undefined_ph(), 0xffff, a) } @@ -8175,7 +8175,7 @@ pub fn _mm256_rsqrt_ph(a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_rsqrt_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { unsafe { vrsqrtph_256(a, src, k) } } @@ -8189,7 +8189,7 @@ pub fn _mm256_mask_rsqrt_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_rsqrt_ph(k: __mmask16, a: __m256h) -> __m256h { _mm256_mask_rsqrt_ph(_mm256_setzero_ph(), k, a) } @@ -8202,7 +8202,7 @@ pub fn _mm256_maskz_rsqrt_ph(k: __mmask16, a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_rsqrt_ph(a: __m512h) -> __m512h { _mm512_mask_rsqrt_ph(_mm512_undefined_ph(), 0xffffffff, a) } @@ -8216,7 +8216,7 @@ pub fn _mm512_rsqrt_ph(a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_rsqrt_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { unsafe { vrsqrtph_512(a, src, k) } } @@ -8230,7 +8230,7 @@ pub fn _mm512_mask_rsqrt_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_rsqrt_ph(k: __mmask32, a: __m512h) -> __m512h { _mm512_mask_rsqrt_ph(_mm512_setzero_ph(), k, a) } @@ -8244,7 +8244,7 @@ pub fn _mm512_maskz_rsqrt_ph(k: __mmask32, a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrsqrtsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_rsqrt_sh(a: __m128h, b: __m128h) -> __m128h { _mm_mask_rsqrt_sh(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -8258,7 +8258,7 @@ pub fn _mm_rsqrt_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrsqrtsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_rsqrt_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { vrsqrtsh(a, b, src, k) } } @@ -8272,7 +8272,7 @@ pub fn _mm_mask_rsqrt_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrsqrtsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_rsqrt_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_rsqrt_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -8284,7 +8284,7 @@ pub fn _mm_maskz_rsqrt_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_sqrt_ph(a: __m128h) -> __m128h { unsafe { simd_fsqrt(a) } } @@ -8296,7 +8296,7 @@ pub fn _mm_sqrt_ph(a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_sqrt_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_sqrt_ph(a), src) } } @@ -8308,7 +8308,7 @@ pub fn _mm_mask_sqrt_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_sqrt_ph(k: __mmask8, a: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_sqrt_ph(a), _mm_setzero_ph()) } } @@ -8320,7 +8320,7 @@ pub fn _mm_maskz_sqrt_ph(k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_sqrt_ph(a: __m256h) -> __m256h { unsafe { simd_fsqrt(a) } } @@ -8332,7 +8332,7 @@ pub fn _mm256_sqrt_ph(a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_sqrt_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_sqrt_ph(a), src) } } @@ -8344,7 +8344,7 @@ pub fn _mm256_mask_sqrt_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_sqrt_ph(k: __mmask16, a: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_sqrt_ph(a), _mm256_setzero_ph()) } } @@ -8356,7 +8356,7 @@ pub fn _mm256_maskz_sqrt_ph(k: __mmask16, a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_sqrt_ph(a: __m512h) -> __m512h { unsafe { simd_fsqrt(a) } } @@ -8368,7 +8368,7 @@ pub fn _mm512_sqrt_ph(a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_sqrt_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_sqrt_ph(a), src) } } @@ -8380,7 +8380,7 @@ pub fn _mm512_mask_sqrt_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_sqrt_ph(k: __mmask32, a: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_sqrt_ph(a), _mm512_setzero_ph()) } } @@ -8400,7 +8400,7 @@ pub fn _mm512_maskz_sqrt_ph(k: __mmask32, a: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_sqrt_round_ph(a: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -8423,7 +8423,7 @@ pub fn _mm512_sqrt_round_ph(a: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_sqrt_round_ph( src: __m512h, k: __mmask32, @@ -8450,7 +8450,7 @@ pub fn _mm512_mask_sqrt_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_sqrt_round_ph(k: __mmask32, a: __m512h) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -8466,7 +8466,7 @@ pub fn _mm512_maskz_sqrt_round_ph(k: __mmask32, a: __m512h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_sqrt_sh(a: __m128h, b: __m128h) -> __m128h { _mm_mask_sqrt_sh(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -8479,7 +8479,7 @@ pub fn _mm_sqrt_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_sqrt_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_sqrt_round_sh::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -8492,7 +8492,7 @@ pub fn _mm_mask_sqrt_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_sqrt_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_sqrt_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -8513,7 +8513,7 @@ pub fn _mm_maskz_sqrt_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_sqrt_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_sqrt_round_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -8535,7 +8535,7 @@ pub fn _mm_sqrt_round_sh(a: __m128h, b: __m128h) -> __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_sqrt_round_sh( src: __m128h, k: __mmask8, @@ -8564,7 +8564,7 @@ pub fn _mm_mask_sqrt_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vsqrtsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_sqrt_round_sh( k: __mmask8, a: __m128h, @@ -8582,7 +8582,7 @@ pub fn _mm_maskz_sqrt_round_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_max_ph(a: __m128h, b: __m128h) -> __m128h { unsafe { vmaxph_128(a, b) } } @@ -8596,7 +8596,7 @@ pub fn _mm_max_ph(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_max_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_max_ph(a, b), src) } } @@ -8610,7 +8610,7 @@ pub fn _mm_mask_max_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_max_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_max_ph(a, b), _mm_setzero_ph()) } } @@ -8623,7 +8623,7 @@ pub fn _mm_maskz_max_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_max_ph(a: __m256h, b: __m256h) -> __m256h { unsafe { vmaxph_256(a, b) } } @@ -8637,7 +8637,7 @@ pub fn _mm256_max_ph(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_max_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_max_ph(a, b), src) } } @@ -8651,7 +8651,7 @@ pub fn _mm256_mask_max_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_max_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_max_ph(a, b), _mm256_setzero_ph()) } } @@ -8664,7 +8664,7 @@ pub fn _mm256_maskz_max_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_max_ph(a: __m512h, b: __m512h) -> __m512h { _mm512_max_round_ph::<_MM_FROUND_CUR_DIRECTION>(a, b) } @@ -8678,7 +8678,7 @@ pub fn _mm512_max_ph(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_max_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_max_ph(a, b), src) } } @@ -8692,7 +8692,7 @@ pub fn _mm512_mask_max_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmaxph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_max_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_max_ph(a, b), _mm512_setzero_ph()) } } @@ -8707,7 +8707,7 @@ pub fn _mm512_maskz_max_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmaxph, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_max_round_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_sae!(SAE); @@ -8725,7 +8725,7 @@ pub fn _mm512_max_round_ph(a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmaxph, SAE = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_max_round_ph( src: __m512h, k: __mmask32, @@ -8748,7 +8748,7 @@ pub fn _mm512_mask_max_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vmaxph, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_max_round_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_sae!(SAE); @@ -8765,7 +8765,7 @@ pub fn _mm512_maskz_max_round_ph(k: __mmask32, a: __m512h, b: __ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_max_sh(a: __m128h, b: __m128h) -> __m128h { _mm_mask_max_sh(_mm_undefined_ph(), 0xff, a, b) } @@ -8779,7 +8779,7 @@ pub fn _mm_max_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_max_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_max_round_sh::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -8793,7 +8793,7 @@ pub fn _mm_mask_max_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_max_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_max_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -8808,7 +8808,7 @@ pub fn _mm_maskz_max_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxsh, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_max_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_sae!(SAE); _mm_mask_max_round_sh::(_mm_undefined_ph(), 0xff, a, b) @@ -8825,7 +8825,7 @@ pub fn _mm_max_round_sh(a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxsh, SAE = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_max_round_sh( src: __m128h, k: __mmask8, @@ -8849,7 +8849,7 @@ pub fn _mm_mask_max_round_sh( #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vmaxsh, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_max_round_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_sae!(SAE); _mm_mask_max_round_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -8863,7 +8863,7 @@ pub fn _mm_maskz_max_round_sh(k: __mmask8, a: __m128h, b: __m128 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_min_ph(a: __m128h, b: __m128h) -> __m128h { unsafe { vminph_128(a, b) } } @@ -8877,7 +8877,7 @@ pub fn _mm_min_ph(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_min_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_min_ph(a, b), src) } } @@ -8891,7 +8891,7 @@ pub fn _mm_mask_min_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_min_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, _mm_min_ph(a, b), _mm_setzero_ph()) } } @@ -8904,7 +8904,7 @@ pub fn _mm_maskz_min_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_min_ph(a: __m256h, b: __m256h) -> __m256h { unsafe { vminph_256(a, b) } } @@ -8918,7 +8918,7 @@ pub fn _mm256_min_ph(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_min_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_min_ph(a, b), src) } } @@ -8932,7 +8932,7 @@ pub fn _mm256_mask_min_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_min_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_min_ph(a, b), _mm256_setzero_ph()) } } @@ -8945,7 +8945,7 @@ pub fn _mm256_maskz_min_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_min_ph(a: __m512h, b: __m512h) -> __m512h { _mm512_min_round_ph::<_MM_FROUND_CUR_DIRECTION>(a, b) } @@ -8959,7 +8959,7 @@ pub fn _mm512_min_ph(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_min_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_min_ph(a, b), src) } } @@ -8973,7 +8973,7 @@ pub fn _mm512_mask_min_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vminph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_min_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_min_ph(a, b), _mm512_setzero_ph()) } } @@ -8987,7 +8987,7 @@ pub fn _mm512_maskz_min_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vminph, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_min_round_ph(a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_sae!(SAE); @@ -9005,7 +9005,7 @@ pub fn _mm512_min_round_ph(a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vminph, SAE = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_min_round_ph( src: __m512h, k: __mmask32, @@ -9028,7 +9028,7 @@ pub fn _mm512_mask_min_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vminph, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_min_round_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { static_assert_sae!(SAE); @@ -9045,7 +9045,7 @@ pub fn _mm512_maskz_min_round_ph(k: __mmask32, a: __m512h, b: __ #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_min_sh(a: __m128h, b: __m128h) -> __m128h { _mm_mask_min_sh(_mm_undefined_ph(), 0xff, a, b) } @@ -9059,7 +9059,7 @@ pub fn _mm_min_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_min_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_min_round_sh::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -9073,7 +9073,7 @@ pub fn _mm_mask_min_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_min_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_min_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -9088,7 +9088,7 @@ pub fn _mm_maskz_min_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminsh, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_min_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_sae!(SAE); _mm_mask_min_round_sh::(_mm_undefined_ph(), 0xff, a, b) @@ -9105,7 +9105,7 @@ pub fn _mm_min_round_sh(a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminsh, SAE = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_min_round_sh( src: __m128h, k: __mmask8, @@ -9129,7 +9129,7 @@ pub fn _mm_mask_min_round_sh( #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vminsh, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_min_round_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_sae!(SAE); _mm_mask_min_round_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -9143,7 +9143,7 @@ pub fn _mm_maskz_min_round_sh(k: __mmask8, a: __m128h, b: __m128 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_getexp_ph(a: __m128h) -> __m128h { _mm_mask_getexp_ph(_mm_undefined_ph(), 0xff, a) } @@ -9157,7 +9157,7 @@ pub fn _mm_getexp_ph(a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_getexp_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { unsafe { vgetexpph_128(a, src, k) } } @@ -9171,7 +9171,7 @@ pub fn _mm_mask_getexp_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_getexp_ph(k: __mmask8, a: __m128h) -> __m128h { _mm_mask_getexp_ph(_mm_setzero_ph(), k, a) } @@ -9184,7 +9184,7 @@ pub fn _mm_maskz_getexp_ph(k: __mmask8, a: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_getexp_ph(a: __m256h) -> __m256h { _mm256_mask_getexp_ph(_mm256_undefined_ph(), 0xffff, a) } @@ -9198,7 +9198,7 @@ pub fn _mm256_getexp_ph(a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_getexp_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { unsafe { vgetexpph_256(a, src, k) } } @@ -9212,7 +9212,7 @@ pub fn _mm256_mask_getexp_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_getexp_ph(k: __mmask16, a: __m256h) -> __m256h { _mm256_mask_getexp_ph(_mm256_setzero_ph(), k, a) } @@ -9225,7 +9225,7 @@ pub fn _mm256_maskz_getexp_ph(k: __mmask16, a: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_getexp_ph(a: __m512h) -> __m512h { _mm512_mask_getexp_ph(_mm512_undefined_ph(), 0xffffffff, a) } @@ -9239,7 +9239,7 @@ pub fn _mm512_getexp_ph(a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_getexp_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { _mm512_mask_getexp_round_ph::<_MM_FROUND_CUR_DIRECTION>(src, k, a) } @@ -9253,7 +9253,7 @@ pub fn _mm512_mask_getexp_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_getexp_ph(k: __mmask32, a: __m512h) -> __m512h { _mm512_mask_getexp_ph(_mm512_setzero_ph(), k, a) } @@ -9268,7 +9268,7 @@ pub fn _mm512_maskz_getexp_ph(k: __mmask32, a: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpph, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_getexp_round_ph(a: __m512h) -> __m512h { static_assert_sae!(SAE); _mm512_mask_getexp_round_ph::(_mm512_undefined_ph(), 0xffffffff, a) @@ -9284,7 +9284,7 @@ pub fn _mm512_getexp_round_ph(a: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpph, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_getexp_round_ph( src: __m512h, k: __mmask32, @@ -9306,7 +9306,7 @@ pub fn _mm512_mask_getexp_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpph, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_getexp_round_ph(k: __mmask32, a: __m512h) -> __m512h { static_assert_sae!(SAE); _mm512_mask_getexp_round_ph::(_mm512_setzero_ph(), k, a) @@ -9321,7 +9321,7 @@ pub fn _mm512_maskz_getexp_round_ph(k: __mmask32, a: __m512h) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_getexp_sh(a: __m128h, b: __m128h) -> __m128h { _mm_mask_getexp_sh(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -9336,7 +9336,7 @@ pub fn _mm_getexp_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_getexp_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_getexp_round_sh::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -9351,7 +9351,7 @@ pub fn _mm_mask_getexp_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_getexp_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_getexp_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -9367,7 +9367,7 @@ pub fn _mm_maskz_getexp_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpsh, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_getexp_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_sae!(SAE); _mm_mask_getexp_round_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -9384,7 +9384,7 @@ pub fn _mm_getexp_round_sh(a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpsh, SAE = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_getexp_round_sh( src: __m128h, k: __mmask8, @@ -9408,7 +9408,7 @@ pub fn _mm_mask_getexp_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vgetexpsh, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_getexp_round_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_sae!(SAE); _mm_mask_getexp_round_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -9436,7 +9436,7 @@ pub fn _mm_maskz_getexp_round_sh(k: __mmask8, a: __m128h, b: __m #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vgetmantph, NORM = 0, SIGN = 0))] #[rustc_legacy_const_generics(1, 2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_getmant_ph( a: __m128h, ) -> __m128h { @@ -9468,7 +9468,7 @@ pub fn _mm_getmant_ph( a: __m256h, ) -> __m256h { @@ -9574,7 +9574,7 @@ pub fn _mm256_getmant_ph( a: __m512h, ) -> __m512h { @@ -9680,7 +9680,7 @@ pub fn _mm512_getmant_ph( a: __m128h, b: __m128h, @@ -9911,7 +9911,7 @@ pub fn _mm_getmant_sh(a: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_roundscale_ph::(_mm_undefined_ph(), 0xff, a) @@ -10131,7 +10131,7 @@ pub fn _mm_roundscale_ph(a: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_roundscale_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -10156,7 +10156,7 @@ pub fn _mm_mask_roundscale_ph(src: __m128h, k: __mmask8, a: __m #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_roundscale_ph(k: __mmask8, a: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_roundscale_ph::(_mm_setzero_ph(), k, a) @@ -10178,7 +10178,7 @@ pub fn _mm_maskz_roundscale_ph(k: __mmask8, a: __m128h) -> __m1 #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_roundscale_ph(a: __m256h) -> __m256h { static_assert_uimm_bits!(IMM8, 8); _mm256_mask_roundscale_ph::(_mm256_undefined_ph(), 0xffff, a) @@ -10201,7 +10201,7 @@ pub fn _mm256_roundscale_ph(a: __m256h) -> __m256h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_roundscale_ph( src: __m256h, k: __mmask16, @@ -10230,7 +10230,7 @@ pub fn _mm256_mask_roundscale_ph( #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_roundscale_ph(k: __mmask16, a: __m256h) -> __m256h { static_assert_uimm_bits!(IMM8, 8); _mm256_mask_roundscale_ph::(_mm256_setzero_ph(), k, a) @@ -10252,7 +10252,7 @@ pub fn _mm256_maskz_roundscale_ph(k: __mmask16, a: __m256h) -> #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_roundscale_ph(a: __m512h) -> __m512h { static_assert_uimm_bits!(IMM8, 8); _mm512_mask_roundscale_ph::(_mm512_undefined_ph(), 0xffffffff, a) @@ -10275,7 +10275,7 @@ pub fn _mm512_roundscale_ph(a: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_roundscale_ph( src: __m512h, k: __mmask32, @@ -10302,7 +10302,7 @@ pub fn _mm512_mask_roundscale_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_roundscale_ph(k: __mmask32, a: __m512h) -> __m512h { static_assert_uimm_bits!(IMM8, 8); _mm512_mask_roundscale_ph::(_mm512_setzero_ph(), k, a) @@ -10325,7 +10325,7 @@ pub fn _mm512_maskz_roundscale_ph(k: __mmask32, a: __m512h) -> #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(1, 2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_roundscale_round_ph(a: __m512h) -> __m512h { static_assert_uimm_bits!(IMM8, 8); static_assert_sae!(SAE); @@ -10350,7 +10350,7 @@ pub fn _mm512_roundscale_round_ph(a: __m512h) - #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(3, 4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_roundscale_round_ph( src: __m512h, k: __mmask32, @@ -10380,7 +10380,7 @@ pub fn _mm512_mask_roundscale_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscaleph, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(2, 3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_roundscale_round_ph( k: __mmask32, a: __m512h, @@ -10407,7 +10407,7 @@ pub fn _mm512_maskz_roundscale_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscalesh, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_roundscale_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_roundscale_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -10430,7 +10430,7 @@ pub fn _mm_roundscale_sh(a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscalesh, IMM8 = 0))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_roundscale_sh( src: __m128h, k: __mmask8, @@ -10458,7 +10458,7 @@ pub fn _mm_mask_roundscale_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscalesh, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_roundscale_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_roundscale_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -10483,7 +10483,7 @@ pub fn _mm_maskz_roundscale_sh(k: __mmask8, a: __m128h, b: __m1 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscalesh, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(2, 3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_roundscale_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); static_assert_sae!(SAE); @@ -10509,7 +10509,7 @@ pub fn _mm_roundscale_round_sh(a: __m128h, b: _ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscalesh, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(4, 5)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_roundscale_round_sh( src: __m128h, k: __mmask8, @@ -10542,7 +10542,7 @@ pub fn _mm_mask_roundscale_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vrndscalesh, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(3, 4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_roundscale_round_sh( k: __mmask8, a: __m128h, @@ -10560,7 +10560,7 @@ pub fn _mm_maskz_roundscale_round_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_scalef_ph(a: __m128h, b: __m128h) -> __m128h { _mm_mask_scalef_ph(_mm_undefined_ph(), 0xff, a, b) } @@ -10572,7 +10572,7 @@ pub fn _mm_scalef_ph(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_scalef_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { vscalefph_128(a, b, src, k) } } @@ -10584,7 +10584,7 @@ pub fn _mm_mask_scalef_ph(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_scalef_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_scalef_ph(_mm_setzero_ph(), k, a, b) } @@ -10596,7 +10596,7 @@ pub fn _mm_maskz_scalef_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_scalef_ph(a: __m256h, b: __m256h) -> __m256h { _mm256_mask_scalef_ph(_mm256_undefined_ph(), 0xffff, a, b) } @@ -10608,7 +10608,7 @@ pub fn _mm256_scalef_ph(a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_scalef_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { vscalefph_256(a, b, src, k) } } @@ -10620,7 +10620,7 @@ pub fn _mm256_mask_scalef_ph(src: __m256h, k: __mmask16, a: __m256h, b: __m256h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_scalef_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { _mm256_mask_scalef_ph(_mm256_setzero_ph(), k, a, b) } @@ -10632,7 +10632,7 @@ pub fn _mm256_maskz_scalef_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_scalef_ph(a: __m512h, b: __m512h) -> __m512h { _mm512_mask_scalef_ph(_mm512_undefined_ph(), 0xffffffff, a, b) } @@ -10644,7 +10644,7 @@ pub fn _mm512_scalef_ph(a: __m512h, b: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_scalef_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_scalef_round_ph::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -10656,7 +10656,7 @@ pub fn _mm512_mask_scalef_ph(src: __m512h, k: __mmask32, a: __m512h, b: __m512h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_scalef_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { _mm512_mask_scalef_ph(_mm512_setzero_ph(), k, a, b) } @@ -10677,7 +10677,7 @@ pub fn _mm512_maskz_scalef_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_scalef_round_ph(a: __m512h, b: __m512h) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mask_scalef_round_ph::(_mm512_undefined_ph(), 0xffffffff, a, b) @@ -10699,7 +10699,7 @@ pub fn _mm512_scalef_round_ph(a: __m512h, b: __m512h) -> __ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefph, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_scalef_round_ph( src: __m512h, k: __mmask32, @@ -10728,7 +10728,7 @@ pub fn _mm512_mask_scalef_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_scalef_round_ph( k: __mmask32, a: __m512h, @@ -10746,7 +10746,7 @@ pub fn _mm512_maskz_scalef_round_ph( #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_scalef_sh(a: __m128h, b: __m128h) -> __m128h { _mm_mask_scalef_sh(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -10759,7 +10759,7 @@ pub fn _mm_scalef_sh(a: __m128h, b: __m128h) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_scalef_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_scalef_round_sh::<_MM_FROUND_CUR_DIRECTION>(src, k, a, b) } @@ -10772,7 +10772,7 @@ pub fn _mm_mask_scalef_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128h) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefsh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_scalef_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { _mm_mask_scalef_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -10794,7 +10794,7 @@ pub fn _mm_maskz_scalef_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefsh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_scalef_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_scalef_round_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -10817,7 +10817,7 @@ pub fn _mm_scalef_round_sh(a: __m128h, b: __m128h) -> __m12 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefsh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_scalef_round_sh( src: __m128h, k: __mmask8, @@ -10847,7 +10847,7 @@ pub fn _mm_mask_scalef_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vscalefsh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_scalef_round_sh( k: __mmask8, a: __m128h, @@ -10873,7 +10873,7 @@ pub fn _mm_maskz_scalef_round_sh( #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_reduce_ph(a: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_reduce_ph::(_mm_undefined_ph(), 0xff, a) @@ -10896,7 +10896,7 @@ pub fn _mm_reduce_ph(a: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_reduce_ph(src: __m128h, k: __mmask8, a: __m128h) -> __m128h { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -10921,7 +10921,7 @@ pub fn _mm_mask_reduce_ph(src: __m128h, k: __mmask8, a: __m128h #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_reduce_ph(k: __mmask8, a: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_reduce_ph::(_mm_setzero_ph(), k, a) @@ -10943,7 +10943,7 @@ pub fn _mm_maskz_reduce_ph(k: __mmask8, a: __m128h) -> __m128h #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_reduce_ph(a: __m256h) -> __m256h { static_assert_uimm_bits!(IMM8, 8); _mm256_mask_reduce_ph::(_mm256_undefined_ph(), 0xffff, a) @@ -10966,7 +10966,7 @@ pub fn _mm256_reduce_ph(a: __m256h) -> __m256h { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_reduce_ph(src: __m256h, k: __mmask16, a: __m256h) -> __m256h { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -10991,7 +10991,7 @@ pub fn _mm256_mask_reduce_ph(src: __m256h, k: __mmask16, a: __m #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_reduce_ph(k: __mmask16, a: __m256h) -> __m256h { static_assert_uimm_bits!(IMM8, 8); _mm256_mask_reduce_ph::(_mm256_setzero_ph(), k, a) @@ -11013,7 +11013,7 @@ pub fn _mm256_maskz_reduce_ph(k: __mmask16, a: __m256h) -> __m2 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_reduce_ph(a: __m512h) -> __m512h { static_assert_uimm_bits!(IMM8, 8); _mm512_mask_reduce_ph::(_mm512_undefined_ph(), 0xffffffff, a) @@ -11036,7 +11036,7 @@ pub fn _mm512_reduce_ph(a: __m512h) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_reduce_ph(src: __m512h, k: __mmask32, a: __m512h) -> __m512h { static_assert_uimm_bits!(IMM8, 8); _mm512_mask_reduce_round_ph::(src, k, a) @@ -11059,7 +11059,7 @@ pub fn _mm512_mask_reduce_ph(src: __m512h, k: __mmask32, a: __m #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_reduce_ph(k: __mmask32, a: __m512h) -> __m512h { static_assert_uimm_bits!(IMM8, 8); _mm512_mask_reduce_ph::(_mm512_setzero_ph(), k, a) @@ -11083,7 +11083,7 @@ pub fn _mm512_maskz_reduce_ph(k: __mmask32, a: __m512h) -> __m5 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(1, 2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_reduce_round_ph(a: __m512h) -> __m512h { static_assert_uimm_bits!(IMM8, 8); static_assert_sae!(SAE); @@ -11109,7 +11109,7 @@ pub fn _mm512_reduce_round_ph(a: __m512h) -> __ #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(3, 4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_reduce_round_ph( src: __m512h, k: __mmask32, @@ -11141,7 +11141,7 @@ pub fn _mm512_mask_reduce_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreduceph, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(2, 3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_reduce_round_ph( k: __mmask32, a: __m512h, @@ -11168,7 +11168,7 @@ pub fn _mm512_maskz_reduce_round_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreducesh, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_reduce_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_reduce_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -11192,7 +11192,7 @@ pub fn _mm_reduce_sh(a: __m128h, b: __m128h) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreducesh, IMM8 = 0))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_reduce_sh( src: __m128h, k: __mmask8, @@ -11221,7 +11221,7 @@ pub fn _mm_mask_reduce_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreducesh, IMM8 = 0))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_reduce_sh(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); _mm_mask_reduce_sh::(f16x8::ZERO.as_m128h(), k, a, b) @@ -11246,7 +11246,7 @@ pub fn _mm_maskz_reduce_sh(k: __mmask8, a: __m128h, b: __m128h) #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreducesh, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(2, 3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_reduce_round_sh(a: __m128h, b: __m128h) -> __m128h { static_assert_uimm_bits!(IMM8, 8); static_assert_sae!(SAE); @@ -11273,7 +11273,7 @@ pub fn _mm_reduce_round_sh(a: __m128h, b: __m12 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreducesh, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(4, 5)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_reduce_round_sh( src: __m128h, k: __mmask8, @@ -11307,7 +11307,7 @@ pub fn _mm_mask_reduce_round_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vreducesh, IMM8 = 0, SAE = 8))] #[rustc_legacy_const_generics(3, 4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_reduce_round_sh( k: __mmask8, a: __m128h, @@ -11582,7 +11582,7 @@ macro_rules! fpclass_asm { // FIXME: use LLVM intrinsics #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfpclassph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fpclass_ph_mask(a: __m128h) -> __mmask8 { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -11609,7 +11609,7 @@ pub fn _mm_fpclass_ph_mask(a: __m128h) -> __mmask8 { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfpclassph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fpclass_ph_mask(k1: __mmask8, a: __m128h) -> __mmask8 { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -11635,7 +11635,7 @@ pub fn _mm_mask_fpclass_ph_mask(k1: __mmask8, a: __m128h) -> __ #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfpclassph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_fpclass_ph_mask(a: __m256h) -> __mmask16 { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -11662,7 +11662,7 @@ pub fn _mm256_fpclass_ph_mask(a: __m256h) -> __mmask16 { #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vfpclassph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_fpclass_ph_mask(k1: __mmask16, a: __m256h) -> __mmask16 { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -11688,7 +11688,7 @@ pub fn _mm256_mask_fpclass_ph_mask(k1: __mmask16, a: __m256h) - #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfpclassph, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_fpclass_ph_mask(a: __m512h) -> __mmask32 { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -11715,7 +11715,7 @@ pub fn _mm512_fpclass_ph_mask(a: __m512h) -> __mmask32 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfpclassph, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_fpclass_ph_mask(k1: __mmask32, a: __m512h) -> __mmask32 { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -11741,7 +11741,7 @@ pub fn _mm512_mask_fpclass_ph_mask(k1: __mmask32, a: __m512h) - #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfpclasssh, IMM8 = 0))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_fpclass_sh_mask(a: __m128h) -> __mmask8 { _mm_mask_fpclass_sh_mask::(0xff, a) } @@ -11765,7 +11765,7 @@ pub fn _mm_fpclass_sh_mask(a: __m128h) -> __mmask8 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vfpclasssh, IMM8 = 0))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_fpclass_sh_mask(k1: __mmask8, a: __m128h) -> __mmask8 { unsafe { static_assert_uimm_bits!(IMM8, 8); @@ -11779,7 +11779,7 @@ pub fn _mm_mask_fpclass_sh_mask(k1: __mmask8, a: __m128h) -> __ /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_blend_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_blend_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { unsafe { simd_select_bitmask(k, b, a) } @@ -11791,7 +11791,7 @@ pub const fn _mm_mask_blend_ph(k: __mmask8, a: __m128h, b: __m128h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_blend_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_blend_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m256h { unsafe { simd_select_bitmask(k, b, a) } @@ -11803,7 +11803,7 @@ pub const fn _mm256_mask_blend_ph(k: __mmask16, a: __m256h, b: __m256h) -> __m25 /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_blend_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm512_mask_blend_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m512h { unsafe { simd_select_bitmask(k, b, a) } @@ -11815,7 +11815,7 @@ pub const fn _mm512_mask_blend_ph(k: __mmask32, a: __m512h, b: __m512h) -> __m51 /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_permutex2var_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_permutex2var_ph(a: __m128h, idx: __m128i, b: __m128h) -> __m128h { _mm_castsi128_ph(_mm_permutex2var_epi16( _mm_castph_si128(a), @@ -11830,7 +11830,7 @@ pub fn _mm_permutex2var_ph(a: __m128h, idx: __m128i, b: __m128h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutex2var_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_permutex2var_ph(a: __m256h, idx: __m256i, b: __m256h) -> __m256h { _mm256_castsi256_ph(_mm256_permutex2var_epi16( _mm256_castph_si256(a), @@ -11845,7 +11845,7 @@ pub fn _mm256_permutex2var_ph(a: __m256h, idx: __m256i, b: __m256h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex2var_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_permutex2var_ph(a: __m512h, idx: __m512i, b: __m512h) -> __m512h { _mm512_castsi512_ph(_mm512_permutex2var_epi16( _mm512_castph_si512(a), @@ -11860,7 +11860,7 @@ pub fn _mm512_permutex2var_ph(a: __m512h, idx: __m512i, b: __m512h) -> __m512h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_permutexvar_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_permutexvar_ph(idx: __m128i, a: __m128h) -> __m128h { _mm_castsi128_ph(_mm_permutexvar_epi16(idx, _mm_castph_si128(a))) } @@ -11871,7 +11871,7 @@ pub fn _mm_permutexvar_ph(idx: __m128i, a: __m128h) -> __m128h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutexvar_ph) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_permutexvar_ph(idx: __m256i, a: __m256h) -> __m256h { _mm256_castsi256_ph(_mm256_permutexvar_epi16(idx, _mm256_castph_si256(a))) } @@ -11882,7 +11882,7 @@ pub fn _mm256_permutexvar_ph(idx: __m256i, a: __m256h) -> __m256h { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutexvar_ph) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_permutexvar_ph(idx: __m512i, a: __m512h) -> __m512h { _mm512_castsi512_ph(_mm512_permutexvar_epi16(idx, _mm512_castph_si512(a))) } @@ -11894,7 +11894,7 @@ pub fn _mm512_permutexvar_ph(idx: __m512i, a: __m512h) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtepi16_ph(a: __m128i) -> __m128h { unsafe { vcvtw2ph_128(a.as_i16x8(), _MM_FROUND_CUR_DIRECTION) } } @@ -11907,7 +11907,7 @@ pub fn _mm_cvtepi16_ph(a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtepi16_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { unsafe { simd_select_bitmask(k, _mm_cvtepi16_ph(a), src) } } @@ -11919,7 +11919,7 @@ pub fn _mm_mask_cvtepi16_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtepi16_ph(k: __mmask8, a: __m128i) -> __m128h { _mm_mask_cvtepi16_ph(_mm_setzero_ph(), k, a) } @@ -11931,7 +11931,7 @@ pub fn _mm_maskz_cvtepi16_ph(k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtepi16_ph(a: __m256i) -> __m256h { unsafe { vcvtw2ph_256(a.as_i16x16(), _MM_FROUND_CUR_DIRECTION) } } @@ -11944,7 +11944,7 @@ pub fn _mm256_cvtepi16_ph(a: __m256i) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtepi16_ph(src: __m256h, k: __mmask16, a: __m256i) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_cvtepi16_ph(a), src) } } @@ -11956,7 +11956,7 @@ pub fn _mm256_mask_cvtepi16_ph(src: __m256h, k: __mmask16, a: __m256i) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtepi16_ph(k: __mmask16, a: __m256i) -> __m256h { _mm256_mask_cvtepi16_ph(_mm256_setzero_ph(), k, a) } @@ -11968,7 +11968,7 @@ pub fn _mm256_maskz_cvtepi16_ph(k: __mmask16, a: __m256i) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtepi16_ph(a: __m512i) -> __m512h { unsafe { vcvtw2ph_512(a.as_i16x32(), _MM_FROUND_CUR_DIRECTION) } } @@ -11981,7 +11981,7 @@ pub fn _mm512_cvtepi16_ph(a: __m512i) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtepi16_ph(src: __m512h, k: __mmask32, a: __m512i) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_cvtepi16_ph(a), src) } } @@ -11993,7 +11993,7 @@ pub fn _mm512_mask_cvtepi16_ph(src: __m512h, k: __mmask32, a: __m512i) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtepi16_ph(k: __mmask32, a: __m512i) -> __m512h { _mm512_mask_cvtepi16_ph(_mm512_setzero_ph(), k, a) } @@ -12014,7 +12014,7 @@ pub fn _mm512_maskz_cvtepi16_ph(k: __mmask32, a: __m512i) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtw2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundepi16_ph(a: __m512i) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -12039,7 +12039,7 @@ pub fn _mm512_cvt_roundepi16_ph(a: __m512i) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtw2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundepi16_ph( src: __m512h, k: __mmask32, @@ -12067,7 +12067,7 @@ pub fn _mm512_mask_cvt_roundepi16_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtw2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundepi16_ph(k: __mmask32, a: __m512i) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundepi16_ph::(_mm512_setzero_ph(), k, a) @@ -12080,7 +12080,7 @@ pub fn _mm512_maskz_cvt_roundepi16_ph(k: __mmask32, a: __m5 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtepu16_ph(a: __m128i) -> __m128h { unsafe { vcvtuw2ph_128(a.as_u16x8(), _MM_FROUND_CUR_DIRECTION) } } @@ -12093,7 +12093,7 @@ pub fn _mm_cvtepu16_ph(a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtepu16_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { unsafe { simd_select_bitmask(k, _mm_cvtepu16_ph(a), src) } } @@ -12105,7 +12105,7 @@ pub fn _mm_mask_cvtepu16_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtepu16_ph(k: __mmask8, a: __m128i) -> __m128h { _mm_mask_cvtepu16_ph(_mm_setzero_ph(), k, a) } @@ -12117,7 +12117,7 @@ pub fn _mm_maskz_cvtepu16_ph(k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtepu16_ph(a: __m256i) -> __m256h { unsafe { vcvtuw2ph_256(a.as_u16x16(), _MM_FROUND_CUR_DIRECTION) } } @@ -12130,7 +12130,7 @@ pub fn _mm256_cvtepu16_ph(a: __m256i) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtepu16_ph(src: __m256h, k: __mmask16, a: __m256i) -> __m256h { unsafe { simd_select_bitmask(k, _mm256_cvtepu16_ph(a), src) } } @@ -12142,7 +12142,7 @@ pub fn _mm256_mask_cvtepu16_ph(src: __m256h, k: __mmask16, a: __m256i) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtepu16_ph(k: __mmask16, a: __m256i) -> __m256h { _mm256_mask_cvtepu16_ph(_mm256_setzero_ph(), k, a) } @@ -12154,7 +12154,7 @@ pub fn _mm256_maskz_cvtepu16_ph(k: __mmask16, a: __m256i) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtepu16_ph(a: __m512i) -> __m512h { unsafe { vcvtuw2ph_512(a.as_u16x32(), _MM_FROUND_CUR_DIRECTION) } } @@ -12167,7 +12167,7 @@ pub fn _mm512_cvtepu16_ph(a: __m512i) -> __m512h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtepu16_ph(src: __m512h, k: __mmask32, a: __m512i) -> __m512h { unsafe { simd_select_bitmask(k, _mm512_cvtepu16_ph(a), src) } } @@ -12179,7 +12179,7 @@ pub fn _mm512_mask_cvtepu16_ph(src: __m512h, k: __mmask32, a: __m512i) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuw2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtepu16_ph(k: __mmask32, a: __m512i) -> __m512h { _mm512_mask_cvtepu16_ph(_mm512_setzero_ph(), k, a) } @@ -12200,7 +12200,7 @@ pub fn _mm512_maskz_cvtepu16_ph(k: __mmask32, a: __m512i) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuw2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundepu16_ph(a: __m512i) -> __m512h { unsafe { static_assert_rounding!(ROUNDING); @@ -12225,7 +12225,7 @@ pub fn _mm512_cvt_roundepu16_ph(a: __m512i) -> __m512h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuw2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundepu16_ph( src: __m512h, k: __mmask32, @@ -12253,7 +12253,7 @@ pub fn _mm512_mask_cvt_roundepu16_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuw2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundepu16_ph(k: __mmask32, a: __m512i) -> __m512h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundepu16_ph::(_mm512_setzero_ph(), k, a) @@ -12266,7 +12266,7 @@ pub fn _mm512_maskz_cvt_roundepu16_ph(k: __mmask32, a: __m5 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtepi32_ph(a: __m128i) -> __m128h { _mm_mask_cvtepi32_ph(_mm_setzero_ph(), 0xff, a) } @@ -12279,7 +12279,7 @@ pub fn _mm_cvtepi32_ph(a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtepi32_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { unsafe { vcvtdq2ph_128(a.as_i32x4(), src, k) } } @@ -12292,7 +12292,7 @@ pub fn _mm_mask_cvtepi32_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtepi32_ph(k: __mmask8, a: __m128i) -> __m128h { _mm_mask_cvtepi32_ph(_mm_setzero_ph(), k, a) } @@ -12304,7 +12304,7 @@ pub fn _mm_maskz_cvtepi32_ph(k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtepi32_ph(a: __m256i) -> __m128h { unsafe { vcvtdq2ph_256(a.as_i32x8(), _MM_FROUND_CUR_DIRECTION) } } @@ -12317,7 +12317,7 @@ pub fn _mm256_cvtepi32_ph(a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtepi32_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h { unsafe { simd_select_bitmask(k, _mm256_cvtepi32_ph(a), src) } } @@ -12329,7 +12329,7 @@ pub fn _mm256_mask_cvtepi32_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtepi32_ph(k: __mmask8, a: __m256i) -> __m128h { _mm256_mask_cvtepi32_ph(_mm_setzero_ph(), k, a) } @@ -12341,7 +12341,7 @@ pub fn _mm256_maskz_cvtepi32_ph(k: __mmask8, a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtepi32_ph(a: __m512i) -> __m256h { unsafe { vcvtdq2ph_512(a.as_i32x16(), _MM_FROUND_CUR_DIRECTION) } } @@ -12354,7 +12354,7 @@ pub fn _mm512_cvtepi32_ph(a: __m512i) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtepi32_ph(src: __m256h, k: __mmask16, a: __m512i) -> __m256h { unsafe { simd_select_bitmask(k, _mm512_cvtepi32_ph(a), src) } } @@ -12366,7 +12366,7 @@ pub fn _mm512_mask_cvtepi32_ph(src: __m256h, k: __mmask16, a: __m512i) -> __m256 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtdq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtepi32_ph(k: __mmask16, a: __m512i) -> __m256h { _mm512_mask_cvtepi32_ph(f16x16::ZERO.as_m256h(), k, a) } @@ -12387,7 +12387,7 @@ pub fn _mm512_maskz_cvtepi32_ph(k: __mmask16, a: __m512i) -> __m256h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtdq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundepi32_ph(a: __m512i) -> __m256h { unsafe { static_assert_rounding!(ROUNDING); @@ -12412,7 +12412,7 @@ pub fn _mm512_cvt_roundepi32_ph(a: __m512i) -> __m256h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtdq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundepi32_ph( src: __m256h, k: __mmask16, @@ -12440,7 +12440,7 @@ pub fn _mm512_mask_cvt_roundepi32_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtdq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundepi32_ph(k: __mmask16, a: __m512i) -> __m256h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundepi32_ph::(f16x16::ZERO.as_m256h(), k, a) @@ -12454,7 +12454,7 @@ pub fn _mm512_maskz_cvt_roundepi32_ph(k: __mmask16, a: __m5 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsi2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvti32_sh(a: __m128h, b: i32) -> __m128h { unsafe { vcvtsi2sh(a, b, _MM_FROUND_CUR_DIRECTION) } } @@ -12476,7 +12476,7 @@ pub fn _mm_cvti32_sh(a: __m128h, b: i32) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsi2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundi32_sh(a: __m128h, b: i32) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -12491,7 +12491,7 @@ pub fn _mm_cvt_roundi32_sh(a: __m128h, b: i32) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtepu32_ph(a: __m128i) -> __m128h { _mm_mask_cvtepu32_ph(_mm_setzero_ph(), 0xff, a) } @@ -12504,7 +12504,7 @@ pub fn _mm_cvtepu32_ph(a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtepu32_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { unsafe { vcvtudq2ph_128(a.as_u32x4(), src, k) } } @@ -12517,7 +12517,7 @@ pub fn _mm_mask_cvtepu32_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtepu32_ph(k: __mmask8, a: __m128i) -> __m128h { _mm_mask_cvtepu32_ph(_mm_setzero_ph(), k, a) } @@ -12529,7 +12529,7 @@ pub fn _mm_maskz_cvtepu32_ph(k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtepu32_ph(a: __m256i) -> __m128h { unsafe { vcvtudq2ph_256(a.as_u32x8(), _MM_FROUND_CUR_DIRECTION) } } @@ -12542,7 +12542,7 @@ pub fn _mm256_cvtepu32_ph(a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtepu32_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h { unsafe { simd_select_bitmask(k, _mm256_cvtepu32_ph(a), src) } } @@ -12554,7 +12554,7 @@ pub fn _mm256_mask_cvtepu32_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtepu32_ph(k: __mmask8, a: __m256i) -> __m128h { _mm256_mask_cvtepu32_ph(_mm_setzero_ph(), k, a) } @@ -12566,7 +12566,7 @@ pub fn _mm256_maskz_cvtepu32_ph(k: __mmask8, a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtepu32_ph(a: __m512i) -> __m256h { unsafe { vcvtudq2ph_512(a.as_u32x16(), _MM_FROUND_CUR_DIRECTION) } } @@ -12579,7 +12579,7 @@ pub fn _mm512_cvtepu32_ph(a: __m512i) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtepu32_ph(src: __m256h, k: __mmask16, a: __m512i) -> __m256h { unsafe { simd_select_bitmask(k, _mm512_cvtepu32_ph(a), src) } } @@ -12591,7 +12591,7 @@ pub fn _mm512_mask_cvtepu32_ph(src: __m256h, k: __mmask16, a: __m512i) -> __m256 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtudq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtepu32_ph(k: __mmask16, a: __m512i) -> __m256h { _mm512_mask_cvtepu32_ph(f16x16::ZERO.as_m256h(), k, a) } @@ -12612,7 +12612,7 @@ pub fn _mm512_maskz_cvtepu32_ph(k: __mmask16, a: __m512i) -> __m256h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtudq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundepu32_ph(a: __m512i) -> __m256h { unsafe { static_assert_rounding!(ROUNDING); @@ -12637,7 +12637,7 @@ pub fn _mm512_cvt_roundepu32_ph(a: __m512i) -> __m256h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtudq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundepu32_ph( src: __m256h, k: __mmask16, @@ -12665,7 +12665,7 @@ pub fn _mm512_mask_cvt_roundepu32_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtudq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundepu32_ph(k: __mmask16, a: __m512i) -> __m256h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundepu32_ph::(f16x16::ZERO.as_m256h(), k, a) @@ -12679,7 +12679,7 @@ pub fn _mm512_maskz_cvt_roundepu32_ph(k: __mmask16, a: __m5 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtusi2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtu32_sh(a: __m128h, b: u32) -> __m128h { unsafe { vcvtusi2sh(a, b, _MM_FROUND_CUR_DIRECTION) } } @@ -12701,7 +12701,7 @@ pub fn _mm_cvtu32_sh(a: __m128h, b: u32) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtusi2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundu32_sh(a: __m128h, b: u32) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -12716,7 +12716,7 @@ pub fn _mm_cvt_roundu32_sh(a: __m128h, b: u32) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtepi64_ph(a: __m128i) -> __m128h { _mm_mask_cvtepi64_ph(_mm_setzero_ph(), 0xff, a) } @@ -12729,7 +12729,7 @@ pub fn _mm_cvtepi64_ph(a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtepi64_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { unsafe { vcvtqq2ph_128(a.as_i64x2(), src, k) } } @@ -12742,7 +12742,7 @@ pub fn _mm_mask_cvtepi64_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtepi64_ph(k: __mmask8, a: __m128i) -> __m128h { _mm_mask_cvtepi64_ph(_mm_setzero_ph(), k, a) } @@ -12754,7 +12754,7 @@ pub fn _mm_maskz_cvtepi64_ph(k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtepi64_ph(a: __m256i) -> __m128h { _mm256_mask_cvtepi64_ph(_mm_setzero_ph(), 0xff, a) } @@ -12767,7 +12767,7 @@ pub fn _mm256_cvtepi64_ph(a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtepi64_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h { unsafe { vcvtqq2ph_256(a.as_i64x4(), src, k) } } @@ -12780,7 +12780,7 @@ pub fn _mm256_mask_cvtepi64_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtepi64_ph(k: __mmask8, a: __m256i) -> __m128h { _mm256_mask_cvtepi64_ph(_mm_setzero_ph(), k, a) } @@ -12792,7 +12792,7 @@ pub fn _mm256_maskz_cvtepi64_ph(k: __mmask8, a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtepi64_ph(a: __m512i) -> __m128h { unsafe { vcvtqq2ph_512(a.as_i64x8(), _MM_FROUND_CUR_DIRECTION) } } @@ -12805,7 +12805,7 @@ pub fn _mm512_cvtepi64_ph(a: __m512i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtepi64_ph(src: __m128h, k: __mmask8, a: __m512i) -> __m128h { unsafe { simd_select_bitmask(k, _mm512_cvtepi64_ph(a), src) } } @@ -12817,7 +12817,7 @@ pub fn _mm512_mask_cvtepi64_ph(src: __m128h, k: __mmask8, a: __m512i) -> __m128h #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtepi64_ph(k: __mmask8, a: __m512i) -> __m128h { _mm512_mask_cvtepi64_ph(f16x8::ZERO.as_m128h(), k, a) } @@ -12838,7 +12838,7 @@ pub fn _mm512_maskz_cvtepi64_ph(k: __mmask8, a: __m512i) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtqq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundepi64_ph(a: __m512i) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -12863,7 +12863,7 @@ pub fn _mm512_cvt_roundepi64_ph(a: __m512i) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtqq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundepi64_ph( src: __m128h, k: __mmask8, @@ -12891,7 +12891,7 @@ pub fn _mm512_mask_cvt_roundepi64_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtqq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundepi64_ph(k: __mmask8, a: __m512i) -> __m128h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundepi64_ph::(f16x8::ZERO.as_m128h(), k, a) @@ -12904,7 +12904,7 @@ pub fn _mm512_maskz_cvt_roundepi64_ph(k: __mmask8, a: __m51 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtepu64_ph(a: __m128i) -> __m128h { _mm_mask_cvtepu64_ph(_mm_setzero_ph(), 0xff, a) } @@ -12917,7 +12917,7 @@ pub fn _mm_cvtepu64_ph(a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtepu64_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { unsafe { vcvtuqq2ph_128(a.as_u64x2(), src, k) } } @@ -12930,7 +12930,7 @@ pub fn _mm_mask_cvtepu64_ph(src: __m128h, k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtepu64_ph(k: __mmask8, a: __m128i) -> __m128h { _mm_mask_cvtepu64_ph(_mm_setzero_ph(), k, a) } @@ -12942,7 +12942,7 @@ pub fn _mm_maskz_cvtepu64_ph(k: __mmask8, a: __m128i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtepu64_ph(a: __m256i) -> __m128h { _mm256_mask_cvtepu64_ph(_mm_setzero_ph(), 0xff, a) } @@ -12955,7 +12955,7 @@ pub fn _mm256_cvtepu64_ph(a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtepu64_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h { unsafe { vcvtuqq2ph_256(a.as_u64x4(), src, k) } } @@ -12968,7 +12968,7 @@ pub fn _mm256_mask_cvtepu64_ph(src: __m128h, k: __mmask8, a: __m256i) -> __m128h #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtepu64_ph(k: __mmask8, a: __m256i) -> __m128h { _mm256_mask_cvtepu64_ph(_mm_setzero_ph(), k, a) } @@ -12980,7 +12980,7 @@ pub fn _mm256_maskz_cvtepu64_ph(k: __mmask8, a: __m256i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtepu64_ph(a: __m512i) -> __m128h { unsafe { vcvtuqq2ph_512(a.as_u64x8(), _MM_FROUND_CUR_DIRECTION) } } @@ -12993,7 +12993,7 @@ pub fn _mm512_cvtepu64_ph(a: __m512i) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtepu64_ph(src: __m128h, k: __mmask8, a: __m512i) -> __m128h { unsafe { simd_select_bitmask(k, _mm512_cvtepu64_ph(a), src) } } @@ -13005,7 +13005,7 @@ pub fn _mm512_mask_cvtepu64_ph(src: __m128h, k: __mmask8, a: __m512i) -> __m128h #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuqq2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtepu64_ph(k: __mmask8, a: __m512i) -> __m128h { _mm512_mask_cvtepu64_ph(f16x8::ZERO.as_m128h(), k, a) } @@ -13026,7 +13026,7 @@ pub fn _mm512_maskz_cvtepu64_ph(k: __mmask8, a: __m512i) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuqq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundepu64_ph(a: __m512i) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -13051,7 +13051,7 @@ pub fn _mm512_cvt_roundepu64_ph(a: __m512i) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuqq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundepu64_ph( src: __m128h, k: __mmask8, @@ -13079,7 +13079,7 @@ pub fn _mm512_mask_cvt_roundepu64_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtuqq2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundepu64_ph(k: __mmask8, a: __m512i) -> __m128h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundepu64_ph::(f16x8::ZERO.as_m128h(), k, a) @@ -13092,7 +13092,7 @@ pub fn _mm512_maskz_cvt_roundepu64_ph(k: __mmask8, a: __m51 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtxps_ph(a: __m128) -> __m128h { _mm_mask_cvtxps_ph(_mm_setzero_ph(), 0xff, a) } @@ -13105,7 +13105,7 @@ pub fn _mm_cvtxps_ph(a: __m128) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtxps_ph(src: __m128h, k: __mmask8, a: __m128) -> __m128h { unsafe { vcvtps2phx_128(a, src, k) } } @@ -13118,7 +13118,7 @@ pub fn _mm_mask_cvtxps_ph(src: __m128h, k: __mmask8, a: __m128) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtxps_ph(k: __mmask8, a: __m128) -> __m128h { _mm_mask_cvtxps_ph(_mm_setzero_ph(), k, a) } @@ -13130,7 +13130,7 @@ pub fn _mm_maskz_cvtxps_ph(k: __mmask8, a: __m128) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtxps_ph(a: __m256) -> __m128h { _mm256_mask_cvtxps_ph(_mm_setzero_ph(), 0xff, a) } @@ -13143,7 +13143,7 @@ pub fn _mm256_cvtxps_ph(a: __m256) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtxps_ph(src: __m128h, k: __mmask8, a: __m256) -> __m128h { unsafe { vcvtps2phx_256(a, src, k) } } @@ -13156,7 +13156,7 @@ pub fn _mm256_mask_cvtxps_ph(src: __m128h, k: __mmask8, a: __m256) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtxps_ph(k: __mmask8, a: __m256) -> __m128h { _mm256_mask_cvtxps_ph(_mm_setzero_ph(), k, a) } @@ -13168,7 +13168,7 @@ pub fn _mm256_maskz_cvtxps_ph(k: __mmask8, a: __m256) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtxps_ph(a: __m512) -> __m256h { _mm512_mask_cvtxps_ph(f16x16::ZERO.as_m256h(), 0xffff, a) } @@ -13181,7 +13181,7 @@ pub fn _mm512_cvtxps_ph(a: __m512) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtxps_ph(src: __m256h, k: __mmask16, a: __m512) -> __m256h { unsafe { vcvtps2phx_512(a, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -13194,7 +13194,7 @@ pub fn _mm512_mask_cvtxps_ph(src: __m256h, k: __mmask16, a: __m512) -> __m256h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtps2phx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtxps_ph(k: __mmask16, a: __m512) -> __m256h { _mm512_mask_cvtxps_ph(f16x16::ZERO.as_m256h(), k, a) } @@ -13215,7 +13215,7 @@ pub fn _mm512_maskz_cvtxps_ph(k: __mmask16, a: __m512) -> __m256h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtps2phx, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtx_roundps_ph(a: __m512) -> __m256h { static_assert_rounding!(ROUNDING); _mm512_mask_cvtx_roundps_ph::(f16x16::ZERO.as_m256h(), 0xffff, a) @@ -13238,7 +13238,7 @@ pub fn _mm512_cvtx_roundps_ph(a: __m512) -> __m256h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtps2phx, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtx_roundps_ph( src: __m256h, k: __mmask16, @@ -13267,7 +13267,7 @@ pub fn _mm512_mask_cvtx_roundps_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtps2phx, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtx_roundps_ph(k: __mmask16, a: __m512) -> __m256h { static_assert_rounding!(ROUNDING); _mm512_mask_cvtx_roundps_ph::(f16x16::ZERO.as_m256h(), k, a) @@ -13281,7 +13281,7 @@ pub fn _mm512_maskz_cvtx_roundps_ph(k: __mmask16, a: __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtss2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtss_sh(a: __m128h, b: __m128) -> __m128h { _mm_mask_cvtss_sh(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -13295,7 +13295,7 @@ pub fn _mm_cvtss_sh(a: __m128h, b: __m128) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtss2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtss_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128) -> __m128h { unsafe { vcvtss2sh(a, b, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -13309,7 +13309,7 @@ pub fn _mm_mask_cvtss_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128) -> __ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtss2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtss_sh(k: __mmask8, a: __m128h, b: __m128) -> __m128h { _mm_mask_cvtss_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -13331,7 +13331,7 @@ pub fn _mm_maskz_cvtss_sh(k: __mmask8, a: __m128h, b: __m128) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtss2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundss_sh(a: __m128h, b: __m128) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_cvt_roundss_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -13355,7 +13355,7 @@ pub fn _mm_cvt_roundss_sh(a: __m128h, b: __m128) -> __m128h #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtss2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvt_roundss_sh( src: __m128h, k: __mmask8, @@ -13386,7 +13386,7 @@ pub fn _mm_mask_cvt_roundss_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtss2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvt_roundss_sh( k: __mmask8, a: __m128h, @@ -13403,7 +13403,7 @@ pub fn _mm_maskz_cvt_roundss_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtpd_ph(a: __m128d) -> __m128h { _mm_mask_cvtpd_ph(_mm_setzero_ph(), 0xff, a) } @@ -13416,7 +13416,7 @@ pub fn _mm_cvtpd_ph(a: __m128d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtpd_ph(src: __m128h, k: __mmask8, a: __m128d) -> __m128h { unsafe { vcvtpd2ph_128(a, src, k) } } @@ -13429,7 +13429,7 @@ pub fn _mm_mask_cvtpd_ph(src: __m128h, k: __mmask8, a: __m128d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtpd_ph(k: __mmask8, a: __m128d) -> __m128h { _mm_mask_cvtpd_ph(_mm_setzero_ph(), k, a) } @@ -13441,7 +13441,7 @@ pub fn _mm_maskz_cvtpd_ph(k: __mmask8, a: __m128d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtpd_ph(a: __m256d) -> __m128h { _mm256_mask_cvtpd_ph(_mm_setzero_ph(), 0xff, a) } @@ -13454,7 +13454,7 @@ pub fn _mm256_cvtpd_ph(a: __m256d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtpd_ph(src: __m128h, k: __mmask8, a: __m256d) -> __m128h { unsafe { vcvtpd2ph_256(a, src, k) } } @@ -13467,7 +13467,7 @@ pub fn _mm256_mask_cvtpd_ph(src: __m128h, k: __mmask8, a: __m256d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtpd_ph(k: __mmask8, a: __m256d) -> __m128h { _mm256_mask_cvtpd_ph(_mm_setzero_ph(), k, a) } @@ -13479,7 +13479,7 @@ pub fn _mm256_maskz_cvtpd_ph(k: __mmask8, a: __m256d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtpd_ph(a: __m512d) -> __m128h { _mm512_mask_cvtpd_ph(f16x8::ZERO.as_m128h(), 0xff, a) } @@ -13492,7 +13492,7 @@ pub fn _mm512_cvtpd_ph(a: __m512d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtpd_ph(src: __m128h, k: __mmask8, a: __m512d) -> __m128h { unsafe { vcvtpd2ph_512(a, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -13505,7 +13505,7 @@ pub fn _mm512_mask_cvtpd_ph(src: __m128h, k: __mmask8, a: __m512d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtpd2ph))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtpd_ph(k: __mmask8, a: __m512d) -> __m128h { _mm512_mask_cvtpd_ph(f16x8::ZERO.as_m128h(), k, a) } @@ -13526,7 +13526,7 @@ pub fn _mm512_maskz_cvtpd_ph(k: __mmask8, a: __m512d) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtpd2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundpd_ph(a: __m512d) -> __m128h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundpd_ph::(f16x8::ZERO.as_m128h(), 0xff, a) @@ -13549,7 +13549,7 @@ pub fn _mm512_cvt_roundpd_ph(a: __m512d) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtpd2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundpd_ph( src: __m128h, k: __mmask8, @@ -13578,7 +13578,7 @@ pub fn _mm512_mask_cvt_roundpd_ph( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtpd2ph, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundpd_ph(k: __mmask8, a: __m512d) -> __m128h { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundpd_ph::(f16x8::ZERO.as_m128h(), k, a) @@ -13592,7 +13592,7 @@ pub fn _mm512_maskz_cvt_roundpd_ph(k: __mmask8, a: __m512d) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsd2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtsd_sh(a: __m128h, b: __m128d) -> __m128h { _mm_mask_cvtsd_sh(f16x8::ZERO.as_m128h(), 0xff, a, b) } @@ -13606,7 +13606,7 @@ pub fn _mm_cvtsd_sh(a: __m128h, b: __m128d) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsd2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtsd_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128d) -> __m128h { unsafe { vcvtsd2sh(a, b, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -13620,7 +13620,7 @@ pub fn _mm_mask_cvtsd_sh(src: __m128h, k: __mmask8, a: __m128h, b: __m128d) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsd2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtsd_sh(k: __mmask8, a: __m128h, b: __m128d) -> __m128h { _mm_mask_cvtsd_sh(f16x8::ZERO.as_m128h(), k, a, b) } @@ -13642,7 +13642,7 @@ pub fn _mm_maskz_cvtsd_sh(k: __mmask8, a: __m128h, b: __m128d) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsd2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundsd_sh(a: __m128h, b: __m128d) -> __m128h { static_assert_rounding!(ROUNDING); _mm_mask_cvt_roundsd_sh::(f16x8::ZERO.as_m128h(), 0xff, a, b) @@ -13666,7 +13666,7 @@ pub fn _mm_cvt_roundsd_sh(a: __m128h, b: __m128d) -> __m128 #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsd2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvt_roundsd_sh( src: __m128h, k: __mmask8, @@ -13697,7 +13697,7 @@ pub fn _mm_mask_cvt_roundsd_sh( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsd2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvt_roundsd_sh( k: __mmask8, a: __m128h, @@ -13714,7 +13714,7 @@ pub fn _mm_maskz_cvt_roundsd_sh( #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtph_epi16(a: __m128h) -> __m128i { _mm_mask_cvtph_epi16(_mm_undefined_si128(), 0xff, a) } @@ -13727,7 +13727,7 @@ pub fn _mm_cvtph_epi16(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtph_epi16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvtph2w_128(a, src.as_i16x8(), k)) } } @@ -13739,7 +13739,7 @@ pub fn _mm_mask_cvtph_epi16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtph_epi16(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvtph_epi16(_mm_setzero_si128(), k, a) } @@ -13751,7 +13751,7 @@ pub fn _mm_maskz_cvtph_epi16(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtph_epi16(a: __m256h) -> __m256i { _mm256_mask_cvtph_epi16(_mm256_undefined_si256(), 0xffff, a) } @@ -13764,7 +13764,7 @@ pub fn _mm256_cvtph_epi16(a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtph_epi16(src: __m256i, k: __mmask16, a: __m256h) -> __m256i { unsafe { transmute(vcvtph2w_256(a, src.as_i16x16(), k)) } } @@ -13776,7 +13776,7 @@ pub fn _mm256_mask_cvtph_epi16(src: __m256i, k: __mmask16, a: __m256h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtph_epi16(k: __mmask16, a: __m256h) -> __m256i { _mm256_mask_cvtph_epi16(_mm256_setzero_si256(), k, a) } @@ -13788,7 +13788,7 @@ pub fn _mm256_maskz_cvtph_epi16(k: __mmask16, a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtph_epi16(a: __m512h) -> __m512i { _mm512_mask_cvtph_epi16(_mm512_undefined_epi32(), 0xffffffff, a) } @@ -13801,7 +13801,7 @@ pub fn _mm512_cvtph_epi16(a: __m512h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtph_epi16(src: __m512i, k: __mmask32, a: __m512h) -> __m512i { unsafe { transmute(vcvtph2w_512( @@ -13820,7 +13820,7 @@ pub fn _mm512_mask_cvtph_epi16(src: __m512i, k: __mmask32, a: __m512h) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtph_epi16(k: __mmask32, a: __m512h) -> __m512i { _mm512_mask_cvtph_epi16(_mm512_setzero_si512(), k, a) } @@ -13841,7 +13841,7 @@ pub fn _mm512_maskz_cvtph_epi16(k: __mmask32, a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2w, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundph_epi16(a: __m512h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epi16::(_mm512_undefined_epi32(), 0xffffffff, a) @@ -13864,7 +13864,7 @@ pub fn _mm512_cvt_roundph_epi16(a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2w, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundph_epi16( src: __m512i, k: __mmask32, @@ -13892,7 +13892,7 @@ pub fn _mm512_mask_cvt_roundph_epi16( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2w, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundph_epi16(k: __mmask32, a: __m512h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epi16::(_mm512_setzero_si512(), k, a) @@ -13905,7 +13905,7 @@ pub fn _mm512_maskz_cvt_roundph_epi16(k: __mmask32, a: __m5 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtph_epu16(a: __m128h) -> __m128i { _mm_mask_cvtph_epu16(_mm_undefined_si128(), 0xff, a) } @@ -13918,7 +13918,7 @@ pub fn _mm_cvtph_epu16(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtph_epu16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvtph2uw_128(a, src.as_u16x8(), k)) } } @@ -13930,7 +13930,7 @@ pub fn _mm_mask_cvtph_epu16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtph_epu16(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvtph_epu16(_mm_setzero_si128(), k, a) } @@ -13942,7 +13942,7 @@ pub fn _mm_maskz_cvtph_epu16(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtph_epu16(a: __m256h) -> __m256i { _mm256_mask_cvtph_epu16(_mm256_undefined_si256(), 0xffff, a) } @@ -13955,7 +13955,7 @@ pub fn _mm256_cvtph_epu16(a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtph_epu16(src: __m256i, k: __mmask16, a: __m256h) -> __m256i { unsafe { transmute(vcvtph2uw_256(a, src.as_u16x16(), k)) } } @@ -13967,7 +13967,7 @@ pub fn _mm256_mask_cvtph_epu16(src: __m256i, k: __mmask16, a: __m256h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtph_epu16(k: __mmask16, a: __m256h) -> __m256i { _mm256_mask_cvtph_epu16(_mm256_setzero_si256(), k, a) } @@ -13979,7 +13979,7 @@ pub fn _mm256_maskz_cvtph_epu16(k: __mmask16, a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtph_epu16(a: __m512h) -> __m512i { _mm512_mask_cvtph_epu16(_mm512_undefined_epi32(), 0xffffffff, a) } @@ -13992,7 +13992,7 @@ pub fn _mm512_cvtph_epu16(a: __m512h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtph_epu16(src: __m512i, k: __mmask32, a: __m512h) -> __m512i { unsafe { transmute(vcvtph2uw_512( @@ -14011,7 +14011,7 @@ pub fn _mm512_mask_cvtph_epu16(src: __m512i, k: __mmask32, a: __m512h) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtph_epu16(k: __mmask32, a: __m512h) -> __m512i { _mm512_mask_cvtph_epu16(_mm512_setzero_si512(), k, a) } @@ -14026,7 +14026,7 @@ pub fn _mm512_maskz_cvtph_epu16(k: __mmask32, a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uw, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundph_epu16(a: __m512h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvt_roundph_epu16::(_mm512_undefined_epi32(), 0xffffffff, a) @@ -14043,7 +14043,7 @@ pub fn _mm512_cvt_roundph_epu16(a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uw, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundph_epu16( src: __m512i, k: __mmask32, @@ -14065,7 +14065,7 @@ pub fn _mm512_mask_cvt_roundph_epu16( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uw, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundph_epu16(k: __mmask32, a: __m512h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvt_roundph_epu16::(_mm512_setzero_si512(), k, a) @@ -14078,7 +14078,7 @@ pub fn _mm512_maskz_cvt_roundph_epu16(k: __mmask32, a: __m512h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttph_epi16(a: __m128h) -> __m128i { _mm_mask_cvttph_epi16(_mm_undefined_si128(), 0xff, a) } @@ -14091,7 +14091,7 @@ pub fn _mm_cvttph_epi16(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvttph_epi16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvttph2w_128(a, src.as_i16x8(), k)) } } @@ -14104,7 +14104,7 @@ pub fn _mm_mask_cvttph_epi16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvttph_epi16(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvttph_epi16(_mm_setzero_si128(), k, a) } @@ -14116,7 +14116,7 @@ pub fn _mm_maskz_cvttph_epi16(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvttph_epi16(a: __m256h) -> __m256i { _mm256_mask_cvttph_epi16(_mm256_undefined_si256(), 0xffff, a) } @@ -14129,7 +14129,7 @@ pub fn _mm256_cvttph_epi16(a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvttph_epi16(src: __m256i, k: __mmask16, a: __m256h) -> __m256i { unsafe { transmute(vcvttph2w_256(a, src.as_i16x16(), k)) } } @@ -14142,7 +14142,7 @@ pub fn _mm256_mask_cvttph_epi16(src: __m256i, k: __mmask16, a: __m256h) -> __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvttph_epi16(k: __mmask16, a: __m256h) -> __m256i { _mm256_mask_cvttph_epi16(_mm256_setzero_si256(), k, a) } @@ -14154,7 +14154,7 @@ pub fn _mm256_maskz_cvttph_epi16(k: __mmask16, a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvttph_epi16(a: __m512h) -> __m512i { _mm512_mask_cvttph_epi16(_mm512_undefined_epi32(), 0xffffffff, a) } @@ -14167,7 +14167,7 @@ pub fn _mm512_cvttph_epi16(a: __m512h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvttph_epi16(src: __m512i, k: __mmask32, a: __m512h) -> __m512i { unsafe { transmute(vcvttph2w_512( @@ -14187,7 +14187,7 @@ pub fn _mm512_mask_cvttph_epi16(src: __m512i, k: __mmask32, a: __m512h) -> __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2w))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvttph_epi16(k: __mmask32, a: __m512h) -> __m512i { _mm512_mask_cvttph_epi16(_mm512_setzero_si512(), k, a) } @@ -14202,7 +14202,7 @@ pub fn _mm512_maskz_cvttph_epi16(k: __mmask32, a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2w, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtt_roundph_epi16(a: __m512h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epi16::(_mm512_undefined_epi32(), 0xffffffff, a) @@ -14219,7 +14219,7 @@ pub fn _mm512_cvtt_roundph_epi16(a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2w, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtt_roundph_epi16( src: __m512i, k: __mmask32, @@ -14242,7 +14242,7 @@ pub fn _mm512_mask_cvtt_roundph_epi16( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2w, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtt_roundph_epi16(k: __mmask32, a: __m512h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epi16::(_mm512_setzero_si512(), k, a) @@ -14255,7 +14255,7 @@ pub fn _mm512_maskz_cvtt_roundph_epi16(k: __mmask32, a: __m512h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttph_epu16(a: __m128h) -> __m128i { _mm_mask_cvttph_epu16(_mm_undefined_si128(), 0xff, a) } @@ -14268,7 +14268,7 @@ pub fn _mm_cvttph_epu16(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvttph_epu16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvttph2uw_128(a, src.as_u16x8(), k)) } } @@ -14281,7 +14281,7 @@ pub fn _mm_mask_cvttph_epu16(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvttph_epu16(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvttph_epu16(_mm_setzero_si128(), k, a) } @@ -14293,7 +14293,7 @@ pub fn _mm_maskz_cvttph_epu16(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvttph_epu16(a: __m256h) -> __m256i { _mm256_mask_cvttph_epu16(_mm256_undefined_si256(), 0xffff, a) } @@ -14306,7 +14306,7 @@ pub fn _mm256_cvttph_epu16(a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvttph_epu16(src: __m256i, k: __mmask16, a: __m256h) -> __m256i { unsafe { transmute(vcvttph2uw_256(a, src.as_u16x16(), k)) } } @@ -14319,7 +14319,7 @@ pub fn _mm256_mask_cvttph_epu16(src: __m256i, k: __mmask16, a: __m256h) -> __m25 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvttph_epu16(k: __mmask16, a: __m256h) -> __m256i { _mm256_mask_cvttph_epu16(_mm256_setzero_si256(), k, a) } @@ -14331,7 +14331,7 @@ pub fn _mm256_maskz_cvttph_epu16(k: __mmask16, a: __m256h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvttph_epu16(a: __m512h) -> __m512i { _mm512_mask_cvttph_epu16(_mm512_undefined_epi32(), 0xffffffff, a) } @@ -14344,7 +14344,7 @@ pub fn _mm512_cvttph_epu16(a: __m512h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvttph_epu16(src: __m512i, k: __mmask32, a: __m512h) -> __m512i { unsafe { transmute(vcvttph2uw_512( @@ -14364,7 +14364,7 @@ pub fn _mm512_mask_cvttph_epu16(src: __m512i, k: __mmask32, a: __m512h) -> __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uw))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvttph_epu16(k: __mmask32, a: __m512h) -> __m512i { _mm512_mask_cvttph_epu16(_mm512_setzero_si512(), k, a) } @@ -14379,7 +14379,7 @@ pub fn _mm512_maskz_cvttph_epu16(k: __mmask32, a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uw, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtt_roundph_epu16(a: __m512h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epu16::(_mm512_undefined_epi32(), 0xffffffff, a) @@ -14396,7 +14396,7 @@ pub fn _mm512_cvtt_roundph_epu16(a: __m512h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uw, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtt_roundph_epu16( src: __m512i, k: __mmask32, @@ -14419,7 +14419,7 @@ pub fn _mm512_mask_cvtt_roundph_epu16( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uw, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtt_roundph_epu16(k: __mmask32, a: __m512h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epu16::(_mm512_setzero_si512(), k, a) @@ -14432,7 +14432,7 @@ pub fn _mm512_maskz_cvtt_roundph_epu16(k: __mmask32, a: __m512h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtph_epi32(a: __m128h) -> __m128i { _mm_mask_cvtph_epi32(_mm_undefined_si128(), 0xff, a) } @@ -14444,7 +14444,7 @@ pub fn _mm_cvtph_epi32(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtph_epi32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvtph2dq_128(a, src.as_i32x4(), k)) } } @@ -14456,7 +14456,7 @@ pub fn _mm_mask_cvtph_epi32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtph_epi32(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvtph_epi32(_mm_setzero_si128(), k, a) } @@ -14468,7 +14468,7 @@ pub fn _mm_maskz_cvtph_epi32(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtph_epi32(a: __m128h) -> __m256i { _mm256_mask_cvtph_epi32(_mm256_undefined_si256(), 0xff, a) } @@ -14480,7 +14480,7 @@ pub fn _mm256_cvtph_epi32(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtph_epi32(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvtph2dq_256(a, src.as_i32x8(), k)) } } @@ -14492,7 +14492,7 @@ pub fn _mm256_mask_cvtph_epi32(src: __m256i, k: __mmask8, a: __m128h) -> __m256i #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtph_epi32(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvtph_epi32(_mm256_setzero_si256(), k, a) } @@ -14504,7 +14504,7 @@ pub fn _mm256_maskz_cvtph_epi32(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtph_epi32(a: __m256h) -> __m512i { _mm512_mask_cvtph_epi32(_mm512_undefined_epi32(), 0xffff, a) } @@ -14516,7 +14516,7 @@ pub fn _mm512_cvtph_epi32(a: __m256h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtph_epi32(src: __m512i, k: __mmask16, a: __m256h) -> __m512i { unsafe { transmute(vcvtph2dq_512( @@ -14535,7 +14535,7 @@ pub fn _mm512_mask_cvtph_epi32(src: __m512i, k: __mmask16, a: __m256h) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtph_epi32(k: __mmask16, a: __m256h) -> __m512i { _mm512_mask_cvtph_epi32(_mm512_setzero_si512(), k, a) } @@ -14556,7 +14556,7 @@ pub fn _mm512_maskz_cvtph_epi32(k: __mmask16, a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2dq, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundph_epi32(a: __m256h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epi32::(_mm512_undefined_epi32(), 0xffff, a) @@ -14578,7 +14578,7 @@ pub fn _mm512_cvt_roundph_epi32(a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2dq, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundph_epi32( src: __m512i, k: __mmask16, @@ -14606,7 +14606,7 @@ pub fn _mm512_mask_cvt_roundph_epi32( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2dq, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundph_epi32(k: __mmask16, a: __m256h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epi32::(_mm512_setzero_si512(), k, a) @@ -14619,7 +14619,7 @@ pub fn _mm512_maskz_cvt_roundph_epi32(k: __mmask16, a: __m2 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2si))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtsh_i32(a: __m128h) -> i32 { unsafe { vcvtsh2si32(a, _MM_FROUND_CUR_DIRECTION) } } @@ -14640,7 +14640,7 @@ pub fn _mm_cvtsh_i32(a: __m128h) -> i32 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2si, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundsh_i32(a: __m128h) -> i32 { unsafe { static_assert_rounding!(ROUNDING); @@ -14655,7 +14655,7 @@ pub fn _mm_cvt_roundsh_i32(a: __m128h) -> i32 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtph_epu32(a: __m128h) -> __m128i { _mm_mask_cvtph_epu32(_mm_undefined_si128(), 0xff, a) } @@ -14667,7 +14667,7 @@ pub fn _mm_cvtph_epu32(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtph_epu32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvtph2udq_128(a, src.as_u32x4(), k)) } } @@ -14679,7 +14679,7 @@ pub fn _mm_mask_cvtph_epu32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtph_epu32(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvtph_epu32(_mm_setzero_si128(), k, a) } @@ -14691,7 +14691,7 @@ pub fn _mm_maskz_cvtph_epu32(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtph_epu32(a: __m128h) -> __m256i { _mm256_mask_cvtph_epu32(_mm256_undefined_si256(), 0xff, a) } @@ -14703,7 +14703,7 @@ pub fn _mm256_cvtph_epu32(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtph_epu32(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvtph2udq_256(a, src.as_u32x8(), k)) } } @@ -14715,7 +14715,7 @@ pub fn _mm256_mask_cvtph_epu32(src: __m256i, k: __mmask8, a: __m128h) -> __m256i #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtph_epu32(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvtph_epu32(_mm256_setzero_si256(), k, a) } @@ -14727,7 +14727,7 @@ pub fn _mm256_maskz_cvtph_epu32(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtph_epu32(a: __m256h) -> __m512i { _mm512_mask_cvtph_epu32(_mm512_undefined_epi32(), 0xffff, a) } @@ -14739,7 +14739,7 @@ pub fn _mm512_cvtph_epu32(a: __m256h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtph_epu32(src: __m512i, k: __mmask16, a: __m256h) -> __m512i { unsafe { transmute(vcvtph2udq_512( @@ -14758,7 +14758,7 @@ pub fn _mm512_mask_cvtph_epu32(src: __m512i, k: __mmask16, a: __m256h) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtph_epu32(k: __mmask16, a: __m256h) -> __m512i { _mm512_mask_cvtph_epu32(_mm512_setzero_si512(), k, a) } @@ -14779,7 +14779,7 @@ pub fn _mm512_maskz_cvtph_epu32(k: __mmask16, a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2udq, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundph_epu32(a: __m256h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epu32::(_mm512_undefined_epi32(), 0xffff, a) @@ -14801,7 +14801,7 @@ pub fn _mm512_cvt_roundph_epu32(a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2udq, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundph_epu32( src: __m512i, k: __mmask16, @@ -14829,7 +14829,7 @@ pub fn _mm512_mask_cvt_roundph_epu32( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2udq, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundph_epu32(k: __mmask16, a: __m256h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epu32::(_mm512_setzero_si512(), k, a) @@ -14842,7 +14842,7 @@ pub fn _mm512_maskz_cvt_roundph_epu32(k: __mmask16, a: __m2 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2usi))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtsh_u32(a: __m128h) -> u32 { unsafe { vcvtsh2usi32(a, _MM_FROUND_CUR_DIRECTION) } } @@ -14857,7 +14857,7 @@ pub fn _mm_cvtsh_u32(a: __m128h) -> u32 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2usi, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundsh_u32(a: __m128h) -> u32 { unsafe { static_assert_rounding!(SAE); @@ -14872,7 +14872,7 @@ pub fn _mm_cvt_roundsh_u32(a: __m128h) -> u32 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttph_epi32(a: __m128h) -> __m128i { _mm_mask_cvttph_epi32(_mm_undefined_si128(), 0xff, a) } @@ -14884,7 +14884,7 @@ pub fn _mm_cvttph_epi32(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvttph_epi32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvttph2dq_128(a, src.as_i32x4(), k)) } } @@ -14896,7 +14896,7 @@ pub fn _mm_mask_cvttph_epi32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvttph_epi32(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvttph_epi32(_mm_setzero_si128(), k, a) } @@ -14908,7 +14908,7 @@ pub fn _mm_maskz_cvttph_epi32(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvttph_epi32(a: __m128h) -> __m256i { _mm256_mask_cvttph_epi32(_mm256_undefined_si256(), 0xff, a) } @@ -14920,7 +14920,7 @@ pub fn _mm256_cvttph_epi32(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvttph_epi32(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvttph2dq_256(a, src.as_i32x8(), k)) } } @@ -14932,7 +14932,7 @@ pub fn _mm256_mask_cvttph_epi32(src: __m256i, k: __mmask8, a: __m128h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvttph_epi32(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvttph_epi32(_mm256_setzero_si256(), k, a) } @@ -14944,7 +14944,7 @@ pub fn _mm256_maskz_cvttph_epi32(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvttph_epi32(a: __m256h) -> __m512i { _mm512_mask_cvttph_epi32(_mm512_undefined_epi32(), 0xffff, a) } @@ -14956,7 +14956,7 @@ pub fn _mm512_cvttph_epi32(a: __m256h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvttph_epi32(src: __m512i, k: __mmask16, a: __m256h) -> __m512i { unsafe { transmute(vcvttph2dq_512( @@ -14975,7 +14975,7 @@ pub fn _mm512_mask_cvttph_epi32(src: __m512i, k: __mmask16, a: __m256h) -> __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2dq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvttph_epi32(k: __mmask16, a: __m256h) -> __m512i { _mm512_mask_cvttph_epi32(_mm512_setzero_si512(), k, a) } @@ -14990,7 +14990,7 @@ pub fn _mm512_maskz_cvttph_epi32(k: __mmask16, a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2dq, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtt_roundph_epi32(a: __m256h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epi32::(_mm512_undefined_epi32(), 0xffff, a) @@ -15006,7 +15006,7 @@ pub fn _mm512_cvtt_roundph_epi32(a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2dq, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtt_roundph_epi32( src: __m512i, k: __mmask16, @@ -15028,7 +15028,7 @@ pub fn _mm512_mask_cvtt_roundph_epi32( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2dq, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtt_roundph_epi32(k: __mmask16, a: __m256h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epi32::(_mm512_setzero_si512(), k, a) @@ -15041,7 +15041,7 @@ pub fn _mm512_maskz_cvtt_roundph_epi32(k: __mmask16, a: __m256h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2si))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttsh_i32(a: __m128h) -> i32 { unsafe { vcvttsh2si32(a, _MM_FROUND_CUR_DIRECTION) } } @@ -15056,7 +15056,7 @@ pub fn _mm_cvttsh_i32(a: __m128h) -> i32 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2si, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtt_roundsh_i32(a: __m128h) -> i32 { unsafe { static_assert_sae!(SAE); @@ -15071,7 +15071,7 @@ pub fn _mm_cvtt_roundsh_i32(a: __m128h) -> i32 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttph_epu32(a: __m128h) -> __m128i { _mm_mask_cvttph_epu32(_mm_undefined_si128(), 0xff, a) } @@ -15083,7 +15083,7 @@ pub fn _mm_cvttph_epu32(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvttph_epu32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvttph2udq_128(a, src.as_u32x4(), k)) } } @@ -15095,7 +15095,7 @@ pub fn _mm_mask_cvttph_epu32(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvttph_epu32(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvttph_epu32(_mm_setzero_si128(), k, a) } @@ -15107,7 +15107,7 @@ pub fn _mm_maskz_cvttph_epu32(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvttph_epu32(a: __m128h) -> __m256i { _mm256_mask_cvttph_epu32(_mm256_undefined_si256(), 0xff, a) } @@ -15119,7 +15119,7 @@ pub fn _mm256_cvttph_epu32(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvttph_epu32(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvttph2udq_256(a, src.as_u32x8(), k)) } } @@ -15131,7 +15131,7 @@ pub fn _mm256_mask_cvttph_epu32(src: __m256i, k: __mmask8, a: __m128h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvttph_epu32(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvttph_epu32(_mm256_setzero_si256(), k, a) } @@ -15143,7 +15143,7 @@ pub fn _mm256_maskz_cvttph_epu32(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvttph_epu32(a: __m256h) -> __m512i { _mm512_mask_cvttph_epu32(_mm512_undefined_epi32(), 0xffff, a) } @@ -15155,7 +15155,7 @@ pub fn _mm512_cvttph_epu32(a: __m256h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvttph_epu32(src: __m512i, k: __mmask16, a: __m256h) -> __m512i { unsafe { transmute(vcvttph2udq_512( @@ -15174,7 +15174,7 @@ pub fn _mm512_mask_cvttph_epu32(src: __m512i, k: __mmask16, a: __m256h) -> __m51 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2udq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvttph_epu32(k: __mmask16, a: __m256h) -> __m512i { _mm512_mask_cvttph_epu32(_mm512_setzero_si512(), k, a) } @@ -15189,7 +15189,7 @@ pub fn _mm512_maskz_cvttph_epu32(k: __mmask16, a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2udq, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtt_roundph_epu32(a: __m256h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epu32::(_mm512_undefined_epi32(), 0xffff, a) @@ -15205,7 +15205,7 @@ pub fn _mm512_cvtt_roundph_epu32(a: __m256h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2udq, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtt_roundph_epu32( src: __m512i, k: __mmask16, @@ -15227,7 +15227,7 @@ pub fn _mm512_mask_cvtt_roundph_epu32( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2udq, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtt_roundph_epu32(k: __mmask16, a: __m256h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epu32::(_mm512_setzero_si512(), k, a) @@ -15240,7 +15240,7 @@ pub fn _mm512_maskz_cvtt_roundph_epu32(k: __mmask16, a: __m256h) #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2usi))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttsh_u32(a: __m128h) -> u32 { unsafe { vcvttsh2usi32(a, _MM_FROUND_CUR_DIRECTION) } } @@ -15255,7 +15255,7 @@ pub fn _mm_cvttsh_u32(a: __m128h) -> u32 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2usi, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtt_roundsh_u32(a: __m128h) -> u32 { unsafe { static_assert_sae!(SAE); @@ -15270,7 +15270,7 @@ pub fn _mm_cvtt_roundsh_u32(a: __m128h) -> u32 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtph_epi64(a: __m128h) -> __m128i { _mm_mask_cvtph_epi64(_mm_undefined_si128(), 0xff, a) } @@ -15282,7 +15282,7 @@ pub fn _mm_cvtph_epi64(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtph_epi64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvtph2qq_128(a, src.as_i64x2(), k)) } } @@ -15294,7 +15294,7 @@ pub fn _mm_mask_cvtph_epi64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtph_epi64(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvtph_epi64(_mm_setzero_si128(), k, a) } @@ -15306,7 +15306,7 @@ pub fn _mm_maskz_cvtph_epi64(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtph_epi64(a: __m128h) -> __m256i { _mm256_mask_cvtph_epi64(_mm256_undefined_si256(), 0xff, a) } @@ -15318,7 +15318,7 @@ pub fn _mm256_cvtph_epi64(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtph_epi64(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvtph2qq_256(a, src.as_i64x4(), k)) } } @@ -15330,7 +15330,7 @@ pub fn _mm256_mask_cvtph_epi64(src: __m256i, k: __mmask8, a: __m128h) -> __m256i #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtph_epi64(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvtph_epi64(_mm256_setzero_si256(), k, a) } @@ -15342,7 +15342,7 @@ pub fn _mm256_maskz_cvtph_epi64(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtph_epi64(a: __m128h) -> __m512i { _mm512_mask_cvtph_epi64(_mm512_undefined_epi32(), 0xff, a) } @@ -15354,7 +15354,7 @@ pub fn _mm512_cvtph_epi64(a: __m128h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtph_epi64(src: __m512i, k: __mmask8, a: __m128h) -> __m512i { unsafe { transmute(vcvtph2qq_512( @@ -15373,7 +15373,7 @@ pub fn _mm512_mask_cvtph_epi64(src: __m512i, k: __mmask8, a: __m128h) -> __m512i #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtph_epi64(k: __mmask8, a: __m128h) -> __m512i { _mm512_mask_cvtph_epi64(_mm512_setzero_si512(), k, a) } @@ -15394,7 +15394,7 @@ pub fn _mm512_maskz_cvtph_epi64(k: __mmask8, a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2qq, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundph_epi64(a: __m128h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epi64::(_mm512_undefined_epi32(), 0xff, a) @@ -15416,7 +15416,7 @@ pub fn _mm512_cvt_roundph_epi64(a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2qq, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundph_epi64( src: __m512i, k: __mmask8, @@ -15444,7 +15444,7 @@ pub fn _mm512_mask_cvt_roundph_epi64( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2qq, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundph_epi64(k: __mmask8, a: __m128h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epi64::(_mm512_setzero_si512(), k, a) @@ -15457,7 +15457,7 @@ pub fn _mm512_maskz_cvt_roundph_epi64(k: __mmask8, a: __m12 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtph_epu64(a: __m128h) -> __m128i { _mm_mask_cvtph_epu64(_mm_undefined_si128(), 0xff, a) } @@ -15469,7 +15469,7 @@ pub fn _mm_cvtph_epu64(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtph_epu64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvtph2uqq_128(a, src.as_u64x2(), k)) } } @@ -15481,7 +15481,7 @@ pub fn _mm_mask_cvtph_epu64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtph_epu64(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvtph_epu64(_mm_setzero_si128(), k, a) } @@ -15493,7 +15493,7 @@ pub fn _mm_maskz_cvtph_epu64(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtph_epu64(a: __m128h) -> __m256i { _mm256_mask_cvtph_epu64(_mm256_undefined_si256(), 0xff, a) } @@ -15505,7 +15505,7 @@ pub fn _mm256_cvtph_epu64(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtph_epu64(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvtph2uqq_256(a, src.as_u64x4(), k)) } } @@ -15517,7 +15517,7 @@ pub fn _mm256_mask_cvtph_epu64(src: __m256i, k: __mmask8, a: __m128h) -> __m256i #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtph_epu64(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvtph_epu64(_mm256_setzero_si256(), k, a) } @@ -15529,7 +15529,7 @@ pub fn _mm256_maskz_cvtph_epu64(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtph_epu64(a: __m128h) -> __m512i { _mm512_mask_cvtph_epu64(_mm512_undefined_epi32(), 0xff, a) } @@ -15541,7 +15541,7 @@ pub fn _mm512_cvtph_epu64(a: __m128h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtph_epu64(src: __m512i, k: __mmask8, a: __m128h) -> __m512i { unsafe { transmute(vcvtph2uqq_512( @@ -15560,7 +15560,7 @@ pub fn _mm512_mask_cvtph_epu64(src: __m512i, k: __mmask8, a: __m128h) -> __m512i #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtph_epu64(k: __mmask8, a: __m128h) -> __m512i { _mm512_mask_cvtph_epu64(_mm512_setzero_si512(), k, a) } @@ -15581,7 +15581,7 @@ pub fn _mm512_maskz_cvtph_epu64(k: __mmask8, a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uqq, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundph_epu64(a: __m128h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epu64::(_mm512_undefined_epi32(), 0xff, a) @@ -15603,7 +15603,7 @@ pub fn _mm512_cvt_roundph_epu64(a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uqq, ROUNDING = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundph_epu64( src: __m512i, k: __mmask8, @@ -15631,7 +15631,7 @@ pub fn _mm512_mask_cvt_roundph_epu64( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2uqq, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundph_epu64(k: __mmask8, a: __m128h) -> __m512i { static_assert_rounding!(ROUNDING); _mm512_mask_cvt_roundph_epu64::(_mm512_setzero_si512(), k, a) @@ -15644,7 +15644,7 @@ pub fn _mm512_maskz_cvt_roundph_epu64(k: __mmask8, a: __m12 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttph_epi64(a: __m128h) -> __m128i { _mm_mask_cvttph_epi64(_mm_undefined_si128(), 0xff, a) } @@ -15656,7 +15656,7 @@ pub fn _mm_cvttph_epi64(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvttph_epi64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvttph2qq_128(a, src.as_i64x2(), k)) } } @@ -15668,7 +15668,7 @@ pub fn _mm_mask_cvttph_epi64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvttph_epi64(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvttph_epi64(_mm_setzero_si128(), k, a) } @@ -15680,7 +15680,7 @@ pub fn _mm_maskz_cvttph_epi64(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvttph_epi64(a: __m128h) -> __m256i { _mm256_mask_cvttph_epi64(_mm256_undefined_si256(), 0xff, a) } @@ -15692,7 +15692,7 @@ pub fn _mm256_cvttph_epi64(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvttph_epi64(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvttph2qq_256(a, src.as_i64x4(), k)) } } @@ -15704,7 +15704,7 @@ pub fn _mm256_mask_cvttph_epi64(src: __m256i, k: __mmask8, a: __m128h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvttph_epi64(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvttph_epi64(_mm256_setzero_si256(), k, a) } @@ -15716,7 +15716,7 @@ pub fn _mm256_maskz_cvttph_epi64(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvttph_epi64(a: __m128h) -> __m512i { _mm512_mask_cvttph_epi64(_mm512_undefined_epi32(), 0xff, a) } @@ -15728,7 +15728,7 @@ pub fn _mm512_cvttph_epi64(a: __m128h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvttph_epi64(src: __m512i, k: __mmask8, a: __m128h) -> __m512i { unsafe { transmute(vcvttph2qq_512( @@ -15747,7 +15747,7 @@ pub fn _mm512_mask_cvttph_epi64(src: __m512i, k: __mmask8, a: __m128h) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2qq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvttph_epi64(k: __mmask8, a: __m128h) -> __m512i { _mm512_mask_cvttph_epi64(_mm512_setzero_si512(), k, a) } @@ -15762,7 +15762,7 @@ pub fn _mm512_maskz_cvttph_epi64(k: __mmask8, a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2qq, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtt_roundph_epi64(a: __m128h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epi64::(_mm512_undefined_epi32(), 0xff, a) @@ -15778,7 +15778,7 @@ pub fn _mm512_cvtt_roundph_epi64(a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2qq, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtt_roundph_epi64( src: __m512i, k: __mmask8, @@ -15800,7 +15800,7 @@ pub fn _mm512_mask_cvtt_roundph_epi64( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2qq, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtt_roundph_epi64(k: __mmask8, a: __m128h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epi64::(_mm512_setzero_si512(), k, a) @@ -15813,7 +15813,7 @@ pub fn _mm512_maskz_cvtt_roundph_epi64(k: __mmask8, a: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttph_epu64(a: __m128h) -> __m128i { _mm_mask_cvttph_epu64(_mm_undefined_si128(), 0xff, a) } @@ -15825,7 +15825,7 @@ pub fn _mm_cvttph_epu64(a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvttph_epu64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { unsafe { transmute(vcvttph2uqq_128(a, src.as_u64x2(), k)) } } @@ -15837,7 +15837,7 @@ pub fn _mm_mask_cvttph_epu64(src: __m128i, k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvttph_epu64(k: __mmask8, a: __m128h) -> __m128i { _mm_mask_cvttph_epu64(_mm_setzero_si128(), k, a) } @@ -15849,7 +15849,7 @@ pub fn _mm_maskz_cvttph_epu64(k: __mmask8, a: __m128h) -> __m128i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvttph_epu64(a: __m128h) -> __m256i { _mm256_mask_cvttph_epu64(_mm256_undefined_si256(), 0xff, a) } @@ -15861,7 +15861,7 @@ pub fn _mm256_cvttph_epu64(a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvttph_epu64(src: __m256i, k: __mmask8, a: __m128h) -> __m256i { unsafe { transmute(vcvttph2uqq_256(a, src.as_u64x4(), k)) } } @@ -15873,7 +15873,7 @@ pub fn _mm256_mask_cvttph_epu64(src: __m256i, k: __mmask8, a: __m128h) -> __m256 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvttph_epu64(k: __mmask8, a: __m128h) -> __m256i { _mm256_mask_cvttph_epu64(_mm256_setzero_si256(), k, a) } @@ -15885,7 +15885,7 @@ pub fn _mm256_maskz_cvttph_epu64(k: __mmask8, a: __m128h) -> __m256i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvttph_epu64(a: __m128h) -> __m512i { _mm512_mask_cvttph_epu64(_mm512_undefined_epi32(), 0xff, a) } @@ -15897,7 +15897,7 @@ pub fn _mm512_cvttph_epu64(a: __m128h) -> __m512i { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvttph_epu64(src: __m512i, k: __mmask8, a: __m128h) -> __m512i { unsafe { transmute(vcvttph2uqq_512( @@ -15916,7 +15916,7 @@ pub fn _mm512_mask_cvttph_epu64(src: __m512i, k: __mmask8, a: __m128h) -> __m512 #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uqq))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvttph_epu64(k: __mmask8, a: __m128h) -> __m512i { _mm512_mask_cvttph_epu64(_mm512_setzero_si512(), k, a) } @@ -15931,7 +15931,7 @@ pub fn _mm512_maskz_cvttph_epu64(k: __mmask8, a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uqq, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtt_roundph_epu64(a: __m128h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epu64::(_mm512_undefined_epi32(), 0xff, a) @@ -15947,7 +15947,7 @@ pub fn _mm512_cvtt_roundph_epu64(a: __m128h) -> __m512i { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uqq, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtt_roundph_epu64( src: __m512i, k: __mmask8, @@ -15969,7 +15969,7 @@ pub fn _mm512_mask_cvtt_roundph_epu64( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttph2uqq, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtt_roundph_epu64(k: __mmask8, a: __m128h) -> __m512i { static_assert_sae!(SAE); _mm512_mask_cvtt_roundph_epu64::(_mm512_setzero_si512(), k, a) @@ -15982,7 +15982,7 @@ pub fn _mm512_maskz_cvtt_roundph_epu64(k: __mmask8, a: __m128h) #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtxph_ps(a: __m128h) -> __m128 { _mm_mask_cvtxph_ps(_mm_setzero_ps(), 0xff, a) } @@ -15995,7 +15995,7 @@ pub fn _mm_cvtxph_ps(a: __m128h) -> __m128 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtxph_ps(src: __m128, k: __mmask8, a: __m128h) -> __m128 { unsafe { vcvtph2psx_128(a, src, k) } } @@ -16008,7 +16008,7 @@ pub fn _mm_mask_cvtxph_ps(src: __m128, k: __mmask8, a: __m128h) -> __m128 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtxph_ps(k: __mmask8, a: __m128h) -> __m128 { _mm_mask_cvtxph_ps(_mm_setzero_ps(), k, a) } @@ -16020,7 +16020,7 @@ pub fn _mm_maskz_cvtxph_ps(k: __mmask8, a: __m128h) -> __m128 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtxph_ps(a: __m128h) -> __m256 { _mm256_mask_cvtxph_ps(_mm256_setzero_ps(), 0xff, a) } @@ -16033,7 +16033,7 @@ pub fn _mm256_cvtxph_ps(a: __m128h) -> __m256 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtxph_ps(src: __m256, k: __mmask8, a: __m128h) -> __m256 { unsafe { vcvtph2psx_256(a, src, k) } } @@ -16046,7 +16046,7 @@ pub fn _mm256_mask_cvtxph_ps(src: __m256, k: __mmask8, a: __m128h) -> __m256 { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtxph_ps(k: __mmask8, a: __m128h) -> __m256 { _mm256_mask_cvtxph_ps(_mm256_setzero_ps(), k, a) } @@ -16058,7 +16058,7 @@ pub fn _mm256_maskz_cvtxph_ps(k: __mmask8, a: __m128h) -> __m256 { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtxph_ps(a: __m256h) -> __m512 { _mm512_mask_cvtxph_ps(_mm512_setzero_ps(), 0xffff, a) } @@ -16071,7 +16071,7 @@ pub fn _mm512_cvtxph_ps(a: __m256h) -> __m512 { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtxph_ps(src: __m512, k: __mmask16, a: __m256h) -> __m512 { unsafe { vcvtph2psx_512(a, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -16084,7 +16084,7 @@ pub fn _mm512_mask_cvtxph_ps(src: __m512, k: __mmask16, a: __m256h) -> __m512 { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2psx))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtxph_ps(k: __mmask16, a: __m256h) -> __m512 { _mm512_mask_cvtxph_ps(_mm512_setzero_ps(), k, a) } @@ -16099,7 +16099,7 @@ pub fn _mm512_maskz_cvtxph_ps(k: __mmask16, a: __m256h) -> __m512 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2psx, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtx_roundph_ps(a: __m256h) -> __m512 { static_assert_sae!(SAE); _mm512_mask_cvtx_roundph_ps::(_mm512_setzero_ps(), 0xffff, a) @@ -16116,7 +16116,7 @@ pub fn _mm512_cvtx_roundph_ps(a: __m256h) -> __m512 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2psx, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtx_roundph_ps( src: __m512, k: __mmask16, @@ -16139,7 +16139,7 @@ pub fn _mm512_mask_cvtx_roundph_ps( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2psx, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtx_roundph_ps(k: __mmask16, a: __m256h) -> __m512 { static_assert_sae!(SAE); _mm512_mask_cvtx_roundph_ps::(_mm512_setzero_ps(), k, a) @@ -16153,7 +16153,7 @@ pub fn _mm512_maskz_cvtx_roundph_ps(k: __mmask16, a: __m256h) -> #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2ss))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtsh_ss(a: __m128, b: __m128h) -> __m128 { _mm_mask_cvtsh_ss(a, 0xff, a, b) } @@ -16167,7 +16167,7 @@ pub fn _mm_cvtsh_ss(a: __m128, b: __m128h) -> __m128 { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2ss))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtsh_ss(src: __m128, k: __mmask8, a: __m128, b: __m128h) -> __m128 { unsafe { vcvtsh2ss(a, b, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -16181,7 +16181,7 @@ pub fn _mm_mask_cvtsh_ss(src: __m128, k: __mmask8, a: __m128, b: __m128h) -> __m #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2ss))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtsh_ss(k: __mmask8, a: __m128, b: __m128h) -> __m128 { _mm_mask_cvtsh_ss(_mm_set_ss(0.0), k, a, b) } @@ -16197,7 +16197,7 @@ pub fn _mm_maskz_cvtsh_ss(k: __mmask8, a: __m128, b: __m128h) -> __m128 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2ss, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundsh_ss(a: __m128, b: __m128h) -> __m128 { static_assert_sae!(SAE); _mm_mask_cvt_roundsh_ss::(_mm_undefined_ps(), 0xff, a, b) @@ -16215,7 +16215,7 @@ pub fn _mm_cvt_roundsh_ss(a: __m128, b: __m128h) -> __m128 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2ss, SAE = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvt_roundsh_ss( src: __m128, k: __mmask8, @@ -16240,7 +16240,7 @@ pub fn _mm_mask_cvt_roundsh_ss( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2ss, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvt_roundsh_ss(k: __mmask8, a: __m128, b: __m128h) -> __m128 { static_assert_sae!(SAE); _mm_mask_cvt_roundsh_ss::(_mm_set_ss(0.0), k, a, b) @@ -16253,7 +16253,7 @@ pub fn _mm_maskz_cvt_roundsh_ss(k: __mmask8, a: __m128, b: __m12 #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtph_pd(a: __m128h) -> __m128d { _mm_mask_cvtph_pd(_mm_setzero_pd(), 0xff, a) } @@ -16266,7 +16266,7 @@ pub fn _mm_cvtph_pd(a: __m128h) -> __m128d { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtph_pd(src: __m128d, k: __mmask8, a: __m128h) -> __m128d { unsafe { vcvtph2pd_128(a, src, k) } } @@ -16279,7 +16279,7 @@ pub fn _mm_mask_cvtph_pd(src: __m128d, k: __mmask8, a: __m128h) -> __m128d { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtph_pd(k: __mmask8, a: __m128h) -> __m128d { _mm_mask_cvtph_pd(_mm_setzero_pd(), k, a) } @@ -16291,7 +16291,7 @@ pub fn _mm_maskz_cvtph_pd(k: __mmask8, a: __m128h) -> __m128d { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_cvtph_pd(a: __m128h) -> __m256d { _mm256_mask_cvtph_pd(_mm256_setzero_pd(), 0xff, a) } @@ -16304,7 +16304,7 @@ pub fn _mm256_cvtph_pd(a: __m128h) -> __m256d { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_mask_cvtph_pd(src: __m256d, k: __mmask8, a: __m128h) -> __m256d { unsafe { vcvtph2pd_256(a, src, k) } } @@ -16317,7 +16317,7 @@ pub fn _mm256_mask_cvtph_pd(src: __m256d, k: __mmask8, a: __m128h) -> __m256d { #[inline] #[target_feature(enable = "avx512fp16,avx512vl")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm256_maskz_cvtph_pd(k: __mmask8, a: __m128h) -> __m256d { _mm256_mask_cvtph_pd(_mm256_setzero_pd(), k, a) } @@ -16329,7 +16329,7 @@ pub fn _mm256_maskz_cvtph_pd(k: __mmask8, a: __m128h) -> __m256d { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvtph_pd(a: __m128h) -> __m512d { _mm512_mask_cvtph_pd(_mm512_setzero_pd(), 0xff, a) } @@ -16342,7 +16342,7 @@ pub fn _mm512_cvtph_pd(a: __m128h) -> __m512d { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvtph_pd(src: __m512d, k: __mmask8, a: __m128h) -> __m512d { unsafe { vcvtph2pd_512(a, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -16355,7 +16355,7 @@ pub fn _mm512_mask_cvtph_pd(src: __m512d, k: __mmask8, a: __m128h) -> __m512d { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2pd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvtph_pd(k: __mmask8, a: __m128h) -> __m512d { _mm512_mask_cvtph_pd(_mm512_setzero_pd(), k, a) } @@ -16370,7 +16370,7 @@ pub fn _mm512_maskz_cvtph_pd(k: __mmask8, a: __m128h) -> __m512d { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2pd, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_cvt_roundph_pd(a: __m128h) -> __m512d { static_assert_sae!(SAE); _mm512_mask_cvt_roundph_pd::(_mm512_setzero_pd(), 0xff, a) @@ -16387,7 +16387,7 @@ pub fn _mm512_cvt_roundph_pd(a: __m128h) -> __m512d { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2pd, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_mask_cvt_roundph_pd( src: __m512d, k: __mmask8, @@ -16410,7 +16410,7 @@ pub fn _mm512_mask_cvt_roundph_pd( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtph2pd, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm512_maskz_cvt_roundph_pd(k: __mmask8, a: __m128h) -> __m512d { static_assert_sae!(SAE); _mm512_mask_cvt_roundph_pd::(_mm512_setzero_pd(), k, a) @@ -16424,7 +16424,7 @@ pub fn _mm512_maskz_cvt_roundph_pd(k: __mmask8, a: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2sd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtsh_sd(a: __m128d, b: __m128h) -> __m128d { _mm_mask_cvtsh_sd(a, 0xff, a, b) } @@ -16438,7 +16438,7 @@ pub fn _mm_cvtsh_sd(a: __m128d, b: __m128h) -> __m128d { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2sd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvtsh_sd(src: __m128d, k: __mmask8, a: __m128d, b: __m128h) -> __m128d { unsafe { vcvtsh2sd(a, b, src, k, _MM_FROUND_CUR_DIRECTION) } } @@ -16451,7 +16451,7 @@ pub fn _mm_mask_cvtsh_sd(src: __m128d, k: __mmask8, a: __m128d, b: __m128h) -> _ #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2sd))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvtsh_sd(k: __mmask8, a: __m128d, b: __m128h) -> __m128d { _mm_mask_cvtsh_sd(_mm_set_sd(0.0), k, a, b) } @@ -16467,7 +16467,7 @@ pub fn _mm_maskz_cvtsh_sd(k: __mmask8, a: __m128d, b: __m128h) -> __m128d { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2sd, SAE = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundsh_sd(a: __m128d, b: __m128h) -> __m128d { static_assert_sae!(SAE); _mm_mask_cvt_roundsh_sd::(a, 0xff, a, b) @@ -16485,7 +16485,7 @@ pub fn _mm_cvt_roundsh_sd(a: __m128d, b: __m128h) -> __m128d { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2sd, SAE = 8))] #[rustc_legacy_const_generics(4)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_mask_cvt_roundsh_sd( src: __m128d, k: __mmask8, @@ -16509,7 +16509,7 @@ pub fn _mm_mask_cvt_roundsh_sd( #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2sd, SAE = 8))] #[rustc_legacy_const_generics(3)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_maskz_cvt_roundsh_sd(k: __mmask8, a: __m128d, b: __m128h) -> __m128d { static_assert_sae!(SAE); _mm_mask_cvt_roundsh_sd::(_mm_set_sd(0.0), k, a, b) @@ -16553,7 +16553,7 @@ pub const fn _mm512_cvtsh_h(a: __m512h) -> f16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si16) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_cvtsi128_si16(a: __m128i) -> i16 { unsafe { simd_extract!(a.as_i16x8(), 0) } @@ -16564,7 +16564,7 @@ pub const fn _mm_cvtsi128_si16(a: __m128i) -> i16 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi16_si128) #[inline] #[target_feature(enable = "avx512fp16")] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_cvtsi16_si128(a: i16) -> __m128i { unsafe { transmute(simd_insert!(i16x8::ZERO, 0, a)) } diff --git a/library/stdarch/crates/core_arch/src/x86/avxneconvert.rs b/library/stdarch/crates/core_arch/src/x86/avxneconvert.rs index 91b6be2b09d7..b8a3b9473af9 100644 --- a/library/stdarch/crates/core_arch/src/x86/avxneconvert.rs +++ b/library/stdarch/crates/core_arch/src/x86/avxneconvert.rs @@ -87,7 +87,7 @@ pub unsafe fn _mm256_cvtneebf16_ps(a: *const __m256bh) -> __m256 { #[inline] #[target_feature(enable = "avxneconvert")] #[cfg_attr(test, assert_instr(vcvtneeph2ps))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub unsafe fn _mm_cvtneeph_ps(a: *const __m128h) -> __m128 { transmute(cvtneeph2ps_128(a)) } @@ -99,7 +99,7 @@ pub unsafe fn _mm_cvtneeph_ps(a: *const __m128h) -> __m128 { #[inline] #[target_feature(enable = "avxneconvert")] #[cfg_attr(test, assert_instr(vcvtneeph2ps))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub unsafe fn _mm256_cvtneeph_ps(a: *const __m256h) -> __m256 { transmute(cvtneeph2ps_256(a)) } @@ -135,7 +135,7 @@ pub unsafe fn _mm256_cvtneobf16_ps(a: *const __m256bh) -> __m256 { #[inline] #[target_feature(enable = "avxneconvert")] #[cfg_attr(test, assert_instr(vcvtneoph2ps))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub unsafe fn _mm_cvtneoph_ps(a: *const __m128h) -> __m128 { transmute(cvtneoph2ps_128(a)) } @@ -147,7 +147,7 @@ pub unsafe fn _mm_cvtneoph_ps(a: *const __m128h) -> __m128 { #[inline] #[target_feature(enable = "avxneconvert")] #[cfg_attr(test, assert_instr(vcvtneoph2ps))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub unsafe fn _mm256_cvtneoph_ps(a: *const __m256h) -> __m256 { transmute(cvtneoph2ps_256(a)) } diff --git a/library/stdarch/crates/core_arch/src/x86/mod.rs b/library/stdarch/crates/core_arch/src/x86/mod.rs index c40fbd3ca317..9396507f0804 100644 --- a/library/stdarch/crates/core_arch/src/x86/mod.rs +++ b/library/stdarch/crates/core_arch/src/x86/mod.rs @@ -401,7 +401,7 @@ types! { } types! { - #![stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] + #![stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] /// 128-bit wide set of 8 `f16` types, x86-specific /// @@ -768,7 +768,7 @@ mod avxneconvert; pub use self::avxneconvert::*; mod avx512fp16; -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub use self::avx512fp16::*; mod kl; diff --git a/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs b/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs index 87e3651ba744..2a511328bb38 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs @@ -10,7 +10,7 @@ use stdarch_test::assert_instr; #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsi2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvti64_sh(a: __m128h, b: i64) -> __m128h { unsafe { vcvtsi642sh(a, b, _MM_FROUND_CUR_DIRECTION) } } @@ -32,7 +32,7 @@ pub fn _mm_cvti64_sh(a: __m128h, b: i64) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsi2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundi64_sh(a: __m128h, b: i64) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -48,7 +48,7 @@ pub fn _mm_cvt_roundi64_sh(a: __m128h, b: i64) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtusi2sh))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtu64_sh(a: __m128h, b: u64) -> __m128h { unsafe { vcvtusi642sh(a, b, _MM_FROUND_CUR_DIRECTION) } } @@ -70,7 +70,7 @@ pub fn _mm_cvtu64_sh(a: __m128h, b: u64) -> __m128h { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtusi2sh, ROUNDING = 8))] #[rustc_legacy_const_generics(2)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundu64_sh(a: __m128h, b: u64) -> __m128h { unsafe { static_assert_rounding!(ROUNDING); @@ -85,7 +85,7 @@ pub fn _mm_cvt_roundu64_sh(a: __m128h, b: u64) -> __m128h { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2si))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtsh_i64(a: __m128h) -> i64 { unsafe { vcvtsh2si64(a, _MM_FROUND_CUR_DIRECTION) } } @@ -106,7 +106,7 @@ pub fn _mm_cvtsh_i64(a: __m128h) -> i64 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2si, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundsh_i64(a: __m128h) -> i64 { unsafe { static_assert_rounding!(ROUNDING); @@ -121,7 +121,7 @@ pub fn _mm_cvt_roundsh_i64(a: __m128h) -> i64 { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2usi))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtsh_u64(a: __m128h) -> u64 { unsafe { vcvtsh2usi64(a, _MM_FROUND_CUR_DIRECTION) } } @@ -142,7 +142,7 @@ pub fn _mm_cvtsh_u64(a: __m128h) -> u64 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvtsh2usi, ROUNDING = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvt_roundsh_u64(a: __m128h) -> u64 { unsafe { static_assert_rounding!(ROUNDING); @@ -157,7 +157,7 @@ pub fn _mm_cvt_roundsh_u64(a: __m128h) -> u64 { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2si))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttsh_i64(a: __m128h) -> i64 { unsafe { vcvttsh2si64(a, _MM_FROUND_CUR_DIRECTION) } } @@ -172,7 +172,7 @@ pub fn _mm_cvttsh_i64(a: __m128h) -> i64 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2si, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtt_roundsh_i64(a: __m128h) -> i64 { unsafe { static_assert_sae!(SAE); @@ -187,7 +187,7 @@ pub fn _mm_cvtt_roundsh_i64(a: __m128h) -> i64 { #[inline] #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2usi))] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvttsh_u64(a: __m128h) -> u64 { unsafe { vcvttsh2usi64(a, _MM_FROUND_CUR_DIRECTION) } } @@ -202,7 +202,7 @@ pub fn _mm_cvttsh_u64(a: __m128h) -> u64 { #[target_feature(enable = "avx512fp16")] #[cfg_attr(test, assert_instr(vcvttsh2usi, SAE = 8))] #[rustc_legacy_const_generics(1)] -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub fn _mm_cvtt_roundsh_u64(a: __m128h) -> u64 { unsafe { static_assert_sae!(SAE); diff --git a/library/stdarch/crates/core_arch/src/x86_64/mod.rs b/library/stdarch/crates/core_arch/src/x86_64/mod.rs index c6dc7a85e785..9caab44e46cd 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/mod.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/mod.rs @@ -75,7 +75,7 @@ mod bt; pub use self::bt::*; mod avx512fp16; -#[stable(feature = "stdarch_x86_avx512fp16", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "stdarch_x86_avx512fp16", since = "1.94.0")] pub use self::avx512fp16::*; mod amx; diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml index a9bc377924dd..be19d34f9167 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml @@ -13,9 +13,9 @@ auto_llvm_sign_conversion: false neon-stable: &neon-stable FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] -# #[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +# #[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] neon-stable-fp16: &neon-stable-fp16 - FnCall: [stable, ['feature = "stdarch_neon_fp16"', 'since = "CURRENT_RUSTC_VERSION"']] + FnCall: [stable, ['feature = "stdarch_neon_fp16"', 'since = "1.94.0"']] # #[cfg(not(target_arch = "arm64ec"))] target-not-arm64ec: &target-not-arm64ec diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml index 52748a4cc056..9c922d1a6501 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml @@ -10,9 +10,9 @@ auto_big_endian: true neon-stable: &neon-stable FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']] -# #[stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION")] +# #[stable(feature = "stdarch_neon_fp16", since = "1.94.0")] neon-stable-fp16: &neon-stable-fp16 - FnCall: [stable, ['feature = "stdarch_neon_fp16"', 'since = "CURRENT_RUSTC_VERSION"']] + FnCall: [stable, ['feature = "stdarch_neon_fp16"', 'since = "1.94.0"']] # #[cfg_attr(target_arch = "arm", unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800"))] neon-cfg-arm-unstable: &neon-cfg-arm-unstable @@ -55,9 +55,9 @@ neon-target-aarch64-arm64ec: &neon-target-aarch64-arm64ec neon-not-arm-stable: &neon-not-arm-stable FnCall: [cfg_attr, [{ FnCall: [not, ['target_arch = "arm"']]}, {FnCall: [stable, ['feature = "neon_intrinsics"', 'since = "1.59.0"']]}]] -# #[cfg_attr(not(target_arch = "arm"), stable(feature = "stdarch_neon_fp16", since = "CURRENT_RUSTC_VERSION"))] +# #[cfg_attr(not(target_arch = "arm"), stable(feature = "stdarch_neon_fp16", since = "1.94.0"))] neon-not-arm-stable-fp16: &neon-not-arm-stable-fp16 - FnCall: [cfg_attr, [{ FnCall: [not, ['target_arch = "arm"']]}, {FnCall: [stable, ['feature = "stdarch_neon_fp16"', 'since = "CURRENT_RUSTC_VERSION"']]}]] + FnCall: [cfg_attr, [{ FnCall: [not, ['target_arch = "arm"']]}, {FnCall: [stable, ['feature = "stdarch_neon_fp16"', 'since = "1.94.0"']]}]] # #[cfg_attr(all(test, not(target_env = "msvc"))] msvc-disabled: &msvc-disabled From dd322a04257d48da8bea668f93f4668a26a8bc51 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 5 Feb 2026 13:42:06 -0800 Subject: [PATCH 586/978] Include library/stdarch for CURRENT_RUSTC_VERSION updates --- src/tools/replace-version-placeholder/src/main.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tools/replace-version-placeholder/src/main.rs b/src/tools/replace-version-placeholder/src/main.rs index fb2838a4ea03..c2a7c4be64ae 100644 --- a/src/tools/replace-version-placeholder/src/main.rs +++ b/src/tools/replace-version-placeholder/src/main.rs @@ -16,7 +16,7 @@ fn main() { &root_path.join("src/doc/rustc"), &root_path.join("src/doc/rustdoc"), ], - |path, _is_dir| walk::filter_dirs(path), + |path, _is_dir| filter_dirs(path), &mut |entry, contents| { if !contents.contains(VERSION_PLACEHOLDER) { return; @@ -27,3 +27,9 @@ fn main() { }, ); } + +fn filter_dirs(path: &std::path::Path) -> bool { + // tidy would skip some paths that we do want to process + let allow = ["library/stdarch"]; + walk::filter_dirs(path) && !allow.iter().any(|p| path.ends_with(p)) +} From c32c48114a8176064e7d7b5ea3ca14e2330861e8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Feb 2026 14:18:08 +1100 Subject: [PATCH 587/978] Improve `is_ignored_attr`. It has a single use. It doesn't need to be public. It doesn't use `self` and so doesn't need to be in the trait. And `IGNORED_ATTRIBUTES` can be moved within it. --- compiler/rustc_query_system/src/ich/hcx.rs | 9 +-------- .../rustc_query_system/src/ich/impls_syntax.rs | 18 ++++++++++++++++-- compiler/rustc_query_system/src/ich/mod.rs | 12 ------------ 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index 840f0b35266d..f350db26eccc 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -5,9 +5,7 @@ use rustc_hir::definitions::DefPathHash; use rustc_session::Session; use rustc_session::cstore::Untracked; use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, CachingSourceMapView, DUMMY_SP, SourceFile, Span, SpanData, Symbol}; - -use crate::ich; +use rustc_span::{BytePos, CachingSourceMapView, DUMMY_SP, SourceFile, Span, SpanData}; /// This is the context state available during incr. comp. hashing. It contains /// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e., @@ -73,11 +71,6 @@ impl<'a> StableHashingContext<'a> { } } - #[inline] - pub fn is_ignored_attr(&self, name: Symbol) -> bool { - ich::IGNORED_ATTRIBUTES.contains(&name) - } - #[inline] pub fn hashing_controls(&self) -> HashingControls { self.hashing_controls.clone() diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs index fe6fb3d65194..3cd25f3a5b9c 100644 --- a/compiler/rustc_query_system/src/ich/impls_syntax.rs +++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs @@ -3,7 +3,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::{self as hir, HashIgnoredAttrId}; -use rustc_span::SourceFile; +use rustc_span::{SourceFile, Symbol, sym}; use smallvec::SmallVec; use crate::ich::StableHashingContext; @@ -24,7 +24,7 @@ impl<'a> HashStable> for [hir::Attribute] { .filter(|attr| { attr.is_doc_comment().is_none() // FIXME(jdonszelmann) have a better way to handle ignored attrs - && !attr.name().is_some_and(|ident| hcx.is_ignored_attr(ident)) + && !attr.name().is_some_and(|ident| is_ignored_attr(ident)) }) .collect(); @@ -35,6 +35,20 @@ impl<'a> HashStable> for [hir::Attribute] { } } +#[inline] +fn is_ignored_attr(name: Symbol) -> bool { + const IGNORED_ATTRIBUTES: &[Symbol] = &[ + sym::cfg_trace, // FIXME(#138844) should this really be ignored? + sym::rustc_if_this_changed, + sym::rustc_then_this_would_need, + sym::rustc_clean, + sym::rustc_partition_reused, + sym::rustc_partition_codegened, + sym::rustc_expected_cgu_reuse, + ]; + IGNORED_ATTRIBUTES.contains(&name) +} + impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { fn hash_attr_id(&mut self, _id: &HashIgnoredAttrId, _hasher: &mut StableHasher) { /* we don't hash HashIgnoredAttrId, we ignore them */ diff --git a/compiler/rustc_query_system/src/ich/mod.rs b/compiler/rustc_query_system/src/ich/mod.rs index 72a7f3b8f970..99575299c978 100644 --- a/compiler/rustc_query_system/src/ich/mod.rs +++ b/compiler/rustc_query_system/src/ich/mod.rs @@ -1,18 +1,6 @@ //! ICH - Incremental Compilation Hash -use rustc_span::{Symbol, sym}; - pub use self::hcx::StableHashingContext; mod hcx; mod impls_syntax; - -pub const IGNORED_ATTRIBUTES: &[Symbol] = &[ - sym::cfg_trace, // FIXME should this really be ignored? - sym::rustc_if_this_changed, - sym::rustc_then_this_would_need, - sym::rustc_clean, - sym::rustc_partition_reused, - sym::rustc_partition_codegened, - sym::rustc_expected_cgu_reuse, -]; From c9f827754a106f0fc82a57077ac96fc4dc2d5344 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Feb 2026 14:56:41 +1100 Subject: [PATCH 588/978] Make `HashingControls` impl `Copy`. It has a single `bool` field. --- compiler/rustc_data_structures/src/stable_hasher.rs | 2 +- compiler/rustc_query_system/src/ich/hcx.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index 3a64c924cc22..9fb4d4352c2f 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -607,7 +607,7 @@ where /// result (for example, using a `Fingerprint` produced while /// hashing `Span`s when a `Fingerprint` without `Span`s is /// being requested) -#[derive(Clone, Hash, Eq, PartialEq, Debug)] +#[derive(Clone, Copy, Hash, Eq, PartialEq, Debug)] pub struct HashingControls { pub hash_spans: bool, } diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index f350db26eccc..fb73178a726b 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -73,7 +73,7 @@ impl<'a> StableHashingContext<'a> { #[inline] pub fn hashing_controls(&self) -> HashingControls { - self.hashing_controls.clone() + self.hashing_controls } } @@ -115,7 +115,7 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { #[inline] fn hashing_controls(&self) -> HashingControls { - self.hashing_controls.clone() + self.hashing_controls } } From cd3c9329fb57ca3e4eae4396b268937b102316c3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Feb 2026 15:25:52 +1100 Subject: [PATCH 589/978] Fix control flow in `assert_default_hashing_controls`. Calling `match` on a struct is a really weird thing to do. As the name suggests, it's an assert, so let's write it as one. Also clarify the comment a little. --- compiler/rustc_span/src/hygiene.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 05f4c8e268a9..07a85ad75daa 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -132,19 +132,21 @@ impl !PartialOrd for LocalExpnId {} /// to maintain separate versions of `ExpnData` hashes for each permutation /// of `HashingControls` settings. fn assert_default_hashing_controls(ctx: &impl HashStableContext, msg: &str) { - match ctx.hashing_controls() { - // Note that we require that `hash_spans` be set according to the global - // `-Z incremental-ignore-spans` option. Normally, this option is disabled, - // which will cause us to require that this method always be called with `Span` hashing - // enabled. - // - // Span hashing can also be disabled without `-Z incremental-ignore-spans`. - // This is the case for instance when building a hash for name mangling. - // Such configuration must not be used for metadata. - HashingControls { hash_spans } - if hash_spans != ctx.unstable_opts_incremental_ignore_spans() => {} - other => panic!("Attempted hashing of {msg} with non-default HashingControls: {other:?}"), - } + let hashing_controls = ctx.hashing_controls(); + let HashingControls { hash_spans } = hashing_controls; + + // Note that we require that `hash_spans` be the inverse of the global + // `-Z incremental-ignore-spans` option. Normally, this option is disabled, + // in which case `hash_spans` must be true. + // + // Span hashing can also be disabled without `-Z incremental-ignore-spans`. + // This is the case for instance when building a hash for name mangling. + // Such configuration must not be used for metadata. + assert_eq!( + hash_spans, + !ctx.unstable_opts_incremental_ignore_spans(), + "Attempted hashing of {msg} with non-default HashingControls: {hashing_controls:?}" + ); } /// A unique hash value associated to an expansion. From e2edce0221ecef2ef1aaa2e58158730151e58f53 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Feb 2026 15:34:29 +1100 Subject: [PATCH 590/978] Remove `rustc_span::HashStableContext::hash_spans`. It reads the `HashingControls::span` field, but there is also the `hashing_controls` method. No need to have two different ways of doing it. --- compiler/rustc_query_system/src/ich/hcx.rs | 5 ----- compiler/rustc_span/src/lib.rs | 3 +-- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index fb73178a726b..ec416b8f807c 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -85,11 +85,6 @@ impl<'a> HashStable> for ast::NodeId { } impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { - #[inline] - fn hash_spans(&self) -> bool { - self.hashing_controls.hash_spans - } - #[inline] fn unstable_opts_incremental_ignore_spans(&self) -> bool { self.incremental_ignore_spans diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index a178f3260d30..0ad80b9d7879 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -2799,7 +2799,6 @@ impl InnerSpan { /// instead of implementing everything in rustc_middle. pub trait HashStableContext { fn def_path_hash(&self, def_id: DefId) -> DefPathHash; - fn hash_spans(&self) -> bool; /// Accesses `sess.opts.unstable_opts.incremental_ignore_spans` since /// we don't have easy access to a `Session` fn unstable_opts_incremental_ignore_spans(&self) -> bool; @@ -2832,7 +2831,7 @@ where const TAG_INVALID_SPAN: u8 = 1; const TAG_RELATIVE_SPAN: u8 = 2; - if !ctx.hash_spans() { + if !ctx.hashing_controls().hash_spans { return; } From 7298e1736619078bd57fef427e23a3371902f972 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Feb 2026 15:50:08 +1100 Subject: [PATCH 591/978] Remove `rustc_hir::HashStableContext::hash_attr_id`. It has a single impl, which does nothing, as you'd expect when hashing a type called `HashIgnoredAttrId`! So this commit just removes it, and `HashIgnoredAttrId::hash_stable` ends up doing nothing (with a comment) instead of calling the trait method to do nothing. --- compiler/rustc_hir/src/stable_hash_impls.rs | 8 +++----- compiler/rustc_query_system/src/ich/impls_syntax.rs | 6 +----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 16e8bac3d8a4..a3f4415ec343 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -11,9 +11,7 @@ use crate::lints::DelayedLints; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro /// instead of implementing everything in `rustc_middle`. -pub trait HashStableContext: rustc_ast::HashStableContext + rustc_abi::HashStableContext { - fn hash_attr_id(&mut self, id: &HashIgnoredAttrId, hasher: &mut StableHasher); -} +pub trait HashStableContext: rustc_ast::HashStableContext + rustc_abi::HashStableContext {} impl ToStableHashKey for BodyId { type KeyType = (DefPathHash, ItemLocalId); @@ -104,7 +102,7 @@ impl HashStable for Crate<'_> { } impl HashStable for HashIgnoredAttrId { - fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { - hcx.hash_attr_id(self, hasher) + fn hash_stable(&self, _hcx: &mut HirCtx, _hasher: &mut StableHasher) { + /* we don't hash HashIgnoredAttrId, we ignore them */ } } diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs index 3cd25f3a5b9c..7a079272cfe6 100644 --- a/compiler/rustc_query_system/src/ich/impls_syntax.rs +++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs @@ -49,11 +49,7 @@ fn is_ignored_attr(name: Symbol) -> bool { IGNORED_ATTRIBUTES.contains(&name) } -impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { - fn hash_attr_id(&mut self, _id: &HashIgnoredAttrId, _hasher: &mut StableHasher) { - /* we don't hash HashIgnoredAttrId, we ignore them */ - } -} +impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {} impl<'a> HashStable> for SourceFile { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { From 99b9f51725033a83653d99d04f0fc54cd67bd2a0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Feb 2026 16:08:41 +1100 Subject: [PATCH 592/978] Merge two fields in `StableHashingContext`. The new type makes the behaviour clearer: we start with the cache in an "unused" form and then instantiate it once it is actually used. --- compiler/rustc_query_system/src/ich/hcx.rs | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index ec416b8f807c..28d40b53b690 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -7,6 +7,14 @@ use rustc_session::cstore::Untracked; use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, CachingSourceMapView, DUMMY_SP, SourceFile, Span, SpanData}; +// Very often, we are hashing something that does not need the `CachingSourceMapView`, so we +// initialize it lazily. +#[derive(Clone)] +enum CachingSourceMap<'a> { + Unused(&'a SourceMap), + InUse(CachingSourceMapView<'a>), +} + /// This is the context state available during incr. comp. hashing. It contains /// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e., /// a reference to the `TyCtxt`) and it holds a few caches for speeding up various @@ -17,10 +25,7 @@ pub struct StableHashingContext<'a> { // The value of `-Z incremental-ignore-spans`. // This field should only be used by `unstable_opts_incremental_ignore_span` incremental_ignore_spans: bool, - // Very often, we are hashing something that does not need the - // `CachingSourceMapView`, so we initialize it lazily. - raw_source_map: &'a SourceMap, - caching_source_map: Option>, + caching_source_map: CachingSourceMap<'a>, hashing_controls: HashingControls, } @@ -32,8 +37,7 @@ impl<'a> StableHashingContext<'a> { StableHashingContext { untracked, incremental_ignore_spans: sess.opts.unstable_opts.incremental_ignore_spans, - caching_source_map: None, - raw_source_map: sess.source_map(), + caching_source_map: CachingSourceMap::Unused(sess.source_map()), hashing_controls: HashingControls { hash_spans: hash_spans_initial }, } } @@ -63,10 +67,10 @@ impl<'a> StableHashingContext<'a> { #[inline] pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> { match self.caching_source_map { - Some(ref mut sm) => sm, - ref mut none => { - *none = Some(CachingSourceMapView::new(self.raw_source_map)); - none.as_mut().unwrap() + CachingSourceMap::InUse(ref mut sm) => sm, + CachingSourceMap::Unused(sm) => { + self.caching_source_map = CachingSourceMap::InUse(CachingSourceMapView::new(sm)); + self.source_map() // this recursive call will hit the `InUse` case } } } From f729340aab3443e54f9a66c7294b8295507c67d3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Feb 2026 17:03:36 +1100 Subject: [PATCH 593/978] Inline and remove two `StableHashingContext` methods. They both have a single use. Also adjust a couple of visibilities. --- compiler/rustc_query_system/src/ich/hcx.rs | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index 28d40b53b690..56a5ac47f4cf 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -51,21 +51,7 @@ impl<'a> StableHashingContext<'a> { } #[inline] - pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash { - if let Some(def_id) = def_id.as_local() { - self.local_def_path_hash(def_id) - } else { - self.untracked.cstore.read().def_path_hash(def_id) - } - } - - #[inline] - pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash { - self.untracked.definitions.read().def_path_hash(def_id) - } - - #[inline] - pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> { + fn source_map(&mut self) -> &mut CachingSourceMapView<'a> { match self.caching_source_map { CachingSourceMap::InUse(ref mut sm) => sm, CachingSourceMap::Unused(sm) => { @@ -96,7 +82,11 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { #[inline] fn def_path_hash(&self, def_id: DefId) -> DefPathHash { - self.def_path_hash(def_id) + if let Some(def_id) = def_id.as_local() { + self.untracked.definitions.read().def_path_hash(def_id) + } else { + self.untracked.cstore.read().def_path_hash(def_id) + } } #[inline] From 93a1a8064d2385633c77a66cf6c2bdade0120a63 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Feb 2026 15:10:42 +1100 Subject: [PATCH 594/978] Move some `impl`s. `HashStableContext` impls should be in `hcx.rs`, and `HashStable` impls should be in `impls_syntax.rs`. This commit moves a few that are in the wrong file. --- compiler/rustc_query_system/src/ich/hcx.rs | 13 ++++--------- compiler/rustc_query_system/src/ich/impls_syntax.rs | 12 +++++++----- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index 56a5ac47f4cf..397ec7994f18 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -1,5 +1,4 @@ -use rustc_ast as ast; -use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher}; +use rustc_data_structures::stable_hasher::HashingControls; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::definitions::DefPathHash; use rustc_session::Session; @@ -67,13 +66,6 @@ impl<'a> StableHashingContext<'a> { } } -impl<'a> HashStable> for ast::NodeId { - #[inline] - fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { - panic!("Node IDs should not appear in incremental state"); - } -} - impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { #[inline] fn unstable_opts_incremental_ignore_spans(&self) -> bool { @@ -108,4 +100,7 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { } } +impl<'a> rustc_abi::HashStableContext for StableHashingContext<'a> {} +impl<'a> rustc_ast::HashStableContext for StableHashingContext<'a> {} +impl<'a> rustc_hir::HashStableContext for StableHashingContext<'a> {} impl<'a> rustc_session::HashStableContext for StableHashingContext<'a> {} diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs index 7a079272cfe6..5592f6553971 100644 --- a/compiler/rustc_query_system/src/ich/impls_syntax.rs +++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs @@ -2,14 +2,18 @@ //! from various crates in no particular order. use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_hir::{self as hir, HashIgnoredAttrId}; use rustc_span::{SourceFile, Symbol, sym}; use smallvec::SmallVec; +use {rustc_ast as ast, rustc_hir as hir}; use crate::ich::StableHashingContext; -impl<'ctx> rustc_abi::HashStableContext for StableHashingContext<'ctx> {} -impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> {} +impl<'a> HashStable> for ast::NodeId { + #[inline] + fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { + panic!("Node IDs should not appear in incremental state"); + } +} impl<'a> HashStable> for [hir::Attribute] { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { @@ -49,8 +53,6 @@ fn is_ignored_attr(name: Symbol) -> bool { IGNORED_ATTRIBUTES.contains(&name) } -impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> {} - impl<'a> HashStable> for SourceFile { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let SourceFile { From 09eb4973960822b93dff415dc385d1e4fb3c1150 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Feb 2026 15:54:28 +1100 Subject: [PATCH 595/978] Remove `Resolver::create_stable_hashing_context`. It only has two uses. We can instead use `with_stable_hashing_context`, which has more than 30 uses. --- Cargo.lock | 1 - compiler/rustc_resolve/Cargo.toml | 1 - compiler/rustc_resolve/src/lib.rs | 5 --- compiler/rustc_resolve/src/macros.rs | 48 +++++++++++++++------------- 4 files changed, 26 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 23abc6626aab..496ceb0b8403 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4570,7 +4570,6 @@ dependencies = [ "rustc_macros", "rustc_metadata", "rustc_middle", - "rustc_query_system", "rustc_session", "rustc_span", "smallvec", diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index 01e268d911d2..feb0a93d0788 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -21,7 +21,6 @@ rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_metadata = { path = "../rustc_metadata" } rustc_middle = { path = "../rustc_middle" } -rustc_query_system = { path = "../rustc_query_system" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 36ec173cc571..0912b46f473f 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -72,7 +72,6 @@ use rustc_middle::ty::{ self, DelegationFnSig, DelegationInfo, Feed, MainDefinition, RegisteredTools, ResolverAstLowering, ResolverGlobalCtxt, TyCtxt, TyCtxtFeed, Visibility, }; -use rustc_query_system::ich::StableHashingContext; use rustc_session::config::CrateType; use rustc_session::lint::builtin::PRIVATE_MACRO_USE; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; @@ -1839,10 +1838,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ResolverOutputs { global_ctxt, ast_lowering } } - fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { - StableHashingContext::new(self.tcx.sess, self.tcx.untracked()) - } - fn cstore(&self) -> FreezeReadGuard<'_, CStore> { CStore::from_tcx(self.tcx) } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index b933c2b9d036..e0973271da52 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -222,17 +222,19 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { ) -> LocalExpnId { let parent_module = parent_module_id.map(|module_id| self.local_def_id(module_id).to_def_id()); - let expn_id = LocalExpnId::fresh( - ExpnData::allow_unstable( - ExpnKind::AstPass(pass), - call_site, - self.tcx.sess.edition(), - features.into(), - None, - parent_module, - ), - self.create_stable_hashing_context(), - ); + let expn_id = self.tcx.with_stable_hashing_context(|hcx| { + LocalExpnId::fresh( + ExpnData::allow_unstable( + ExpnKind::AstPass(pass), + call_site, + self.tcx.sess.edition(), + features.into(), + None, + parent_module, + ), + hcx, + ) + }); let parent_scope = parent_module.map_or(self.empty_module, |def_id| self.expect_module(def_id)); @@ -322,17 +324,19 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { let span = invoc.span(); let def_id = if deleg_impl.is_some() { None } else { res.opt_def_id() }; - invoc_id.set_expn_data( - ext.expn_data( - parent_scope.expansion, - span, - fast_print_path(path), - kind, - def_id, - def_id.map(|def_id| self.macro_def_scope(def_id).nearest_parent_mod()), - ), - self.create_stable_hashing_context(), - ); + self.tcx.with_stable_hashing_context(|hcx| { + invoc_id.set_expn_data( + ext.expn_data( + parent_scope.expansion, + span, + fast_print_path(path), + kind, + def_id, + def_id.map(|def_id| self.macro_def_scope(def_id).nearest_parent_mod()), + ), + hcx, + ) + }); Ok(ext) } From e35fd451a090e01ae10331dcbf87f1813708a86d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Feb 2026 16:55:23 +1100 Subject: [PATCH 596/978] Add a useful comment about the `RawList` stable hash cache. I tried removing it to see what happened. Not a good idea! --- compiler/rustc_middle/src/ty/impls_ty.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index ac45ce887c9a..95a1a1bf5bce 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -20,6 +20,9 @@ where T: HashStable>, { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + // Note: this cache makes an *enormous* performance difference on certain benchmarks. E.g. + // without it, compiling `diesel-2.2.10` can be 74% slower, and compiling + // `deeply-nested-multi` can be ~4,000x slower(!) thread_local! { static CACHE: RefCell> = RefCell::new(Default::default()); From 0bbc2f2008d7af8069c477ec9757a46d2fd27330 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Tue, 3 Feb 2026 00:40:57 +0100 Subject: [PATCH 597/978] Remove USE_XCODE_CLANG Instead, always use the Xcode-provided Clang to build LLVM. --- src/ci/citool/tests/jobs.rs | 2 +- src/ci/citool/tests/test-jobs.yml | 1 - src/ci/github-actions/jobs.yml | 3 --- src/ci/scripts/install-clang.sh | 35 +++++++++++++------------------ 4 files changed, 15 insertions(+), 26 deletions(-) diff --git a/src/ci/citool/tests/jobs.rs b/src/ci/citool/tests/jobs.rs index b0309c52003f..33fdb3f67b9b 100644 --- a/src/ci/citool/tests/jobs.rs +++ b/src/ci/citool/tests/jobs.rs @@ -6,7 +6,7 @@ const TEST_JOBS_YML_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/tes fn auto_jobs() { let stdout = get_matrix("push", "commit", "refs/heads/automation/bors/auto"); insta::assert_snapshot!(stdout, @r#" - jobs=[{"name":"aarch64-gnu","full_name":"auto - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"x86_64-gnu-llvm-18-1","full_name":"auto - x86_64-gnu-llvm-18-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DOCKER_SCRIPT":"stage_2_test_set1.sh","IMAGE":"x86_64-gnu-llvm-18","READ_ONLY_SRC":"0","RUST_BACKTRACE":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"aarch64-apple","full_name":"auto - aarch64-apple","os":"macos-14","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DEVELOPER_DIR":"/Applications/Xcode_15.4.app/Contents/Developer","MACOSX_DEPLOYMENT_TARGET":11.0,"MACOSX_STD_DEPLOYMENT_TARGET":11.0,"NO_DEBUG_ASSERTIONS":1,"NO_LLVM_ASSERTIONS":1,"NO_OVERFLOW_CHECKS":1,"RUSTC_RETRY_LINKER_ON_SEGFAULT":1,"RUST_CONFIGURE_ARGS":"--enable-sanitizers --enable-profiler --set rust.jemalloc","SCRIPT":"./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin","TOOLSTATE_PUBLISH":1,"USE_XCODE_CLANG":1}},{"name":"dist-i686-msvc","full_name":"auto - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}},{"name":"pr-check-1","full_name":"auto - pr-check-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"pr-check-2","full_name":"auto - pr-check-2","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"tidy","full_name":"auto - tidy","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true,"doc_url":"https://foo.bar"}] + jobs=[{"name":"aarch64-gnu","full_name":"auto - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"x86_64-gnu-llvm-18-1","full_name":"auto - x86_64-gnu-llvm-18-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DOCKER_SCRIPT":"stage_2_test_set1.sh","IMAGE":"x86_64-gnu-llvm-18","READ_ONLY_SRC":"0","RUST_BACKTRACE":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"aarch64-apple","full_name":"auto - aarch64-apple","os":"macos-14","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DEVELOPER_DIR":"/Applications/Xcode_15.4.app/Contents/Developer","MACOSX_DEPLOYMENT_TARGET":11.0,"MACOSX_STD_DEPLOYMENT_TARGET":11.0,"NO_DEBUG_ASSERTIONS":1,"NO_LLVM_ASSERTIONS":1,"NO_OVERFLOW_CHECKS":1,"RUSTC_RETRY_LINKER_ON_SEGFAULT":1,"RUST_CONFIGURE_ARGS":"--enable-sanitizers --enable-profiler --set rust.jemalloc","SCRIPT":"./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin","TOOLSTATE_PUBLISH":1}},{"name":"dist-i686-msvc","full_name":"auto - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}},{"name":"pr-check-1","full_name":"auto - pr-check-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"pr-check-2","full_name":"auto - pr-check-2","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"tidy","full_name":"auto - tidy","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true,"doc_url":"https://foo.bar"}] run_type=auto "#); } diff --git a/src/ci/citool/tests/test-jobs.yml b/src/ci/citool/tests/test-jobs.yml index 95cd328e7848..b2dded6a98e2 100644 --- a/src/ci/citool/tests/test-jobs.yml +++ b/src/ci/citool/tests/test-jobs.yml @@ -113,7 +113,6 @@ auto: --set rust.jemalloc RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer - USE_XCODE_CLANG: 1 # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else # supports the hardware, so only need to test it there. MACOSX_DEPLOYMENT_TARGET: 11.0 diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 6f333ecde79b..dec8876519ed 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -460,7 +460,6 @@ auto: MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer - USE_XCODE_CLANG: 1 DIST_REQUIRE_ALL_TOOLS: 1 CODEGEN_BACKENDS: llvm,cranelift <<: *job-macos @@ -497,7 +496,6 @@ auto: MACOSX_DEPLOYMENT_TARGET: 11.0 MACOSX_STD_DEPLOYMENT_TARGET: 11.0 DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer - USE_XCODE_CLANG: 1 DIST_REQUIRE_ALL_TOOLS: 1 CODEGEN_BACKENDS: llvm,cranelift <<: *job-macos @@ -512,7 +510,6 @@ auto: --enable-profiler --set rust.jemalloc DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer - USE_XCODE_CLANG: 1 # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else # supports the hardware, so only need to test it there. MACOSX_DEPLOYMENT_TARGET: 11.0 diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh index 657e1492a6d6..889f6ea692bc 100755 --- a/src/ci/scripts/install-clang.sh +++ b/src/ci/scripts/install-clang.sh @@ -9,35 +9,28 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" -# Update both macOS's and Windows's tarballs when bumping the version here. +# Update Windows's tarballs when bumping the version here. # Try to keep this in sync with src/ci/docker/scripts/build-clang.sh LLVM_VERSION="20.1.3" if isMacOS; then - # FIXME: This is the latest pre-built version of LLVM that's available for - # x86_64 MacOS. We may want to consider building our own LLVM binaries - # instead, or set `USE_XCODE_CLANG` like AArch64 does. - LLVM_VERSION="15.0.7" - - # If the job selects a specific Xcode version, use that instead of - # downloading our own version. - if [[ ${USE_XCODE_CLANG-0} -eq 1 ]]; then - bindir="$(xcode-select --print-path)/Toolchains/XcodeDefault.xctoolchain/usr/bin" - else - file="${MIRRORS_BASE}/clang%2Bllvm-${LLVM_VERSION}-x86_64-apple-darwin21.0.tar.xz" - retry curl -f "${file}" -o "clang+llvm-${LLVM_VERSION}-x86_64-apple-darwin21.0.tar.xz" - tar xJf "clang+llvm-${LLVM_VERSION}-x86_64-apple-darwin21.0.tar.xz" - bindir="$(pwd)/clang+llvm-${LLVM_VERSION}-x86_64-apple-darwin21.0/bin" - fi + # Clang comes preinstalled on macOS via Xcode, so let's use that. + # + # Besides, it's kind of a hazzle to install it manually, since LLVM no + # longer provide prebuilt macOS x86_64 binaries. + bindir="$(xcode-select --print-path)/Toolchains/XcodeDefault.xctoolchain/usr/bin" ciCommandSetEnv CC "${bindir}/clang" ciCommandSetEnv CXX "${bindir}/clang++" - # macOS 10.15 onwards doesn't have libraries in /usr/include anymore: those - # are now located deep into the filesystem, under Xcode's own files. The - # native clang is configured to use the correct path, but our custom one - # doesn't. This sets the SDKROOT environment variable to the SDK so that - # our own clang can figure out the correct include path on its own. + # macOS 10.15 onwards doesn't have libraries in /usr/include anymore: + # those are now located deep into the filesystem, under Xcode's own files. + # + # The binary in `/usr/bin/clang` is a magical "trampoline" binary that + # sets this environment variable and invokes the real Clang binary, which + # makes invoking `clang` still work in the common case, but since we point + # to the real Clang binary directly above, we need to also set this + # variable ourselves. ciCommandSetEnv SDKROOT "$(xcrun --sdk macosx --show-sdk-path)" # Configure `AR` specifically so bootstrap doesn't try to infer it as From 19a7bd9a97e087e2070396d3310f7aee8aa89898 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Tue, 3 Feb 2026 00:43:13 +0100 Subject: [PATCH 598/978] Remove AR=ar env var Bootstrap no longer infers the archiver as `clang-ar`, so we don't need to set this explicitly. --- src/ci/scripts/install-clang.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh index 889f6ea692bc..bd929a975e32 100755 --- a/src/ci/scripts/install-clang.sh +++ b/src/ci/scripts/install-clang.sh @@ -32,10 +32,6 @@ if isMacOS; then # to the real Clang binary directly above, we need to also set this # variable ourselves. ciCommandSetEnv SDKROOT "$(xcrun --sdk macosx --show-sdk-path)" - - # Configure `AR` specifically so bootstrap doesn't try to infer it as - # `clang-ar` by accident. - ciCommandSetEnv AR "ar" elif isWindows && ! isKnownToBeMingwBuild; then # If we're compiling for MSVC then we, like most other distribution builders, # switch to clang as the compiler. This'll allow us eventually to enable LTO From 3882573751461114c16817006a0c9f04387c546e Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Tue, 3 Feb 2026 00:46:24 +0100 Subject: [PATCH 599/978] Always use default Clang on macOS Instead of manually setting up CC/CXX environment variables, use the default configuration that Xcode gives us. --- src/ci/scripts/install-clang.sh | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh index bd929a975e32..75e8fc240660 100755 --- a/src/ci/scripts/install-clang.sh +++ b/src/ci/scripts/install-clang.sh @@ -13,26 +13,7 @@ source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" # Try to keep this in sync with src/ci/docker/scripts/build-clang.sh LLVM_VERSION="20.1.3" -if isMacOS; then - # Clang comes preinstalled on macOS via Xcode, so let's use that. - # - # Besides, it's kind of a hazzle to install it manually, since LLVM no - # longer provide prebuilt macOS x86_64 binaries. - bindir="$(xcode-select --print-path)/Toolchains/XcodeDefault.xctoolchain/usr/bin" - - ciCommandSetEnv CC "${bindir}/clang" - ciCommandSetEnv CXX "${bindir}/clang++" - - # macOS 10.15 onwards doesn't have libraries in /usr/include anymore: - # those are now located deep into the filesystem, under Xcode's own files. - # - # The binary in `/usr/bin/clang` is a magical "trampoline" binary that - # sets this environment variable and invokes the real Clang binary, which - # makes invoking `clang` still work in the common case, but since we point - # to the real Clang binary directly above, we need to also set this - # variable ourselves. - ciCommandSetEnv SDKROOT "$(xcrun --sdk macosx --show-sdk-path)" -elif isWindows && ! isKnownToBeMingwBuild; then +if isWindows && ! isKnownToBeMingwBuild; then # If we're compiling for MSVC then we, like most other distribution builders, # switch to clang as the compiler. This'll allow us eventually to enable LTO # amongst LLVM and rustc. Note that we only do this on MSVC as I don't think From 8e26944f625951fd5611fc53e0204d20a2c8a111 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 2 Feb 2026 10:29:32 -0800 Subject: [PATCH 600/978] Update wasi-sdk used in CI/releases This is similar to prior updates such as 149037 in that this is just updating a URL. This update though has some technical updates accompanying it as well, however: * The `wasm32-wasip2` target no longer uses APIs from WASIp1 on this target, even for startup. This means that the final binary no longer has an "adapter" which can help making instantiation of a component a bit more lean. * In 147572 libstd was updated to use wasi-libc more often on the `wasm32-wasip2` target. This uncovered a number of bugs in wasi-libc such as 149864, 150291, and 151016. These are all fixed in wasi-sdk-30 so the workarounds in the standard library are all removed. Overall this is not expected to have any sort of major impact on users of WASI targets. Instead it's expected to be a normal routine update to keep the wheels greased and oiled. --- library/std/src/sys/fs/unix.rs | 3 --- library/std/src/sys/thread/unix.rs | 9 --------- src/ci/docker/host-x86_64/dist-various-2/Dockerfile | 4 ++-- src/ci/docker/host-x86_64/pr-check-2/Dockerfile | 4 ++-- src/ci/docker/host-x86_64/test-various/Dockerfile | 4 ++-- 5 files changed, 6 insertions(+), 18 deletions(-) diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 3ca84db0f47f..7db474544f04 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -2132,9 +2132,6 @@ pub fn link(original: &CStr, link: &CStr) -> io::Result<()> { // Android has `linkat` on newer versions, but we happen to know // `link` always has the correct behavior, so it's here as well. target_os = "android", - // wasi-sdk-29-and-prior have a buggy `linkat` so use `link` instead - // until wasi-sdk is updated (see WebAssembly/wasi-libc#690) - target_os = "wasi", // Other misc platforms target_os = "horizon", target_os = "vita", diff --git a/library/std/src/sys/thread/unix.rs b/library/std/src/sys/thread/unix.rs index b758737d00c6..22f9bfef5a38 100644 --- a/library/std/src/sys/thread/unix.rs +++ b/library/std/src/sys/thread/unix.rs @@ -44,15 +44,6 @@ impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn new(stack: usize, init: Box) -> io::Result { - // FIXME: remove this block once wasi-sdk is updated with the fix from - // https://github.com/WebAssembly/wasi-libc/pull/716 - // WASI does not support threading via pthreads. While wasi-libc provides - // pthread stubs, pthread_create returns EAGAIN, which causes confusing - // errors. We return UNSUPPORTED_PLATFORM directly instead. - if cfg!(all(target_os = "wasi", not(target_feature = "atomics"))) { - return Err(io::Error::UNSUPPORTED_PLATFORM); - } - let data = init; let mut attr: mem::MaybeUninit = mem::MaybeUninit::uninit(); assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0); diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index 323cd409a978..dacf3c0db202 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -85,9 +85,9 @@ RUN /tmp/build-fuchsia-toolchain.sh COPY host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/ RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh -RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-29/wasi-sdk-29.0-x86_64-linux.tar.gz | \ +RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-30/wasi-sdk-30.0-x86_64-linux.tar.gz | \ tar -xz -ENV WASI_SDK_PATH=/tmp/wasi-sdk-29.0-x86_64-linux +ENV WASI_SDK_PATH=/tmp/wasi-sdk-30.0-x86_64-linux COPY scripts/freebsd-toolchain.sh /tmp/ RUN /tmp/freebsd-toolchain.sh i686 diff --git a/src/ci/docker/host-x86_64/pr-check-2/Dockerfile b/src/ci/docker/host-x86_64/pr-check-2/Dockerfile index 68162d136c3f..885bf0b30b18 100644 --- a/src/ci/docker/host-x86_64/pr-check-2/Dockerfile +++ b/src/ci/docker/host-x86_64/pr-check-2/Dockerfile @@ -21,9 +21,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ mingw-w64 \ && rm -rf /var/lib/apt/lists/* -RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-29/wasi-sdk-29.0-x86_64-linux.tar.gz | \ +RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-30/wasi-sdk-30.0-x86_64-linux.tar.gz | \ tar -xz -ENV WASI_SDK_PATH=/wasi-sdk-29.0-x86_64-linux +ENV WASI_SDK_PATH=/wasi-sdk-30.0-x86_64-linux ENV RUST_CONFIGURE_ARGS="--set rust.validate-mir-opts=3" diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile index 9b1bf6c0df99..6512240730cc 100644 --- a/src/ci/docker/host-x86_64/test-various/Dockerfile +++ b/src/ci/docker/host-x86_64/test-various/Dockerfile @@ -41,9 +41,9 @@ WORKDIR / COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-29/wasi-sdk-29.0-x86_64-linux.tar.gz | \ +RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-30/wasi-sdk-30.0-x86_64-linux.tar.gz | \ tar -xz -ENV WASI_SDK_PATH=/wasi-sdk-29.0-x86_64-linux +ENV WASI_SDK_PATH=/wasi-sdk-30.0-x86_64-linux ENV RUST_CONFIGURE_ARGS \ --musl-root-x86_64=/usr/local/x86_64-linux-musl \ From eb9d5153dc3eee1a051d7d4b4862c1b655faf183 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 5 Feb 2026 19:30:33 +0100 Subject: [PATCH 601/978] extract `TyAndLayout::peel_transparent_wrappers` helper --- compiler/rustc_abi/src/layout/ty.rs | 16 ++++++++++++++-- .../src/hir_ty_lowering/cmse.rs | 16 ++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index 41ad14f550ab..aafb124986e1 100644 --- a/compiler/rustc_abi/src/layout/ty.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -290,7 +290,19 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { /// function call isn't allowed (a.k.a. `va_list`). /// /// This function handles transparent types automatically. - pub fn pass_indirectly_in_non_rustic_abis(mut self, cx: &C) -> bool + pub fn pass_indirectly_in_non_rustic_abis(self, cx: &C) -> bool + where + Ty: TyAbiInterface<'a, C> + Copy, + { + let base = self.peel_transparent_wrappers(cx); + Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(base) + } + + /// Recursively peel away transparent wrappers, returning the inner value. + /// + /// The return value is not `repr(transparent)` and/or does + /// not have a non-1zst field. + pub fn peel_transparent_wrappers(mut self, cx: &C) -> Self where Ty: TyAbiInterface<'a, C> + Copy, { @@ -300,7 +312,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { self = field; } - Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(self) + self } /// Finds the one field that is not a 1-ZST. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 6b8c2e4d0610..58c296d92c24 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -160,7 +160,7 @@ fn is_valid_cmse_output<'tcx>( } /// Returns whether the output will fit into the available registers -fn is_valid_cmse_output_layout<'tcx>(cx: LayoutCx<'tcx>, mut layout: TyAndLayout<'tcx>) -> bool { +fn is_valid_cmse_output_layout<'tcx>(cx: LayoutCx<'tcx>, layout: TyAndLayout<'tcx>) -> bool { let size = layout.layout.size().bytes(); if size <= 4 { @@ -169,21 +169,9 @@ fn is_valid_cmse_output_layout<'tcx>(cx: LayoutCx<'tcx>, mut layout: TyAndLayout return false; } - // Find the wrapped inner type of a transparent wrapper. - loop { - match layout.ty.kind() { - ty::Adt(adt_def, _) if adt_def.repr().transparent() => { - // Find the non-1-ZST field, and recurse. - (_, layout) = layout.non_1zst_field(&cx).unwrap(); - } - // Not a transparent type, no further unfolding. - _ => break, - } - } - // Accept (transparently wrapped) scalar 64-bit primitives. matches!( - layout.ty.kind(), + layout.peel_transparent_wrappers(&cx).ty.kind(), ty::Int(ty::IntTy::I64) | ty::Uint(ty::UintTy::U64) | ty::Float(ty::FloatTy::F64) ) } From bce8c00e2f6bbd0d68a42fc7ee09b9eae6303f33 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 01:13:41 +0100 Subject: [PATCH 602/978] Remove the 4 failing tests from rustdoc-gui --- tests/rustdoc-gui/headers-color.goml | 71 ----- tests/rustdoc-gui/notable-trait.goml | 256 ------------------- tests/rustdoc-gui/search-filter.goml | 86 ------- tests/rustdoc-gui/search-result-display.goml | 114 --------- 4 files changed, 527 deletions(-) delete mode 100644 tests/rustdoc-gui/headers-color.goml delete mode 100644 tests/rustdoc-gui/notable-trait.goml delete mode 100644 tests/rustdoc-gui/search-filter.goml delete mode 100644 tests/rustdoc-gui/search-result-display.goml diff --git a/tests/rustdoc-gui/headers-color.goml b/tests/rustdoc-gui/headers-color.goml deleted file mode 100644 index 81346fc12d06..000000000000 --- a/tests/rustdoc-gui/headers-color.goml +++ /dev/null @@ -1,71 +0,0 @@ -// This test check for headings text and background colors for the different themes. - -include: "utils.goml" - -define-function: ( - "check-colors", - [theme, color, code_header_color, focus_background_color, headings_color], - block { - go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" - // This is needed so that the text color is computed. - show-text: true - call-function: ("switch-theme", {"theme": |theme|}) - assert-css: ( - ".impl", - {"color": |color|, "background-color": "rgba(0, 0, 0, 0)"}, - ALL, - ) - assert-css: ( - ".impl .code-header", - {"color": |code_header_color|, "background-color": "rgba(0, 0, 0, 0)"}, - ALL, - ) - go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#impl-Foo" - assert-css: ( - "#impl-Foo", - {"color": |color|, "background-color": |focus_background_color|}, - ) - go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#method.must_use" - assert-css: ( - "#method\.must_use", - {"color": |color|, "background-color": |focus_background_color|}, - ALL, - ) - go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" - assert-css: (".section-header a", {"color": |color|}, ALL) - go-to: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html" - // We select headings (h2, h3, h...). - assert-css: (".docblock > :not(p) > a", {"color": |headings_color|}, ALL) - }, -) - -call-function: ( - "check-colors", - { - "theme": "ayu", - "color": "#c5c5c5", - "code_header_color": "#e6e1cf", - "focus_background_color": "rgba(255, 236, 164, 0.06)", - "headings_color": "#c5c5c5", - }, -) -call-function: ( - "check-colors", - { - "theme": "dark", - "color": "#ddd", - "code_header_color": "#ddd", - "focus_background_color": "#494a3d", - "headings_color": "#ddd", - }, -) -call-function: ( - "check-colors", - { - "theme": "light", - "color": "black", - "code_header_color": "black", - "focus_background_color": "#fdffd3", - "headings_color": "black", - }, -) diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml deleted file mode 100644 index 8e4c180e0ef1..000000000000 --- a/tests/rustdoc-gui/notable-trait.goml +++ /dev/null @@ -1,256 +0,0 @@ -// This test checks the position of the `i` for the notable traits. -include: "utils.goml" -go-to: "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html" -show-text: true - -define-function: ( - "check-notable-tooltip-position", - [x, i_x], - block { - // Checking they have the same y position. - compare-elements-position-near: ( - "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']", - "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", - {"y": 1}, - ) - // Checking they don't have the same x position. - compare-elements-position-false: ( - "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']", - "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", - ["x"], - ) - // The `i` should be *after* the type. - assert-position: ( - "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']", - {"x": |x|}, - ) - assert-position: ( - "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", - {"x": |i_x|}, - ) - }, -) - -define-function: ( - "check-notable-tooltip-position-complete", - [x, i_x, popover_x], - block { - call-function: ("check-notable-tooltip-position", {"x": |x|, "i_x": |i_x|}) - assert-count: ("//*[@class='tooltip popover']", 0) - click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']" - assert-count: ("//*[@class='tooltip popover']", 1) - compare-elements-position-near: ( - "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", - "//*[@class='tooltip popover']", - {"y": 30} - ) - compare-elements-position-false: ( - "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", - "//*[@class='tooltip popover']", - ["x"] - ) - assert-position: ( - "//*[@class='tooltip popover']", - {"x": |popover_x|} - ) - click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']" - move-cursor-to: "//h1" - assert-count: ("//*[@class='tooltip popover']", 0) - }, -) - -// We start with a wide screen. -set-window-size: (1100, 600) -call-function: ("check-notable-tooltip-position-complete", { - "x": 682, - "i_x": 960, - "popover_x": 468, -}) - -// Now only the `i` should be on the next line. -set-window-size: (1055, 600) -compare-elements-position-false: ( - "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']", - "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", - ["y", "x"], -) - -// Now both the `i` and the struct name should be on the next line. -set-window-size: (980, 600) -call-function: ("check-notable-tooltip-position", { - "x": 250, - "i_x": 528, -}) - -go-to: "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html" -// This is needed to ensure that the text color is computed. -show-text: true - -// Now check the colors. -define-function: ( - "check-colors", - [theme, header_color, content_color, type_color, trait_color, link_color], - block { - call-function: ("switch-theme", {"theme": |theme|}) - - assert-css: ( - "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", - {"color": |content_color|}, - ALL, - ) - - move-cursor-to: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']" - wait-for-count: (".tooltip.popover", 1) - - assert-css: ( - "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", - {"color": |link_color|}, - ALL, - ) - - assert-css: ( - ".tooltip.popover h3", - {"color": |header_color|}, - ALL, - ) - assert-css: ( - ".tooltip.popover pre", - {"color": |content_color|}, - ALL, - ) - assert-css: ( - ".tooltip.popover pre a.struct", - {"color": |type_color|}, - ALL, - ) - assert-css: ( - ".tooltip.popover pre a.trait", - {"color": |trait_color|}, - ALL, - ) - }, -) - -call-function: ( - "check-colors", - { - "theme": "ayu", - "link_color": "#39afd7", - "content_color": "#e6e1cf", - "header_color": "#fff", - "type_color": "#ffa0a5", - "trait_color": "#39afd7", - }, -) - -call-function: ( - "check-colors", - { - "theme": "dark", - "link_color": "#d2991d", - "content_color": "#ddd", - "header_color": "#ddd", - "type_color": "#2dbfb8", - "trait_color": "#b78cf2", - }, -) - -call-function: ( - "check-colors", - { - "theme": "light", - "link_color": "#3873ad", - "content_color": "black", - "header_color": "black", - "type_color": "#ad378a", - "trait_color": "#6e4fc9", - }, -) - -// Checking on mobile now. -set-window-size: (650, 600) -wait-for-size: ("body", {"width": 650}) -call-function: ("check-notable-tooltip-position-complete", { - "x": 26, - "i_x": 305, - "popover_x": 0, -}) - -reload: - -// Check that pressing escape works -click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']" -move-cursor-to: "//*[@class='tooltip popover']" -assert-count: ("//*[@class='tooltip popover']", 1) -press-key: "Escape" -assert-count: ("//*[@class='tooltip popover']", 0) -assert: "#method\.create_an_iterator_from_read .tooltip:focus" - -// Check that clicking outside works. -click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']" -assert-count: ("//*[@class='tooltip popover']", 1) -click: ".main-heading h1" -assert-count: ("//*[@class='tooltip popover']", 0) -assert-false: "#method\.create_an_iterator_from_read .tooltip:focus" - -// Check that pressing tab over and over works. -click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']" -move-cursor-to: "//*[@class='tooltip popover']" -assert-count: ("//*[@class='tooltip popover']", 1) -press-key: "Tab" -press-key: "Tab" -press-key: "Tab" -press-key: "Tab" -press-key: "Tab" -press-key: "Tab" -press-key: "Tab" -assert-count: ("//*[@class='tooltip popover']", 0) -assert: "#method\.create_an_iterator_from_read .tooltip:focus" - -define-function: ( - "setup-popup", - [], - block { - store-window-property: {"scrollY": scroll} - click: "#method\.create_an_iterator_from_read .fn" - // We ensure that the scroll position changed. - assert-window-property-false: {"scrollY": |scroll|} - // Store the new position. - store-window-property: {"scrollY": scroll} - click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']" - wait-for: "//*[@class='tooltip popover']" - click: ".main-heading h1" - } -) - -// Now we check that the focus isn't given back to the wrong item when opening -// another popover. -call-function: ("setup-popup", {}) -click: ".main-heading h1" -// We ensure we didn't come back to the previous focused item. -assert-window-property-false: {"scrollY": |scroll|} - -// Same but with Escape handling. -call-function: ("setup-popup", {}) -press-key: "Escape" -// We ensure we didn't come back to the previous focused item. -assert-window-property-false: {"scrollY": |scroll|} - -// Opening the mobile sidebar should close the popover. -set-window-size: (650, 600) -click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']" -assert-count: ("//*[@class='tooltip popover']", 1) -click: ".sidebar-menu-toggle" -assert: "//*[@class='sidebar shown']" -assert-count: ("//*[@class='tooltip popover']", 0) -assert-false: "#method\.create_an_iterator_from_read .tooltip:focus" - -// Also check the focus handling for the settings button. -set-window-size: (1100, 600) -reload: -assert-count: ("//*[@class='tooltip popover']", 0) -click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']" -wait-for-count: ("//*[@class='tooltip popover']", 1) -call-function: ("open-settings-menu", {}) -wait-for-count: ("//*[@class='tooltip popover']", 0) -assert-false: "#method\.create_an_iterator_from_read .tooltip:focus" diff --git a/tests/rustdoc-gui/search-filter.goml b/tests/rustdoc-gui/search-filter.goml deleted file mode 100644 index 6bd7eaa92063..000000000000 --- a/tests/rustdoc-gui/search-filter.goml +++ /dev/null @@ -1,86 +0,0 @@ -// Checks that the crate search filtering is handled correctly and changes the results. -include: "utils.goml" -go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" -show-text: true -call-function: ("perform-search", {"query": "test"}) -assert-text: ("#results .externcrate", "test_docs") - -wait-for: "#crate-search" -// We now want to change the crate filter. -click: "#crate-search" -// We select "lib2" option then press enter to change the filter. -press-key: "ArrowDown" -press-key: "ArrowDown" -press-key: "ArrowDown" -press-key: "ArrowDown" -press-key: "ArrowDown" -press-key: "Enter" -// Waiting for the search results to appear... -wait-for: "#search-tabs" -wait-for-false: "#search-tabs .count.loading" -assert-document-property: ({"URL": "&filter-crate="}, CONTAINS) -// We check that there is no more "test_docs" appearing. -assert-false: "#results .externcrate" -// We also check that "lib2" is the filter crate. -assert-property: ("#crate-search", {"value": "lib2"}) - -// Now we check that leaving the search results and putting them back keeps the -// crate filtering. -press-key: "Escape" -wait-for-css: ("#main-content", {"display": "block"}) -click: "#search-button" -wait-for: ".search-input" -wait-for-css: ("#main-content", {"display": "none"}) -// We check that there is no more "test_docs" appearing. -assert-false: "#results .externcrate" -assert-property: ("#crate-search", {"value": "lib2"}) - -// Selecting back "All crates" -click: "#crate-search" -press-key: "ArrowUp" -press-key: "ArrowUp" -press-key: "ArrowUp" -press-key: "ArrowUp" -press-key: "ArrowUp" -press-key: "Enter" -// Waiting for the search results to appear... -wait-for: "#search-tabs" -wait-for-false: "#search-tabs .count.loading" -assert-property: ("#crate-search", {"value": "all crates"}) - -// Checking that the URL parameter is taken into account for crate filtering. -go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=test&filter-crate=lib2" -wait-for: "#crate-search" -assert-property: ("#crate-search", {"value": "lib2"}) -assert-false: "#results .externcrate" - -// Checking that the text for the "title" is correct (the "all crates" comes from the "` is correctly handled when it goes to next line. -// To do so we need to update the length of one of its `

` (where P is one of the previous types except `Self`) - -hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty}` - .note = type of `self` must be `Self` or some type implementing `Receiver` - -hir_analysis_invalid_receiver_ty_help = - consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` - -hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types = - consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) - -hir_analysis_invalid_receiver_ty_help_nonnull_note = - `NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver` - -hir_analysis_invalid_receiver_ty_help_weak_note = - `Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver` - -hir_analysis_invalid_receiver_ty_no_arbitrary_self_types = invalid `self` parameter type: `{$receiver_ty}` - .note = type of `self` must be `Self` or a type that dereferences to it - -hir_analysis_invalid_union_field = - field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union - .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` - -hir_analysis_invalid_union_field_sugg = - wrap the field type in `ManuallyDrop<...>` - -hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl - .label = const parameter declared here - -hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetimes from an fn or impl - .label = lifetime declared here - -hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl - .label = type parameter declared here - -hir_analysis_lifetime_implicitly_captured = `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - .param_label = all lifetime parameters originating from a trait are captured implicitly - -hir_analysis_lifetime_must_be_first = lifetime parameter `{$name}` must be listed before non-lifetime parameters - .label = move the lifetime before this parameter - -hir_analysis_lifetime_not_captured = `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - .label = lifetime captured due to being mentioned in the bounds of the `impl Trait` - .param_label = this lifetime parameter is captured - -hir_analysis_lifetimes_or_bounds_mismatch_on_eii = - lifetime parameters or bounds of `{$ident}` do not match the declaration - .label = lifetimes do not match - .generics_label = lifetimes in impl do not match this signature - .where_label = this `where` clause might not match the one in the declaration - .bounds_label = this bound might be missing in the implementation - -hir_analysis_lifetimes_or_bounds_mismatch_on_trait = - lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration - .label = lifetimes do not match {$item_kind} in trait - .generics_label = lifetimes in impl do not match this {$item_kind} in trait - .where_label = this `where` clause might not match the one in the trait - .bounds_label = this bound might be missing in the impl - -hir_analysis_linkage_type = - invalid type for variable with `#[linkage]` attribute - -hir_analysis_main_function_async = `main` function is not allowed to be `async` - .label = `main` function is not allowed to be `async` - -hir_analysis_main_function_generic_parameters = `main` function is not allowed to have generic parameters - .label = `main` cannot have generic parameters - -hir_analysis_main_function_return_type_generic = `main` function return type is not allowed to have generic parameters - -hir_analysis_manual_implementation = - manual implementations of `{$trait_name}` are experimental - .label = manual implementations of `{$trait_name}` are experimental - .help = add `#![feature(unboxed_closures)]` to the crate attributes to enable - -hir_analysis_method_should_return_future = method should be `async` or return a future, but it is synchronous - .note = this method is `async` so it expects a future to be returned - -hir_analysis_missing_generic_params = - the {$descr} {$parameterCount -> - [one] parameter - *[other] parameters - } {$parameters} must be explicitly specified - .label = {$descr} {$parameterCount -> - [one] parameter - *[other] parameters - } {$parameters} must be specified for this - .suggestion = explicitly specify the {$descr} {$parameterCount -> - [one] parameter - *[other] parameters - } - .no_suggestion_label = missing {$parameterCount -> - [one] reference - *[other] references - } to {$parameters} - .note = because the parameter {$parameterCount -> - [one] default references - *[other] defaults reference - } `Self`, the {$parameterCount -> - [one] parameter - *[other] parameters - } must be specified on the trait object type - -hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}` - .label = missing one of `{$missing_items_msg}` in implementation - .note = required because of this annotation - -hir_analysis_missing_trait_item = not all trait items implemented, missing: `{$missing_items_msg}` - .label = missing `{$missing_items_msg}` in implementation - -hir_analysis_missing_trait_item_label = `{$item}` from trait - -hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snippet}` - -hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}` - .note = default implementation of `{$missing_item_name}` is unstable - .some_note = use of unstable library feature `{$feature}`: {$reason} - .none_note = use of unstable library feature `{$feature}` - -hir_analysis_no_variant_named = no variant named `{$ident}` found for enum `{$ty}` - -hir_analysis_not_supported_delegation = {$descr} - .label = callee defined here - -hir_analysis_only_current_traits_adt = `{$name}` is not defined in the current crate - -hir_analysis_only_current_traits_arbitrary = only traits defined in the current crate can be implemented for arbitrary types - -hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait - -hir_analysis_only_current_traits_name = this is not defined in the current crate because {$name} are always foreign - -hir_analysis_only_current_traits_note = define and implement a trait or new type instead - -hir_analysis_only_current_traits_note_more_info = for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules - -hir_analysis_only_current_traits_note_uncovered = impl doesn't have any local type before any uncovered type parameters - -hir_analysis_only_current_traits_opaque = type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate - -hir_analysis_only_current_traits_outside = only traits defined in the current crate can be implemented for types defined outside of the crate - -hir_analysis_only_current_traits_pointer = `{$pointer}` is not defined in the current crate because raw pointers are always foreign - -hir_analysis_only_current_traits_pointer_sugg = consider introducing a new wrapper type - -hir_analysis_only_current_traits_primitive = only traits defined in the current crate can be implemented for primitive types - -hir_analysis_only_current_traits_ty = `{$ty}` is not defined in the current crate - -hir_analysis_opaque_captures_higher_ranked_lifetime = `impl Trait` cannot capture {$bad_place} - .label = `impl Trait` implicitly captures all lifetimes in scope - .note = lifetime declared here - -hir_analysis_param_in_ty_of_assoc_const_binding = - the type of the associated constant `{$assoc_const}` must not depend on {$param_category -> - [self] `Self` - [synthetic] `impl Trait` - *[normal] generic parameters - } - .label = its type must not depend on {$param_category -> - [self] `Self` - [synthetic] `impl Trait` - *[normal] the {$param_def_kind} `{$param_name}` - } - .param_defined_here_label = {$param_category -> - [synthetic] the `impl Trait` is specified here - *[normal] the {$param_def_kind} `{$param_name}` is defined here - } - -hir_analysis_param_not_captured = `impl Trait` must mention all {$kind} parameters in scope in `use<...>` - .label = {$kind} parameter is implicitly captured by this `impl Trait` - .note = currently, all {$kind} parameters are required to be mentioned in the precise captures list - -hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation - .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it - -hir_analysis_parenthesized_fn_trait_expansion = - parenthesized trait syntax expands to `{$expanded_type}` - -hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind} - .label = not allowed in type signatures - -hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias - .label = `Self` is not a generic argument, but an alias to the type of the {$what} - -hir_analysis_recursive_generic_parameter = {$param_def_kind} `{$param_name}` is only used recursively - .label = {$param_def_kind} must be used non-recursively in the definition - .note = all type parameters must be used in a non-recursive way in order to constrain their variance - -hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}` - .note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}` - -hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}` - -hir_analysis_return_type_notation_equality_bound = - return type notation is not allowed to use type equality - -hir_analysis_return_type_notation_illegal_param_const = - return type notation is not allowed for functions that have const parameters - .label = const parameter declared here -hir_analysis_return_type_notation_illegal_param_type = - return type notation is not allowed for functions that have type parameters - .label = type parameter declared here - -hir_analysis_return_type_notation_on_non_rpitit = - return type notation used on function that is not `async` and does not return `impl Trait` - .note = function returns `{$ty}`, which is not compatible with associated type return bounds - .label = this function must be `async` or return `impl Trait` - -hir_analysis_rpitit_refined = impl trait in impl method signature does not match trait method signature - .suggestion = replace the return type so that it matches the trait - .label = return type from trait method defined here - .unmatched_bound_label = this bound is stronger than that defined on the trait - .note = add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate - .feedback_note = we are soliciting feedback, see issue #121718 for more information - -hir_analysis_rpitit_refined_lifetimes = impl trait in impl method captures fewer lifetimes than in trait - .suggestion = modify the `use<..>` bound to capture the same lifetimes that the trait does - .note = add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate - .feedback_note = we are soliciting feedback, see issue #121718 for more information - -hir_analysis_self_in_impl_self = - `Self` is not valid in the self type of an impl block - .note = replace `Self` with a different type - -hir_analysis_self_ty_not_captured = `impl Trait` must mention the `Self` type of the trait in `use<...>` - .label = `Self` type parameter is implicitly captured by this `impl Trait` - .note = currently, all type parameters are required to be mentioned in the precise captures list - -hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code - .help = add `#![feature(simd_ffi)]` to the crate attributes to enable - -hir_analysis_specialization_trait = implementing `rustc_specialization_trait` traits is unstable - .help = add `#![feature(min_specialization)]` to the crate attributes to enable - -hir_analysis_static_specialize = cannot specialize on `'static` lifetime - -hir_analysis_supertrait_item_multiple_shadowee = items from several supertraits are shadowed: {$traits} - -hir_analysis_supertrait_item_shadowee = item from `{$supertrait}` is shadowed by a subtrait item - -hir_analysis_supertrait_item_shadowing = trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait - -hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]` - -hir_analysis_too_large_static = extern static is too large for the target architecture - -hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]` - .suggestion = remove this annotation - -hir_analysis_trait_cannot_impl_for_ty = the trait `{$trait_name}` cannot be implemented for this type - .label = this field does not implement `{$trait_name}` - -hir_analysis_trait_object_declared_with_no_traits = - at least one trait is required for an object type - .alias_span = this alias does not contain a trait - -hir_analysis_traits_with_default_impl = traits with a default impl, like `{$traits}`, cannot be implemented for {$problematic_kind} `{$self_ty}` - .note = a trait object implements `{$traits}` if and only if `{$traits}` is one of the trait object's trait bounds - -hir_analysis_transparent_enum_variant = transparent enum needs exactly one variant, but has {$number} - .label = needs exactly one variant, but has {$number} - .many_label = too many variants in `{$path}` - .multi_label = variant here - -hir_analysis_transparent_non_zero_sized = transparent {$desc} needs at most one field with non-trivial size or alignment, but has {$field_count} - .label = needs at most one field with non-trivial size or alignment, but has {$field_count} - .labels = this field has non-zero size or requires alignment - -hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$desc} needs at most one field with non-trivial size or alignment, but has {$field_count} - .label = needs at most one field with non-trivial size or alignment, but has {$field_count} - .labels = this field has non-zero size or requires alignment - -hir_analysis_ty_of_assoc_const_binding_note = `{$assoc_const}` has type `{$ty}` - -hir_analysis_ty_param_first_local = type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`) - .label = type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`) - .note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type - .case_note = in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last - -hir_analysis_ty_param_some = type parameter `{$param}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param}>`) - .label = type parameter `{$param}` must be used as the type parameter for some local type - .note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local - .only_note = only traits defined in the current crate can be implemented for a type parameter - -hir_analysis_type_of = {$ty} - -hir_analysis_unconstrained_generic_parameter = the {$param_def_kind} `{$param_name}` is not constrained by the impl trait, self type, or predicates - .label = unconstrained {$param_def_kind} - .const_param_note = expressions using a const parameter must map each value to a distinct output value - .const_param_note2 = proving the result of expressions other than the parameter are unique is not supported - -hir_analysis_unconstrained_opaque_type = unconstrained opaque type - .note = `{$name}` must be used in combination with a concrete type within the same {$what} - -hir_analysis_unrecognized_intrinsic_function = - unrecognized intrinsic function: `{$name}` - .label = unrecognized intrinsic - .help = if you're adding an intrinsic, be sure to update `check_intrinsic_type` - -hir_analysis_unused_associated_type_bounds = - unnecessary associated type bound for dyn-incompatible associated type - .note = this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized` - .suggestion = remove this bound - -hir_analysis_unused_generic_parameter = - {$param_def_kind} `{$param_name}` is never used - .label = unused {$param_def_kind} - .const_param_help = if you intended `{$param_name}` to be a const parameter, use `const {$param_name}: /* Type */` instead - .usage_spans = `{$param_name}` is named here, but is likely unused in the containing type - -hir_analysis_unused_generic_parameter_adt_help = - consider removing `{$param_name}`, referring to it in a field, or using a marker such as `{$phantom_data}` -hir_analysis_unused_generic_parameter_adt_no_phantom_data_help = - consider removing `{$param_name}` or referring to it in a field -hir_analysis_unused_generic_parameter_ty_alias_help = - consider removing `{$param_name}` or referring to it in the body of the type alias - -hir_analysis_useless_impl_item = this item cannot be used as its where bounds are not satisfied for the `Self` type - -hir_analysis_value_of_associated_struct_already_specified = - the value of the associated type `{$item_name}` in trait `{$def_path}` is already specified - .label = re-bound here - .previous_bound_label = `{$item_name}` bound here first - -hir_analysis_variadic_function_compatible_convention = C-variadic functions with the {$convention} calling convention are not supported - .label = C-variadic function must have a compatible calling convention - -hir_analysis_variances_of = {$variances} - -hir_analysis_where_clause_on_main = `main` function is not allowed to have a `where` clause - .label = `main` cannot have a `where` clause - -hir_analysis_within_macro = due to this macro variable - -hir_analysis_wrong_number_of_generic_arguments_to_intrinsic = - intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected} - .label = expected {$expected} {$descr} {$expected -> - [one] parameter - *[other] parameters - } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 8b50eceb26e4..d3b5350061a8 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -5,7 +5,9 @@ use hir::intravisit::{self, Visitor}; use rustc_abi::{ExternAbi, ScalableElt}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; -use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; +use rustc_errors::{ + Applicability, ErrorGuaranteed, inline_fluent, pluralize, struct_span_code_err, +}; use rustc_hir::attrs::{AttributeKind, EiiDecl, EiiImpl, EiiImplResolution}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -42,8 +44,8 @@ use {rustc_ast as ast, rustc_hir as hir}; use super::compare_eii::compare_eii_function_types; use crate::autoderef::Autoderef; use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params}; +use crate::errors; use crate::errors::InvalidReceiverTyHint; -use crate::{errors, fluent_generated as fluent}; pub(super) struct WfCheckingCtxt<'a, 'tcx> { pub(super) ocx: ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>, @@ -1740,7 +1742,7 @@ fn check_method_receiver<'tcx>( the `arbitrary_self_types` feature", ), ) - .with_help(fluent::hir_analysis_invalid_receiver_ty_help) + .with_help(inline_fluent!("consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc`")) .emit() } None | Some(ArbitrarySelfTypesLevel::Basic) @@ -1764,7 +1766,7 @@ fn check_method_receiver<'tcx>( the `arbitrary_self_types_pointers` feature", ), ) - .with_help(fluent::hir_analysis_invalid_receiver_ty_help) + .with_help(inline_fluent!("consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc`")) .emit() } _ => @@ -2442,8 +2444,8 @@ fn lint_redundant_lifetimes<'tcx>( } #[derive(LintDiagnostic)] -#[diag(hir_analysis_redundant_lifetime_args)] -#[note] +#[diag("unnecessary lifetime parameter `{$victim}`")] +#[note("you can use the `{$candidate}` lifetime directly, in place of `{$victim}`")] struct RedundantLifetimeArgsLint<'tcx> { /// The lifetime we have found to be redundant. victim: ty::Region<'tcx>, diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index c996fc97cd67..6a23b42ae098 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -4,24 +4,22 @@ use rustc_abi::ExternAbi; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, - MultiSpan, listify, + MultiSpan, inline_fluent, listify, }; use rustc_hir::limit::Limit; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; use rustc_span::{Ident, Span, Symbol}; - -use crate::fluent_generated as fluent; pub(crate) mod wrong_number_of_generic_args; mod precise_captures; pub(crate) use precise_captures::*; #[derive(Diagnostic)] -#[diag(hir_analysis_ambiguous_assoc_item)] +#[diag("ambiguous associated {$assoc_kind} `{$assoc_ident}` in bounds of `{$qself}`")] pub(crate) struct AmbiguousAssocItem<'a> { #[primary_span] - #[label] + #[label("ambiguous associated {$assoc_kind} `{$assoc_ident}`")] pub span: Span, pub assoc_kind: &'static str, pub assoc_ident: Ident, @@ -29,29 +27,26 @@ pub(crate) struct AmbiguousAssocItem<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_assoc_kind_mismatch)] +#[diag("expected {$expected}, found {$got}")] pub(crate) struct AssocKindMismatch { #[primary_span] - #[label] + #[label("unexpected {$got}")] pub span: Span, pub expected: &'static str, pub got: &'static str, - #[label(hir_analysis_expected_because_label)] + #[label("expected a {$expected} because of this associated {$expected}")] pub expected_because_label: Option, pub assoc_kind: &'static str, - #[note] + #[note("the associated {$assoc_kind} is defined here")] pub def_span: Span, - #[label(hir_analysis_bound_on_assoc_const_label)] + #[label("bounds are not allowed on associated constants")] pub bound_on_assoc_const_label: Option, #[subdiagnostic] pub wrap_in_braces_sugg: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion( - hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg, - applicability = "maybe-incorrect" -)] +#[multipart_suggestion("consider adding braces here", applicability = "maybe-incorrect")] pub(crate) struct AssocKindMismatchWrapInBracesSugg { #[suggestion_part(code = "{{ ")] pub lo: Span, @@ -60,19 +55,19 @@ pub(crate) struct AssocKindMismatchWrapInBracesSugg { } #[derive(Diagnostic)] -#[diag(hir_analysis_assoc_item_is_private, code = E0624)] +#[diag("{$kind} `{$name}` is private", code = E0624)] pub(crate) struct AssocItemIsPrivate { #[primary_span] - #[label] + #[label("private {$kind}")] pub span: Span, pub kind: &'static str, pub name: Ident, - #[label(hir_analysis_defined_here_label)] + #[label("the {$kind} is defined here")] pub defined_here_label: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_assoc_item_not_found, code = E0220)] +#[diag("associated {$assoc_kind} `{$assoc_ident}` not found for `{$qself}`", code = E0220)] pub(crate) struct AssocItemNotFound<'a> { #[primary_span] pub span: Span, @@ -83,18 +78,23 @@ pub(crate) struct AssocItemNotFound<'a> { pub label: Option>, #[subdiagnostic] pub sugg: Option>, - #[label(hir_analysis_within_macro)] + #[label("due to this macro variable")] pub within_macro_span: Option, } #[derive(Subdiagnostic)] pub(crate) enum AssocItemNotFoundLabel<'a> { - #[label(hir_analysis_assoc_item_not_found_label)] + #[label("associated {$assoc_kind} `{$assoc_ident}` not found")] NotFound { #[primary_span] span: Span, }, - #[label(hir_analysis_assoc_item_not_found_found_in_other_trait_label)] + #[label( + "there is {$identically_named -> + [true] an + *[false] a similarly named + } associated {$assoc_kind} `{$suggested_name}` in the trait `{$trait_name}`" + )] FoundInOtherTrait { #[primary_span] span: Span, @@ -109,7 +109,7 @@ pub(crate) enum AssocItemNotFoundLabel<'a> { pub(crate) enum AssocItemNotFoundSugg<'a> { #[suggestion( - hir_analysis_assoc_item_not_found_similar_sugg, + "there is an associated {$assoc_kind} with a similar name", code = "{suggested_name}", applicability = "maybe-incorrect" )] @@ -120,7 +120,7 @@ pub(crate) enum AssocItemNotFoundSugg<'a> { suggested_name: Symbol, }, #[suggestion( - hir_analysis_assoc_item_not_found_similar_in_other_trait_sugg, + "change the associated {$assoc_kind} name to use `{$suggested_name}` from `{$trait_name}`", code = "{suggested_name}", style = "verbose", applicability = "maybe-incorrect" @@ -133,7 +133,10 @@ pub(crate) enum AssocItemNotFoundSugg<'a> { suggested_name: Symbol, }, #[multipart_suggestion( - hir_analysis_assoc_item_not_found_similar_in_other_trait_qpath_sugg, + "consider fully qualifying{$identically_named -> + [true] {\"\"} + *[false] {\" \"}and renaming + } the associated {$assoc_kind}", style = "verbose" )] SimilarInOtherTraitQPath { @@ -150,7 +153,7 @@ pub(crate) enum AssocItemNotFoundSugg<'a> { applicability: Applicability, }, #[suggestion( - hir_analysis_assoc_item_not_found_other_sugg, + "`{$qself}` has the following associated {$assoc_kind}", code = "{suggested_name}", applicability = "maybe-incorrect" )] @@ -164,10 +167,15 @@ pub(crate) enum AssocItemNotFoundSugg<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_wrong_number_of_generic_arguments_to_intrinsic, code = E0094)] +#[diag("intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected}", code = E0094)] pub(crate) struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { #[primary_span] - #[label] + #[label( + "expected {$expected} {$descr} {$expected -> + [one] parameter + *[other] parameters + }" + )] pub span: Span, pub found: usize, pub expected: usize, @@ -175,90 +183,90 @@ pub(crate) struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_unrecognized_intrinsic_function, code = E0093)] -#[help] +#[diag("unrecognized intrinsic function: `{$name}`", code = E0093)] +#[help("if you're adding an intrinsic, be sure to update `check_intrinsic_type`")] pub(crate) struct UnrecognizedIntrinsicFunction { #[primary_span] - #[label] + #[label("unrecognized intrinsic")] pub span: Span, pub name: Symbol, } #[derive(Diagnostic)] -#[diag(hir_analysis_lifetimes_or_bounds_mismatch_on_trait, code = E0195)] +#[diag("lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration", code = E0195)] pub(crate) struct LifetimesOrBoundsMismatchOnTrait { #[primary_span] - #[label] + #[label("lifetimes do not match {$item_kind} in trait")] pub span: Span, - #[label(hir_analysis_generics_label)] + #[label("lifetimes in impl do not match this {$item_kind} in trait")] pub generics_span: Span, - #[label(hir_analysis_where_label)] + #[label("this `where` clause might not match the one in the trait")] pub where_span: Option, - #[label(hir_analysis_bounds_label)] + #[label("this bound might be missing in the impl")] pub bounds_span: Vec, pub item_kind: &'static str, pub ident: Ident, } #[derive(Diagnostic)] -#[diag(hir_analysis_drop_impl_on_wrong_item, code = E0120)] +#[diag("the `{$trait_}` trait may only be implemented for local structs, enums, and unions", code = E0120)] pub(crate) struct DropImplOnWrongItem { #[primary_span] - #[label] + #[label("must be a struct, enum, or union in the current crate")] pub span: Span, pub trait_: Symbol, } #[derive(Diagnostic)] pub(crate) enum FieldAlreadyDeclared { - #[diag(hir_analysis_field_already_declared, code = E0124)] + #[diag("field `{$field_name}` is already declared", code = E0124)] NotNested { field_name: Ident, #[primary_span] - #[label] + #[label("field already declared")] span: Span, - #[label(hir_analysis_previous_decl_label)] + #[label("`{$field_name}` first declared here")] prev_span: Span, }, - #[diag(hir_analysis_field_already_declared_current_nested)] + #[diag("field `{$field_name}` is already declared")] CurrentNested { field_name: Ident, #[primary_span] - #[label] + #[label("field `{$field_name}` declared in this unnamed field")] span: Span, - #[note(hir_analysis_nested_field_decl_note)] + #[note("field `{$field_name}` declared here")] nested_field_span: Span, #[subdiagnostic] help: FieldAlreadyDeclaredNestedHelp, - #[label(hir_analysis_previous_decl_label)] + #[label("`{$field_name}` first declared here")] prev_span: Span, }, - #[diag(hir_analysis_field_already_declared_previous_nested)] + #[diag("field `{$field_name}` is already declared")] PreviousNested { field_name: Ident, #[primary_span] - #[label] + #[label("field already declared")] span: Span, - #[label(hir_analysis_previous_decl_label)] + #[label("`{$field_name}` first declared here in this unnamed field")] prev_span: Span, - #[note(hir_analysis_previous_nested_field_decl_note)] + #[note("field `{$field_name}` first declared here")] prev_nested_field_span: Span, #[subdiagnostic] prev_help: FieldAlreadyDeclaredNestedHelp, }, - #[diag(hir_analysis_field_already_declared_both_nested)] + #[diag("field `{$field_name}` is already declared")] BothNested { field_name: Ident, #[primary_span] - #[label] + #[label("field `{$field_name}` declared in this unnamed field")] span: Span, - #[note(hir_analysis_nested_field_decl_note)] + #[note("field `{$field_name}` declared here")] nested_field_span: Span, #[subdiagnostic] help: FieldAlreadyDeclaredNestedHelp, - #[label(hir_analysis_previous_decl_label)] + #[label("`{$field_name}` first declared here in this unnamed field")] prev_span: Span, - #[note(hir_analysis_previous_nested_field_decl_note)] + #[note("field `{$field_name}` first declared here")] prev_nested_field_span: Span, #[subdiagnostic] prev_help: FieldAlreadyDeclaredNestedHelp, @@ -266,67 +274,67 @@ pub(crate) enum FieldAlreadyDeclared { } #[derive(Subdiagnostic)] -#[help(hir_analysis_field_already_declared_nested_help)] +#[help("fields from the type of this unnamed field are considered fields of the outer type")] pub(crate) struct FieldAlreadyDeclaredNestedHelp { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_copy_impl_on_type_with_dtor, code = E0184)] +#[diag("the trait `Copy` cannot be implemented for this type; the type has a destructor", code = E0184)] pub(crate) struct CopyImplOnTypeWithDtor { #[primary_span] - #[label] + #[label("`Copy` not allowed on types with destructors")] pub span: Span, - #[note] + #[note("destructor declared here")] pub impl_: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_copy_impl_on_non_adt, code = E0206)] +#[diag("the trait `Copy` cannot be implemented for this type", code = E0206)] pub(crate) struct CopyImplOnNonAdt { #[primary_span] - #[label] + #[label("type is not a structure or enumeration")] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_const_param_ty_impl_on_unsized)] +#[diag("the trait `ConstParamTy` may not be implemented for this type")] pub(crate) struct ConstParamTyImplOnUnsized { #[primary_span] - #[label] + #[label("type is not `Sized`")] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_const_param_ty_impl_on_non_adt)] +#[diag("the trait `ConstParamTy` may not be implemented for this type")] pub(crate) struct ConstParamTyImplOnNonAdt { #[primary_span] - #[label] + #[label("type is not a structure or enumeration")] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_trait_object_declared_with_no_traits, code = E0224)] +#[diag("at least one trait is required for an object type", code = E0224)] pub(crate) struct TraitObjectDeclaredWithNoTraits { #[primary_span] pub span: Span, - #[label(hir_analysis_alias_span)] + #[label("this alias does not contain a trait")] pub trait_alias_span: Option, } #[derive(Diagnostic)] -#[diag(hir_analysis_ambiguous_lifetime_bound, code = E0227)] +#[diag("ambiguous lifetime bound, explicit lifetime bound required", code = E0227)] pub(crate) struct AmbiguousLifetimeBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_assoc_item_constraints_not_allowed_here, code = E0229)] +#[diag("associated item constraints are not allowed here", code = E0229)] pub(crate) struct AssocItemConstraintsNotAllowedHere { #[primary_span] - #[label] + #[label("associated item constraint not allowed here")] pub span: Span, #[subdiagnostic] @@ -334,45 +342,64 @@ pub(crate) struct AssocItemConstraintsNotAllowedHere { } #[derive(Diagnostic)] -#[diag(hir_analysis_param_in_ty_of_assoc_const_binding)] +#[diag( + "the type of the associated constant `{$assoc_const}` must not depend on {$param_category -> + [self] `Self` + [synthetic] `impl Trait` + *[normal] generic parameters + }" +)] pub(crate) struct ParamInTyOfAssocConstBinding<'tcx> { #[primary_span] - #[label] + #[label( + "its type must not depend on {$param_category -> + [self] `Self` + [synthetic] `impl Trait` + *[normal] the {$param_def_kind} `{$param_name}` + }" + )] pub span: Span, pub assoc_const: Ident, pub param_name: Symbol, pub param_def_kind: &'static str, pub param_category: &'static str, - #[label(hir_analysis_param_defined_here_label)] + #[label( + "{$param_category -> + [synthetic] the `impl Trait` is specified here + *[normal] the {$param_def_kind} `{$param_name}` is defined here + }" + )] pub param_defined_here_label: Option, #[subdiagnostic] pub ty_note: Option>, } #[derive(Subdiagnostic, Clone, Copy)] -#[note(hir_analysis_ty_of_assoc_const_binding_note)] +#[note("`{$assoc_const}` has type `{$ty}`")] pub(crate) struct TyOfAssocConstBindingNote<'tcx> { pub assoc_const: Ident, pub ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(hir_analysis_escaping_bound_var_in_ty_of_assoc_const_binding)] +#[diag( + "the type of the associated constant `{$assoc_const}` cannot capture late-bound generic parameters" +)] pub(crate) struct EscapingBoundVarInTyOfAssocConstBinding<'tcx> { #[primary_span] - #[label] + #[label("its type cannot capture the late-bound {$var_def_kind} `{$var_name}`")] pub span: Span, pub assoc_const: Ident, pub var_name: Symbol, pub var_def_kind: &'static str, - #[label(hir_analysis_var_defined_here_label)] + #[label("the late-bound {$var_def_kind} `{$var_name}` is defined here")] pub var_defined_here_label: Span, #[subdiagnostic] pub ty_note: Option>, } #[derive(Subdiagnostic)] -#[help(hir_analysis_parenthesized_fn_trait_expansion)] +#[help("parenthesized trait syntax expands to `{$expanded_type}`")] pub(crate) struct ParenthesizedFnTraitExpansion { #[primary_span] pub span: Span, @@ -381,20 +408,20 @@ pub(crate) struct ParenthesizedFnTraitExpansion { } #[derive(Diagnostic)] -#[diag(hir_analysis_value_of_associated_struct_already_specified, code = E0719)] +#[diag("the value of the associated type `{$item_name}` in trait `{$def_path}` is already specified", code = E0719)] pub(crate) struct ValueOfAssociatedStructAlreadySpecified { #[primary_span] - #[label] + #[label("re-bound here")] pub span: Span, - #[label(hir_analysis_previous_bound_label)] + #[label("`{$item_name}` bound here first")] pub prev_span: Span, pub item_name: Ident, pub def_path: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_unconstrained_opaque_type)] -#[note] +#[diag("unconstrained opaque type")] +#[note("`{$name}` must be used in combination with a concrete type within the same {$what}")] pub(crate) struct UnconstrainedOpaqueType { #[primary_span] pub span: Span, @@ -414,10 +441,27 @@ pub(crate) struct MissingGenericParams { impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingGenericParams { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { - let mut err = Diag::new(dcx, level, fluent::hir_analysis_missing_generic_params); + let mut err = Diag::new( + dcx, + level, + inline_fluent!( + "the {$descr} {$parameterCount -> + [one] parameter + *[other] parameters + } {$parameters} must be explicitly specified" + ), + ); err.span(self.span); err.code(E0393); - err.span_label(self.def_span, fluent::hir_analysis_label); + err.span_label( + self.def_span, + inline_fluent!( + "{$descr} {$parameterCount -> + [one] parameter + *[other] parameters + } {$parameters} must be specified for this" + ), + ); enum Descr { Generic, @@ -467,7 +511,12 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingGenericParams { // least we can clue them to the correct syntax `Trait`. err.span_suggestion_verbose( self.span.shrink_to_hi(), - fluent::hir_analysis_suggestion, + inline_fluent!( + "explicitly specify the {$descr} {$parameterCount -> + [one] parameter + *[other] parameters + }" + ), format!( "<{}>", self.missing_generic_params @@ -482,84 +531,112 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingGenericParams { } } if !suggested { - err.span_label(self.span, fluent::hir_analysis_no_suggestion_label); + err.span_label( + self.span, + inline_fluent!( + "missing {$parameterCount -> + [one] reference + *[other] references + } to {$parameters}" + ), + ); } - err.note(fluent::hir_analysis_note); + err.note(inline_fluent!( + "because the parameter {$parameterCount -> + [one] default references + *[other] defaults reference + } `Self`, the {$parameterCount -> + [one] parameter + *[other] parameters + } must be specified on the trait object type" + )); err } } #[derive(Diagnostic)] -#[diag(hir_analysis_manual_implementation, code = E0183)] -#[help] +#[diag("manual implementations of `{$trait_name}` are experimental", code = E0183)] +#[help("add `#![feature(unboxed_closures)]` to the crate attributes to enable")] pub(crate) struct ManualImplementation { #[primary_span] - #[label] + #[label("manual implementations of `{$trait_name}` are experimental")] pub span: Span, pub trait_name: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_generic_args_on_overridden_impl)] +#[diag("could not resolve generic parameters on overridden impl")] pub(crate) struct GenericArgsOnOverriddenImpl { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_const_impl_for_non_const_trait)] +#[diag("const `impl` for trait `{$trait_name}` which is not `const`")] pub(crate) struct ConstImplForNonConstTrait { #[primary_span] - #[label] + #[label("this trait is not `const`")] pub trait_ref_span: Span, pub trait_name: String, - #[suggestion(applicability = "machine-applicable", code = "const ", style = "verbose")] + #[suggestion( + "{$suggestion_pre}mark `{$trait_name}` as `const` to allow it to have `const` implementations", + applicability = "machine-applicable", + code = "const ", + style = "verbose" + )] pub suggestion: Option, pub suggestion_pre: &'static str, - #[note] + #[note("marking a trait with `const` ensures all default method bodies are `const`")] pub marking: (), - #[note(hir_analysis_adding)] + #[note("adding a non-const method body in the future would be a breaking change")] pub adding: (), } #[derive(Diagnostic)] -#[diag(hir_analysis_const_bound_for_non_const_trait)] +#[diag("`{$modifier}` can only be applied to `const` traits")] pub(crate) struct ConstBoundForNonConstTrait { #[primary_span] - #[label] + #[label("can't be applied to `{$trait_name}`")] pub span: Span, pub modifier: &'static str, - #[note] + #[note("`{$trait_name}` can't be used with `{$modifier}` because it isn't `const`")] pub def_span: Option, - #[suggestion(applicability = "machine-applicable", code = "const ", style = "verbose")] + #[suggestion( + "{$suggestion_pre}mark `{$trait_name}` as `const` to allow it to have `const` implementations", + applicability = "machine-applicable", + code = "const ", + style = "verbose" + )] pub suggestion: Option, pub suggestion_pre: &'static str, pub trait_name: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_self_in_impl_self)] +#[diag("`Self` is not valid in the self type of an impl block")] pub(crate) struct SelfInImplSelf { #[primary_span] pub span: MultiSpan, - #[note] + #[note("replace `Self` with a different type")] pub note: (), } #[derive(Diagnostic)] -#[diag(hir_analysis_linkage_type, code = E0791)] +#[diag("invalid type for variable with `#[linkage]` attribute", code = E0791)] pub(crate) struct LinkageType { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[help] -#[diag(hir_analysis_auto_deref_reached_recursion_limit, code = E0055)] +#[help( + "consider increasing the recursion limit by adding a `#![recursion_limit = \"{$suggested_limit}\"]` attribute to your crate (`{$crate_name}`)" +)] +#[diag("reached the recursion limit while auto-dereferencing `{$ty}`", code = E0055)] pub(crate) struct AutoDerefReachedRecursionLimit<'a> { #[primary_span] - #[label] + #[label("deref recursion limit reached")] pub span: Span, pub ty: Ty<'a>, pub suggested_limit: Limit, @@ -567,96 +644,96 @@ pub(crate) struct AutoDerefReachedRecursionLimit<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_where_clause_on_main, code = E0646)] +#[diag("`main` function is not allowed to have a `where` clause", code = E0646)] pub(crate) struct WhereClauseOnMain { #[primary_span] pub span: Span, - #[label] + #[label("`main` cannot have a `where` clause")] pub generics_span: Option, } #[derive(Diagnostic)] -#[diag(hir_analysis_track_caller_on_main)] +#[diag("`main` function is not allowed to be `#[track_caller]`")] pub(crate) struct TrackCallerOnMain { #[primary_span] - #[suggestion(applicability = "maybe-incorrect", code = "")] + #[suggestion("remove this annotation", applicability = "maybe-incorrect", code = "")] pub span: Span, - #[label(hir_analysis_track_caller_on_main)] + #[label("`main` function is not allowed to be `#[track_caller]`")] pub annotated: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_target_feature_on_main)] +#[diag("`main` function is not allowed to have `#[target_feature]`")] pub(crate) struct TargetFeatureOnMain { #[primary_span] - #[label(hir_analysis_target_feature_on_main)] + #[label("`main` function is not allowed to have `#[target_feature]`")] pub main: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_main_function_return_type_generic, code = E0131)] +#[diag("`main` function return type is not allowed to have generic parameters", code = E0131)] pub(crate) struct MainFunctionReturnTypeGeneric { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_main_function_async, code = E0752)] +#[diag("`main` function is not allowed to be `async`", code = E0752)] pub(crate) struct MainFunctionAsync { #[primary_span] pub span: Span, - #[label] + #[label("`main` function is not allowed to be `async`")] pub asyncness: Option, } #[derive(Diagnostic)] -#[diag(hir_analysis_main_function_generic_parameters, code = E0131)] +#[diag("`main` function is not allowed to have generic parameters", code = E0131)] pub(crate) struct MainFunctionGenericParameters { #[primary_span] pub span: Span, - #[label] + #[label("`main` cannot have generic parameters")] pub label_span: Option, } #[derive(Diagnostic)] -#[diag(hir_analysis_variadic_function_compatible_convention, code = E0045)] +#[diag("C-variadic functions with the {$convention} calling convention are not supported", code = E0045)] pub(crate) struct VariadicFunctionCompatibleConvention<'a> { #[primary_span] - #[label] + #[label("C-variadic function must have a compatible calling convention")] pub span: Span, pub convention: &'a str, } #[derive(Diagnostic)] pub(crate) enum CannotCaptureLateBound { - #[diag(hir_analysis_cannot_capture_late_bound_ty)] + #[diag("cannot capture late-bound type parameter in {$what}")] Type { #[primary_span] use_span: Span, - #[label] + #[label("parameter defined here")] def_span: Span, what: &'static str, }, - #[diag(hir_analysis_cannot_capture_late_bound_const)] + #[diag("cannot capture late-bound const parameter in {$what}")] Const { #[primary_span] use_span: Span, - #[label] + #[label("parameter defined here")] def_span: Span, what: &'static str, }, - #[diag(hir_analysis_cannot_capture_late_bound_lifetime)] + #[diag("cannot capture late-bound lifetime in {$what}")] Lifetime { #[primary_span] use_span: Span, - #[label] + #[label("lifetime defined here")] def_span: Span, what: &'static str, }, } #[derive(Diagnostic)] -#[diag(hir_analysis_variances_of)] +#[diag("{$variances}")] pub(crate) struct VariancesOf { #[primary_span] pub span: Span, @@ -664,7 +741,7 @@ pub(crate) struct VariancesOf { } #[derive(Diagnostic)] -#[diag(hir_analysis_type_of)] +#[diag("{$ty}")] pub(crate) struct TypeOf<'tcx> { #[primary_span] pub span: Span, @@ -672,30 +749,37 @@ pub(crate) struct TypeOf<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_analysis_invalid_union_field, code = E0740)] +#[diag("field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union", code = E0740)] pub(crate) struct InvalidUnionField { #[primary_span] pub field_span: Span, #[subdiagnostic] pub sugg: InvalidUnionFieldSuggestion, - #[note] + #[note( + "union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`" + )] pub note: (), } #[derive(Diagnostic)] -#[diag(hir_analysis_return_type_notation_on_non_rpitit)] +#[diag( + "return type notation used on function that is not `async` and does not return `impl Trait`" +)] pub(crate) struct ReturnTypeNotationOnNonRpitit<'tcx> { #[primary_span] pub span: Span, pub ty: Ty<'tcx>, - #[label] + #[label("this function must be `async` or return `impl Trait`")] pub fn_span: Option, - #[note] + #[note("function returns `{$ty}`, which is not compatible with associated type return bounds")] pub note: (), } #[derive(Subdiagnostic)] -#[multipart_suggestion(hir_analysis_invalid_union_field_sugg, applicability = "machine-applicable")] +#[multipart_suggestion( + "wrap the field type in `ManuallyDrop<...>`", + applicability = "machine-applicable" +)] pub(crate) struct InvalidUnionFieldSuggestion { #[suggestion_part(code = "std::mem::ManuallyDrop<")] pub lo: Span, @@ -704,27 +788,32 @@ pub(crate) struct InvalidUnionFieldSuggestion { } #[derive(Diagnostic)] -#[diag(hir_analysis_return_type_notation_equality_bound)] +#[diag("return type notation is not allowed to use type equality")] pub(crate) struct ReturnTypeNotationEqualityBound { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = E0121)] +#[diag("the placeholder `_` is not allowed within types on item signatures for {$kind}", code = E0121)] pub(crate) struct PlaceholderNotAllowedItemSignatures { #[primary_span] - #[label] + #[label("not allowed in type signatures")] pub spans: Vec, pub kind: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = E0212)] +#[diag("cannot use the {$what} of a trait with uninferred generic parameters", code = E0212)] pub(crate) struct AssociatedItemTraitUninferredGenericParams { #[primary_span] pub span: Span, - #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "{bound}")] + #[suggestion( + "use a fully qualified path with inferred lifetimes", + style = "verbose", + applicability = "maybe-incorrect", + code = "{bound}" + )] pub inferred_sugg: Option, pub bound: String, #[subdiagnostic] @@ -734,7 +823,7 @@ pub(crate) struct AssociatedItemTraitUninferredGenericParams { #[derive(Subdiagnostic)] #[multipart_suggestion( - hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion, + "use a fully qualified path with explicit lifetimes", applicability = "maybe-incorrect" )] pub(crate) struct AssociatedItemTraitUninferredGenericParamsMultipartSuggestion { @@ -747,11 +836,11 @@ pub(crate) struct AssociatedItemTraitUninferredGenericParamsMultipartSuggestion } #[derive(Diagnostic)] -#[diag(hir_analysis_enum_discriminant_overflowed, code = E0370)] -#[note] +#[diag("enum discriminant overflowed", code = E0370)] +#[note("explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome")] pub(crate) struct EnumDiscriminantOverflowed { #[primary_span] - #[label] + #[label("overflowed on value after {$discr}")] pub span: Span, pub discr: String, pub item_name: Ident, @@ -759,16 +848,18 @@ pub(crate) struct EnumDiscriminantOverflowed { } #[derive(Diagnostic)] -#[diag(hir_analysis_paren_sugar_attribute)] -#[help] +#[diag( + "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation" +)] +#[help("add `#![feature(unboxed_closures)]` to the crate attributes to use it")] pub(crate) struct ParenSugarAttribute { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_simd_ffi_highly_experimental)] -#[help] +#[diag("use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code")] +#[help("add `#![feature(simd_ffi)]` to the crate attributes to enable")] pub(crate) struct SIMDFFIHighlyExperimental { #[primary_span] pub span: Span, @@ -777,18 +868,18 @@ pub(crate) struct SIMDFFIHighlyExperimental { #[derive(Diagnostic)] pub(crate) enum ImplNotMarkedDefault { - #[diag(hir_analysis_impl_not_marked_default, code = E0520)] - #[note] + #[diag("`{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`", code = E0520)] + #[note("to specialize, `{$ident}` in the parent `impl` must be marked `default`")] Ok { #[primary_span] - #[label] + #[label("cannot specialize default item `{$ident}`")] span: Span, - #[label(hir_analysis_ok_label)] + #[label("parent `impl` is here")] ok_label: Span, ident: Ident, }, - #[diag(hir_analysis_impl_not_marked_default_err, code = E0520)] - #[note] + #[diag("`{$ident}` specializes an item from a parent `impl`, but that item is not marked `default`", code = E0520)] + #[note("parent implementation is in crate `{$cname}`")] Err { #[primary_span] span: Span, @@ -798,14 +889,14 @@ pub(crate) enum ImplNotMarkedDefault { } #[derive(LintDiagnostic)] -#[diag(hir_analysis_useless_impl_item)] +#[diag("this item cannot be used as its where bounds are not satisfied for the `Self` type")] pub(crate) struct UselessImplItem; #[derive(Diagnostic)] -#[diag(hir_analysis_missing_trait_item, code = E0046)] +#[diag("not all trait items implemented, missing: `{$missing_items_msg}`", code = E0046)] pub(crate) struct MissingTraitItem { #[primary_span] - #[label] + #[label("missing `{$missing_items_msg}` in implementation")] pub span: Span, #[subdiagnostic] pub missing_trait_item_label: Vec, @@ -817,7 +908,7 @@ pub(crate) struct MissingTraitItem { } #[derive(Subdiagnostic)] -#[label(hir_analysis_missing_trait_item_label)] +#[label("`{$item}` from trait")] pub(crate) struct MissingTraitItemLabel { #[primary_span] pub span: Span, @@ -826,7 +917,7 @@ pub(crate) struct MissingTraitItemLabel { #[derive(Subdiagnostic)] #[suggestion( - hir_analysis_missing_trait_item_suggestion, + "implement the missing item: `{$snippet}`", style = "tool-only", applicability = "has-placeholders", code = "{code}" @@ -840,7 +931,7 @@ pub(crate) struct MissingTraitItemSuggestion { #[derive(Subdiagnostic)] #[suggestion( - hir_analysis_missing_trait_item_suggestion, + "implement the missing item: `{$snippet}`", style = "hidden", applicability = "has-placeholders", code = "{code}" @@ -853,25 +944,25 @@ pub(crate) struct MissingTraitItemSuggestionNone { } #[derive(Diagnostic)] -#[diag(hir_analysis_missing_one_of_trait_item, code = E0046)] +#[diag("not all trait items implemented, missing one of: `{$missing_items_msg}`", code = E0046)] pub(crate) struct MissingOneOfTraitItem { #[primary_span] - #[label] + #[label("missing one of `{$missing_items_msg}` in implementation")] pub span: Span, - #[note] + #[note("required because of this annotation")] pub note: Option, pub missing_items_msg: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_missing_trait_item_unstable, code = E0046)] -#[note] +#[diag("not all trait items implemented, missing: `{$missing_item_name}`", code = E0046)] +#[note("default implementation of `{$missing_item_name}` is unstable")] pub(crate) struct MissingTraitItemUnstable { #[primary_span] pub span: Span, - #[note(hir_analysis_some_note)] + #[note("use of unstable library feature `{$feature}`: {$reason}")] pub some_note: bool, - #[note(hir_analysis_none_note)] + #[note("use of unstable library feature `{$feature}`")] pub none_note: bool, pub missing_item_name: Ident, pub feature: Symbol, @@ -879,78 +970,78 @@ pub(crate) struct MissingTraitItemUnstable { } #[derive(Diagnostic)] -#[diag(hir_analysis_transparent_enum_variant, code = E0731)] +#[diag("transparent enum needs exactly one variant, but has {$number}", code = E0731)] pub(crate) struct TransparentEnumVariant { #[primary_span] - #[label] + #[label("needs exactly one variant, but has {$number}")] pub span: Span, - #[label(hir_analysis_multi_label)] + #[label("variant here")] pub spans: Vec, - #[label(hir_analysis_many_label)] + #[label("too many variants in `{$path}`")] pub many: Option, pub number: usize, pub path: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_transparent_non_zero_sized_enum, code = E0690)] +#[diag("the variant of a transparent {$desc} needs at most one field with non-trivial size or alignment, but has {$field_count}", code = E0690)] pub(crate) struct TransparentNonZeroSizedEnum<'a> { #[primary_span] - #[label] + #[label("needs at most one field with non-trivial size or alignment, but has {$field_count}")] pub span: Span, - #[label(hir_analysis_labels)] + #[label("this field has non-zero size or requires alignment")] pub spans: Vec, pub field_count: usize, pub desc: &'a str, } #[derive(Diagnostic)] -#[diag(hir_analysis_transparent_non_zero_sized, code = E0690)] +#[diag("transparent {$desc} needs at most one field with non-trivial size or alignment, but has {$field_count}", code = E0690)] pub(crate) struct TransparentNonZeroSized<'a> { #[primary_span] - #[label] + #[label("needs at most one field with non-trivial size or alignment, but has {$field_count}")] pub span: Span, - #[label(hir_analysis_labels)] + #[label("this field has non-zero size or requires alignment")] pub spans: Vec, pub field_count: usize, pub desc: &'a str, } #[derive(Diagnostic)] -#[diag(hir_analysis_too_large_static)] +#[diag("extern static is too large for the target architecture")] pub(crate) struct TooLargeStatic { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_specialization_trait)] -#[help] +#[diag("implementing `rustc_specialization_trait` traits is unstable")] +#[help("add `#![feature(min_specialization)]` to the crate attributes to enable")] pub(crate) struct SpecializationTrait { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_closure_implicit_hrtb)] +#[diag("implicit types in closure signatures are forbidden when `for<...>` is present")] pub(crate) struct ClosureImplicitHrtb { #[primary_span] pub spans: Vec, - #[label] + #[label("`for<...>` is here")] pub for_sp: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_empty_specialization)] +#[diag("specialization impl does not specialize any associated items")] pub(crate) struct EmptySpecialization { #[primary_span] pub span: Span, - #[note] + #[note("impl is a specialization of this impl")] pub base_impl_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_static_specialize)] +#[diag("cannot specialize on `'static` lifetime")] pub(crate) struct StaticSpecialize { #[primary_span] pub span: Span, @@ -958,12 +1049,12 @@ pub(crate) struct StaticSpecialize { #[derive(Diagnostic)] pub(crate) enum DropImplPolarity { - #[diag(hir_analysis_drop_impl_negative)] + #[diag("negative `Drop` impls are not supported")] Negative { #[primary_span] span: Span, }, - #[diag(hir_analysis_drop_impl_reservation)] + #[diag("reservation `Drop` impls are not supported")] Reservation { #[primary_span] span: Span, @@ -972,65 +1063,75 @@ pub(crate) enum DropImplPolarity { #[derive(Diagnostic)] pub(crate) enum ReturnTypeNotationIllegalParam { - #[diag(hir_analysis_return_type_notation_illegal_param_type)] + #[diag("return type notation is not allowed for functions that have type parameters")] Type { #[primary_span] span: Span, - #[label] + #[label("type parameter declared here")] param_span: Span, }, - #[diag(hir_analysis_return_type_notation_illegal_param_const)] + #[diag("return type notation is not allowed for functions that have const parameters")] Const { #[primary_span] span: Span, - #[label] + #[label("const parameter declared here")] param_span: Span, }, } #[derive(Diagnostic)] pub(crate) enum LateBoundInApit { - #[diag(hir_analysis_late_bound_type_in_apit)] + #[diag("`impl Trait` can only mention type parameters from an fn or impl")] Type { #[primary_span] span: Span, - #[label] + #[label("type parameter declared here")] param_span: Span, }, - #[diag(hir_analysis_late_bound_const_in_apit)] + #[diag("`impl Trait` can only mention const parameters from an fn or impl")] Const { #[primary_span] span: Span, - #[label] + #[label("const parameter declared here")] param_span: Span, }, - #[diag(hir_analysis_late_bound_lifetime_in_apit)] + #[diag("`impl Trait` can only mention lifetimes from an fn or impl")] Lifetime { #[primary_span] span: Span, - #[label] + #[label("lifetime declared here")] param_span: Span, }, } #[derive(LintDiagnostic)] -#[diag(hir_analysis_unused_associated_type_bounds)] -#[note] +#[diag("unnecessary associated type bound for dyn-incompatible associated type")] +#[note( + "this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized`" +)] pub(crate) struct UnusedAssociatedTypeBounds { - #[suggestion(code = "")] + #[suggestion("remove this bound", code = "")] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(hir_analysis_rpitit_refined)] -#[note] -#[note(hir_analysis_feedback_note)] +#[diag("impl trait in impl method signature does not match trait method signature")] +#[note( + "add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate" +)] +#[note( + "we are soliciting feedback, see issue #121718 for more information" +)] pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { - #[suggestion(applicability = "maybe-incorrect", code = "{pre}{return_ty}{post}")] + #[suggestion( + "replace the return type so that it matches the trait", + applicability = "maybe-incorrect", + code = "{pre}{return_ty}{post}" + )] pub impl_return_span: Span, - #[label] + #[label("return type from trait method defined here")] pub trait_return_span: Option, - #[label(hir_analysis_unmatched_bound_label)] + #[label("this bound is stronger than that defined on the trait")] pub unmatched_bound: Option, pub pre: &'static str, @@ -1039,33 +1140,43 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { } #[derive(LintDiagnostic)] -#[diag(hir_analysis_rpitit_refined_lifetimes)] -#[note] -#[note(hir_analysis_feedback_note)] +#[diag("impl trait in impl method captures fewer lifetimes than in trait")] +#[note( + "add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate" +)] +#[note( + "we are soliciting feedback, see issue #121718 for more information" +)] pub(crate) struct ReturnPositionImplTraitInTraitRefinedLifetimes { - #[suggestion(applicability = "maybe-incorrect", code = "{suggestion}")] + #[suggestion( + "modify the `use<..>` bound to capture the same lifetimes that the trait does", + applicability = "maybe-incorrect", + code = "{suggestion}" + )] pub suggestion_span: Span, pub suggestion: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_ty_outside, code = E0390)] -#[help] +#[diag("cannot define inherent `impl` for a type outside of the crate where the type is defined", code = E0390)] +#[help("consider moving this inherent impl into the crate defining the type if possible")] pub(crate) struct InherentTyOutside { #[primary_span] - #[help(hir_analysis_span_help)] + #[help( + "alternatively add `#[rustc_has_incoherent_inherent_impls]` to the type and `#[rustc_allow_incoherent_impl]` to the relevant impl items" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_dispatch_from_dyn_repr, code = E0378)] +#[diag("structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]`", code = E0378)] pub(crate) struct DispatchFromDynRepr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_pointee_not_struct, code = E0802)] +#[diag("`derive(CoercePointee)` is only applicable to `struct`, instead of `{$kind}`", code = E0802)] pub(crate) struct CoercePointeeNotStruct { #[primary_span] pub span: Span, @@ -1073,65 +1184,65 @@ pub(crate) struct CoercePointeeNotStruct { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_pointee_not_concrete_ty, code = E0802)] +#[diag("`derive(CoercePointee)` is only applicable to `struct`", code = E0802)] pub(crate) struct CoercePointeeNotConcreteType { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_pointee_no_user_validity_assertion, code = E0802)] +#[diag("asserting applicability of `derive(CoercePointee)` on a target data is forbidden", code = E0802)] pub(crate) struct CoercePointeeNoUserValidityAssertion { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_pointee_not_transparent, code = E0802)] +#[diag("`derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout", code = E0802)] pub(crate) struct CoercePointeeNotTransparent { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_pointee_no_field, code = E0802)] +#[diag("`CoercePointee` can only be derived on `struct`s with at least one field", code = E0802)] pub(crate) struct CoercePointeeNoField { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)] -#[help] +#[diag("cannot define inherent `impl` for a type outside of the crate where the type is defined", code = E0390)] +#[help("consider moving this inherent impl into the crate defining the type if possible")] pub(crate) struct InherentTyOutsideRelevant { #[primary_span] pub span: Span, - #[help(hir_analysis_span_help)] + #[help("alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items")] pub help_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_ty_outside_new, code = E0116)] -#[note] +#[diag("cannot define inherent `impl` for a type outside of the crate where the type is defined", code = E0116)] +#[note("define and implement a trait or new type instead")] pub(crate) struct InherentTyOutsideNew { #[primary_span] - #[label] + #[label("impl for type defined outside of crate")] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_ty_outside_primitive, code = E0390)] -#[help] +#[diag("cannot define inherent `impl` for primitive types outside of `core`", code = E0390)] +#[help("consider moving this inherent impl into `core` if possible")] pub(crate) struct InherentTyOutsidePrimitive { #[primary_span] pub span: Span, - #[help(hir_analysis_span_help)] + #[help("alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items")] pub help_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_primitive_ty, code = E0390)] -#[help] +#[diag("cannot define inherent `impl` for primitive types", code = E0390)] +#[help("consider using an extension trait instead")] pub(crate) struct InherentPrimitiveTy<'a> { #[primary_span] pub span: Span, @@ -1140,32 +1251,34 @@ pub(crate) struct InherentPrimitiveTy<'a> { } #[derive(Subdiagnostic)] -#[note(hir_analysis_inherent_primitive_ty_note)] +#[note( + "you could also try moving the reference to uses of `{$subty}` (such as `self`) within the implementation" +)] pub(crate) struct InherentPrimitiveTyNote<'a> { pub subty: Ty<'a>, } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_dyn, code = E0785)] -#[note] +#[diag("cannot define inherent `impl` for a dyn auto trait", code = E0785)] +#[note("define and implement a new trait or type instead")] pub(crate) struct InherentDyn { #[primary_span] - #[label] + #[label("impl requires at least one non-auto trait")] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_inherent_nominal, code = E0118)] -#[note] +#[diag("no nominal type found for inherent implementation", code = E0118)] +#[note("either implement a trait on it or create a newtype to wrap it instead")] pub(crate) struct InherentNominal { #[primary_span] - #[label] + #[label("impl requires a nominal type")] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_dispatch_from_dyn_zst, code = E0378)] -#[note] +#[diag("the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment that don't mention type/const generics, and nothing else", code = E0378)] +#[note("extra field `{$name}` of type `{$ty}` is not allowed")] pub(crate) struct DispatchFromDynZST<'a> { #[primary_span] pub span: Span, @@ -1174,28 +1287,30 @@ pub(crate) struct DispatchFromDynZST<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_zero, code = E0374)] +#[diag("implementing `{$trait_name}` requires a field to be coerced", code = E0374)] pub(crate) struct CoerceNoField { #[primary_span] pub span: Span, pub trait_name: &'static str, - #[note(hir_analysis_coercion_between_struct_single_note)] + #[note("expected a single field to be coerced, none found")] pub note: bool, } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_multi, code = E0375)] +#[diag("implementing `{$trait_name}` does not allow multiple fields to be coerced", code = E0375)] pub(crate) struct CoerceMulti { pub trait_name: &'static str, #[primary_span] pub span: Span, pub number: usize, - #[note] + #[note( + "the trait `{$trait_name}` may only be implemented when a single field is being coerced" + )] pub fields: MultiSpan, } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_may, code = E0377)] +#[diag("the trait `{$trait_name}` may only be implemented for a coercion between structures", code = E0377)] pub(crate) struct CoerceUnsizedNonStruct { #[primary_span] pub span: Span, @@ -1203,7 +1318,7 @@ pub(crate) struct CoerceUnsizedNonStruct { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_same_pat_kind)] +#[diag("only pattern types with the same pattern can be coerced between each other")] pub(crate) struct CoerceSamePatKind { #[primary_span] pub span: Span, @@ -1213,43 +1328,49 @@ pub(crate) struct CoerceSamePatKind { } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_may, code = E0377)] +#[diag("the trait `{$trait_name}` may only be implemented for a coercion between structures", code = E0377)] pub(crate) struct CoerceSameStruct { #[primary_span] pub span: Span, pub trait_name: &'static str, - #[note(hir_analysis_coercion_between_struct_same_note)] + #[note( + "expected coercion between the same definition; expected `{$source_path}`, found `{$target_path}`" + )] pub note: bool, pub source_path: String, pub target_path: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_coerce_unsized_field_validity)] +#[diag( + "for `{$ty}` to have a valid implementation of `{$trait_name}`, it must be possible to coerce the field of type `{$field_ty}`" +)] pub(crate) struct CoerceFieldValidity<'tcx> { #[primary_span] pub span: Span, pub ty: Ty<'tcx>, pub trait_name: &'static str, - #[label] + #[label( + "`{$field_ty}` must be a pointer, reference, or smart pointer that is allowed to be unsized" + )] pub field_span: Span, pub field_ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(hir_analysis_trait_cannot_impl_for_ty, code = E0204)] +#[diag("the trait `{$trait_name}` cannot be implemented for this type", code = E0204)] pub(crate) struct TraitCannotImplForTy { #[primary_span] pub span: Span, pub trait_name: String, - #[label] + #[label("this field does not implement `{$trait_name}`")] pub label_spans: Vec, #[subdiagnostic] pub notes: Vec, } #[derive(Subdiagnostic)] -#[note(hir_analysis_requires_note)] +#[note("the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}`")] pub(crate) struct ImplForTyRequires { #[primary_span] pub span: MultiSpan, @@ -1259,8 +1380,10 @@ pub(crate) struct ImplForTyRequires { } #[derive(Diagnostic)] -#[diag(hir_analysis_traits_with_default_impl, code = E0321)] -#[note] +#[diag("traits with a default impl, like `{$traits}`, cannot be implemented for {$problematic_kind} `{$self_ty}`", code = E0321)] +#[note( + "a trait object implements `{$traits}` if and only if `{$traits}` is one of the trait object's trait bounds" +)] pub(crate) struct TraitsWithDefaultImpl<'a> { #[primary_span] pub span: Span, @@ -1270,26 +1393,26 @@ pub(crate) struct TraitsWithDefaultImpl<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_cross_crate_traits, code = E0321)] +#[diag("cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type, not `{$self_ty}`", code = E0321)] pub(crate) struct CrossCrateTraits<'a> { #[primary_span] - #[label] + #[label("can't implement cross-crate trait with a default impl for non-struct/enum type")] pub span: Span, pub traits: String, pub self_ty: Ty<'a>, } #[derive(Diagnostic)] -#[diag(hir_analysis_cross_crate_traits_defined, code = E0321)] +#[diag("cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type defined in the current crate", code = E0321)] pub(crate) struct CrossCrateTraitsDefined { #[primary_span] - #[label] + #[label("can't implement cross-crate trait for type in another crate")] pub span: Span, pub traits: String, } #[derive(Diagnostic)] -#[diag(hir_analysis_no_variant_named, code = E0599)] +#[diag("no variant named `{$ident}` found for enum `{$ty}`", code = E0599)] pub struct NoVariantNamed<'tcx> { #[primary_span] pub span: Span, @@ -1300,99 +1423,123 @@ pub struct NoVariantNamed<'tcx> { // FIXME(fmease): Deduplicate: #[derive(Diagnostic)] -#[diag(hir_analysis_ty_param_first_local, code = E0210)] -#[note] +#[diag("type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)", code = E0210)] +#[note( + "implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type" +)] pub(crate) struct TyParamFirstLocal<'tcx> { #[primary_span] - #[label] + #[label( + "type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)" + )] pub span: Span, - #[note(hir_analysis_case_note)] + #[note( + "in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last" + )] pub note: (), pub param: Ident, pub local_type: Ty<'tcx>, } #[derive(LintDiagnostic)] -#[diag(hir_analysis_ty_param_first_local, code = E0210)] -#[note] +#[diag("type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)", code = E0210)] +#[note( + "implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type" +)] pub(crate) struct TyParamFirstLocalLint<'tcx> { - #[label] + #[label( + "type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)" + )] pub span: Span, - #[note(hir_analysis_case_note)] + #[note( + "in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last" + )] pub note: (), pub param: Ident, pub local_type: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(hir_analysis_ty_param_some, code = E0210)] -#[note] +#[diag("type parameter `{$param}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param}>`)", code = E0210)] +#[note( + "implementing a foreign trait is only possible if at least one of the types for which it is implemented is local" +)] pub(crate) struct TyParamSome { #[primary_span] - #[label] + #[label("type parameter `{$param}` must be used as the type parameter for some local type")] pub span: Span, - #[note(hir_analysis_only_note)] + #[note("only traits defined in the current crate can be implemented for a type parameter")] pub note: (), pub param: Ident, } #[derive(LintDiagnostic)] -#[diag(hir_analysis_ty_param_some, code = E0210)] -#[note] +#[diag("type parameter `{$param}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param}>`)", code = E0210)] +#[note( + "implementing a foreign trait is only possible if at least one of the types for which it is implemented is local" +)] pub(crate) struct TyParamSomeLint { - #[label] + #[label("type parameter `{$param}` must be used as the type parameter for some local type")] pub span: Span, - #[note(hir_analysis_only_note)] + #[note("only traits defined in the current crate can be implemented for a type parameter")] pub note: (), pub param: Ident, } #[derive(Diagnostic)] pub(crate) enum OnlyCurrentTraits { - #[diag(hir_analysis_only_current_traits_outside, code = E0117)] + #[diag("only traits defined in the current crate can be implemented for types defined outside of the crate", code = E0117)] Outside { #[primary_span] span: Span, - #[note(hir_analysis_only_current_traits_note_uncovered)] - #[note(hir_analysis_only_current_traits_note_more_info)] - #[note(hir_analysis_only_current_traits_note)] + #[note("impl doesn't have any local type before any uncovered type parameters")] + #[note( + "for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules" + )] + #[note("define and implement a trait or new type instead")] note: (), }, - #[diag(hir_analysis_only_current_traits_primitive, code = E0117)] + #[diag("only traits defined in the current crate can be implemented for primitive types", code = E0117)] Primitive { #[primary_span] span: Span, - #[note(hir_analysis_only_current_traits_note_uncovered)] - #[note(hir_analysis_only_current_traits_note_more_info)] - #[note(hir_analysis_only_current_traits_note)] + #[note("impl doesn't have any local type before any uncovered type parameters")] + #[note( + "for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules" + )] + #[note("define and implement a trait or new type instead")] note: (), }, - #[diag(hir_analysis_only_current_traits_arbitrary, code = E0117)] + #[diag("only traits defined in the current crate can be implemented for arbitrary types", code = E0117)] Arbitrary { #[primary_span] span: Span, - #[note(hir_analysis_only_current_traits_note_uncovered)] - #[note(hir_analysis_only_current_traits_note_more_info)] - #[note(hir_analysis_only_current_traits_note)] + #[note("impl doesn't have any local type before any uncovered type parameters")] + #[note( + "for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules" + )] + #[note("define and implement a trait or new type instead")] note: (), }, } #[derive(Subdiagnostic)] -#[label(hir_analysis_only_current_traits_opaque)] +#[label( + "type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate" +)] pub(crate) struct OnlyCurrentTraitsOpaque { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] -#[label(hir_analysis_only_current_traits_foreign)] +#[label("this is not defined in the current crate because this is a foreign trait")] pub(crate) struct OnlyCurrentTraitsForeign { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] -#[label(hir_analysis_only_current_traits_name)] +#[label("this is not defined in the current crate because {$name} are always foreign")] pub(crate) struct OnlyCurrentTraitsName<'a> { #[primary_span] pub span: Span, @@ -1400,7 +1547,7 @@ pub(crate) struct OnlyCurrentTraitsName<'a> { } #[derive(Subdiagnostic)] -#[label(hir_analysis_only_current_traits_pointer)] +#[label("`{$pointer}` is not defined in the current crate because raw pointers are always foreign")] pub(crate) struct OnlyCurrentTraitsPointer<'a> { #[primary_span] pub span: Span, @@ -1408,7 +1555,7 @@ pub(crate) struct OnlyCurrentTraitsPointer<'a> { } #[derive(Subdiagnostic)] -#[label(hir_analysis_only_current_traits_ty)] +#[label("`{$ty}` is not defined in the current crate")] pub(crate) struct OnlyCurrentTraitsTy<'a> { #[primary_span] pub span: Span, @@ -1416,7 +1563,7 @@ pub(crate) struct OnlyCurrentTraitsTy<'a> { } #[derive(Subdiagnostic)] -#[label(hir_analysis_only_current_traits_adt)] +#[label("`{$name}` is not defined in the current crate")] pub(crate) struct OnlyCurrentTraitsAdt { #[primary_span] pub span: Span, @@ -1425,7 +1572,7 @@ pub(crate) struct OnlyCurrentTraitsAdt { #[derive(Subdiagnostic)] #[multipart_suggestion( - hir_analysis_only_current_traits_pointer_sugg, + "consider introducing a new wrapper type", applicability = "maybe-incorrect" )] pub(crate) struct OnlyCurrentTraitsPointerSugg<'a> { @@ -1438,104 +1585,120 @@ pub(crate) struct OnlyCurrentTraitsPointerSugg<'a> { } #[derive(Diagnostic)] -#[diag(hir_analysis_not_supported_delegation)] +#[diag("{$descr}")] pub(crate) struct UnsupportedDelegation<'a> { #[primary_span] pub span: Span, pub descr: &'a str, - #[label] + #[label("callee defined here")] pub callee_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_method_should_return_future)] +#[diag("method should be `async` or return a future, but it is synchronous")] pub(crate) struct MethodShouldReturnFuture { #[primary_span] pub span: Span, pub method_name: Ident, - #[note] + #[note("this method is `async` so it expects a future to be returned")] pub trait_item_span: Option, } #[derive(Diagnostic)] -#[diag(hir_analysis_unused_generic_parameter)] +#[diag("{$param_def_kind} `{$param_name}` is never used")] pub(crate) struct UnusedGenericParameter { #[primary_span] - #[label] + #[label("unused {$param_def_kind}")] pub span: Span, pub param_name: Ident, pub param_def_kind: &'static str, - #[label(hir_analysis_usage_spans)] + #[label("`{$param_name}` is named here, but is likely unused in the containing type")] pub usage_spans: Vec, #[subdiagnostic] pub help: UnusedGenericParameterHelp, - #[help(hir_analysis_const_param_help)] + #[help( + "if you intended `{$param_name}` to be a const parameter, use `const {$param_name}: /* Type */` instead" + )] pub const_param_help: bool, } #[derive(Diagnostic)] -#[diag(hir_analysis_recursive_generic_parameter)] +#[diag("{$param_def_kind} `{$param_name}` is only used recursively")] pub(crate) struct RecursiveGenericParameter { #[primary_span] pub spans: Vec, - #[label] + #[label("{$param_def_kind} must be used non-recursively in the definition")] pub param_span: Span, pub param_name: Ident, pub param_def_kind: &'static str, #[subdiagnostic] pub help: UnusedGenericParameterHelp, - #[note] + #[note( + "all type parameters must be used in a non-recursive way in order to constrain their variance" + )] pub note: (), } #[derive(Subdiagnostic)] pub(crate) enum UnusedGenericParameterHelp { - #[help(hir_analysis_unused_generic_parameter_adt_help)] + #[help( + "consider removing `{$param_name}`, referring to it in a field, or using a marker such as `{$phantom_data}`" + )] Adt { param_name: Ident, phantom_data: String }, - #[help(hir_analysis_unused_generic_parameter_adt_no_phantom_data_help)] + #[help("consider removing `{$param_name}` or referring to it in a field")] AdtNoPhantomData { param_name: Ident }, - #[help(hir_analysis_unused_generic_parameter_ty_alias_help)] + #[help("consider removing `{$param_name}` or referring to it in the body of the type alias")] TyAlias { param_name: Ident }, } #[derive(Diagnostic)] -#[diag(hir_analysis_unconstrained_generic_parameter)] +#[diag( + "the {$param_def_kind} `{$param_name}` is not constrained by the impl trait, self type, or predicates" +)] pub(crate) struct UnconstrainedGenericParameter { #[primary_span] - #[label] + #[label("unconstrained {$param_def_kind}")] pub span: Span, pub param_name: Ident, pub param_def_kind: &'static str, - #[note(hir_analysis_const_param_note)] + #[note("expressions using a const parameter must map each value to a distinct output value")] pub const_param_note: bool, - #[note(hir_analysis_const_param_note2)] + #[note( + "proving the result of expressions other than the parameter are unique is not supported" + )] pub const_param_note2: bool, } #[derive(Diagnostic)] -#[diag(hir_analysis_opaque_captures_higher_ranked_lifetime, code = E0657)] +#[diag("`impl Trait` cannot capture {$bad_place}", code = E0657)] pub(crate) struct OpaqueCapturesHigherRankedLifetime { #[primary_span] pub span: MultiSpan, - #[label] + #[label("`impl Trait` implicitly captures all lifetimes in scope")] pub label: Option, - #[note] + #[note("lifetime declared here")] pub decl_span: MultiSpan, pub bad_place: &'static str, } #[derive(Subdiagnostic)] pub(crate) enum InvalidReceiverTyHint { - #[note(hir_analysis_invalid_receiver_ty_help_weak_note)] + #[note( + "`Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver`" + )] Weak, - #[note(hir_analysis_invalid_receiver_ty_help_nonnull_note)] + #[note( + "`NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver`" + )] NonNull, } #[derive(Diagnostic)] -#[diag(hir_analysis_invalid_receiver_ty_no_arbitrary_self_types, code = E0307)] -#[note] -#[help(hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types)] +#[diag("invalid `self` parameter type: `{$receiver_ty}`", code = E0307)] +#[note("type of `self` must be `Self` or a type that dereferences to it")] +#[help( + "consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`)" +)] pub(crate) struct InvalidReceiverTyNoArbitrarySelfTypes<'tcx> { #[primary_span] pub span: Span, @@ -1543,9 +1706,11 @@ pub(crate) struct InvalidReceiverTyNoArbitrarySelfTypes<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_analysis_invalid_receiver_ty, code = E0307)] -#[note] -#[help(hir_analysis_invalid_receiver_ty_help)] +#[diag("invalid `self` parameter type: `{$receiver_ty}`", code = E0307)] +#[note("type of `self` must be `Self` or some type implementing `Receiver`")] +#[help( + "consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc`" +)] pub(crate) struct InvalidReceiverTy<'tcx> { #[primary_span] pub span: Span, @@ -1555,9 +1720,11 @@ pub(crate) struct InvalidReceiverTy<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_analysis_invalid_generic_receiver_ty, code = E0801)] -#[note] -#[help(hir_analysis_invalid_generic_receiver_ty_help)] +#[diag("invalid generic `self` parameter type: `{$receiver_ty}`", code = E0801)] +#[note("type of `self` must not be a method generic parameter type")] +#[help( + "use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`)" +)] pub(crate) struct InvalidGenericReceiverTy<'tcx> { #[primary_span] pub span: Span, @@ -1565,28 +1732,32 @@ pub(crate) struct InvalidGenericReceiverTy<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_analysis_cmse_inputs_stack_spill, code = E0798)] -#[note] +#[diag("arguments for `{$abi}` function too large to pass via registers", code = E0798)] +#[note( + "functions with the `{$abi}` ABI must pass all their arguments via the 4 32-bit argument registers" +)] pub(crate) struct CmseInputsStackSpill { #[primary_span] - #[label] + #[label("does not fit in the available registers")] pub spans: Vec, pub abi: ExternAbi, } #[derive(Diagnostic)] -#[diag(hir_analysis_cmse_output_stack_spill, code = E0798)] -#[note(hir_analysis_note1)] -#[note(hir_analysis_note2)] +#[diag("return value of `{$abi}` function too large to pass via registers", code = E0798)] +#[note("functions with the `{$abi}` ABI must pass their result via the available return registers")] +#[note( + "the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size" +)] pub(crate) struct CmseOutputStackSpill { #[primary_span] - #[label] + #[label("this type doesn't fit in the available registers")] pub span: Span, pub abi: ExternAbi, } #[derive(Diagnostic)] -#[diag(hir_analysis_cmse_generic, code = E0798)] +#[diag("generics are not allowed in `extern {$abi}` signatures", code = E0798)] pub(crate) struct CmseGeneric { #[primary_span] pub span: Span, @@ -1594,7 +1765,7 @@ pub(crate) struct CmseGeneric { } #[derive(Diagnostic)] -#[diag(hir_analysis_cmse_impl_trait, code = E0798)] +#[diag("`impl Trait` is not allowed in `extern {$abi}` signatures", code = E0798)] pub(crate) struct CmseImplTrait { #[primary_span] pub span: Span, @@ -1602,14 +1773,14 @@ pub(crate) struct CmseImplTrait { } #[derive(Diagnostic)] -#[diag(hir_analysis_bad_return_type_notation_position)] +#[diag("return type notation not allowed in this position yet")] pub(crate) struct BadReturnTypeNotation { #[primary_span] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(hir_analysis_supertrait_item_shadowing)] +#[diag("trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait")] pub(crate) struct SupertraitItemShadowing { pub item: Symbol, pub subtrait: Symbol, @@ -1619,13 +1790,13 @@ pub(crate) struct SupertraitItemShadowing { #[derive(Subdiagnostic)] pub(crate) enum SupertraitItemShadowee { - #[note(hir_analysis_supertrait_item_shadowee)] + #[note("item from `{$supertrait}` is shadowed by a subtrait item")] Labeled { #[primary_span] span: Span, supertrait: Symbol, }, - #[note(hir_analysis_supertrait_item_multiple_shadowee)] + #[note("items from several supertraits are shadowed: {$traits}")] Several { #[primary_span] spans: MultiSpan, @@ -1634,23 +1805,25 @@ pub(crate) enum SupertraitItemShadowee { } #[derive(Diagnostic)] -#[diag(hir_analysis_dyn_trait_assoc_item_binding_mentions_self)] +#[diag("{$kind} binding in trait object type mentions `Self`")] pub(crate) struct DynTraitAssocItemBindingMentionsSelf { #[primary_span] - #[label] + #[label("contains a mention of `Self`")] pub span: Span, pub kind: &'static str, - #[label(hir_analysis_binding_label)] + #[label("this binding mentions `Self`")] pub binding: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_abi_custom_clothed_function)] +#[diag( + "items with the \"custom\" ABI can only be declared externally or defined via naked functions" +)] pub(crate) struct AbiCustomClothedFunction { #[primary_span] pub span: Span, #[suggestion( - hir_analysis_suggestion, + "convert this to an `#[unsafe(naked)]` function", applicability = "maybe-incorrect", code = "#[unsafe(naked)]\n", style = "short" @@ -1659,47 +1832,49 @@ pub(crate) struct AbiCustomClothedFunction { } #[derive(Diagnostic)] -#[diag(hir_analysis_async_drop_without_sync_drop)] -#[help] +#[diag("`AsyncDrop` impl without `Drop` impl")] +#[help( + "type implementing `AsyncDrop` trait must also implement `Drop` trait to be used in sync context and unwinds" +)] pub(crate) struct AsyncDropWithoutSyncDrop { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_lifetimes_or_bounds_mismatch_on_eii)] +#[diag("lifetime parameters or bounds of `{$ident}` do not match the declaration")] pub(crate) struct LifetimesOrBoundsMismatchOnEii { #[primary_span] - #[label] + #[label("lifetimes do not match")] pub span: Span, - #[label(hir_analysis_generics_label)] + #[label("lifetimes in impl do not match this signature")] pub generics_span: Span, - #[label(hir_analysis_where_label)] + #[label("this `where` clause might not match the one in the trait")] pub where_span: Option, - #[label(hir_analysis_bounds_label)] + #[label("this bound might be missing in the impl")] pub bounds_span: Vec, pub ident: Symbol, } #[derive(Diagnostic)] -#[diag(hir_analysis_eii_with_generics)] -#[help] +#[diag("`{$impl_name}` cannot have generic parameters other than lifetimes")] +#[help("`#[{$eii_name}]` marks the implementation of an \"externally implementable item\"")] pub(crate) struct EiiWithGenerics { #[primary_span] pub span: Span, - #[label] + #[label("required by this attribute")] pub attr: Span, pub eii_name: Symbol, pub impl_name: Symbol, } #[derive(Diagnostic)] -#[diag(hir_analysis_impl_unpin_for_pin_projected_type)] +#[diag("explicit impls for the `Unpin` trait are not permitted for structurally pinned types")] pub(crate) struct ImplUnpinForPinProjectedType { #[primary_span] - #[label] + #[label("impl of `Unpin` not allowed")] pub span: Span, - #[help] + #[help("`{$adt_name}` is structurally pinned because it is marked as `#[pin_v2]`")] pub adt_span: Span, pub adt_name: Symbol, } diff --git a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs index 8a83866b7fa4..f9e62b8ebcf8 100644 --- a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs +++ b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs @@ -3,48 +3,54 @@ use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] -#[diag(hir_analysis_param_not_captured)] -#[note] +#[diag("`impl Trait` must mention all {$kind} parameters in scope in `use<...>`")] +#[note( + "currently, all {$kind} parameters are required to be mentioned in the precise captures list" +)] pub(crate) struct ParamNotCaptured { #[primary_span] pub opaque_span: Span, - #[label] + #[label("{$kind} parameter is implicitly captured by this `impl Trait`")] pub param_span: Span, pub kind: &'static str, } #[derive(Diagnostic)] -#[diag(hir_analysis_self_ty_not_captured)] -#[note] +#[diag("`impl Trait` must mention the `Self` type of the trait in `use<...>`")] +#[note("currently, all type parameters are required to be mentioned in the precise captures list")] pub(crate) struct SelfTyNotCaptured { #[primary_span] pub opaque_span: Span, - #[label] + #[label("`Self` type parameter is implicitly captured by this `impl Trait`")] pub trait_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_lifetime_not_captured)] +#[diag( + "`impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list" +)] pub(crate) struct LifetimeNotCaptured { #[primary_span] pub use_span: Span, - #[label(hir_analysis_param_label)] + #[label("this lifetime parameter is captured")] pub param_span: Span, - #[label] + #[label("lifetime captured due to being mentioned in the bounds of the `impl Trait`")] pub opaque_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_lifetime_implicitly_captured)] +#[diag( + "`impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list" +)] pub(crate) struct LifetimeImplicitlyCaptured { #[primary_span] pub opaque_span: Span, - #[label(hir_analysis_param_label)] + #[label("all lifetime parameters originating from a trait are captured implicitly")] pub param_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_bad_precise_capture)] +#[diag("expected {$kind} parameter in `use<...>` precise captures list, found {$found}")] pub(crate) struct BadPreciseCapture { #[primary_span] pub span: Span, @@ -53,31 +59,31 @@ pub(crate) struct BadPreciseCapture { } #[derive(Diagnostic)] -#[diag(hir_analysis_precise_capture_self_alias, code = E0799)] +#[diag("`Self` can't be captured in `use<...>` precise captures list, since it is an alias", code = E0799)] pub(crate) struct PreciseCaptureSelfAlias { #[primary_span] pub span: Span, - #[label] + #[label("`Self` is not a generic argument, but an alias to the type of the {$what}")] pub self_span: Span, pub what: &'static str, } #[derive(Diagnostic)] -#[diag(hir_analysis_duplicate_precise_capture)] +#[diag("cannot capture parameter `{$name}` twice")] pub(crate) struct DuplicatePreciseCapture { #[primary_span] pub first_span: Span, pub name: Symbol, - #[label] + #[label("parameter captured again here")] pub second_span: Span, } #[derive(Diagnostic)] -#[diag(hir_analysis_lifetime_must_be_first)] +#[diag("lifetime parameter `{$name}` must be listed before non-lifetime parameters")] pub(crate) struct LifetimesMustBeFirst { #[primary_span] pub lifetime_span: Span, pub name: Symbol, - #[label] + #[label("move the lifetime before this parameter")] pub other_span: Span, } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index d114691b25e8..36dae4c2798e 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -3,8 +3,8 @@ use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::unord::UnordMap; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, ErrorGuaranteed, MultiSpan, SuggestionStyle, listify, pluralize, - struct_span_code_err, + Applicability, Diag, ErrorGuaranteed, MultiSpan, SuggestionStyle, inline_fluent, listify, + pluralize, struct_span_code_err, }; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; @@ -31,7 +31,6 @@ use crate::errors::{ self, AssocItemConstraintsNotAllowedHere, ManualImplementation, ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits, }; -use crate::fluent_generated as fluent; use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer}; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { @@ -305,7 +304,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // was also not an exact match, so we also suggest changing it. err.span_suggestion_verbose( assoc_ident.span, - fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg, + inline_fluent!("...and changing the associated {$assoc_kind} name"), suggested_name, Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index f7a143435959..37c8cece1bf0 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -102,8 +102,6 @@ use rustc_trait_selection::traits; pub use crate::collect::suggest_impl_trait; use crate::hir_ty_lowering::HirTyLowerer; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - fn check_c_variadic_abi(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: ExternAbi, span: Span) { if !decl.c_variadic { // Not even a variadic function. From 0436efe1b4bebcce1df69171f9a8f983428aea3a Mon Sep 17 00:00:00 2001 From: jyn Date: Sat, 31 Jan 2026 16:38:11 -0500 Subject: [PATCH 615/978] Get rid of `paths` function Some history about `paths()`. The original intent Mark-Simulacrum had when he introduced PathSet, to my knowledge, was that multiple paths could be aliases for the same step. That's what rustdoc is doing; both paths for rustdoc run exactly the same Step, regardless of whether one or both are present. That never really caught on. To my knowledge, rustdoc is the only usage of paths() there's ever been. Later, in 95503, I repurposed PathSet to mean "each crate in this set should be passed to Step::make_run in RunConfig". That was not the previous meaning. Rustdoc never looks at run.paths in make_run, so it's safe to just treat it as an alias, like elsewhere in bootstrap. Same for all the other tool steps. Co-authored-by: Tshepang Mbambo --- src/bootstrap/src/core/build_steps/check.rs | 2 +- src/bootstrap/src/core/build_steps/test.rs | 2 +- .../builder/cli_paths/snapshots/x_bench.snap | 3 +- .../builder/cli_paths/snapshots/x_check.snap | 3 +- ...eck_compiletest_include_default_paths.snap | 3 +- .../builder/cli_paths/snapshots/x_fix.snap | 3 +- .../builder/cli_paths/snapshots/x_test.snap | 3 +- .../snapshots/x_test_librustdoc_rustdoc.snap | 3 +- .../snapshots/x_test_skip_coverage.snap | 3 +- .../snapshots/x_test_skip_tests.snap | 3 +- .../snapshots/x_test_skip_tests_etc.snap | 3 +- src/bootstrap/src/core/builder/mod.rs | 39 +++++-------------- 12 files changed, 30 insertions(+), 40 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 8bbd03ac3afa..55426bfffc73 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -706,7 +706,7 @@ macro_rules! tool_check_step { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.paths(&[ $path, $( $alt_path ),* ]) + run.path($path) $( .path( $alt_path ) )* } fn is_default_step(_builder: &Builder<'_>) -> bool { diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 7130517a91de..2eac69e117cd 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -3155,7 +3155,7 @@ impl Step for CrateRustdoc { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.paths(&["src/librustdoc", "src/tools/rustdoc"]) + run.path("src/librustdoc").path("src/tools/rustdoc") } fn is_default_step(_builder: &Builder<'_>) -> bool { diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap index 8a7815487913..13a06e353d89 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap @@ -98,4 +98,5 @@ expression: bench - Set({bench::compiler/rustc_windows_rc}) [Bench] test::CrateRustdoc targets: [x86_64-unknown-linux-gnu] - - Set({bench::src/librustdoc, bench::src/tools/rustdoc}) + - Set({bench::src/librustdoc}) + - Set({bench::src/tools/rustdoc}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap index 0fe26fac57fc..4c3b6e11b0e4 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap @@ -82,7 +82,8 @@ expression: check - Set({check::compiler/rustc_windows_rc}) [Check] check::Rustdoc targets: [x86_64-unknown-linux-gnu] - - Set({check::src/librustdoc, check::src/tools/rustdoc}) + - Set({check::src/librustdoc}) + - Set({check::src/tools/rustdoc}) [Check] check::CraneliftCodegenBackend targets: [x86_64-unknown-linux-gnu] - Set({check::cg_clif}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap index dae515c67ec6..16348adc79df 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap @@ -82,7 +82,8 @@ expression: check compiletest --include-default-paths - Set({check::compiler/rustc_windows_rc}) [Check] check::Rustdoc targets: [x86_64-unknown-linux-gnu] - - Set({check::src/librustdoc, check::src/tools/rustdoc}) + - Set({check::src/librustdoc}) + - Set({check::src/tools/rustdoc}) [Check] check::CraneliftCodegenBackend targets: [x86_64-unknown-linux-gnu] - Set({check::cg_clif}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap index 222c0ffb4050..8a11b4d89dde 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap @@ -82,7 +82,8 @@ expression: fix - Set({fix::compiler/rustc_windows_rc}) [Fix] check::Rustdoc targets: [x86_64-unknown-linux-gnu] - - Set({fix::src/librustdoc, fix::src/tools/rustdoc}) + - Set({fix::src/librustdoc}) + - Set({fix::src/tools/rustdoc}) [Fix] check::CraneliftCodegenBackend targets: [x86_64-unknown-linux-gnu] - Set({fix::cg_clif}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap index 4ab84c3cabc1..46e93aa667cc 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap @@ -148,7 +148,8 @@ expression: test - Set({test::compiler/rustc_windows_rc}) [Test] test::CrateRustdoc targets: [x86_64-unknown-linux-gnu] - - Set({test::src/librustdoc, test::src/tools/rustdoc}) + - Set({test::src/librustdoc}) + - Set({test::src/tools/rustdoc}) [Test] test::CrateRustdocJsonTypes targets: [x86_64-unknown-linux-gnu] - Set({test::src/rustdoc-json-types}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_librustdoc_rustdoc.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_librustdoc_rustdoc.snap index c8eee72aec42..8dcdce0c17ab 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_librustdoc_rustdoc.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_librustdoc_rustdoc.snap @@ -4,7 +4,8 @@ expression: test librustdoc rustdoc --- [Test] test::CrateRustdoc targets: [x86_64-unknown-linux-gnu] - - Set({test::src/librustdoc, test::src/tools/rustdoc}) + - Set({test::src/librustdoc}) + - Set({test::src/tools/rustdoc}) [Test] test::RustdocBook targets: [x86_64-unknown-linux-gnu] - Set({test::src/doc/rustdoc}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap index 2a4805e4fd68..c27da5a2a9e2 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap @@ -147,7 +147,8 @@ expression: test --skip=coverage - Set({test::compiler/rustc_windows_rc}) [Test] test::CrateRustdoc targets: [x86_64-unknown-linux-gnu] - - Set({test::src/librustdoc, test::src/tools/rustdoc}) + - Set({test::src/librustdoc}) + - Set({test::src/tools/rustdoc}) [Test] test::CrateRustdocJsonTypes targets: [x86_64-unknown-linux-gnu] - Set({test::src/rustdoc-json-types}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap index 1468964c7818..d5d709a60b49 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap @@ -112,7 +112,8 @@ expression: test --skip=tests - Set({test::compiler/rustc_windows_rc}) [Test] test::CrateRustdoc targets: [x86_64-unknown-linux-gnu] - - Set({test::src/librustdoc, test::src/tools/rustdoc}) + - Set({test::src/librustdoc}) + - Set({test::src/tools/rustdoc}) [Test] test::CrateRustdocJsonTypes targets: [x86_64-unknown-linux-gnu] - Set({test::src/rustdoc-json-types}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap index 7ff6a201e77a..85ca8f6ef7a0 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap @@ -92,7 +92,8 @@ expression: test --skip=tests --skip=coverage-map --skip=coverage-run --skip=lib - Set({test::compiler/rustc_windows_rc}) [Test] test::CrateRustdoc targets: [x86_64-unknown-linux-gnu] - - Set({test::src/librustdoc, test::src/tools/rustdoc}) + - Set({test::src/librustdoc}) + - Set({test::src/tools/rustdoc}) [Test] test::CrateRustdocJsonTypes targets: [x86_64-unknown-linux-gnu] - Set({test::src/rustdoc-json-types}) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index a995f5c8a219..ae91b2040629 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -558,38 +558,19 @@ impl<'a> ShouldRun<'a> { /// single, non-aliased path /// /// Must be an on-disk path; use `alias` for names that do not correspond to on-disk paths. - pub fn path(self, path: &str) -> Self { - self.paths(&[path]) - } - - /// Multiple aliases for the same job. - /// - /// This differs from [`path`] in that multiple calls to path will end up calling `make_run` - /// multiple times, whereas a single call to `paths` will only ever generate a single call to - /// `make_run`. - /// - /// This is analogous to `all_krates`, although `all_krates` is gone now. Prefer [`path`] where possible. - /// - /// [`path`]: ShouldRun::path - pub fn paths(mut self, paths: &[&str]) -> Self { + pub fn path(mut self, path: &str) -> Self { let submodules_paths = self.builder.submodule_paths(); - self.paths.insert(PathSet::Set( - paths - .iter() - .map(|p| { - // assert only if `p` isn't submodule - if !submodules_paths.iter().any(|sm_p| p.contains(sm_p)) { - assert!( - self.builder.src.join(p).exists(), - "`should_run.paths` should correspond to real on-disk paths - use `alias` if there is no relevant path: {p}" - ); - } + // assert only if `p` isn't submodule + if !submodules_paths.iter().any(|sm_p| path.contains(sm_p)) { + assert!( + self.builder.src.join(path).exists(), + "`should_run.path` should correspond to a real on-disk path - use `alias` if there is no relevant path: {path}" + ); + } - TaskPath { path: p.into(), kind: Some(self.kind) } - }) - .collect(), - )); + let task = TaskPath { path: path.into(), kind: Some(self.kind) }; + self.paths.insert(PathSet::Set(BTreeSet::from_iter([task]))); self } From ea430356543781e2e638d72ac689e0a609bbaa7a Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Thu, 5 Feb 2026 23:31:06 +0100 Subject: [PATCH 616/978] Convert to inline diagnostics in `rustc_passes` --- Cargo.lock | 2 - compiler/rustc_driver_impl/Cargo.toml | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_passes/Cargo.toml | 1 - compiler/rustc_passes/messages.ftl | 576 -------------------- compiler/rustc_passes/src/check_attr.rs | 23 +- compiler/rustc_passes/src/errors.rs | 674 +++++++++++++++--------- compiler/rustc_passes/src/lib.rs | 2 - 8 files changed, 437 insertions(+), 843 deletions(-) delete mode 100644 compiler/rustc_passes/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 430a1d149a2b..9ea22911d515 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3789,7 +3789,6 @@ dependencies = [ "rustc_mir_build", "rustc_mir_transform", "rustc_parse", - "rustc_passes", "rustc_public", "rustc_resolve", "rustc_session", @@ -4417,7 +4416,6 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index d28a190ea9c1..10e1b1987194 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -29,7 +29,6 @@ rustc_middle = { path = "../rustc_middle" } rustc_mir_build = { path = "../rustc_mir_build" } rustc_mir_transform = { path = "../rustc_mir_transform" } rustc_parse = { path = "../rustc_parse" } -rustc_passes = { path = "../rustc_passes" } rustc_public = { path = "../rustc_public", features = ["rustc_internal"] } rustc_resolve = { path = "../rustc_resolve" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 72831a8d8ff6..4bbcf7373589 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -117,7 +117,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ rustc_lint::DEFAULT_LOCALE_RESOURCE, rustc_mir_build::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE, - rustc_passes::DEFAULT_LOCALE_RESOURCE, // tidy-alphabetical-end ]; diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index 10da57f56ecf..b65a0ad404a5 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -13,7 +13,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl deleted file mode 100644 index fae0052ab7a4..000000000000 --- a/compiler/rustc_passes/messages.ftl +++ /dev/null @@ -1,576 +0,0 @@ --passes_previously_accepted = - this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - --passes_see_issue = - see issue #{$issue} for more information - -passes_abi_invalid_attribute = - `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions -passes_abi_ne = - ABIs are not compatible - left ABI = {$left} - right ABI = {$right} -passes_abi_of = - fn_abi_of({$fn_name}) = {$fn_abi} - -passes_attr_application_enum = - attribute should be applied to an enum - .label = not an enum - -passes_attr_application_struct = - attribute should be applied to a struct - .label = not a struct - -passes_attr_application_struct_enum_union = - attribute should be applied to a struct, enum, or union - .label = not a struct, enum, or union - -passes_attr_application_struct_union = - attribute should be applied to a struct or union - .label = not a struct or union - -passes_autodiff_attr = - `#[autodiff]` should be applied to a function - .label = not a function - -passes_both_ffi_const_and_pure = - `#[ffi_const]` function cannot be `#[ffi_pure]` - -passes_cannot_stabilize_deprecated = - an API can't be stabilized after it is deprecated - .label = invalid version - .item = the stability attribute annotates this item - -passes_change_fields_to_be_of_unit_type = - consider changing the { $num -> - [one] field - *[other] fields - } to be of unit type to suppress this warning while preserving the field numbering, or remove the { $num -> - [one] field - *[other] fields - } - -passes_const_continue_attr = - `#[const_continue]` should be applied to a break expression - .label = not a break expression - -passes_const_stable_not_stable = - attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]` - .label = attribute specified here - -passes_custom_mir_incompatible_dialect_and_phase = - the {$dialect} dialect is not compatible with the {$phase} phase - .dialect_span = this dialect... - .phase_span = ... is not compatible with this phase - -passes_custom_mir_phase_requires_dialect = - `dialect` key required - .phase_span = `phase` argument requires a `dialect` argument - - -passes_dead_codes = - { $multiple -> - *[true] multiple {$descr}s are - [false] { $num -> - [one] {$descr} {$name_list} is - *[other] {$descr}s {$name_list} are - } - } never {$participle} - -passes_debug_visualizer_unreadable = - couldn't read {$file}: {$error} - -passes_deprecated_annotation_has_no_effect = - this `#[deprecated]` annotation has no effect - .suggestion = remove the unnecessary deprecation attribute - -passes_deprecated_attribute = - deprecated attribute must be paired with either stable or unstable attribute - -passes_diagnostic_diagnostic_on_const_only_for_non_const_trait_impls = - `#[diagnostic::on_const]` can only be applied to non-const trait impls - .label = this is a const trait impl - -passes_diagnostic_diagnostic_on_const_only_for_trait_impls = - `#[diagnostic::on_const]` can only be applied to trait impls - .label = not a trait impl - -passes_diagnostic_diagnostic_on_unimplemented_only_for_traits = - `#[diagnostic::on_unimplemented]` can only be applied to trait definitions - -passes_diagnostic_item_first_defined = - the diagnostic item is first defined here - -passes_doc_alias_bad_location = - `#[doc(alias = "...")]` isn't allowed on {$location} - -passes_doc_alias_not_an_alias = - `#[doc(alias = "{$attr_str}"]` is the same as the item's name - -passes_doc_fake_variadic_not_valid = - `#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity - -passes_doc_inline_conflict = - conflicting doc inlining attributes - .help = remove one of the conflicting attributes - -passes_doc_inline_conflict_first = - this attribute... - -passes_doc_inline_conflict_second = - {"."}..conflicts with this attribute - -passes_doc_inline_only_use = - this attribute can only be applied to a `use` item - .label = only applicable on `use` items - .not_a_use_item_label = not a `use` item - .note = read for more information - -passes_doc_keyword_attribute_empty_mod = - `#[doc({$attr_name} = "...")]` should be used on empty modules - -passes_doc_keyword_attribute_not_mod = - `#[doc({$attr_name} = "...")]` should be used on modules - -passes_doc_keyword_only_impl = - `#[doc(keyword = "...")]` should be used on impl blocks - -passes_doc_masked_not_extern_crate_self = - this attribute cannot be applied to an `extern crate self` item - .label = not applicable on `extern crate self` items - .extern_crate_self_label = `extern crate self` defined here - -passes_doc_masked_only_extern_crate = - this attribute can only be applied to an `extern crate` item - .label = only applicable on `extern crate` items - .not_an_extern_crate_label = not an `extern crate` item - .note = read for more information - -passes_doc_rust_logo = - the `#[doc(rust_logo)]` attribute is used for Rust branding - -passes_doc_search_unbox_invalid = - `#[doc(search_unbox)]` should be used on generic structs and enums - -passes_duplicate_diagnostic_item_in_crate = - duplicate diagnostic item in crate `{$crate_name}`: `{$name}` - .note = the diagnostic item is first defined in crate `{$orig_crate_name}` - -passes_duplicate_eii_impls = - multiple implementations of `#[{$name}]` - .first = first implemented here in crate `{$first_crate}` - .second = also implemented here in crate `{$second_crate}` - .note = in addition to these two, { $num_additional_crates -> - [one] another implementation was found in crate {$additional_crate_names} - *[other] more implementations were also found in the following crates: {$additional_crate_names} - } - - .help = an "externally implementable item" can only have a single implementation in the final artifact. When multiple implementations are found, also in different crates, they conflict - -passes_duplicate_feature_err = - the feature `{$feature}` has already been enabled - -passes_duplicate_lang_item = - found duplicate lang item `{$lang_item_name}` - .first_defined_span = the lang item is first defined here - .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on) - .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}` - .first_definition_local = first definition in the local crate (`{$orig_crate_name}`) - .second_definition_local = second definition in the local crate (`{$crate_name}`) - .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path} - .second_definition_path = second definition in `{$crate_name}` loaded from {$path} - -passes_duplicate_lang_item_crate = - duplicate lang item in crate `{$crate_name}`: `{$lang_item_name}` - .first_defined_span = the lang item is first defined here - .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on) - .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}` - .first_definition_local = first definition in the local crate (`{$orig_crate_name}`) - .second_definition_local = second definition in the local crate (`{$crate_name}`) - .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path} - .second_definition_path = second definition in `{$crate_name}` loaded from {$path} - -passes_duplicate_lang_item_crate_depends = - duplicate lang item in crate `{$crate_name}` (which `{$dependency_of}` depends on): `{$lang_item_name}` - .first_defined_span = the lang item is first defined here - .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on) - .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}` - .first_definition_local = first definition in the local crate (`{$orig_crate_name}`) - .second_definition_local = second definition in the local crate (`{$crate_name}`) - .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path} - .second_definition_path = second definition in `{$crate_name}` loaded from {$path} - -passes_eii_fn_with_track_caller = - `#[{$name}]` is not allowed to have `#[track_caller]` - .label = `#[{$name}]` is not allowed to have `#[track_caller]` - -passes_eii_impl_not_function = - `eii_macro_for` is only valid on functions - -passes_eii_impl_requires_unsafe = - `#[{$name}]` is unsafe to implement -passes_eii_impl_requires_unsafe_suggestion = wrap the attribute in `unsafe(...)` - -passes_eii_without_impl = - `#[{$name}]` required, but not found - .label = expected because `#[{$name}]` was declared here in crate `{$decl_crate_name}` - .help = expected at least one implementation in crate `{$current_crate_name}` or any of its dependencies - -passes_enum_variant_same_name = - it is impossible to refer to the {$dead_descr} `{$dead_name}` because it is shadowed by this enum variant with the same name - -passes_extern_main = - the `main` function cannot be declared in an `extern` block - -passes_feature_previously_declared = - feature `{$feature}` is declared {$declared}, but was previously declared {$prev_declared} - -passes_feature_stable_twice = - feature `{$feature}` is declared stable since {$since}, but was previously declared stable since {$prev_since} - -passes_function_not_found_in_trait = function not found in this trait - -passes_function_not_have_default_implementation = function doesn't have a default implementation - .note = required by this annotation - -passes_functions_names_duplicated = functions names are duplicated - .note = all `#[rustc_must_implement_one_of]` arguments must be unique - -passes_ignored_derived_impls = - `{$name}` has {$trait_list_len -> - [one] a derived impl - *[other] derived impls - } for the {$trait_list_len -> - [one] trait {$trait_list}, but this is - *[other] traits {$trait_list}, but these are - } intentionally ignored during dead code analysis - -passes_implied_feature_not_exist = - feature `{$implied_by}` implying `{$feature}` does not exist - -passes_incorrect_crate_type = lang items are not allowed in stable dylibs - -passes_incorrect_do_not_recommend_location = - `#[diagnostic::do_not_recommend]` can only be placed on trait implementations - -passes_incorrect_target = - `{$name}` lang item must be applied to a {$kind} with {$at_least -> - [true] at least {$num} - *[false] {$num} - } generic {$num -> - [one] argument - *[other] arguments - } - .label = this {$kind} has {$actual_num} generic {$actual_num -> - [one] argument - *[other] arguments - } - -passes_ineffective_unstable_impl = an `#[unstable]` annotation here has no effect - .note = see issue #55436 for more information - -passes_inline_ignored_for_exported = - `#[inline]` is ignored on externally exported functions - .help = externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]` - -passes_inner_crate_level_attr = - crate-level attribute should be in the root module - -passes_invalid_attr_at_crate_level = - `{$name}` attribute cannot be used at crate level - .suggestion = perhaps you meant to use an outer attribute - -passes_invalid_attr_at_crate_level_item = - the inner attribute doesn't annotate this {$kind} - -passes_lang_item_fn = {$name -> - [panic_impl] `#[panic_handler]` - *[other] `{$name}` lang item -} function - -passes_lang_item_fn_with_target_feature = - {passes_lang_item_fn} is not allowed to have `#[target_feature]` - .label = {passes_lang_item_fn} is not allowed to have `#[target_feature]` - -passes_lang_item_fn_with_track_caller = - {passes_lang_item_fn} is not allowed to have `#[track_caller]` - .label = {passes_lang_item_fn} is not allowed to have `#[track_caller]` - -passes_lang_item_on_incorrect_target = - `{$name}` lang item must be applied to a {$expected_target} - .label = attribute should be applied to a {$expected_target}, not a {$actual_target} - -passes_layout_abi = - abi: {$abi} -passes_layout_align = - align: {$align} -passes_layout_homogeneous_aggregate = - homogeneous_aggregate: {$homogeneous_aggregate} -passes_layout_of = - layout_of({$normalized_ty}) = {$ty_layout} -passes_layout_size = - size: {$size} - -passes_link = - attribute should be applied to an `extern` block with non-Rust ABI - .warn = {-passes_previously_accepted} - .label = not an `extern` block - -passes_loop_match_attr = - `#[loop_match]` should be applied to a loop - .label = not a loop - -passes_macro_export_on_decl_macro = - `#[macro_export]` has no effect on declarative macro definitions - .note = declarative macros follow the same exporting rules as regular items - -passes_macro_only_attribute = - attribute should be applied to a macro - .label = not a macro - -passes_may_dangle = - `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl - -passes_missing_const_err = - attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const` - .help = make the function or method const - -passes_missing_const_stab_attr = - {$descr} has missing const stability attribute - -passes_missing_lang_item = - lang item required, but not found: `{$name}` - .note = this can occur when a binary crate with `#![no_std]` is compiled for a target where `{$name}` is defined in the standard library - .help = you may be able to compile for a target that doesn't need `{$name}`, specify a target with `--target` or in `.cargo/config` - -passes_missing_panic_handler = - `#[panic_handler]` function required, but not found - -passes_missing_stability_attr = - {$descr} has missing stability attribute - -passes_misspelled_feature = there is a feature with a similar name: `{$actual_name}` - -passes_mixed_export_name_and_no_mangle = `{$no_mangle_attr}` attribute may not be used in combination with `{$export_name_attr}` - .label = `{$no_mangle_attr}` is ignored - .note = `{$export_name_attr}` takes precedence - .suggestion = remove the `{$no_mangle_attr}` attribute - -passes_multiple_rustc_main = - multiple functions with a `#[rustc_main]` attribute - .first = first `#[rustc_main]` function - .additional = additional `#[rustc_main]` function - -passes_must_implement_not_function = not a function - -passes_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names - -passes_must_implement_not_function_span_note = required by this annotation - -passes_no_main_function = - `main` function not found in crate `{$crate_name}` - .here_is_main = here is a function named `main` - .one_or_more_possible_main = you have one or more functions named `main` not defined at the crate level - .consider_moving_main = consider moving the `main` function definitions - .main_must_be_defined_at_crate = the main function must be defined at the crate level{$has_filename -> - [true] {" "}(in `{$filename}`) - *[false] {""} - } - .consider_adding_main_to_file = consider adding a `main` function to `{$filename}` - .consider_adding_main_at_crate = consider adding a `main` function at the crate level - .teach_note = if you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/ - .non_function_main = non-function item at `crate::main` is found - -passes_non_exhaustive_with_default_field_values = - `#[non_exhaustive]` can't be used to annotate items with default field values - .label = this struct has default field values - -passes_non_exported_macro_invalid_attrs = - attribute should be applied to function or closure - .label = not a function or closure - -passes_object_lifetime_err = - {$repr} - -passes_outer_crate_level_attr = - crate-level attribute should be an inner attribute - -passes_outer_crate_level_attr_suggestion = - add a `!` - -passes_panic_unwind_without_std = - unwinding panics are not supported without std - .note = since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem - .help = using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding - -passes_parent_info = - {$num -> - [one] {$descr} - *[other] {$descr}s - } in this {$parent_descr} - -passes_proc_macro_bad_sig = {$kind} has incorrect signature - -passes_remove_fields = - consider removing { $num -> - [one] this - *[other] these - } { $num -> - [one] field - *[other] fields - } - -passes_repr_align_greater_than_target_max = - alignment must not be greater than `isize::MAX` bytes - .note = `isize::MAX` is {$size} for the current target - -passes_repr_align_should_be_align = - `#[repr(align(...))]` is not supported on {$item} - .help = use `#[rustc_align(...)]` instead - -passes_repr_align_should_be_align_static = - `#[repr(align(...))]` is not supported on {$item} - .help = use `#[rustc_align_static(...)]` instead - -passes_repr_conflicting = - conflicting representation hints - -passes_rustc_allow_const_fn_unstable = - attribute should be applied to `const fn` - .label = not a `const fn` - -passes_rustc_const_stable_indirect_pairing = - `const_stable_indirect` attribute does not make sense on `rustc_const_stable` function, its behavior is already implied - -passes_rustc_force_inline_coro = - attribute cannot be applied to a `async`, `gen` or `async gen` function - .label = `async`, `gen` or `async gen` function - -passes_rustc_legacy_const_generics_index = - #[rustc_legacy_const_generics] must have one index for each generic parameter - .label = generic parameters - -passes_rustc_legacy_const_generics_index_exceed = - index exceeds number of arguments - .label = there {$arg_count -> - [one] is - *[other] are - } only {$arg_count} {$arg_count -> - [one] argument - *[other] arguments - } - -passes_rustc_legacy_const_generics_only = - #[rustc_legacy_const_generics] functions must only have const generics - .label = non-const generic parameter - - -passes_rustc_pub_transparent = - attribute should be applied to `#[repr(transparent)]` types - .label = not a `#[repr(transparent)]` type - -passes_sanitize_attribute_not_allowed = - sanitize attribute not allowed here - .not_fn_impl_mod = not a function, impl block, or module - .no_body = function has no body - .help = sanitize attribute can be applied to a function (with body), impl block, or module - -passes_trait_impl_const_stability_mismatch = const stability on the impl does not match the const stability on the trait -passes_trait_impl_const_stability_mismatch_impl_stable = this impl is (implicitly) stable... -passes_trait_impl_const_stability_mismatch_impl_unstable = this impl is unstable... -passes_trait_impl_const_stability_mismatch_trait_stable = ...but the trait is stable -passes_trait_impl_const_stability_mismatch_trait_unstable = ...but the trait is unstable - -passes_trait_impl_const_stable = - trait implementations cannot be const stable yet - .note = see issue #143874 for more information - -passes_transparent_incompatible = - transparent {$target} cannot have other repr hints - -passes_unexportable_adt_with_private_fields = ADT types with private fields are not exportable - .note = `{$field_name}` is private - -passes_unexportable_fn_abi = only functions with "C" ABI are exportable - -passes_unexportable_generic_fn = generic functions are not exportable - -passes_unexportable_item = {$descr}'s are not exportable - -passes_unexportable_priv_item = private items are not exportable - .note = is only usable at visibility `{$vis_descr}` - -passes_unexportable_type_in_interface = {$desc} with `#[export_stable]` attribute uses type `{$ty}`, which is not exportable - .label = not exportable - -passes_unexportable_type_repr = types with unstable layout are not exportable - -passes_unknown_external_lang_item = - unknown external lang item: `{$lang_item}` - -passes_unknown_feature = - unknown feature `{$feature}` - -passes_unknown_feature_alias = - feature `{$alias}` has been renamed to `{$feature}` - -passes_unknown_lang_item = - definition of an unknown lang item: `{$name}` - .label = definition of unknown lang item `{$name}` - -passes_unnecessary_partial_stable_feature = the feature `{$feature}` has been partially stabilized since {$since} and is succeeded by the feature `{$implies}` - .suggestion = if you are using features which are still unstable, change to using `{$implies}` - .suggestion_remove = if you are using features which are now stable, remove this line - -passes_unnecessary_stable_feature = the feature `{$feature}` has been stable since {$since} and no longer requires an attribute to enable - -passes_unrecognized_argument = - unrecognized argument - -passes_unstable_attr_for_already_stable_feature = - can't mark as unstable using an already stable feature - .label = this feature is already stable - .item = the stability attribute annotates this item - .help = consider removing the attribute - -passes_unsupported_attributes_in_where = - most attributes are not supported in `where` clauses - .help = only `#[cfg]` and `#[cfg_attr]` are supported - -passes_unused = - unused attribute - .suggestion = remove this attribute - -passes_unused_default_method_body_const_note = - `default_method_body_is_const` has been replaced with `const` on traits - -passes_unused_duplicate = - unused attribute - .suggestion = remove this attribute - .note = attribute also specified here - .warn = {-passes_previously_accepted} - -passes_unused_empty_lints_note = - attribute `{$name}` with an empty list has no effect - -passes_unused_linker_messages_note = - the `linker_messages` lint can only be controlled at the root of a crate that needs to be linked - -passes_unused_multiple = - multiple `{$name}` attributes - .suggestion = remove this attribute - .note = attribute also specified here - -passes_unused_no_lints_note = - attribute `{$name}` without any lints has no effect - -passes_useless_assignment = - useless assignment of {$is_field_assign -> - [true] field - *[false] variable - } of type `{$ty}` to itself - -passes_useless_stability = - this stability annotation is useless - .label = useless stability annotation - .item = the stability attribute annotates this item diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c8980e4aadc7..c207d7455f74 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -15,7 +15,7 @@ use rustc_attr_parsing::{AttributeParser, Late}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::unord::UnordMap; -use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey}; +use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey, inline_fluent}; use rustc_feature::{ ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, @@ -54,23 +54,23 @@ use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; use rustc_trait_selection::traits::ObligationCtxt; use tracing::debug; -use crate::{errors, fluent_generated as fluent}; +use crate::errors; #[derive(LintDiagnostic)] -#[diag(passes_diagnostic_diagnostic_on_unimplemented_only_for_traits)] +#[diag("`#[diagnostic::on_unimplemented]` can only be applied to trait definitions")] struct DiagnosticOnUnimplementedOnlyForTraits; #[derive(LintDiagnostic)] -#[diag(passes_diagnostic_diagnostic_on_const_only_for_trait_impls)] +#[diag("`#[diagnostic::on_const]` can only be applied to trait impls")] struct DiagnosticOnConstOnlyForTraitImpls { - #[label] + #[label("not a trait impl")] item_span: Span, } #[derive(LintDiagnostic)] -#[diag(passes_diagnostic_diagnostic_on_const_only_for_non_const_trait_impls)] +#[diag("`#[diagnostic::on_const]` can only be applied to non-const trait impls")] struct DiagnosticOnConstOnlyForNonConstTraitImpls { - #[label] + #[label("this is a const trait impl")] item_span: Span, } @@ -1010,8 +1010,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { for (inline2, span2) in rest { if inline2 != inline { let mut spans = MultiSpan::from_spans(vec![*span, *span2]); - spans.push_span_label(*span, fluent::passes_doc_inline_conflict_first); - spans.push_span_label(*span2, fluent::passes_doc_inline_conflict_second); + spans.push_span_label(*span, inline_fluent!("this attribute...")); + spans.push_span_label( + *span2, + inline_fluent!("{\".\"}..conflicts with this attribute"), + ); self.dcx().emit_err(errors::DocInlineConflict { spans }); return; } @@ -1155,7 +1158,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &self.tcx.sess, sym::rustdoc_internals, *span, - fluent::passes_doc_rust_logo, + inline_fluent!("the `#[doc(rust_logo)]` attribute is used for Rust branding"), ) .emit(); } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index d0fa1c4f0e03..90b4d1b32bf7 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, - MultiSpan, + MultiSpan, inline_fluent, }; use rustc_hir::Target; use rustc_hir::attrs::{MirDialect, MirPhase}; @@ -13,80 +13,84 @@ use rustc_middle::ty::{MainDefinition, Ty}; use rustc_span::{DUMMY_SP, Span, Symbol}; use crate::check_attr::ProcMacroKind; -use crate::fluent_generated as fluent; use crate::lang_items::Duplicate; #[derive(LintDiagnostic)] -#[diag(passes_incorrect_do_not_recommend_location)] +#[diag("`#[diagnostic::do_not_recommend]` can only be placed on trait implementations")] pub(crate) struct IncorrectDoNotRecommendLocation; #[derive(Diagnostic)] -#[diag(passes_autodiff_attr)] +#[diag("`#[autodiff]` should be applied to a function")] pub(crate) struct AutoDiffAttr { #[primary_span] - #[label] + #[label("not a function")] pub attr_span: Span, } #[derive(Diagnostic)] -#[diag(passes_loop_match_attr)] +#[diag("`#[loop_match]` should be applied to a loop")] pub(crate) struct LoopMatchAttr { #[primary_span] pub attr_span: Span, - #[label] + #[label("not a loop")] pub node_span: Span, } #[derive(Diagnostic)] -#[diag(passes_const_continue_attr)] +#[diag("`#[const_continue]` should be applied to a break expression")] pub(crate) struct ConstContinueAttr { #[primary_span] pub attr_span: Span, - #[label] + #[label("not a break expression")] pub node_span: Span, } #[derive(LintDiagnostic)] -#[diag(passes_mixed_export_name_and_no_mangle)] +#[diag("`{$no_mangle_attr}` attribute may not be used in combination with `{$export_name_attr}`")] pub(crate) struct MixedExportNameAndNoMangle { - #[label] - #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] + #[label("`{$no_mangle_attr}` is ignored")] + #[suggestion( + "remove the `{$no_mangle_attr}` attribute", + style = "verbose", + code = "", + applicability = "machine-applicable" + )] pub no_mangle_span: Span, - #[note] + #[note("`{$export_name_attr}` takes precedence")] pub export_name_span: Span, pub no_mangle_attr: &'static str, pub export_name_attr: &'static str, } #[derive(LintDiagnostic)] -#[diag(passes_outer_crate_level_attr)] +#[diag("crate-level attribute should be an inner attribute")] pub(crate) struct OuterCrateLevelAttr { #[subdiagnostic] pub suggestion: OuterCrateLevelAttrSuggestion, } #[derive(Subdiagnostic)] -#[multipart_suggestion(passes_outer_crate_level_attr_suggestion, style = "verbose")] +#[multipart_suggestion("add a `!`", style = "verbose")] pub(crate) struct OuterCrateLevelAttrSuggestion { #[suggestion_part(code = "!")] pub bang_position: Span, } #[derive(LintDiagnostic)] -#[diag(passes_inner_crate_level_attr)] +#[diag("crate-level attribute should be in the root module")] pub(crate) struct InnerCrateLevelAttr; #[derive(Diagnostic)] -#[diag(passes_non_exhaustive_with_default_field_values)] +#[diag("`#[non_exhaustive]` can't be used to annotate items with default field values")] pub(crate) struct NonExhaustiveWithDefaultFieldValues { #[primary_span] pub attr_span: Span, - #[label] + #[label("this struct has default field values")] pub defn_span: Span, } #[derive(Diagnostic)] -#[diag(passes_doc_alias_bad_location)] +#[diag("`#[doc(alias = \"...\")]` isn't allowed on {$location}")] pub(crate) struct DocAliasBadLocation<'a> { #[primary_span] pub span: Span, @@ -94,7 +98,7 @@ pub(crate) struct DocAliasBadLocation<'a> { } #[derive(Diagnostic)] -#[diag(passes_doc_alias_not_an_alias)] +#[diag("`#[doc(alias = \"{$attr_str}\"]` is the same as the item's name")] pub(crate) struct DocAliasNotAnAlias { #[primary_span] pub span: Span, @@ -102,7 +106,7 @@ pub(crate) struct DocAliasNotAnAlias { } #[derive(Diagnostic)] -#[diag(passes_doc_keyword_attribute_empty_mod)] +#[diag("`#[doc({$attr_name} = \"...\")]` should be used on empty modules")] pub(crate) struct DocKeywordAttributeEmptyMod { #[primary_span] pub span: Span, @@ -110,7 +114,7 @@ pub(crate) struct DocKeywordAttributeEmptyMod { } #[derive(Diagnostic)] -#[diag(passes_doc_keyword_attribute_not_mod)] +#[diag("`#[doc({$attr_name} = \"...\")]` should be used on modules")] pub(crate) struct DocKeywordAttributeNotMod { #[primary_span] pub span: Span, @@ -118,115 +122,131 @@ pub(crate) struct DocKeywordAttributeNotMod { } #[derive(Diagnostic)] -#[diag(passes_doc_fake_variadic_not_valid)] +#[diag( + "`#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity" +)] pub(crate) struct DocFakeVariadicNotValid { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_doc_keyword_only_impl)] +#[diag("`#[doc(keyword = \"...\")]` should be used on impl blocks")] pub(crate) struct DocKeywordOnlyImpl { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_doc_search_unbox_invalid)] +#[diag("`#[doc(search_unbox)]` should be used on generic structs and enums")] pub(crate) struct DocSearchUnboxInvalid { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_doc_inline_conflict)] -#[help] +#[diag("conflicting doc inlining attributes")] +#[help("remove one of the conflicting attributes")] pub(crate) struct DocInlineConflict { #[primary_span] pub spans: MultiSpan, } #[derive(LintDiagnostic)] -#[diag(passes_doc_inline_only_use)] -#[note] +#[diag("this attribute can only be applied to a `use` item")] +#[note( + "read for more information" +)] pub(crate) struct DocInlineOnlyUse { - #[label] + #[label("only applicable on `use` items")] pub attr_span: Span, - #[label(passes_not_a_use_item_label)] + #[label("not a `use` item")] pub item_span: Span, } #[derive(LintDiagnostic)] -#[diag(passes_doc_masked_only_extern_crate)] -#[note] +#[diag("this attribute can only be applied to an `extern crate` item")] +#[note( + "read for more information" +)] pub(crate) struct DocMaskedOnlyExternCrate { - #[label] + #[label("only applicable on `extern crate` items")] pub attr_span: Span, - #[label(passes_not_an_extern_crate_label)] + #[label("not an `extern crate` item")] pub item_span: Span, } #[derive(LintDiagnostic)] -#[diag(passes_doc_masked_not_extern_crate_self)] +#[diag("this attribute cannot be applied to an `extern crate self` item")] pub(crate) struct DocMaskedNotExternCrateSelf { - #[label] + #[label("not applicable on `extern crate self` items")] pub attr_span: Span, - #[label(passes_extern_crate_self_label)] + #[label("`extern crate self` defined here")] pub item_span: Span, } #[derive(Diagnostic)] -#[diag(passes_both_ffi_const_and_pure, code = E0757)] +#[diag("`#[ffi_const]` function cannot be `#[ffi_pure]`", code = E0757)] pub(crate) struct BothFfiConstAndPure { #[primary_span] pub attr_span: Span, } #[derive(LintDiagnostic)] -#[diag(passes_link)] -#[warning] +#[diag("attribute should be applied to an `extern` block with non-Rust ABI")] +#[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" +)] pub(crate) struct Link { - #[label] + #[label("not an `extern` block")] pub span: Option, } #[derive(Diagnostic)] -#[diag(passes_rustc_legacy_const_generics_only)] +#[diag("#[rustc_legacy_const_generics] functions must only have const generics")] pub(crate) struct RustcLegacyConstGenericsOnly { #[primary_span] pub attr_span: Span, - #[label] + #[label("non-const generic parameter")] pub param_span: Span, } #[derive(Diagnostic)] -#[diag(passes_rustc_legacy_const_generics_index)] +#[diag("#[rustc_legacy_const_generics] must have one index for each generic parameter")] pub(crate) struct RustcLegacyConstGenericsIndex { #[primary_span] pub attr_span: Span, - #[label] + #[label("generic parameters")] pub generics_span: Span, } #[derive(Diagnostic)] -#[diag(passes_rustc_legacy_const_generics_index_exceed)] +#[diag("index exceeds number of arguments")] pub(crate) struct RustcLegacyConstGenericsIndexExceed { #[primary_span] - #[label] + #[label( + "there {$arg_count -> + [one] is + *[other] are + } only {$arg_count} {$arg_count -> + [one] argument + *[other] arguments + }" + )] pub span: Span, pub arg_count: usize, } #[derive(Diagnostic)] -#[diag(passes_repr_conflicting, code = E0566)] +#[diag("conflicting representation hints", code = E0566)] pub(crate) struct ReprConflicting { #[primary_span] pub hint_spans: Vec, } #[derive(Diagnostic)] -#[diag(passes_repr_align_greater_than_target_max, code = E0589)] -#[note] +#[diag("alignment must not be greater than `isize::MAX` bytes", code = E0589)] +#[note("`isize::MAX` is {$size} for the current target")] pub(crate) struct InvalidReprAlignForTarget { #[primary_span] pub span: Span, @@ -234,20 +254,20 @@ pub(crate) struct InvalidReprAlignForTarget { } #[derive(LintDiagnostic)] -#[diag(passes_repr_conflicting, code = E0566)] +#[diag("conflicting representation hints", code = E0566)] pub(crate) struct ReprConflictingLint; #[derive(Diagnostic)] -#[diag(passes_macro_only_attribute)] +#[diag("attribute should be applied to a macro")] pub(crate) struct MacroOnlyAttribute { #[primary_span] pub attr_span: Span, - #[label] + #[label("not a macro")] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_debug_visualizer_unreadable)] +#[diag("couldn't read {$file}: {$error}")] pub(crate) struct DebugVisualizerUnreadable<'a> { #[primary_span] pub span: Span, @@ -256,106 +276,114 @@ pub(crate) struct DebugVisualizerUnreadable<'a> { } #[derive(Diagnostic)] -#[diag(passes_rustc_allow_const_fn_unstable)] +#[diag("attribute should be applied to `const fn`")] pub(crate) struct RustcAllowConstFnUnstable { #[primary_span] pub attr_span: Span, - #[label] + #[label("not a `const fn`")] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_rustc_pub_transparent)] +#[diag("attribute should be applied to `#[repr(transparent)]` types")] pub(crate) struct RustcPubTransparent { #[primary_span] pub attr_span: Span, - #[label] + #[label("not a `#[repr(transparent)]` type")] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_rustc_force_inline_coro)] +#[diag("attribute cannot be applied to a `async`, `gen` or `async gen` function")] pub(crate) struct RustcForceInlineCoro { #[primary_span] pub attr_span: Span, - #[label] + #[label("`async`, `gen` or `async gen` function")] pub span: Span, } #[derive(LintDiagnostic)] pub(crate) enum MacroExport { - #[diag(passes_macro_export_on_decl_macro)] - #[note] + #[diag("`#[macro_export]` has no effect on declarative macro definitions")] + #[note("declarative macros follow the same exporting rules as regular items")] OnDeclMacro, } #[derive(Subdiagnostic)] pub(crate) enum UnusedNote { - #[note(passes_unused_empty_lints_note)] + #[note("attribute `{$name}` with an empty list has no effect")] EmptyList { name: Symbol }, - #[note(passes_unused_no_lints_note)] + #[note("attribute `{$name}` without any lints has no effect")] NoLints { name: Symbol }, - #[note(passes_unused_default_method_body_const_note)] + #[note("`default_method_body_is_const` has been replaced with `const` on traits")] DefaultMethodBodyConst, - #[note(passes_unused_linker_messages_note)] + #[note( + "the `linker_messages` lint can only be controlled at the root of a crate that needs to be linked" + )] LinkerMessagesBinaryCrateOnly, } #[derive(LintDiagnostic)] -#[diag(passes_unused)] +#[diag("unused attribute")] pub(crate) struct Unused { - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] pub attr_span: Span, #[subdiagnostic] pub note: UnusedNote, } #[derive(Diagnostic)] -#[diag(passes_non_exported_macro_invalid_attrs, code = E0518)] +#[diag("attribute should be applied to function or closure", code = E0518)] pub(crate) struct NonExportedMacroInvalidAttrs { #[primary_span] - #[label] + #[label("not a function or closure")] pub attr_span: Span, } #[derive(Diagnostic)] -#[diag(passes_may_dangle)] +#[diag("`#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl")] pub(crate) struct InvalidMayDangle { #[primary_span] pub attr_span: Span, } #[derive(LintDiagnostic)] -#[diag(passes_unused_duplicate)] +#[diag("unused attribute")] pub(crate) struct UnusedDuplicate { - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] pub this: Span, - #[note] + #[note("attribute also specified here")] pub other: Span, - #[warning] + #[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" + )] pub warning: bool, } #[derive(Diagnostic)] -#[diag(passes_unused_multiple)] +#[diag("multiple `{$name}` attributes")] pub(crate) struct UnusedMultiple { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] pub this: Span, - #[note] + #[note("attribute also specified here")] pub other: Span, pub name: Symbol, } #[derive(LintDiagnostic)] -#[diag(passes_deprecated_annotation_has_no_effect)] +#[diag("this `#[deprecated]` annotation has no effect")] pub(crate) struct DeprecatedAnnotationHasNoEffect { - #[suggestion(applicability = "machine-applicable", code = "")] + #[suggestion( + "remove the unnecessary deprecation attribute", + applicability = "machine-applicable", + code = "" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_unknown_external_lang_item, code = E0264)] +#[diag("unknown external lang item: `{$lang_item}`", code = E0264)] pub(crate) struct UnknownExternLangItem { #[primary_span] pub span: Span, @@ -363,48 +391,74 @@ pub(crate) struct UnknownExternLangItem { } #[derive(Diagnostic)] -#[diag(passes_missing_panic_handler)] +#[diag("`#[panic_handler]` function required, but not found")] pub(crate) struct MissingPanicHandler; #[derive(Diagnostic)] -#[diag(passes_panic_unwind_without_std)] -#[help] -#[note] +#[diag("unwinding panics are not supported without std")] +#[help("using nightly cargo, use -Zbuild-std with panic=\"abort\" to avoid unwinding")] +#[note( + "since the core library is usually precompiled with panic=\"unwind\", rebuilding your crate with panic=\"abort\" may not be enough to fix the problem" +)] pub(crate) struct PanicUnwindWithoutStd; #[derive(Diagnostic)] -#[diag(passes_missing_lang_item)] -#[note] -#[help] +#[diag("lang item required, but not found: `{$name}`")] +#[note( + "this can occur when a binary crate with `#![no_std]` is compiled for a target where `{$name}` is defined in the standard library" +)] +#[help( + "you may be able to compile for a target that doesn't need `{$name}`, specify a target with `--target` or in `.cargo/config`" +)] pub(crate) struct MissingLangItem { pub name: Symbol, } #[derive(Diagnostic)] -#[diag(passes_lang_item_fn_with_track_caller)] +#[diag( + "{$name -> + [panic_impl] `#[panic_handler]` + *[other] `{$name}` lang item +} function is not allowed to have `#[track_caller]`" +)] pub(crate) struct LangItemWithTrackCaller { #[primary_span] pub attr_span: Span, pub name: Symbol, - #[label] + #[label( + "{$name -> + [panic_impl] `#[panic_handler]` + *[other] `{$name}` lang item + } function is not allowed to have `#[track_caller]`" + )] pub sig_span: Span, } #[derive(Diagnostic)] -#[diag(passes_lang_item_fn_with_target_feature)] +#[diag( + "{$name -> + [panic_impl] `#[panic_handler]` + *[other] `{$name}` lang item + } function is not allowed to have `#[target_feature]`" +)] pub(crate) struct LangItemWithTargetFeature { #[primary_span] pub attr_span: Span, pub name: Symbol, - #[label] + #[label( + "{$name -> + [panic_impl] `#[panic_handler]` + *[other] `{$name}` lang item + } function is not allowed to have `#[target_feature]`" + )] pub sig_span: Span, } #[derive(Diagnostic)] -#[diag(passes_lang_item_on_incorrect_target, code = E0718)] +#[diag("`{$name}` lang item must be applied to a {$expected_target}", code = E0718)] pub(crate) struct LangItemOnIncorrectTarget { #[primary_span] - #[label] + #[label("attribute should be applied to a {$expected_target}, not a {$actual_target}")] pub span: Span, pub name: Symbol, pub expected_target: Target, @@ -412,10 +466,10 @@ pub(crate) struct LangItemOnIncorrectTarget { } #[derive(Diagnostic)] -#[diag(passes_unknown_lang_item, code = E0522)] +#[diag("definition of an unknown lang item: `{$name}`", code = E0522)] pub(crate) struct UnknownLangItem { #[primary_span] - #[label] + #[label("definition of unknown lang item `{$name}`")] pub span: Span, pub name: Symbol, } @@ -436,7 +490,11 @@ pub(crate) struct ItemFollowingInnerAttr { impl Diagnostic<'_, G> for InvalidAttrAtCrateLevel { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::passes_invalid_attr_at_crate_level); + let mut diag = Diag::new( + dcx, + level, + inline_fluent!("`{$name}` attribute cannot be used at crate level"), + ); diag.span(self.span); diag.arg("name", self.name); // Only emit an error with a suggestion if we can create a string out @@ -444,27 +502,30 @@ impl Diagnostic<'_, G> for InvalidAttrAtCrateLevel { if let Some(span) = self.sugg_span { diag.span_suggestion_verbose( span, - fluent::passes_suggestion, + inline_fluent!("perhaps you meant to use an outer attribute"), String::new(), Applicability::MachineApplicable, ); } if let Some(item) = self.item { diag.arg("kind", item.kind); - diag.span_label(item.span, fluent::passes_invalid_attr_at_crate_level_item); + diag.span_label( + item.span, + inline_fluent!("the inner attribute doesn't annotate this {$kind}"), + ); } diag } } #[derive(Diagnostic)] -#[diag(passes_duplicate_diagnostic_item_in_crate)] +#[diag("duplicate diagnostic item in crate `{$crate_name}`: `{$name}`")] pub(crate) struct DuplicateDiagnosticItemInCrate { #[primary_span] pub duplicate_span: Option, - #[note(passes_diagnostic_item_first_defined)] + #[note("the diagnostic item is first defined here")] pub orig_span: Option, - #[note] + #[note("the diagnostic item is first defined in crate `{$orig_crate_name}`")] pub different_crates: bool, pub crate_name: Symbol, pub orig_crate_name: Symbol, @@ -472,7 +533,7 @@ pub(crate) struct DuplicateDiagnosticItemInCrate { } #[derive(Diagnostic)] -#[diag(passes_layout_abi)] +#[diag("abi: {$abi}")] pub(crate) struct LayoutAbi { #[primary_span] pub span: Span, @@ -480,7 +541,7 @@ pub(crate) struct LayoutAbi { } #[derive(Diagnostic)] -#[diag(passes_layout_align)] +#[diag("align: {$align}")] pub(crate) struct LayoutAlign { #[primary_span] pub span: Span, @@ -488,7 +549,7 @@ pub(crate) struct LayoutAlign { } #[derive(Diagnostic)] -#[diag(passes_layout_size)] +#[diag("size: {$size}")] pub(crate) struct LayoutSize { #[primary_span] pub span: Span, @@ -496,7 +557,7 @@ pub(crate) struct LayoutSize { } #[derive(Diagnostic)] -#[diag(passes_layout_homogeneous_aggregate)] +#[diag("homogeneous_aggregate: {$homogeneous_aggregate}")] pub(crate) struct LayoutHomogeneousAggregate { #[primary_span] pub span: Span, @@ -504,7 +565,7 @@ pub(crate) struct LayoutHomogeneousAggregate { } #[derive(Diagnostic)] -#[diag(passes_layout_of)] +#[diag("layout_of({$normalized_ty}) = {$ty_layout}")] pub(crate) struct LayoutOf<'tcx> { #[primary_span] pub span: Span, @@ -513,7 +574,7 @@ pub(crate) struct LayoutOf<'tcx> { } #[derive(Diagnostic)] -#[diag(passes_abi_of)] +#[diag("fn_abi_of({$fn_name}) = {$fn_abi}")] pub(crate) struct AbiOf { #[primary_span] pub span: Span, @@ -522,7 +583,11 @@ pub(crate) struct AbiOf { } #[derive(Diagnostic)] -#[diag(passes_abi_ne)] +#[diag( + "ABIs are not compatible + left ABI = {$left} + right ABI = {$right}" +)] pub(crate) struct AbiNe { #[primary_span] pub span: Span, @@ -531,21 +596,23 @@ pub(crate) struct AbiNe { } #[derive(Diagnostic)] -#[diag(passes_abi_invalid_attribute)] +#[diag( + "`#[rustc_abi]` can only be applied to function items, type aliases, and associated functions" +)] pub(crate) struct AbiInvalidAttribute { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_unrecognized_argument)] +#[diag("unrecognized argument")] pub(crate) struct UnrecognizedArgument { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_feature_stable_twice, code = E0711)] +#[diag("feature `{$feature}` is declared stable since {$since}, but was previously declared stable since {$prev_since}", code = E0711)] pub(crate) struct FeatureStableTwice { #[primary_span] pub span: Span, @@ -555,7 +622,7 @@ pub(crate) struct FeatureStableTwice { } #[derive(Diagnostic)] -#[diag(passes_feature_previously_declared, code = E0711)] +#[diag("feature `{$feature}` is declared {$declared}, but was previously declared {$prev_declared}", code = E0711)] pub(crate) struct FeaturePreviouslyDeclared<'a> { #[primary_span] pub span: Span, @@ -565,18 +632,18 @@ pub(crate) struct FeaturePreviouslyDeclared<'a> { } #[derive(Diagnostic)] -#[diag(passes_multiple_rustc_main, code = E0137)] +#[diag("multiple functions with a `#[rustc_main]` attribute", code = E0137)] pub(crate) struct MultipleRustcMain { #[primary_span] pub span: Span, - #[label(passes_first)] + #[label("first `#[rustc_main]` function")] pub first: Span, - #[label(passes_additional)] + #[label("additional `#[rustc_main]` function")] pub additional: Span, } #[derive(Diagnostic)] -#[diag(passes_extern_main)] +#[diag("the `main` function cannot be declared in an `extern` block")] pub(crate) struct ExternMain { #[primary_span] pub span: Span, @@ -596,7 +663,11 @@ pub(crate) struct NoMainErr { impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NoMainErr { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { - let mut diag = Diag::new(dcx, level, fluent::passes_no_main_function); + let mut diag = Diag::new( + dcx, + level, + inline_fluent!("`main` function not found in crate `{$crate_name}`"), + ); diag.span(DUMMY_SP); diag.code(E0601); diag.arg("crate_name", self.crate_name); @@ -604,16 +675,23 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NoMainErr { diag.arg("has_filename", self.has_filename); let note = if !self.non_main_fns.is_empty() { for &span in &self.non_main_fns { - diag.span_note(span, fluent::passes_here_is_main); + diag.span_note(span, inline_fluent!("here is a function named `main`")); } - diag.note(fluent::passes_one_or_more_possible_main); - diag.help(fluent::passes_consider_moving_main); + diag.note(inline_fluent!( + "you have one or more functions named `main` not defined at the crate level" + )); + diag.help(inline_fluent!("consider moving the `main` function definitions")); // There were some functions named `main` though. Try to give the user a hint. - fluent::passes_main_must_be_defined_at_crate + inline_fluent!( + "the main function must be defined at the crate level{$has_filename -> + [true] {\" \"}(in `{$filename}`) + *[false] {\"\"} + }" + ) } else if self.has_filename { - fluent::passes_consider_adding_main_to_file + inline_fluent!("consider adding a `main` function to `{$filename}`") } else { - fluent::passes_consider_adding_main_at_crate + inline_fluent!("consider adding a `main` function at the crate level") }; if self.file_empty { diag.note(note); @@ -626,11 +704,14 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NoMainErr { && main_def.opt_fn_def_id().is_none() { // There is something at `crate::main`, but it is not a function definition. - diag.span_label(main_def.span, fluent::passes_non_function_main); + diag.span_label( + main_def.span, + inline_fluent!("non-function item at `crate::main` is found"), + ); } if self.add_teach_note { - diag.note(fluent::passes_teach_note); + diag.note(inline_fluent!("if you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/")); } diag } @@ -658,9 +739,13 @@ impl Diagnostic<'_, G> for DuplicateLangItem { dcx, level, match self.duplicate { - Duplicate::Plain => fluent::passes_duplicate_lang_item, - Duplicate::Crate => fluent::passes_duplicate_lang_item_crate, - Duplicate::CrateDepends => fluent::passes_duplicate_lang_item_crate_depends, + Duplicate::Plain => inline_fluent!("found duplicate lang item `{$lang_item_name}`"), + Duplicate::Crate => inline_fluent!( + "duplicate lang item in crate `{$crate_name}`: `{$lang_item_name}`" + ), + Duplicate::CrateDepends => inline_fluent!( + "duplicate lang item in crate `{$crate_name}` (which `{$dependency_of}` depends on): `{$lang_item_name}`" + ), }, ); diag.code(E0152); @@ -681,24 +766,32 @@ impl Diagnostic<'_, G> for DuplicateLangItem { diag.span(span); } if let Some(span) = self.first_defined_span { - diag.span_note(span, fluent::passes_first_defined_span); + diag.span_note(span, inline_fluent!("the lang item is first defined here")); } else { if self.orig_dependency_of.is_none() { - diag.note(fluent::passes_first_defined_crate); + diag.note(inline_fluent!( + "the lang item is first defined in crate `{$orig_crate_name}`" + )); } else { - diag.note(fluent::passes_first_defined_crate_depends); + diag.note(inline_fluent!("the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on)")); } if self.orig_is_local { - diag.note(fluent::passes_first_definition_local); + diag.note(inline_fluent!( + "first definition in the local crate (`{$orig_crate_name}`)" + )); } else { - diag.note(fluent::passes_first_definition_path); + diag.note(inline_fluent!( + "first definition in `{$orig_crate_name}` loaded from {$orig_path}" + )); } if self.is_local { - diag.note(fluent::passes_second_definition_local); + diag.note(inline_fluent!("second definition in the local crate (`{$crate_name}`)")); } else { - diag.note(fluent::passes_second_definition_path); + diag.note(inline_fluent!( + "second definition in `{$crate_name}` loaded from {$path}" + )); } } diag @@ -706,11 +799,22 @@ impl Diagnostic<'_, G> for DuplicateLangItem { } #[derive(Diagnostic)] -#[diag(passes_incorrect_target, code = E0718)] +#[diag("`{$name}` lang item must be applied to a {$kind} with {$at_least -> + [true] at least {$num} + *[false] {$num} + } generic {$num -> + [one] argument + *[other] arguments + }", code = E0718)] pub(crate) struct IncorrectTarget<'a> { #[primary_span] pub span: Span, - #[label] + #[label( + "this {$kind} has {$actual_num} generic {$actual_num -> + [one] argument + *[other] arguments + }" + )] pub generics_span: Span, pub name: &'a str, // cannot be symbol because it renders e.g. `r#fn` instead of `fn` pub kind: &'static str, @@ -720,26 +824,33 @@ pub(crate) struct IncorrectTarget<'a> { } #[derive(Diagnostic)] -#[diag(passes_incorrect_crate_type)] +#[diag("lang items are not allowed in stable dylibs")] pub(crate) struct IncorrectCrateType { #[primary_span] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(passes_useless_assignment)] +#[diag( + "useless assignment of {$is_field_assign -> + [true] field + *[false] variable + } of type `{$ty}` to itself" +)] pub(crate) struct UselessAssignment<'a> { pub is_field_assign: bool, pub ty: Ty<'a>, } #[derive(LintDiagnostic)] -#[diag(passes_inline_ignored_for_exported)] -#[help] +#[diag("`#[inline]` is ignored on externally exported functions")] +#[help( + "externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`" +)] pub(crate) struct InlineIgnoredForExported {} #[derive(Diagnostic)] -#[diag(passes_object_lifetime_err)] +#[diag("{$repr}")] pub(crate) struct ObjectLifetimeErr { #[primary_span] pub span: Span, @@ -748,38 +859,38 @@ pub(crate) struct ObjectLifetimeErr { #[derive(Diagnostic)] pub(crate) enum AttrApplication { - #[diag(passes_attr_application_enum, code = E0517)] + #[diag("attribute should be applied to an enum", code = E0517)] Enum { #[primary_span] hint_span: Span, - #[label] + #[label("not an enum")] span: Span, }, - #[diag(passes_attr_application_struct, code = E0517)] + #[diag("attribute should be applied to a struct", code = E0517)] Struct { #[primary_span] hint_span: Span, - #[label] + #[label("not a struct")] span: Span, }, - #[diag(passes_attr_application_struct_union, code = E0517)] + #[diag("attribute should be applied to a struct or union", code = E0517)] StructUnion { #[primary_span] hint_span: Span, - #[label] + #[label("not a struct or union")] span: Span, }, - #[diag(passes_attr_application_struct_enum_union, code = E0517)] + #[diag("attribute should be applied to a struct, enum, or union", code = E0517)] StructEnumUnion { #[primary_span] hint_span: Span, - #[label] + #[label("not a struct, enum, or union")] span: Span, }, } #[derive(Diagnostic)] -#[diag(passes_transparent_incompatible, code = E0692)] +#[diag("transparent {$target} cannot have other repr hints", code = E0692)] pub(crate) struct TransparentIncompatible { #[primary_span] pub hint_spans: Vec, @@ -787,45 +898,45 @@ pub(crate) struct TransparentIncompatible { } #[derive(Diagnostic)] -#[diag(passes_deprecated_attribute, code = E0549)] +#[diag("deprecated attribute must be paired with either stable or unstable attribute", code = E0549)] pub(crate) struct DeprecatedAttribute { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_useless_stability)] +#[diag("this stability annotation is useless")] pub(crate) struct UselessStability { #[primary_span] - #[label] + #[label("useless stability annotation")] pub span: Span, - #[label(passes_item)] + #[label("the stability attribute annotates this item")] pub item_sp: Span, } #[derive(Diagnostic)] -#[diag(passes_cannot_stabilize_deprecated)] +#[diag("an API can't be stabilized after it is deprecated")] pub(crate) struct CannotStabilizeDeprecated { #[primary_span] - #[label] + #[label("invalid version")] pub span: Span, - #[label(passes_item)] + #[label("the stability attribute annotates this item")] pub item_sp: Span, } #[derive(Diagnostic)] -#[diag(passes_unstable_attr_for_already_stable_feature)] +#[diag("can't mark as unstable using an already stable feature")] pub(crate) struct UnstableAttrForAlreadyStableFeature { #[primary_span] - #[label] - #[help] + #[label("this feature is already stable")] + #[help("consider removing the attribute")] pub attr_span: Span, - #[label(passes_item)] + #[label("the stability attribute annotates this item")] pub item_span: Span, } #[derive(Diagnostic)] -#[diag(passes_missing_stability_attr)] +#[diag("{$descr} has missing stability attribute")] pub(crate) struct MissingStabilityAttr<'a> { #[primary_span] pub span: Span, @@ -833,7 +944,7 @@ pub(crate) struct MissingStabilityAttr<'a> { } #[derive(Diagnostic)] -#[diag(passes_missing_const_stab_attr)] +#[diag("{$descr} has missing const stability attribute")] pub(crate) struct MissingConstStabAttr<'a> { #[primary_span] pub span: Span, @@ -841,15 +952,15 @@ pub(crate) struct MissingConstStabAttr<'a> { } #[derive(Diagnostic)] -#[diag(passes_trait_impl_const_stable)] -#[note] +#[diag("trait implementations cannot be const stable yet")] +#[note("see issue #143874 for more information")] pub(crate) struct TraitImplConstStable { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_trait_impl_const_stability_mismatch)] +#[diag("const stability on the impl does not match the const stability on the trait")] pub(crate) struct TraitImplConstStabilityMismatch { #[primary_span] pub span: Span, @@ -861,12 +972,12 @@ pub(crate) struct TraitImplConstStabilityMismatch { #[derive(Subdiagnostic)] pub(crate) enum TraitConstStability { - #[note(passes_trait_impl_const_stability_mismatch_trait_stable)] + #[note("...but the trait is stable")] Stable { #[primary_span] span: Span, }, - #[note(passes_trait_impl_const_stability_mismatch_trait_unstable)] + #[note("...but the trait is unstable")] Unstable { #[primary_span] span: Span, @@ -875,12 +986,12 @@ pub(crate) enum TraitConstStability { #[derive(Subdiagnostic)] pub(crate) enum ImplConstStability { - #[note(passes_trait_impl_const_stability_mismatch_impl_stable)] + #[note("this impl is (implicitly) stable...")] Stable { #[primary_span] span: Span, }, - #[note(passes_trait_impl_const_stability_mismatch_impl_unstable)] + #[note("this impl is unstable...")] Unstable { #[primary_span] span: Span, @@ -888,7 +999,7 @@ pub(crate) enum ImplConstStability { } #[derive(Diagnostic)] -#[diag(passes_unknown_feature, code = E0635)] +#[diag("unknown feature `{$feature}`", code = E0635)] pub(crate) struct UnknownFeature { #[primary_span] pub span: Span, @@ -899,7 +1010,7 @@ pub(crate) struct UnknownFeature { #[derive(Subdiagnostic)] #[suggestion( - passes_misspelled_feature, + "there is a feature with a similar name: `{$actual_name}`", style = "verbose", code = "{actual_name}", applicability = "maybe-incorrect" @@ -911,7 +1022,7 @@ pub(crate) struct MisspelledFeature { } #[derive(Diagnostic)] -#[diag(passes_unknown_feature_alias, code = E0635)] +#[diag("feature `{$alias}` has been renamed to `{$feature}`", code = E0635)] pub(crate) struct RenamedFeature { #[primary_span] pub span: Span, @@ -920,7 +1031,7 @@ pub(crate) struct RenamedFeature { } #[derive(Diagnostic)] -#[diag(passes_implied_feature_not_exist)] +#[diag("feature `{$implied_by}` implying `{$feature}` does not exist")] pub(crate) struct ImpliedFeatureNotExist { #[primary_span] pub span: Span, @@ -929,7 +1040,7 @@ pub(crate) struct ImpliedFeatureNotExist { } #[derive(Diagnostic)] -#[diag(passes_duplicate_feature_err, code = E0636)] +#[diag("the feature `{$feature}` has already been enabled", code = E0636)] pub(crate) struct DuplicateFeatureErr { #[primary_span] pub span: Span, @@ -937,25 +1048,37 @@ pub(crate) struct DuplicateFeatureErr { } #[derive(Diagnostic)] -#[diag(passes_missing_const_err)] +#[diag( + "attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`" +)] pub(crate) struct MissingConstErr { #[primary_span] - #[help] + #[help("make the function or method const")] pub fn_sig_span: Span, } #[derive(Diagnostic)] -#[diag(passes_const_stable_not_stable)] +#[diag( + "attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]`" +)] pub(crate) struct ConstStableNotStable { #[primary_span] pub fn_sig_span: Span, - #[label] + #[label("attribute specified here")] pub const_span: Span, } #[derive(LintDiagnostic)] pub(crate) enum MultipleDeadCodes<'tcx> { - #[diag(passes_dead_codes)] + #[diag( + "{ $multiple -> + *[true] multiple {$descr}s are + [false] { $num -> + [one] {$descr} {$name_list} is + *[other] {$descr}s {$name_list} are + } + } never {$participle}" + )] DeadCodes { multiple: bool, num: usize, @@ -970,7 +1093,15 @@ pub(crate) enum MultipleDeadCodes<'tcx> { #[subdiagnostic] ignored_derived_impls: Option, }, - #[diag(passes_dead_codes)] + #[diag( + "{ $multiple -> + *[true] multiple {$descr}s are + [false] { $num -> + [one] {$descr} {$name_list} is + *[other] {$descr}s {$name_list} are + } + } never {$participle}" + )] UnusedTupleStructFields { multiple: bool, num: usize, @@ -987,7 +1118,9 @@ pub(crate) enum MultipleDeadCodes<'tcx> { } #[derive(Subdiagnostic)] -#[note(passes_enum_variant_same_name)] +#[note( + "it is impossible to refer to the {$dead_descr} `{$dead_name}` because it is shadowed by this enum variant with the same name" +)] pub(crate) struct EnumVariantSameName<'tcx> { #[primary_span] pub variant_span: Span, @@ -996,7 +1129,12 @@ pub(crate) struct EnumVariantSameName<'tcx> { } #[derive(Subdiagnostic)] -#[label(passes_parent_info)] +#[label( + "{$num -> + [one] {$descr} + *[other] {$descr}s + } in this {$parent_descr}" +)] pub(crate) struct ParentInfo<'tcx> { pub num: usize, pub descr: &'tcx str, @@ -1006,7 +1144,15 @@ pub(crate) struct ParentInfo<'tcx> { } #[derive(Subdiagnostic)] -#[note(passes_ignored_derived_impls)] +#[note( + "`{$name}` has {$trait_list_len -> + [one] a derived impl + *[other] derived impls + } for the {$trait_list_len -> + [one] trait {$trait_list}, but this is + *[other] traits {$trait_list}, but these are + } intentionally ignored during dead code analysis" +)] pub(crate) struct IgnoredDerivedImpls { pub name: Symbol, pub trait_list: DiagSymbolList, @@ -1016,7 +1162,13 @@ pub(crate) struct IgnoredDerivedImpls { #[derive(Subdiagnostic)] pub(crate) enum ChangeFields { #[multipart_suggestion( - passes_change_fields_to_be_of_unit_type, + "consider changing the { $num -> + [one] field + *[other] fields + } to be of unit type to suppress this warning while preserving the field numbering, or remove the { $num -> + [one] field + *[other] fields + }", applicability = "has-placeholders" )] ChangeToUnitTypeOrRemove { @@ -1024,12 +1176,20 @@ pub(crate) enum ChangeFields { #[suggestion_part(code = "()")] spans: Vec, }, - #[help(passes_remove_fields)] + #[help( + "consider removing { $num -> + [one] this + *[other] these + } { $num -> + [one] field + *[other] fields + }" + )] Remove { num: usize }, } #[derive(Diagnostic)] -#[diag(passes_proc_macro_bad_sig)] +#[diag("{$kind} has incorrect signature")] pub(crate) struct ProcMacroBadSig { #[primary_span] pub span: Span, @@ -1037,18 +1197,30 @@ pub(crate) struct ProcMacroBadSig { } #[derive(LintDiagnostic)] -#[diag(passes_unnecessary_stable_feature)] +#[diag( + "the feature `{$feature}` has been stable since {$since} and no longer requires an attribute to enable" +)] pub(crate) struct UnnecessaryStableFeature { pub feature: Symbol, pub since: Symbol, } #[derive(LintDiagnostic)] -#[diag(passes_unnecessary_partial_stable_feature)] +#[diag( + "the feature `{$feature}` has been partially stabilized since {$since} and is succeeded by the feature `{$implies}`" +)] pub(crate) struct UnnecessaryPartialStableFeature { - #[suggestion(code = "{implies}", applicability = "maybe-incorrect")] + #[suggestion( + "if you are using features which are still unstable, change to using `{$implies}`", + code = "{implies}", + applicability = "maybe-incorrect" + )] pub span: Span, - #[suggestion(passes_suggestion_remove, code = "", applicability = "maybe-incorrect")] + #[suggestion( + "if you are using features which are now stable, remove this line", + code = "", + applicability = "maybe-incorrect" + )] pub line: Span, pub feature: Symbol, pub since: Symbol, @@ -1056,38 +1228,36 @@ pub(crate) struct UnnecessaryPartialStableFeature { } #[derive(LintDiagnostic)] -#[diag(passes_ineffective_unstable_impl)] -#[note] +#[diag("an `#[unstable]` annotation here has no effect")] +#[note("see issue #55436 for more information")] pub(crate) struct IneffectiveUnstableImpl; -/// "sanitize attribute not allowed here" #[derive(Diagnostic)] -#[diag(passes_sanitize_attribute_not_allowed)] +#[diag("sanitize attribute not allowed here")] pub(crate) struct SanitizeAttributeNotAllowed { #[primary_span] pub attr_span: Span, - /// "not a function, impl block, or module" - #[label(passes_not_fn_impl_mod)] + #[label("not a function, impl block, or module")] pub not_fn_impl_mod: Option, - /// "function has no body" - #[label(passes_no_body)] + #[label("function has no body")] pub no_body: Option, - /// "sanitize attribute can be applied to a function (with body), impl block, or module" - #[help] + #[help("sanitize attribute can be applied to a function (with body), impl block, or module")] pub help: (), } // FIXME(jdonszelmann): move back to rustc_attr #[derive(Diagnostic)] -#[diag(passes_rustc_const_stable_indirect_pairing)] +#[diag( + "`const_stable_indirect` attribute does not make sense on `rustc_const_stable` function, its behavior is already implied" +)] pub(crate) struct RustcConstStableIndirectPairing { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_unsupported_attributes_in_where)] -#[help] +#[diag("most attributes are not supported in `where` clauses")] +#[help("only `#[cfg]` and `#[cfg_attr]` are supported")] pub(crate) struct UnsupportedAttributesInWhere { #[primary_span] pub span: MultiSpan, @@ -1095,100 +1265,100 @@ pub(crate) struct UnsupportedAttributesInWhere { #[derive(Diagnostic)] pub(crate) enum UnexportableItem<'a> { - #[diag(passes_unexportable_item)] + #[diag("{$descr}'s are not exportable")] Item { #[primary_span] span: Span, descr: &'a str, }, - #[diag(passes_unexportable_generic_fn)] + #[diag("generic functions are not exportable")] GenericFn(#[primary_span] Span), - #[diag(passes_unexportable_fn_abi)] + #[diag("only functions with \"C\" ABI are exportable")] FnAbi(#[primary_span] Span), - #[diag(passes_unexportable_type_repr)] + #[diag("types with unstable layout are not exportable")] TypeRepr(#[primary_span] Span), - #[diag(passes_unexportable_type_in_interface)] + #[diag("{$desc} with `#[export_stable]` attribute uses type `{$ty}`, which is not exportable")] TypeInInterface { #[primary_span] span: Span, desc: &'a str, ty: &'a str, - #[label] + #[label("not exportable")] ty_span: Span, }, - #[diag(passes_unexportable_priv_item)] + #[diag("private items are not exportable")] PrivItem { #[primary_span] span: Span, - #[note] + #[note("is only usable at visibility `{$vis_descr}`")] vis_note: Span, vis_descr: &'a str, }, - #[diag(passes_unexportable_adt_with_private_fields)] + #[diag("ADT types with private fields are not exportable")] AdtWithPrivFields { #[primary_span] span: Span, - #[note] + #[note("`{$field_name}` is private")] vis_note: Span, field_name: &'a str, }, } #[derive(Diagnostic)] -#[diag(passes_repr_align_should_be_align)] +#[diag("`#[repr(align(...))]` is not supported on {$item}")] pub(crate) struct ReprAlignShouldBeAlign { #[primary_span] - #[help] + #[help("use `#[rustc_align(...)]` instead")] pub span: Span, pub item: &'static str, } #[derive(Diagnostic)] -#[diag(passes_repr_align_should_be_align_static)] +#[diag("`#[repr(align(...))]` is not supported on {$item}")] pub(crate) struct ReprAlignShouldBeAlignStatic { #[primary_span] - #[help] + #[help("use `#[rustc_align_static(...)]` instead")] pub span: Span, pub item: &'static str, } #[derive(Diagnostic)] -#[diag(passes_custom_mir_phase_requires_dialect)] +#[diag("`dialect` key required")] pub(crate) struct CustomMirPhaseRequiresDialect { #[primary_span] pub attr_span: Span, - #[label] + #[label("`phase` argument requires a `dialect` argument")] pub phase_span: Span, } #[derive(Diagnostic)] -#[diag(passes_custom_mir_incompatible_dialect_and_phase)] +#[diag("the {$dialect} dialect is not compatible with the {$phase} phase")] pub(crate) struct CustomMirIncompatibleDialectAndPhase { pub dialect: MirDialect, pub phase: MirPhase, #[primary_span] pub attr_span: Span, - #[label] + #[label("this dialect...")] pub dialect_span: Span, - #[label] + #[label("... is not compatible with this phase")] pub phase_span: Span, } #[derive(Diagnostic)] -#[diag(passes_eii_impl_not_function)] +#[diag("`eii_macro_for` is only valid on functions")] pub(crate) struct EiiImplNotFunction { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_eii_impl_requires_unsafe)] +#[diag("`#[{$name}]` is unsafe to implement")] pub(crate) struct EiiImplRequiresUnsafe { #[primary_span] pub span: Span, @@ -1198,10 +1368,7 @@ pub(crate) struct EiiImplRequiresUnsafe { } #[derive(Subdiagnostic)] -#[multipart_suggestion( - passes_eii_impl_requires_unsafe_suggestion, - applicability = "machine-applicable" -)] +#[multipart_suggestion("wrap the attribute in `unsafe(...)`", applicability = "machine-applicable")] pub(crate) struct EiiImplRequiresUnsafeSuggestion { #[suggestion_part(code = "unsafe(")] pub left: Span, @@ -1210,64 +1377,71 @@ pub(crate) struct EiiImplRequiresUnsafeSuggestion { } #[derive(Diagnostic)] -#[diag(passes_eii_fn_with_track_caller)] +#[diag("`#[{$name}]` is not allowed to have `#[track_caller]`")] pub(crate) struct EiiWithTrackCaller { #[primary_span] pub attr_span: Span, pub name: Symbol, - #[label] + #[label("`#[{$name}]` is not allowed to have `#[track_caller]`")] pub sig_span: Span, } #[derive(Diagnostic)] -#[diag(passes_eii_without_impl)] +#[diag("`#[{$name}]` required, but not found")] pub(crate) struct EiiWithoutImpl { #[primary_span] - #[label] + #[label("expected because `#[{$name}]` was declared here in crate `{$decl_crate_name}`")] pub span: Span, pub name: Symbol, pub current_crate_name: Symbol, pub decl_crate_name: Symbol, - #[help] + #[help( + "expected at least one implementation in crate `{$current_crate_name}` or any of its dependencies" + )] pub help: (), } #[derive(Diagnostic)] -#[diag(passes_duplicate_eii_impls)] +#[diag("multiple implementations of `#[{$name}]`")] pub(crate) struct DuplicateEiiImpls { pub name: Symbol, #[primary_span] - #[label(passes_first)] + #[label("first implemented here in crate `{$first_crate}`")] pub first_span: Span, pub first_crate: Symbol, - #[label(passes_second)] + #[label("also implemented here in crate `{$second_crate}`")] pub second_span: Span, pub second_crate: Symbol, - #[note] + #[note("in addition to these two, { $num_additional_crates -> + [one] another implementation was found in crate {$additional_crate_names} + *[other] more implementations were also found in the following crates: {$additional_crate_names} + }")] pub additional_crates: Option<()>, pub num_additional_crates: usize, pub additional_crate_names: String, - #[help] + #[help( + "an \"externally implementable item\" can only have a single implementation in the final artifact. When multiple implementations are found, also in different crates, they conflict" + )] pub help: (), } #[derive(Diagnostic)] -#[diag(passes_function_not_have_default_implementation)] +#[diag("function doesn't have a default implementation")] pub(crate) struct FunctionNotHaveDefaultImplementation { #[primary_span] pub span: Span, - #[note] + #[note("required by this annotation")] pub note_span: Span, } #[derive(Diagnostic)] -#[diag(passes_must_implement_not_function)] +#[diag("not a function")] pub(crate) struct MustImplementNotFunction { #[primary_span] pub span: Span, @@ -1278,26 +1452,26 @@ pub(crate) struct MustImplementNotFunction { } #[derive(Subdiagnostic)] -#[note(passes_must_implement_not_function_span_note)] +#[note("required by this annotation")] pub(crate) struct MustImplementNotFunctionSpanNote { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] -#[note(passes_must_implement_not_function_note)] +#[note("all `#[rustc_must_implement_one_of]` arguments must be associated function names")] pub(crate) struct MustImplementNotFunctionNote {} #[derive(Diagnostic)] -#[diag(passes_function_not_found_in_trait)] +#[diag("function not found in this trait")] pub(crate) struct FunctionNotFoundInTrait { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(passes_functions_names_duplicated)] -#[note] +#[diag("functions names are duplicated")] +#[note("all `#[rustc_must_implement_one_of]` arguments must be unique")] pub(crate) struct FunctionNamesDuplicated { #[primary_span] pub spans: Vec, diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index d371589cba6c..ef6a8e80c72f 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -30,8 +30,6 @@ pub mod stability; mod upvars; mod weak_lang_items; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn provide(providers: &mut Providers) { check_attr::provide(providers); dead::provide(providers); From 54a9be469a66808ad57e471b659204849756a0b7 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Fri, 6 Feb 2026 14:04:55 +0100 Subject: [PATCH 617/978] mGCA: Support directly represented negated literals --- compiler/rustc_ast_lowering/src/lib.rs | 14 +++++++++++++- compiler/rustc_hir/src/hir.rs | 7 ++++--- compiler/rustc_hir/src/intravisit.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 14 ++++++++++---- compiler/rustc_hir_pretty/src/lib.rs | 7 +++++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- src/librustdoc/clean/mod.rs | 4 ++-- .../clippy/clippy_lints/src/utils/author.rs | 2 +- src/tools/clippy/clippy_utils/src/consts.rs | 2 +- src/tools/clippy/clippy_utils/src/hir_utils.rs | 18 +++++++++++++++--- .../ui/const-generics/mgca/negated-literal.rs | 17 +++++++++++++++++ 11 files changed, 70 insertions(+), 19 deletions(-) create mode 100644 tests/ui/const-generics/mgca/negated-literal.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8c6ee9d6bc63..47240ba185f4 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2572,7 +2572,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ConstArg { hir_id: self.lower_node_id(expr.id), - kind: hir::ConstArgKind::Literal(literal.node), + kind: hir::ConstArgKind::Literal { lit: literal.node, negated: false }, + span, + } + } + ExprKind::Unary(UnOp::Neg, inner_expr) + if let ExprKind::Lit(literal) = &inner_expr.kind => + { + let span = expr.span; + let literal = self.lower_lit(literal, span); + + ConstArg { + hir_id: self.lower_node_id(expr.id), + kind: hir::ConstArgKind::Literal { lit: literal.node, negated: true }, span, } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4c1bcffa1cf4..17c7de39b21b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -520,7 +520,10 @@ pub enum ConstArgKind<'hir, Unambig = ()> { /// This variant is not always used to represent inference consts, sometimes /// [`GenericArg::Infer`] is used instead. Infer(Unambig), - Literal(LitKind), + Literal { + lit: LitKind, + negated: bool, + }, } #[derive(Clone, Copy, Debug, HashStable_Generic)] @@ -1953,8 +1956,6 @@ pub struct PatExpr<'hir> { pub enum PatExprKind<'hir> { Lit { lit: Lit, - // FIXME: move this into `Lit` and handle negated literal expressions - // once instead of matching on unop neg expressions everywhere. negated: bool, }, /// A path pattern for a unit struct/variant or a (maybe-associated) constant. diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index d1b75325af26..bd863abaceb4 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1110,7 +1110,7 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>( ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, *hir_id, qpath.span()), ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon), ConstArgKind::Error(_) => V::Result::output(), // errors and spans are not important - ConstArgKind::Literal(..) => V::Result::output(), // FIXME(mcga) + ConstArgKind::Literal { .. } => V::Result::output(), // FIXME(mcga) } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 9f84f652698b..850211451158 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2397,8 +2397,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::ConstArgKind::Anon(anon) => self.lower_const_arg_anon(anon), hir::ConstArgKind::Infer(()) => self.ct_infer(None, const_arg.span), hir::ConstArgKind::Error(e) => ty::Const::new_error(tcx, e), - hir::ConstArgKind::Literal(kind) => { - self.lower_const_arg_literal(&kind, ty, const_arg.span) + hir::ConstArgKind::Literal { lit, negated } => { + self.lower_const_arg_literal(&lit, negated, ty, const_arg.span) } } } @@ -2805,9 +2805,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } #[instrument(skip(self), level = "debug")] - fn lower_const_arg_literal(&self, kind: &LitKind, ty: Ty<'tcx>, span: Span) -> Const<'tcx> { + fn lower_const_arg_literal( + &self, + kind: &LitKind, + neg: bool, + ty: Ty<'tcx>, + span: Span, + ) -> Const<'tcx> { let tcx = self.tcx(); - let input = LitToConstInput { lit: *kind, ty, neg: false }; + let input = LitToConstInput { lit: *kind, ty, neg }; tcx.at(span).lit_to_const(input) } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index e0e9fe775853..d045ec0eb6c7 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1158,9 +1158,12 @@ impl<'a> State<'a> { ConstArgKind::Anon(anon) => self.print_anon_const(anon), ConstArgKind::Error(_) => self.word("/*ERROR*/"), ConstArgKind::Infer(..) => self.word("_"), - ConstArgKind::Literal(node) => { + ConstArgKind::Literal { lit, negated } => { + if *negated { + self.word("-"); + } let span = const_arg.span; - self.print_literal(&Spanned { span, node: *node }) + self.print_literal(&Spanned { span, node: *lit }) } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 471c19ed4d4e..5974afd7b33e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1444,7 +1444,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { | hir::ConstArgKind::TupleCall(..) | hir::ConstArgKind::Tup(..) | hir::ConstArgKind::Path(..) - | hir::ConstArgKind::Literal(..) + | hir::ConstArgKind::Literal { .. } | hir::ConstArgKind::Infer(..) => true, hir::ConstArgKind::Anon(..) => false, }, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1c9154238657..753fba3ed482 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -334,7 +334,7 @@ pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg<'tcx>) -> ConstantKind } hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body }, hir::ConstArgKind::Infer(..) | hir::ConstArgKind::Error(..) => ConstantKind::Infer, - hir::ConstArgKind::Literal(..) => { + hir::ConstArgKind::Literal { .. } => { ConstantKind::Path { path: "/* LITERAL */".to_string().into() } } } @@ -1829,7 +1829,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T | hir::ConstArgKind::TupleCall(..) | hir::ConstArgKind::Tup(..) | hir::ConstArgKind::Array(..) - | hir::ConstArgKind::Literal(..) => { + | hir::ConstArgKind::Literal { .. } => { let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, cx.tcx.types.usize); print_const(cx, ct) } diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index e6fadc783621..d5191794b6b0 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -325,7 +325,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { ConstArgKind::Infer(..) => chain!(self, "let ConstArgKind::Infer(..) = {const_arg}.kind"), ConstArgKind::Error(..) => chain!(self, "let ConstArgKind::Error(..) = {const_arg}.kind"), ConstArgKind::Tup(..) => chain!(self, "let ConstArgKind::Tup(..) = {const_arg}.kind"), - ConstArgKind::Literal(..) => chain!(self, "let ConstArgKind::Literal(..) = {const_arg}.kind"), + ConstArgKind::Literal { .. } => chain!(self, "let ConstArgKind::Literal {{ .. }} = {const_arg}.kind"), } } diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index e2ada37d53b3..8177a5806d78 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -1142,7 +1142,7 @@ pub fn const_item_rhs_to_expr<'tcx>(tcx: TyCtxt<'tcx>, ct_rhs: ConstItemRhs<'tcx ConstArgKind::Anon(anon) => Some(tcx.hir_body(anon.body).value), ConstArgKind::Struct(..) | ConstArgKind::Tup(..) - | ConstArgKind::Literal(..) + | ConstArgKind::Literal { .. } | ConstArgKind::TupleCall(..) | ConstArgKind::Array(..) | ConstArgKind::Path(_) diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index b9f104a79a27..abc6885bef2d 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -686,7 +686,16 @@ impl HirEqInterExpr<'_, '_, '_> { .zip(*args_b) .all(|(arg_a, arg_b)| self.eq_const_arg(arg_a, arg_b)) }, - (ConstArgKind::Literal(kind_l), ConstArgKind::Literal(kind_r)) => kind_l == kind_r, + ( + ConstArgKind::Literal { + lit: kind_l, + negated: negated_l, + }, + ConstArgKind::Literal { + lit: kind_r, + negated: negated_r, + }, + ) => kind_l == kind_r && negated_l == negated_r, (ConstArgKind::Array(l_arr), ConstArgKind::Array(r_arr)) => { l_arr.elems.len() == r_arr.elems.len() && l_arr @@ -703,7 +712,7 @@ impl HirEqInterExpr<'_, '_, '_> { | ConstArgKind::TupleCall(..) | ConstArgKind::Infer(..) | ConstArgKind::Struct(..) - | ConstArgKind::Literal(..) + | ConstArgKind::Literal { .. } | ConstArgKind::Array(..) | ConstArgKind::Error(..), _, @@ -1599,7 +1608,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } }, ConstArgKind::Infer(..) | ConstArgKind::Error(..) => {}, - ConstArgKind::Literal(lit) => lit.hash(&mut self.s), + ConstArgKind::Literal { lit, negated } => { + lit.hash(&mut self.s); + negated.hash(&mut self.s); + }, } } diff --git a/tests/ui/const-generics/mgca/negated-literal.rs b/tests/ui/const-generics/mgca/negated-literal.rs new file mode 100644 index 000000000000..a7651822b0a8 --- /dev/null +++ b/tests/ui/const-generics/mgca/negated-literal.rs @@ -0,0 +1,17 @@ +//@ check-pass + +#![feature(adt_const_params, min_generic_const_args)] +#![allow(incomplete_features)] + +use std::marker::ConstParamTy; + +#[derive(Eq, PartialEq, ConstParamTy)] +struct Foo { + field: isize +} + +fn foo() {} + +fn main() { + foo::<{ Foo { field: -1 } }>(); +} From e94a62d8001b1c12b317174ae887c5d619294254 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Fri, 6 Feb 2026 14:04:55 +0100 Subject: [PATCH 618/978] mGCA: Support directly represented negated literals --- clippy_lints/src/utils/author.rs | 2 +- clippy_utils/src/consts.rs | 2 +- clippy_utils/src/hir_utils.rs | 18 +++++++++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index e6fadc783621..d5191794b6b0 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -325,7 +325,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { ConstArgKind::Infer(..) => chain!(self, "let ConstArgKind::Infer(..) = {const_arg}.kind"), ConstArgKind::Error(..) => chain!(self, "let ConstArgKind::Error(..) = {const_arg}.kind"), ConstArgKind::Tup(..) => chain!(self, "let ConstArgKind::Tup(..) = {const_arg}.kind"), - ConstArgKind::Literal(..) => chain!(self, "let ConstArgKind::Literal(..) = {const_arg}.kind"), + ConstArgKind::Literal { .. } => chain!(self, "let ConstArgKind::Literal {{ .. }} = {const_arg}.kind"), } } diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index e2ada37d53b3..8177a5806d78 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -1142,7 +1142,7 @@ pub fn const_item_rhs_to_expr<'tcx>(tcx: TyCtxt<'tcx>, ct_rhs: ConstItemRhs<'tcx ConstArgKind::Anon(anon) => Some(tcx.hir_body(anon.body).value), ConstArgKind::Struct(..) | ConstArgKind::Tup(..) - | ConstArgKind::Literal(..) + | ConstArgKind::Literal { .. } | ConstArgKind::TupleCall(..) | ConstArgKind::Array(..) | ConstArgKind::Path(_) diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index b9f104a79a27..abc6885bef2d 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -686,7 +686,16 @@ impl HirEqInterExpr<'_, '_, '_> { .zip(*args_b) .all(|(arg_a, arg_b)| self.eq_const_arg(arg_a, arg_b)) }, - (ConstArgKind::Literal(kind_l), ConstArgKind::Literal(kind_r)) => kind_l == kind_r, + ( + ConstArgKind::Literal { + lit: kind_l, + negated: negated_l, + }, + ConstArgKind::Literal { + lit: kind_r, + negated: negated_r, + }, + ) => kind_l == kind_r && negated_l == negated_r, (ConstArgKind::Array(l_arr), ConstArgKind::Array(r_arr)) => { l_arr.elems.len() == r_arr.elems.len() && l_arr @@ -703,7 +712,7 @@ impl HirEqInterExpr<'_, '_, '_> { | ConstArgKind::TupleCall(..) | ConstArgKind::Infer(..) | ConstArgKind::Struct(..) - | ConstArgKind::Literal(..) + | ConstArgKind::Literal { .. } | ConstArgKind::Array(..) | ConstArgKind::Error(..), _, @@ -1599,7 +1608,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } }, ConstArgKind::Infer(..) | ConstArgKind::Error(..) => {}, - ConstArgKind::Literal(lit) => lit.hash(&mut self.s), + ConstArgKind::Literal { lit, negated } => { + lit.hash(&mut self.s); + negated.hash(&mut self.s); + }, } } From ee2c39a2b4f0e7075bd1b5dc08a75dc106c8fa29 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Fri, 6 Feb 2026 22:24:36 +0900 Subject: [PATCH 619/978] re-add TaKO8Ki to triagebot review queue --- triagebot.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index eb25d6e1b201..1b0ba07ecf11 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1466,6 +1466,7 @@ compiler = [ "@oli-obk", "@petrochenkov", "@SparrowLii", + "@TaKO8Ki", "@tiif", "@WaffleLapkin", "@wesleywiser", @@ -1512,6 +1513,7 @@ diagnostics = [ "@davidtwco", "@oli-obk", "@chenyukang", + "@TaKO8Ki" ] parser = [ "@davidtwco", From dc24aae43e6e1751c498df619ca572eaa7adf4a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 29 Jan 2026 21:13:09 +0100 Subject: [PATCH 620/978] Modernize diagnostic for indeterminate trait object lifetime bounds --- compiler/rustc_hir_analysis/src/collect.rs | 32 +++++++++++-------- .../src/hir_ty_lowering/dyn_trait.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 2 +- .../object-lifetime-default-ambiguous.rs | 6 ++-- .../object-lifetime-default-ambiguous.stderr | 21 ++++++++++-- ...lifetime-default-dyn-binding-nonstatic1.rs | 2 +- ...time-default-dyn-binding-nonstatic1.stderr | 7 +++- ...lifetime-default-dyn-binding-nonstatic2.rs | 2 +- ...time-default-dyn-binding-nonstatic2.stderr | 7 +++- ...lifetime-default-dyn-binding-nonstatic3.rs | 2 +- ...time-default-dyn-binding-nonstatic3.stderr | 7 +++- 11 files changed, 63 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index dd399f9d90de..919199f0b573 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -22,9 +22,7 @@ use rustc_abi::{ExternAbi, Size}; use rustc_ast::Recovered; use rustc_data_structures::assert_matches; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; -use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, E0228, ErrorGuaranteed, StashKey, struct_span_code_err, -}; +use rustc_errors::{Applicability, Diag, DiagCtxtHandle, E0228, ErrorGuaranteed, StashKey}; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -316,16 +314,24 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { } fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> { - if let RegionInferReason::ObjectLifetimeDefault = reason { - let e = struct_span_code_err!( - self.dcx(), - span, - E0228, - "the lifetime bound for this object type cannot be deduced \ - from context; please supply an explicit bound" - ) - .emit(); - ty::Region::new_error(self.tcx(), e) + if let RegionInferReason::ObjectLifetimeDefault(sugg_sp) = reason { + // FIXME: Account for trailing plus `dyn Trait+`, the need of parens in + // `*const dyn Trait` and `Fn() -> *const dyn Trait`. + let guar = self + .dcx() + .struct_span_err( + span, + "cannot deduce the lifetime bound for this trait object type from context", + ) + .with_code(E0228) + .with_span_suggestion_verbose( + sugg_sp, + "please supply an explicit bound", + " + /* 'a */", + Applicability::HasPlaceholders, + ) + .emit(); + ty::Region::new_error(self.tcx(), guar) } else { // This indicates an illegal lifetime in a non-assoc-trait position ty::Region::new_error_with_message(self.tcx(), span, "unelided lifetime in signature") diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index 29f29761b605..37a9f41e8942 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -460,7 +460,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Parent lifetime must have failed to resolve. Don't emit a redundant error. RegionInferReason::ExplicitObjectLifetime } else { - RegionInferReason::ObjectLifetimeDefault + RegionInferReason::ObjectLifetimeDefault(span.shrink_to_hi()) } } else { RegionInferReason::ExplicitObjectLifetime diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 867c588e302d..ccccb6145c46 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -105,7 +105,7 @@ pub enum RegionInferReason<'a> { /// Lifetime on a trait object that is spelled explicitly, e.g. `+ 'a` or `+ '_`. ExplicitObjectLifetime, /// A trait object's lifetime when it is elided, e.g. `dyn Any`. - ObjectLifetimeDefault, + ObjectLifetimeDefault(Span), /// Generic lifetime parameter Param(&'a ty::GenericParamDef), RegionPredicate, diff --git a/tests/ui/object-lifetime/object-lifetime-default-ambiguous.rs b/tests/ui/object-lifetime/object-lifetime-default-ambiguous.rs index 5dae92fee5f9..0a0f44073740 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-ambiguous.rs +++ b/tests/ui/object-lifetime/object-lifetime-default-ambiguous.rs @@ -21,11 +21,11 @@ struct Ref2<'a,'b:'a,T:'a+'b+?Sized> { } fn a<'a,'b>(t: Ref2<'a,'b, dyn Test>) { - //~^ ERROR lifetime bound for this object type cannot be deduced from context + //~^ ERROR cannot deduce the lifetime bound for this trait object type } fn b(t: Ref2) { - //~^ ERROR lifetime bound for this object type cannot be deduced from context + //~^ ERROR cannot deduce the lifetime bound for this trait object type } fn c(t: Ref2<&dyn Test>) { @@ -41,7 +41,7 @@ fn e(t: Ref2>) { } fn f(t: &Ref2) { - //~^ ERROR lifetime bound for this object type cannot be deduced from context + //~^ ERROR cannot deduce the lifetime bound for this trait object type } fn main() { diff --git a/tests/ui/object-lifetime/object-lifetime-default-ambiguous.stderr b/tests/ui/object-lifetime/object-lifetime-default-ambiguous.stderr index bd50a27fd5e5..6aa3da66fda0 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-ambiguous.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-ambiguous.stderr @@ -1,20 +1,35 @@ -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound +error[E0228]: cannot deduce the lifetime bound for this trait object type from context --> $DIR/object-lifetime-default-ambiguous.rs:23:28 | LL | fn a<'a,'b>(t: Ref2<'a,'b, dyn Test>) { | ^^^^^^^^ + | +help: please supply an explicit bound + | +LL | fn a<'a,'b>(t: Ref2<'a,'b, dyn Test + /* 'a */>) { + | ++++++++++ -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound +error[E0228]: cannot deduce the lifetime bound for this trait object type from context --> $DIR/object-lifetime-default-ambiguous.rs:27:14 | LL | fn b(t: Ref2) { | ^^^^^^^^ + | +help: please supply an explicit bound + | +LL | fn b(t: Ref2) { + | ++++++++++ -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound +error[E0228]: cannot deduce the lifetime bound for this trait object type from context --> $DIR/object-lifetime-default-ambiguous.rs:43:15 | LL | fn f(t: &Ref2) { | ^^^^^^^^ + | +help: please supply an explicit bound + | +LL | fn f(t: &Ref2) { + | ++++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs index 7337383e2978..7a7bba02879e 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs @@ -18,7 +18,7 @@ fn is_static(_: T) where T: 'static { } // Here, we should default to `dyn Bar + 'static`, but the current // code forces us into a conservative, hacky path. fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } -//~^ ERROR please supply an explicit bound +//~^ ERROR cannot deduce the lifetime bound for this trait object type fn main() { let s = format!("foo"); diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr index 8d44b4de55a4..5744d0dd162c 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr @@ -1,8 +1,13 @@ -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound +error[E0228]: cannot deduce the lifetime bound for this trait object type from context --> $DIR/object-lifetime-default-dyn-binding-nonstatic1.rs:20:50 | LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } | ^^^^^^^ + | +help: please supply an explicit bound + | +LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar + /* 'a */> { &() } + | ++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs index 2a7415174f8a..9ddf792eaada 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs @@ -18,7 +18,7 @@ fn is_static(_: T) where T: 'static { } // Here, we default to `dyn Bar + 'a`. Or, we *should*, but the // current code forces us into a conservative, hacky path. fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } -//~^ ERROR please supply an explicit bound +//~^ ERROR cannot deduce the lifetime bound for this trait object type fn main() { let s = format!("foo"); diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr index 0846dd60723a..ca8612f57934 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr @@ -1,8 +1,13 @@ -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound +error[E0228]: cannot deduce the lifetime bound for this trait object type from context --> $DIR/object-lifetime-default-dyn-binding-nonstatic2.rs:20:50 | LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } | ^^^^^^^ + | +help: please supply an explicit bound + | +LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar + /* 'a */> { &() } + | ++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs index 51be999a6329..48ac5623f898 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs @@ -14,7 +14,7 @@ fn is_static(_: T) where T: 'static { } // Here, we should default to `dyn Bar + 'static`, but the current // code forces us into a conservative, hacky path. fn bar(x: &str) -> &dyn Foo { &() } -//~^ ERROR please supply an explicit bound +//~^ ERROR cannot deduce the lifetime bound for this trait object type fn main() { let s = format!("foo"); diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr index 688f8af0822b..05620d3878f7 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr @@ -1,8 +1,13 @@ -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound +error[E0228]: cannot deduce the lifetime bound for this trait object type from context --> $DIR/object-lifetime-default-dyn-binding-nonstatic3.rs:16:36 | LL | fn bar(x: &str) -> &dyn Foo { &() } | ^^^^^^^ + | +help: please supply an explicit bound + | +LL | fn bar(x: &str) -> &dyn Foo { &() } + | ++++++++++ error: aborting due to 1 previous error From e6f5b97152a4e96de2b0eae09ffabb25d0eface7 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Fri, 6 Feb 2026 15:35:18 +0100 Subject: [PATCH 621/978] MGCA: require #[type_const] on free consts too --- .../src/hir_ty_lowering/mod.rs | 65 +++++++++++-------- .../auxiliary/non_local_type_const.rs | 5 ++ .../generic_const_exprs/non-local-const.rs | 6 +- .../non-local-const.stderr | 10 +-- .../assoc-const-without-type_const.stderr | 16 +++-- .../mgca/auxiliary/non_local_const.rs | 1 + ...const-arg-coherence-conflicting-methods.rs | 1 + ...t-arg-coherence-conflicting-methods.stderr | 6 +- .../non-local-const-without-type_const.rs | 9 +++ .../non-local-const-without-type_const.stderr | 10 +++ .../mgca/tuple_ctor_erroneous.rs | 1 + .../mgca/tuple_ctor_erroneous.stderr | 20 +++--- .../mgca/unmarked-free-const.rs | 11 ++++ .../mgca/unmarked-free-const.stderr | 14 ++++ 14 files changed, 125 insertions(+), 50 deletions(-) create mode 100644 tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs create mode 100644 tests/ui/const-generics/mgca/auxiliary/non_local_const.rs create mode 100644 tests/ui/const-generics/mgca/non-local-const-without-type_const.rs create mode 100644 tests/ui/const-generics/mgca/non-local-const-without-type_const.stderr create mode 100644 tests/ui/const-generics/mgca/unmarked-free-const.rs create mode 100644 tests/ui/const-generics/mgca/unmarked-free-const.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index d4b9d2e359d5..dcdd40773d3b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1422,14 +1422,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { LowerTypeRelativePathMode::Const, )? { TypeRelativePath::AssocItem(def_id, args) => { - if !self.tcx().is_type_const(def_id) { - let mut err = self.dcx().struct_span_err( - span, - "use of trait associated const without `#[type_const]`", - ); - err.note("the declaration in the trait must be marked with `#[type_const]`"); - return Err(err.emit()); - } + self.require_type_const_attribute(def_id, span)?; let ct = Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(def_id, args)); let ct = self.check_param_uses_if_mcg(ct, span, false); Ok(ct) @@ -1885,30 +1878,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { item_def_id: DefId, trait_segment: Option<&hir::PathSegment<'tcx>>, item_segment: &hir::PathSegment<'tcx>, - ) -> Const<'tcx> { - match self.lower_resolved_assoc_item_path( + ) -> Result, ErrorGuaranteed> { + let (item_def_id, item_args) = self.lower_resolved_assoc_item_path( span, opt_self_ty, item_def_id, trait_segment, item_segment, ty::AssocTag::Const, - ) { - Ok((item_def_id, item_args)) => { - if !self.tcx().is_type_const(item_def_id) { - let mut err = self.dcx().struct_span_err( - span, - "use of `const` in the type system without `#[type_const]`", - ); - err.note("the declaration must be marked with `#[type_const]`"); - return Const::new_error(self.tcx(), err.emit()); - } - - let uv = ty::UnevaluatedConst::new(item_def_id, item_args); - Const::new_unevaluated(self.tcx(), uv) - } - Err(guar) => Const::new_error(self.tcx(), guar), - } + )?; + self.require_type_const_attribute(item_def_id, span)?; + let uv = ty::UnevaluatedConst::new(item_def_id, item_args); + Ok(Const::new_unevaluated(self.tcx(), uv)) } /// Lower a [resolved][hir::QPath::Resolved] (type-level) associated item path. @@ -2668,6 +2649,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_const_param(def_id, hir_id) } Res::Def(DefKind::Const, did) => { + if let Err(guar) = self.require_type_const_attribute(did, span) { + return Const::new_error(self.tcx(), guar); + } + assert_eq!(opt_self_ty, None); let [leading_segments @ .., segment] = path.segments else { bug!() }; let _ = self @@ -2718,6 +2703,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { trait_segment, path.segments.last().unwrap(), ) + .unwrap_or_else(|guar| Const::new_error(tcx, guar)) } Res::Def(DefKind::Static { .. }, _) => { span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported") @@ -2843,6 +2829,33 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .map(|l| tcx.at(expr.span).lit_to_const(l)) } + fn require_type_const_attribute( + &self, + def_id: DefId, + span: Span, + ) -> Result<(), ErrorGuaranteed> { + let tcx = self.tcx(); + if tcx.is_type_const(def_id) { + Ok(()) + } else { + let mut err = self + .dcx() + .struct_span_err(span, "use of `const` in the type system without `#[type_const]`"); + if def_id.is_local() { + let name = tcx.def_path_str(def_id); + err.span_suggestion( + tcx.def_span(def_id).shrink_to_lo(), + format!("add `#[type_const]` attribute to `{name}`"), + format!("#[type_const]\n"), + Applicability::MaybeIncorrect, + ); + } else { + err.note("only consts marked with `#[type_const]` may be used in types"); + } + Err(err.emit()) + } + } + fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> { let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id()); match idx { diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs new file mode 100644 index 000000000000..6ec1071461c5 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs @@ -0,0 +1,5 @@ +#![feature(min_generic_const_args)] +#![allow(incomplete_features)] + +#[type_const] +pub const NON_LOCAL_CONST: char = 'a'; diff --git a/tests/ui/const-generics/generic_const_exprs/non-local-const.rs b/tests/ui/const-generics/generic_const_exprs/non-local-const.rs index 0a30cc385ac4..d0efdb2c2017 100644 --- a/tests/ui/const-generics/generic_const_exprs/non-local-const.rs +++ b/tests/ui/const-generics/generic_const_exprs/non-local-const.rs @@ -1,10 +1,12 @@ // regression test for #133808. +//@ aux-build:non_local_type_const.rs #![feature(generic_const_exprs)] #![feature(min_generic_const_args)] #![allow(incomplete_features)] #![crate_type = "lib"] +extern crate non_local_type_const; pub trait Foo {} -impl Foo for [u8; std::path::MAIN_SEPARATOR] {} -//~^ ERROR the constant `MAIN_SEPARATOR` is not of type `usize` +impl Foo for [u8; non_local_type_const::NON_LOCAL_CONST] {} +//~^ ERROR the constant `'a'` is not of type `usize` diff --git a/tests/ui/const-generics/generic_const_exprs/non-local-const.stderr b/tests/ui/const-generics/generic_const_exprs/non-local-const.stderr index d8df3269a19e..3d1ec60eb908 100644 --- a/tests/ui/const-generics/generic_const_exprs/non-local-const.stderr +++ b/tests/ui/const-generics/generic_const_exprs/non-local-const.stderr @@ -1,10 +1,10 @@ -error: the constant `MAIN_SEPARATOR` is not of type `usize` - --> $DIR/non-local-const.rs:9:14 +error: the constant `'a'` is not of type `usize` + --> $DIR/non-local-const.rs:11:14 | -LL | impl Foo for [u8; std::path::MAIN_SEPARATOR] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `char` +LL | impl Foo for [u8; non_local_type_const::NON_LOCAL_CONST] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `char` | - = note: the length of array `[u8; MAIN_SEPARATOR]` must be type `usize` + = note: the length of array `[u8; 'a']` must be type `usize` error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr b/tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr index 7872e0967626..e06850747ff3 100644 --- a/tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr +++ b/tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr @@ -1,18 +1,26 @@ -error: use of trait associated const without `#[type_const]` +error: use of `const` in the type system without `#[type_const]` --> $DIR/assoc-const-without-type_const.rs:8:35 | LL | fn mk_array(_x: T) -> [(); T::SIZE] { | ^^^^^^^ | - = note: the declaration in the trait must be marked with `#[type_const]` +help: add `#[type_const]` attribute to `Tr::SIZE` + | +LL + #[type_const] +LL | const SIZE: usize; + | -error: use of trait associated const without `#[type_const]` +error: use of `const` in the type system without `#[type_const]` --> $DIR/assoc-const-without-type_const.rs:10:10 | LL | [(); T::SIZE] | ^^^^^^^ | - = note: the declaration in the trait must be marked with `#[type_const]` +help: add `#[type_const]` attribute to `Tr::SIZE` + | +LL + #[type_const] +LL | const SIZE: usize; + | error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/auxiliary/non_local_const.rs b/tests/ui/const-generics/mgca/auxiliary/non_local_const.rs new file mode 100644 index 000000000000..19091e4780fe --- /dev/null +++ b/tests/ui/const-generics/mgca/auxiliary/non_local_const.rs @@ -0,0 +1 @@ +pub const N: usize = 2; diff --git a/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs index 68aa30bd65bb..efab01489404 100644 --- a/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs +++ b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs @@ -3,6 +3,7 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] +#[type_const] const C: usize = 0; pub struct A {} impl A { diff --git a/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.stderr b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.stderr index 3d74d1db206e..6b2b871ba4b9 100644 --- a/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.stderr +++ b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.stderr @@ -1,11 +1,11 @@ error[E0107]: missing generics for struct `A` - --> $DIR/const-arg-coherence-conflicting-methods.rs:12:6 + --> $DIR/const-arg-coherence-conflicting-methods.rs:13:6 | LL | impl A { | ^ expected 1 generic argument | note: struct defined here, with 1 generic parameter: `M` - --> $DIR/const-arg-coherence-conflicting-methods.rs:7:12 + --> $DIR/const-arg-coherence-conflicting-methods.rs:8:12 | LL | pub struct A {} | ^ -------------- @@ -15,7 +15,7 @@ LL | impl A { | +++ error[E0592]: duplicate definitions with name `fun1` - --> $DIR/const-arg-coherence-conflicting-methods.rs:9:5 + --> $DIR/const-arg-coherence-conflicting-methods.rs:10:5 | LL | fn fun1() {} | ^^^^^^^^^ duplicate definitions for `fun1` diff --git a/tests/ui/const-generics/mgca/non-local-const-without-type_const.rs b/tests/ui/const-generics/mgca/non-local-const-without-type_const.rs new file mode 100644 index 000000000000..e98cbdf8e617 --- /dev/null +++ b/tests/ui/const-generics/mgca/non-local-const-without-type_const.rs @@ -0,0 +1,9 @@ +// Just a test of the error message (it's different for non-local consts) +//@ aux-build:non_local_const.rs +#![feature(min_generic_const_args)] +#![allow(incomplete_features)] +extern crate non_local_const; +fn main() { + let x = [(); non_local_const::N]; + //~^ ERROR use of `const` in the type system without `#[type_const]` +} diff --git a/tests/ui/const-generics/mgca/non-local-const-without-type_const.stderr b/tests/ui/const-generics/mgca/non-local-const-without-type_const.stderr new file mode 100644 index 000000000000..671dfa5fbb9e --- /dev/null +++ b/tests/ui/const-generics/mgca/non-local-const-without-type_const.stderr @@ -0,0 +1,10 @@ +error: use of `const` in the type system without `#[type_const]` + --> $DIR/non-local-const-without-type_const.rs:7:18 + | +LL | let x = [(); non_local_const::N]; + | ^^^^^^^^^^^^^^^^^^ + | + = note: only consts marked with `#[type_const]` may be used in types + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs index 84ded05fdd0e..ebbe097c226e 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs @@ -12,6 +12,7 @@ enum MyEnum { Unit, } +#[type_const] const CONST_ITEM: u32 = 42; fn accepts_point() {} diff --git a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr index cc6144b9c88a..dc6a700a8e12 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr +++ b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find function, tuple struct or tuple variant `UnresolvedIdent` in this scope - --> $DIR/tuple_ctor_erroneous.rs:29:23 + --> $DIR/tuple_ctor_erroneous.rs:30:23 | LL | accepts_point::<{ UnresolvedIdent(N, N) }>(); | ^^^^^^^^^^^^^^^ not found in this scope @@ -10,55 +10,55 @@ LL | fn test_errors() { | +++++++++++++++++++++++++++++++++++ error: tuple constructor has 2 arguments but 1 were provided - --> $DIR/tuple_ctor_erroneous.rs:23:23 + --> $DIR/tuple_ctor_erroneous.rs:24:23 | LL | accepts_point::<{ Point(N) }>(); | ^^^^^^^^ error: tuple constructor has 2 arguments but 3 were provided - --> $DIR/tuple_ctor_erroneous.rs:26:23 + --> $DIR/tuple_ctor_erroneous.rs:27:23 | LL | accepts_point::<{ Point(N, N, N) }>(); | ^^^^^^^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/tuple_ctor_erroneous.rs:29:23 + --> $DIR/tuple_ctor_erroneous.rs:30:23 | LL | accepts_point::<{ UnresolvedIdent(N, N) }>(); | ^^^^^^^^^^^^^^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/tuple_ctor_erroneous.rs:33:23 + --> $DIR/tuple_ctor_erroneous.rs:34:23 | LL | accepts_point::<{ non_ctor(N, N) }>(); | ^^^^^^^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/tuple_ctor_erroneous.rs:36:23 + --> $DIR/tuple_ctor_erroneous.rs:37:23 | LL | accepts_point::<{ CONST_ITEM(N, N) }>(); | ^^^^^^^^^^^^^^^^ error: the constant `Point` is not of type `Point` - --> $DIR/tuple_ctor_erroneous.rs:39:23 + --> $DIR/tuple_ctor_erroneous.rs:40:23 | LL | accepts_point::<{ Point }>(); | ^^^^^ expected `Point`, found struct constructor | note: required by a const generic parameter in `accepts_point` - --> $DIR/tuple_ctor_erroneous.rs:17:18 + --> $DIR/tuple_ctor_erroneous.rs:18:18 | LL | fn accepts_point() {} | ^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_point` error: the constant `MyEnum::::Variant` is not of type `MyEnum` - --> $DIR/tuple_ctor_erroneous.rs:42:22 + --> $DIR/tuple_ctor_erroneous.rs:43:22 | LL | accepts_enum::<{ MyEnum::Variant:: }>(); | ^^^^^^^^^^^^^^^^^^^^^^ expected `MyEnum`, found enum constructor | note: required by a const generic parameter in `accepts_enum` - --> $DIR/tuple_ctor_erroneous.rs:18:17 + --> $DIR/tuple_ctor_erroneous.rs:19:17 | LL | fn accepts_enum>() {} | ^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_enum` diff --git a/tests/ui/const-generics/mgca/unmarked-free-const.rs b/tests/ui/const-generics/mgca/unmarked-free-const.rs new file mode 100644 index 000000000000..a517231facb7 --- /dev/null +++ b/tests/ui/const-generics/mgca/unmarked-free-const.rs @@ -0,0 +1,11 @@ +// regression test, used to ICE + +#![feature(min_generic_const_args)] +#![allow(incomplete_features)] + +const N: usize = 4; + +fn main() { + let x = [(); N]; + //~^ ERROR use of `const` in the type system without `#[type_const]` +} diff --git a/tests/ui/const-generics/mgca/unmarked-free-const.stderr b/tests/ui/const-generics/mgca/unmarked-free-const.stderr new file mode 100644 index 000000000000..052ae39fdf67 --- /dev/null +++ b/tests/ui/const-generics/mgca/unmarked-free-const.stderr @@ -0,0 +1,14 @@ +error: use of `const` in the type system without `#[type_const]` + --> $DIR/unmarked-free-const.rs:9:18 + | +LL | let x = [(); N]; + | ^ + | +help: add `#[type_const]` attribute to `N` + | +LL + #[type_const] +LL | const N: usize = 4; + | + +error: aborting due to 1 previous error + From 001d710747478b57b11abaa1bac23657b0c1dec1 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 6 Feb 2026 09:03:59 -0800 Subject: [PATCH 622/978] Replace a stale clippy `CURRENT_RUSTC_VERSION` --- src/tools/clippy/clippy_lints/src/deprecated_lints.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs index 6e62e983d2f3..ff92cd059839 100644 --- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs +++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs @@ -123,7 +123,7 @@ declare_with_version! { RENAMED(RENAMED_VERSION) = [ ("clippy::into_iter_on_array", "array_into_iter"), #[clippy::version = ""] ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"), - #[clippy::version = "CURRENT_RUSTC_VERSION"] + #[clippy::version = "1.88.0"] ("clippy::invalid_null_ptr_usage", "invalid_null_arguments"), #[clippy::version = ""] ("clippy::invalid_ref", "invalid_value"), From dcfc23abe417ffa6561cfa2f0d5c579ed7043233 Mon Sep 17 00:00:00 2001 From: arferreira Date: Fri, 6 Feb 2026 12:41:01 -0500 Subject: [PATCH 623/978] Use relative paths for std links in rustc-docs Signed-off-by: arferreira --- src/bootstrap/src/core/build_steps/doc.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index a918ae929d2e..325f54d78a50 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -953,6 +953,13 @@ impl Step for Rustc { cargo.rustdocflag("--extern-html-root-url"); cargo.rustdocflag("ena=https://docs.rs/ena/latest/"); + // Point std library crate links to local docs for offline usage. + for krate in STD_PUBLIC_CRATES { + cargo.rustdocflag("--extern-html-root-url"); + cargo.rustdocflag(&format!("{krate}=../")); + } + cargo.rustdocflag("--extern-html-root-takes-precedence"); + let mut to_open = None; let out_dir = builder.stage_out(build_compiler, Mode::Rustc).join(target).join("doc"); From 343b469cad0b6814b5b74b84403d237b3aa1863b Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 2 Feb 2026 22:53:36 +0100 Subject: [PATCH 624/978] Update to Xcode 26.2 This also updates the macOS runners to run on macOS 15 (the macOS 14 runners only have up to Xcode 16.2 available). --- src/ci/citool/tests/jobs.rs | 2 +- src/ci/citool/tests/test-jobs.yml | 6 +++--- src/ci/github-actions/jobs.yml | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ci/citool/tests/jobs.rs b/src/ci/citool/tests/jobs.rs index 33fdb3f67b9b..247871de6025 100644 --- a/src/ci/citool/tests/jobs.rs +++ b/src/ci/citool/tests/jobs.rs @@ -6,7 +6,7 @@ const TEST_JOBS_YML_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/tes fn auto_jobs() { let stdout = get_matrix("push", "commit", "refs/heads/automation/bors/auto"); insta::assert_snapshot!(stdout, @r#" - jobs=[{"name":"aarch64-gnu","full_name":"auto - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"x86_64-gnu-llvm-18-1","full_name":"auto - x86_64-gnu-llvm-18-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DOCKER_SCRIPT":"stage_2_test_set1.sh","IMAGE":"x86_64-gnu-llvm-18","READ_ONLY_SRC":"0","RUST_BACKTRACE":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"aarch64-apple","full_name":"auto - aarch64-apple","os":"macos-14","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DEVELOPER_DIR":"/Applications/Xcode_15.4.app/Contents/Developer","MACOSX_DEPLOYMENT_TARGET":11.0,"MACOSX_STD_DEPLOYMENT_TARGET":11.0,"NO_DEBUG_ASSERTIONS":1,"NO_LLVM_ASSERTIONS":1,"NO_OVERFLOW_CHECKS":1,"RUSTC_RETRY_LINKER_ON_SEGFAULT":1,"RUST_CONFIGURE_ARGS":"--enable-sanitizers --enable-profiler --set rust.jemalloc","SCRIPT":"./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin","TOOLSTATE_PUBLISH":1}},{"name":"dist-i686-msvc","full_name":"auto - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}},{"name":"pr-check-1","full_name":"auto - pr-check-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"pr-check-2","full_name":"auto - pr-check-2","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"tidy","full_name":"auto - tidy","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true,"doc_url":"https://foo.bar"}] + jobs=[{"name":"aarch64-gnu","full_name":"auto - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"x86_64-gnu-llvm-18-1","full_name":"auto - x86_64-gnu-llvm-18-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DOCKER_SCRIPT":"stage_2_test_set1.sh","IMAGE":"x86_64-gnu-llvm-18","READ_ONLY_SRC":"0","RUST_BACKTRACE":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"aarch64-apple","full_name":"auto - aarch64-apple","os":"macos-15","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DEVELOPER_DIR":"/Applications/Xcode_26.2.app/Contents/Developer","MACOSX_DEPLOYMENT_TARGET":11.0,"MACOSX_STD_DEPLOYMENT_TARGET":11.0,"NO_DEBUG_ASSERTIONS":1,"NO_LLVM_ASSERTIONS":1,"NO_OVERFLOW_CHECKS":1,"RUSTC_RETRY_LINKER_ON_SEGFAULT":1,"RUST_CONFIGURE_ARGS":"--enable-sanitizers --enable-profiler --set rust.jemalloc","SCRIPT":"./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin","TOOLSTATE_PUBLISH":1}},{"name":"dist-i686-msvc","full_name":"auto - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}},{"name":"pr-check-1","full_name":"auto - pr-check-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"pr-check-2","full_name":"auto - pr-check-2","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true},{"name":"tidy","full_name":"auto - tidy","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"continue_on_error":false,"free_disk":true,"doc_url":"https://foo.bar"}] run_type=auto "#); } diff --git a/src/ci/citool/tests/test-jobs.yml b/src/ci/citool/tests/test-jobs.yml index b2dded6a98e2..3bad1fe1b427 100644 --- a/src/ci/citool/tests/test-jobs.yml +++ b/src/ci/citool/tests/test-jobs.yml @@ -13,7 +13,7 @@ runners: <<: *base-job - &job-macos-m1 - os: macos-14 + os: macos-15 <<: *base-job - &job-windows @@ -33,7 +33,7 @@ envs: # Ensure that host tooling is tested on our minimum supported macOS version. MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 - DEVELOPER_DIR: /Applications/Xcode_15.2.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_26.2.app/Contents/Developer NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 @@ -112,7 +112,7 @@ auto: --enable-profiler --set rust.jemalloc RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_26.2.app/Contents/Developer # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else # supports the hardware, so only need to test it there. MACOSX_DEPLOYMENT_TARGET: 11.0 diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index dec8876519ed..fafac482206e 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -23,7 +23,7 @@ runners: <<: *base-job - &job-macos - os: macos-14 + os: macos-15 # macOS 15 Arm64 <<: *base-job - &job-windows @@ -459,7 +459,7 @@ auto: # Ensure that host tooling is built to support our minimum support macOS version. MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 - DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_26.2.app/Contents/Developer DIST_REQUIRE_ALL_TOOLS: 1 CODEGEN_BACKENDS: llvm,cranelift <<: *job-macos @@ -474,7 +474,7 @@ auto: # FIXME(madsmtm): This might be redundant, as we're not building host tooling here (?) MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 - DEVELOPER_DIR: /Applications/Xcode_15.2.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_26.2.app/Contents/Developer <<: *job-macos - name: dist-aarch64-apple @@ -495,7 +495,7 @@ auto: # supports the hardware. MACOSX_DEPLOYMENT_TARGET: 11.0 MACOSX_STD_DEPLOYMENT_TARGET: 11.0 - DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_26.2.app/Contents/Developer DIST_REQUIRE_ALL_TOOLS: 1 CODEGEN_BACKENDS: llvm,cranelift <<: *job-macos @@ -509,7 +509,7 @@ auto: --enable-sanitizers --enable-profiler --set rust.jemalloc - DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_26.2.app/Contents/Developer # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else # supports the hardware, so only need to test it there. MACOSX_DEPLOYMENT_TARGET: 11.0 From a86cfbbaabb6ac635c01e4c11a57453ff5241ff0 Mon Sep 17 00:00:00 2001 From: Boxy Date: Fri, 6 Feb 2026 14:46:41 +0000 Subject: [PATCH 625/978] keep const blocks around --- compiler/rustc_ast_lowering/src/item.rs | 10 ++- compiler/rustc_ast_lowering/src/lib.rs | 66 +++++++------------- compiler/rustc_parse/src/parser/expr.rs | 12 +--- compiler/rustc_parse/src/parser/mod.rs | 19 +----- compiler/rustc_parse/src/parser/path.rs | 13 ++-- compiler/rustc_parse/src/parser/ty.rs | 12 +--- src/tools/rustfmt/tests/source/issue-6788.rs | 7 +++ src/tools/rustfmt/tests/target/issue-6788.rs | 10 +++ 8 files changed, 61 insertions(+), 88 deletions(-) create mode 100644 src/tools/rustfmt/tests/source/issue-6788.rs create mode 100644 src/tools/rustfmt/tests/target/issue-6788.rs diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index b497c6beeb98..cde8b8f9fe2e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -827,7 +827,10 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id, def_id: self.local_def_id(v.id), data: self.lower_variant_data(hir_id, item_kind, &v.data), - disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const_to_anon_const(e)), + disr_expr: v + .disr_expr + .as_ref() + .map(|e| self.lower_anon_const_to_anon_const(e, e.value.span)), ident: self.lower_ident(v.ident), span: self.lower_span(v.span), } @@ -917,7 +920,10 @@ impl<'hir> LoweringContext<'_, 'hir> { None => Ident::new(sym::integer(index), self.lower_span(f.span)), }, vis_span: self.lower_span(f.vis.span), - default: f.default.as_ref().map(|v| self.lower_anon_const_to_anon_const(v)), + default: f + .default + .as_ref() + .map(|v| self.lower_anon_const_to_anon_const(v, v.value.span)), ty, safety: self.lower_safety(f.safety, hir::Safety::Safe), } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e4f431fd2431..adf4ffd88101 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2425,15 +2425,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); let lowered_args = self.arena.alloc_from_iter(args.iter().map(|arg| { - let const_arg = if let ExprKind::ConstBlock(anon_const) = &arg.kind { - let def_id = self.local_def_id(anon_const.id); - let def_kind = self.tcx.def_kind(def_id); - assert_eq!(DefKind::AnonConst, def_kind); - self.lower_anon_const_to_const_arg(anon_const) - } else { - self.lower_expr_to_const_arg_direct(arg) - }; - + let const_arg = self.lower_expr_to_const_arg_direct(arg); &*self.arena.alloc(const_arg) })); @@ -2445,16 +2437,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ExprKind::Tup(exprs) => { let exprs = self.arena.alloc_from_iter(exprs.iter().map(|expr| { - let expr = if let ExprKind::ConstBlock(anon_const) = &expr.kind { - let def_id = self.local_def_id(anon_const.id); - let def_kind = self.tcx.def_kind(def_id); - assert_eq!(DefKind::AnonConst, def_kind); - - self.lower_anon_const_to_const_arg(anon_const) - } else { - self.lower_expr_to_const_arg_direct(&expr) - }; - + let expr = self.lower_expr_to_const_arg_direct(&expr); &*self.arena.alloc(expr) })); @@ -2494,16 +2477,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // then go unused as the `Target::ExprField` is not actually // corresponding to `Node::ExprField`. self.lower_attrs(hir_id, &f.attrs, f.span, Target::ExprField); - - let expr = if let ExprKind::ConstBlock(anon_const) = &f.expr.kind { - let def_id = self.local_def_id(anon_const.id); - let def_kind = self.tcx.def_kind(def_id); - assert_eq!(DefKind::AnonConst, def_kind); - - self.lower_anon_const_to_const_arg(anon_const) - } else { - self.lower_expr_to_const_arg_direct(&f.expr) - }; + let expr = self.lower_expr_to_const_arg_direct(&f.expr); &*self.arena.alloc(hir::ConstArgExprField { hir_id, @@ -2521,13 +2495,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ExprKind::Array(elements) => { let lowered_elems = self.arena.alloc_from_iter(elements.iter().map(|element| { - let const_arg = if let ExprKind::ConstBlock(anon_const) = &element.kind { - let def_id = self.local_def_id(anon_const.id); - assert_eq!(DefKind::AnonConst, self.tcx.def_kind(def_id)); - self.lower_anon_const_to_const_arg(anon_const) - } else { - self.lower_expr_to_const_arg_direct(element) - }; + let const_arg = self.lower_expr_to_const_arg_direct(element); &*self.arena.alloc(const_arg) })); let array_expr = self.arena.alloc(hir::ConstArgArrayExpr { @@ -2557,6 +2525,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { | ExprKind::Call(..) | ExprKind::Tup(..) | ExprKind::Array(..) + | ExprKind::ConstBlock(..) ) { return self.lower_expr_to_const_arg_direct(expr); @@ -2574,6 +2543,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span, } } + ExprKind::ConstBlock(anon_const) => { + let def_id = self.local_def_id(anon_const.id); + assert_eq!(DefKind::AnonConst, self.tcx.def_kind(def_id)); + self.lower_anon_const_to_const_arg(anon_const, span) + } _ => overly_complex_const(self), } } @@ -2584,11 +2558,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, anon: &AnonConst, ) -> &'hir hir::ConstArg<'hir> { - self.arena.alloc(self.lower_anon_const_to_const_arg(anon)) + self.arena.alloc(self.lower_anon_const_to_const_arg(anon, anon.value.span)) } #[instrument(level = "debug", skip(self))] - fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> { + fn lower_anon_const_to_const_arg( + &mut self, + anon: &AnonConst, + span: Span, + ) -> hir::ConstArg<'hir> { let tcx = self.tcx; // We cannot change parsing depending on feature gates available, @@ -2599,7 +2577,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if tcx.features().min_generic_const_args() { return match anon.mgca_disambiguation { MgcaDisambiguation::AnonConst => { - let lowered_anon = self.lower_anon_const_to_anon_const(anon); + let lowered_anon = self.lower_anon_const_to_anon_const(anon, span); ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Anon(lowered_anon), @@ -2645,7 +2623,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; } - let lowered_anon = self.lower_anon_const_to_anon_const(anon); + let lowered_anon = self.lower_anon_const_to_anon_const(anon, anon.value.span); ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Anon(lowered_anon), @@ -2655,7 +2633,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// See [`hir::ConstArg`] for when to use this function vs /// [`Self::lower_anon_const_to_const_arg`]. - fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { + fn lower_anon_const_to_anon_const( + &mut self, + c: &AnonConst, + span: Span, + ) -> &'hir hir::AnonConst { self.arena.alloc(self.with_new_scopes(c.value.span, |this| { let def_id = this.local_def_id(c.id); let hir_id = this.lower_node_id(c.id); @@ -2663,7 +2645,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { def_id, hir_id, body: this.lower_const_body(c.value.span, Some(&c.value)), - span: this.lower_span(c.value.span), + span: this.lower_span(span), } })) } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 84fe6770be58..11cde35fab17 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1627,16 +1627,8 @@ impl<'a> Parser<'a> { let first_expr = self.parse_expr()?; if self.eat(exp!(Semi)) { // Repeating array syntax: `[ 0; 512 ]` - let count = if self.eat_keyword(exp!(Const)) { - // While we could just disambiguate `Direct` from `AnonConst` by - // treating all const block exprs as `AnonConst`, that would - // complicate the DefCollector and likely all other visitors. - // So we strip the const blockiness and just store it as a block - // in the AST with the extra disambiguator on the AnonConst - self.parse_mgca_const_block(false)? - } else { - self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))? - }; + let count = + self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?; self.expect(close)?; ExprKind::Repeat(first_expr, count) } else if self.eat(exp!(Comma)) { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 0ff0b6622936..a6b956b09bc1 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -33,9 +33,9 @@ use rustc_ast::tokenstream::{ }; use rustc_ast::util::case::Case; use rustc_ast::{ - self as ast, AnonConst, AttrArgs, AttrId, BlockCheckMode, ByRef, Const, CoroutineKind, - DUMMY_NODE_ID, DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, MgcaDisambiguation, - Mutability, Recovered, Safety, StrLit, Visibility, VisibilityKind, + self as ast, AnonConst, AttrArgs, AttrId, ByRef, Const, CoroutineKind, DUMMY_NODE_ID, + DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, MgcaDisambiguation, Mutability, + Recovered, Safety, StrLit, Visibility, VisibilityKind, }; use rustc_ast_pretty::pprust; use rustc_data_structures::debug_assert_matches; @@ -1269,19 +1269,6 @@ impl<'a> Parser<'a> { } } - fn parse_mgca_const_block(&mut self, gate_syntax: bool) -> PResult<'a, AnonConst> { - let kw_span = self.prev_token.span; - let value = self.parse_expr_block(None, kw_span, BlockCheckMode::Default)?; - if gate_syntax { - self.psess.gated_spans.gate(sym::min_generic_const_args, kw_span.to(value.span)); - } - Ok(AnonConst { - id: ast::DUMMY_NODE_ID, - value, - mgca_disambiguation: MgcaDisambiguation::AnonConst, - }) - } - /// Parses inline const expressions. fn parse_const_block(&mut self, span: Span) -> PResult<'a, Box> { self.expect_keyword(exp!(Const))?; diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index dd190707c42b..9196d8d156d8 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -847,6 +847,7 @@ impl<'a> Parser<'a> { /// - A literal. /// - A numeric literal prefixed by `-`. /// - A single-segment path. + /// - A const block (under mGCA) pub(super) fn expr_is_valid_const_arg(&self, expr: &Box) -> bool { match &expr.kind { ast::ExprKind::Block(_, _) @@ -863,6 +864,10 @@ impl<'a> Parser<'a> { { true } + ast::ExprKind::ConstBlock(_) => { + self.psess.gated_spans.gate(sym::min_generic_const_args, expr.span); + true + } _ => false, } } @@ -874,14 +879,6 @@ impl<'a> Parser<'a> { let (value, mgca_disambiguation) = if self.token.kind == token::OpenBrace { let value = self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)?; (value, MgcaDisambiguation::Direct) - } else if self.eat_keyword(exp!(Const)) { - // While we could just disambiguate `Direct` from `AnonConst` by - // treating all const block exprs as `AnonConst`, that would - // complicate the DefCollector and likely all other visitors. - // So we strip the const blockiness and just store it as a block - // in the AST with the extra disambiguator on the AnonConst - let value = self.parse_mgca_const_block(true)?; - (value.value, MgcaDisambiguation::AnonConst) } else { self.parse_unambiguous_unbraced_const_arg()? }; diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 380b6a214846..6ff165eb22b7 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -658,16 +658,8 @@ impl<'a> Parser<'a> { }; let ty = if self.eat(exp!(Semi)) { - let mut length = if self.eat_keyword(exp!(Const)) { - // While we could just disambiguate `Direct` from `AnonConst` by - // treating all const block exprs as `AnonConst`, that would - // complicate the DefCollector and likely all other visitors. - // So we strip the const blockiness and just store it as a block - // in the AST with the extra disambiguator on the AnonConst - self.parse_mgca_const_block(false)? - } else { - self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))? - }; + let mut length = + self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?; if let Err(e) = self.expect(exp!(CloseBracket)) { // Try to recover from `X` when `X::` works diff --git a/src/tools/rustfmt/tests/source/issue-6788.rs b/src/tools/rustfmt/tests/source/issue-6788.rs new file mode 100644 index 000000000000..0e63ab53a1ac --- /dev/null +++ b/src/tools/rustfmt/tests/source/issue-6788.rs @@ -0,0 +1,7 @@ +fn foo() { + let a = [(); const { let x = 1; x }]; +} + +fn foo() { + let x = [(); const { 1 }]; +} diff --git a/src/tools/rustfmt/tests/target/issue-6788.rs b/src/tools/rustfmt/tests/target/issue-6788.rs new file mode 100644 index 000000000000..c559438b2d52 --- /dev/null +++ b/src/tools/rustfmt/tests/target/issue-6788.rs @@ -0,0 +1,10 @@ +fn foo() { + let a = [(); const { + let x = 1; + x + }]; +} + +fn foo() { + let x = [(); const { 1 }]; +} From 4b427b2f33fe122ea8acb01991f03aea5f10d658 Mon Sep 17 00:00:00 2001 From: nxsaken Date: Sat, 7 Feb 2026 00:33:52 +0400 Subject: [PATCH 626/978] Stabilize const ControlFlow predicates --- library/core/src/ops/control_flow.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 3cc184f0ab75..84fc98cf73f1 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -151,7 +151,7 @@ impl ControlFlow { /// ``` #[inline] #[stable(feature = "control_flow_enum_is", since = "1.59.0")] - #[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")] + #[rustc_const_stable(feature = "min_const_control_flow", since = "CURRENT_RUSTC_VERSION")] pub const fn is_break(&self) -> bool { matches!(*self, ControlFlow::Break(_)) } @@ -168,7 +168,7 @@ impl ControlFlow { /// ``` #[inline] #[stable(feature = "control_flow_enum_is", since = "1.59.0")] - #[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")] + #[rustc_const_stable(feature = "min_const_control_flow", since = "CURRENT_RUSTC_VERSION")] pub const fn is_continue(&self) -> bool { matches!(*self, ControlFlow::Continue(_)) } @@ -264,7 +264,7 @@ impl ControlFlow { /// ``` #[inline] #[unstable(feature = "control_flow_ok", issue = "140266")] - #[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")] + #[rustc_const_unstable(feature = "control_flow_ok", issue = "140266")] pub const fn break_ok(self) -> Result { match self { ControlFlow::Continue(c) => Err(c), @@ -377,7 +377,7 @@ impl ControlFlow { /// ``` #[inline] #[unstable(feature = "control_flow_ok", issue = "140266")] - #[rustc_const_unstable(feature = "min_const_control_flow", issue = "148738")] + #[rustc_const_unstable(feature = "control_flow_ok", issue = "140266")] pub const fn continue_ok(self) -> Result { match self { ControlFlow::Continue(c) => Ok(c), From 885a8081c4df3f18f2e42b7fde8a780c23446f98 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 Feb 2026 19:10:20 +0100 Subject: [PATCH 627/978] Convert to inline diagnostics in `rustc_mir_build` --- Cargo.lock | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_mir_build/Cargo.toml | 1 - compiler/rustc_mir_build/messages.ftl | 513 ------------ compiler/rustc_mir_build/src/errors.rs | 761 +++++++++++------- compiler/rustc_mir_build/src/lib.rs | 2 - .../src/thir/pattern/check_match.rs | 11 +- .../src/thir/pattern/const_to_pat.rs | 7 +- 8 files changed, 488 insertions(+), 809 deletions(-) delete mode 100644 compiler/rustc_mir_build/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 430a1d149a2b..fe68de293c0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4282,7 +4282,6 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_infer", diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 72831a8d8ff6..8e4998662827 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -115,7 +115,6 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ // tidy-alphabetical-start rustc_const_eval::DEFAULT_LOCALE_RESOURCE, rustc_lint::DEFAULT_LOCALE_RESOURCE, - rustc_mir_build::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE, rustc_passes::DEFAULT_LOCALE_RESOURCE, // tidy-alphabetical-end diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index f756f0a19ee9..f05183d7c068 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -12,7 +12,6 @@ rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl deleted file mode 100644 index 8b0c38dd3b53..000000000000 --- a/compiler/rustc_mir_build/messages.ftl +++ /dev/null @@ -1,513 +0,0 @@ -mir_build_adt_defined_here = `{$ty}` defined here - -mir_build_already_borrowed = cannot borrow value as mutable because it is also borrowed as immutable - -mir_build_already_mut_borrowed = cannot borrow value as immutable because it is also borrowed as mutable - -mir_build_bindings_with_variant_name = - pattern binding `{$name}` is named the same as one of the variants of the type `{$ty_path}` - .suggestion = to match on the variant, qualify the path - -mir_build_borrow = value is borrowed by `{$name}` here - -mir_build_borrow_of_layout_constrained_field_requires_unsafe = - borrow of layout constrained field with interior mutability is unsafe and requires unsafe block - .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values - .label = borrow of layout constrained field with interior mutability - -mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block - .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values - .label = borrow of layout constrained field with interior mutability - -mir_build_borrow_of_moved_value = borrow of moved value - .label = value moved into `{$name}` here - .occurs_because_label = move occurs because `{$name}` has type `{$ty}`, which does not implement the `Copy` trait - .value_borrowed_label = value borrowed here after move - .suggestion = borrow this binding in the pattern to avoid moving the value - -mir_build_call_to_deprecated_safe_fn_requires_unsafe = - call to deprecated safe function `{$function}` is unsafe and requires unsafe block - .note = consult the function's documentation for information on how to avoid undefined behavior - .label = call to unsafe function - .suggestion = you can wrap the call in an `unsafe` block if you can guarantee {$guarantee} - -mir_build_call_to_fn_with_requires_unsafe = - call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block - .help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> - [1] feature - *[count] features - }: {$missing_target_features} - .note = the {$build_target_features} target {$build_target_features_count -> - [1] feature - *[count] features - } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> - [1] it - *[count] them - } in `#[target_feature]` - .label = call to function with `#[target_feature]` - -mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block - .help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> - [1] feature - *[count] features - }: {$missing_target_features} - .note = the {$build_target_features} target {$build_target_features_count -> - [1] feature - *[count] features - } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> - [1] it - *[count] them - } in `#[target_feature]` - .label = call to function with `#[target_feature]` - -mir_build_call_to_unsafe_fn_requires_unsafe = - call to unsafe function `{$function}` is unsafe and requires unsafe block - .note = consult the function's documentation for information on how to avoid undefined behavior - .label = call to unsafe function - -mir_build_call_to_unsafe_fn_requires_unsafe_nameless = - call to unsafe function is unsafe and requires unsafe block - .note = consult the function's documentation for information on how to avoid undefined behavior - .label = call to unsafe function - -mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed = - call to unsafe function is unsafe and requires unsafe function or block - .note = consult the function's documentation for information on how to avoid undefined behavior - .label = call to unsafe function - -mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - call to unsafe function `{$function}` is unsafe and requires unsafe function or block - .note = consult the function's documentation for information on how to avoid undefined behavior - .label = call to unsafe function - -mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable - -mir_build_const_continue_bad_const = could not determine the target branch for this `#[const_continue]` - .label = this value is too generic - -mir_build_const_continue_missing_label_or_value = a `#[const_continue]` must break to a label with a value - -mir_build_const_continue_not_const = could not determine the target branch for this `#[const_continue]` - .help = try extracting the expression into a `const` item - -mir_build_const_continue_not_const_const_block = `const` blocks may use generics, and are not evaluated early enough -mir_build_const_continue_not_const_const_other = this value must be a literal or a monomorphic const -mir_build_const_continue_not_const_constant_parameter = constant parameters may use generics, and are not evaluated early enough - -mir_build_const_continue_unknown_jump_target = the target of this `#[const_continue]` is not statically known - .label = this value must be a literal or a monomorphic const - -mir_build_const_defined_here = constant defined here - -mir_build_const_param_in_pattern = constant parameters cannot be referenced in patterns - .label = can't be used in patterns -mir_build_const_param_in_pattern_def = constant defined here - -mir_build_const_pattern_depends_on_generic_parameter = constant pattern cannot depend on generic parameters - .label = `const` depends on a generic parameter - -mir_build_could_not_eval_const_pattern = could not evaluate constant pattern - .label = could not evaluate constant - -mir_build_deref_raw_pointer_requires_unsafe = - dereference of raw pointer is unsafe and requires unsafe block - .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior - .label = dereference of raw pointer - -mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - dereference of raw pointer is unsafe and requires unsafe function or block - .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior - .label = dereference of raw pointer - -mir_build_extern_static_requires_unsafe = - use of extern static is unsafe and requires unsafe block - .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior - .label = use of extern static - -mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - use of extern static is unsafe and requires unsafe function or block - .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior - .label = use of extern static - -mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - -mir_build_initializing_type_with_requires_unsafe = - initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block - .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior - .label = initializing type with `rustc_layout_scalar_valid_range` attr - -mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block - .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior - .label = initializing type with `rustc_layout_scalar_valid_range` attr - -mir_build_initializing_type_with_unsafe_field_requires_unsafe = - initializing type with an unsafe field is unsafe and requires unsafe block - .note = unsafe fields may carry library invariants - .label = initialization of struct with unsafe field - -mir_build_initializing_type_with_unsafe_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - initializing type with an unsafe field is unsafe and requires unsafe block - .note = unsafe fields may carry library invariants - .label = initialization of struct with unsafe field - -mir_build_inline_assembly_requires_unsafe = - use of inline assembly is unsafe and requires unsafe block - .note = inline assembly is entirely unchecked and can cause undefined behavior - .label = use of inline assembly - -mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - use of inline assembly is unsafe and requires unsafe function or block - .note = inline assembly is entirely unchecked and can cause undefined behavior - .label = use of inline assembly - -mir_build_interpreted_as_const = introduce a variable instead - -mir_build_invalid_pattern = {$prefix} `{$non_sm_ty}` cannot be used in patterns - .label = {$prefix} can't be used in patterns - -mir_build_irrefutable_let_patterns_if_let = irrefutable `if let` {$count -> - [one] pattern - *[other] patterns - } - .note = {$count -> - [one] this pattern - *[other] these patterns - } will always match, so the `if let` is useless - .help = consider replacing the `if let` with a `let` - -mir_build_irrefutable_let_patterns_if_let_guard = irrefutable `if let` guard {$count -> - [one] pattern - *[other] patterns - } - .note = {$count -> - [one] this pattern - *[other] these patterns - } will always match, so the guard is useless - .help = consider removing the guard and adding a `let` inside the match arm - -mir_build_irrefutable_let_patterns_let_else = irrefutable `let...else` {$count -> - [one] pattern - *[other] patterns - } - .note = {$count -> - [one] this pattern - *[other] these patterns - } will always match, so the `else` clause is useless - .help = consider removing the `else` clause - -mir_build_irrefutable_let_patterns_while_let = irrefutable `while let` {$count -> - [one] pattern - *[other] patterns - } - .note = {$count -> - [one] this pattern - *[other] these patterns - } will always match, so the loop will never exit - .help = consider instead using a `loop {"{"} ... {"}"}` with a `let` inside it - -mir_build_leading_irrefutable_let_patterns = leading irrefutable {$count -> - [one] pattern - *[other] patterns - } in let chain - .note = {$count -> - [one] this pattern - *[other] these patterns - } will always match - .help = consider moving {$count -> - [one] it - *[other] them - } outside of the construct - -mir_build_literal_in_range_out_of_bounds = - literal out of range for `{$ty}` - .label = this value does not fit into the type `{$ty}` whose range is `{$min}..={$max}` - -mir_build_loop_match_arm_with_guard = - match arms that are part of a `#[loop_match]` cannot have guards - -mir_build_loop_match_bad_rhs = - this expression must be a single `match` wrapped in a labeled block - -mir_build_loop_match_bad_statements = - statements are not allowed in this position within a `#[loop_match]` - -mir_build_loop_match_invalid_match = - invalid match on `#[loop_match]` state - .note = a local variable must be the scrutinee within a `#[loop_match]` - -mir_build_loop_match_invalid_update = - invalid update of the `#[loop_match]` state - .label = the assignment must update this variable - -mir_build_loop_match_missing_assignment = - expected a single assignment expression - -mir_build_loop_match_unsupported_type = - this `#[loop_match]` state value has type `{$ty}`, which is not supported - .note = only integers, floats, bool, char, and enums without fields are supported - -mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper = - lower bound for range pattern must be less than or equal to upper bound - .label = lower bound larger than upper bound - .teach_note = When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range. - -mir_build_lower_range_bound_must_be_less_than_upper = lower bound for range pattern must be less than upper bound - -mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html - -mir_build_moved = value is moved into `{$name}` here - -mir_build_moved_while_borrowed = cannot move out of value because it is borrowed - -mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once at a time - -mir_build_mutable_borrow = value is mutably borrowed by `{$name}` here - -mir_build_mutable_static_requires_unsafe = - use of mutable static is unsafe and requires unsafe block - .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior - .label = use of mutable static - -mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - use of mutable static is unsafe and requires unsafe function or block - .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior - .label = use of mutable static - -mir_build_mutation_of_layout_constrained_field_requires_unsafe = - mutation of layout constrained field is unsafe and requires unsafe block - .note = mutating layout constrained fields cannot statically be checked for valid values - .label = mutation of layout constrained field - -mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - mutation of layout constrained field is unsafe and requires unsafe function or block - .note = mutating layout constrained fields cannot statically be checked for valid values - .label = mutation of layout constrained field - -mir_build_nan_pattern = cannot use NaN in patterns - .label = evaluates to `NaN`, which is not allowed in patterns - .note = NaNs compare inequal to everything, even themselves, so this pattern would never match - .help = try using the `is_nan` method instead - -mir_build_non_const_path = runtime values cannot be referenced in patterns - .label = references a runtime value - -mir_build_non_empty_never_pattern = - mismatched types - .label = a never pattern must be used on an uninhabited type - .note = the matched value is of type `{$ty}` - -mir_build_non_exhaustive_match_all_arms_guarded = - match arms with guards don't count towards exhaustivity - -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}` - .non_exhaustive_type_note = the matched value is of type `{$ty}`, which is marked as non-exhaustive - .reference_note = references are always considered inhabited - .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern - -mir_build_non_partial_eq_match = constant of non-structural type `{$ty}` in a pattern - .label = constant of non-structural type - -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 raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon - .label = can't be used in patterns - .note = 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 - -mir_build_static_in_pattern = statics cannot be referenced in patterns - .label = can't be used in patterns -mir_build_static_in_pattern_def = `static` defined here - -mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits - - -mir_build_suggest_if_let = you might want to use `if let` to ignore the {$count -> - [one] variant that isn't - *[other] variants that aren't - } matched - -mir_build_suggest_let_else = you might want to use `let...else` to handle the {$count -> - [one] variant that isn't - *[other] variants that aren't - } matched - -mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count -> - [one] pattern - *[other] patterns - } in let chain - .note = {$count -> - [one] this pattern - *[other] these patterns - } will always match - .help = consider moving {$count -> - [one] it - *[other] them - } into the body - -mir_build_type_not_structural = constant of non-structural type `{$ty}` in a pattern - .label = constant of non-structural type -mir_build_type_not_structural_def = `{$ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns -mir_build_type_not_structural_more_info = see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details -mir_build_type_not_structural_tip = - the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - -mir_build_union_field_requires_unsafe = - access to union field is unsafe and requires unsafe block - .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior - .label = access to union field - -mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - access to union field is unsafe and requires unsafe function or block - .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior - .label = access to union field - -mir_build_union_pattern = cannot use unions in constant patterns - .label = can't use a `union` here - -mir_build_unreachable_due_to_uninhabited = unreachable {$descr} - .label = unreachable {$descr} - .label_orig = any code following this expression is unreachable - .note = this expression has type `{$ty}`, which is uninhabited - -mir_build_unreachable_making_this_unreachable = collectively making this unreachable - -mir_build_unreachable_making_this_unreachable_n_more = ...and {$covered_by_many_n_more_count} other patterns collectively make this unreachable - -mir_build_unreachable_matches_same_values = matches some of the same values - -mir_build_unreachable_pattern = unreachable pattern - .label = no value can reach this - .unreachable_matches_no_values = matches no values because `{$matches_no_values_ty}` is uninhabited - .unreachable_uninhabited_note = to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - .unreachable_covered_by_catchall = matches any value - .unreachable_covered_by_one = matches all the relevant values - .unreachable_covered_by_many = multiple earlier patterns match some of the same values - .unreachable_pattern_const_reexport_accessible = there is a constant of the same name imported in another scope, which could have been used to pattern match against its value instead of introducing a new catch-all binding, but it needs to be imported in the pattern's scope - .unreachable_pattern_wanted_const = you might have meant to pattern match against the value of {$is_typo -> - [true] similarly named constant - *[false] constant - } `{$const_name}` instead of introducing a new catch-all binding - .unreachable_pattern_const_inaccessible = there is a constant of the same name, which could have been used to pattern match against its value instead of introducing a new catch-all binding, but it is not accessible from this scope - .unreachable_pattern_let_binding = there is a binding of the same name; if you meant to pattern match against the value of that binding, that is a feature of constants that is not available for `let` bindings - .suggestion = remove the match arm - -mir_build_unsafe_binder_cast_requires_unsafe = - unsafe binder cast is unsafe and requires unsafe block - .label = unsafe binder cast - .note = casting to or from an `unsafe<...>` binder type is unsafe since it erases lifetime - information that may be required to uphold safety guarantees of a type - -mir_build_unsafe_binder_cast_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - unsafe binder cast is unsafe and requires unsafe block or unsafe fn - .label = unsafe binder cast - .note = casting to or from an `unsafe<...>` binder type is unsafe since it erases lifetime - information that may be required to uphold safety guarantees of a type - -mir_build_unsafe_field_requires_unsafe = - use of unsafe field is unsafe and requires unsafe block - .note = unsafe fields may carry library invariants - .label = use of unsafe field - -mir_build_unsafe_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - use of unsafe field is unsafe and requires unsafe block - .note = unsafe fields may carry library invariants - .label = use of unsafe field - -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 = - borrow of layout constrained field with interior mutability is unsafe and requires unsafe block - .note = references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values - .label = borrow of layout constrained field with interior mutability - -mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe = - call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block - .help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> - [1] feature - *[count] features - }: {$missing_target_features} - .note = the {$build_target_features} target {$build_target_features_count -> - [1] feature - *[count] features - } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> - [1] it - *[count] them - } in `#[target_feature]` - .label = call to function with `#[target_feature]` - -mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe = - call to unsafe function `{$function}` is unsafe and requires unsafe block - .note = consult the function's documentation for information on how to avoid undefined behavior - .label = call to unsafe function - -mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless = - call to unsafe function is unsafe and requires unsafe block - .note = consult the function's documentation for information on how to avoid undefined behavior - .label = call to unsafe function - -mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe = - dereference of raw pointer is unsafe and requires unsafe block - .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior - .label = dereference of raw pointer - -mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe = - use of extern static is unsafe and requires unsafe block - .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior - .label = use of extern static - -mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe = - initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block - .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior - .label = initializing type with `rustc_layout_scalar_valid_range` attr - -mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_unsafe_field_requires_unsafe = - initializing type with an unsafe field is unsafe and requires unsafe block - .note = unsafe fields may carry library invariants - .label = initialization of struct with unsafe field - -mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe = - use of inline assembly is unsafe and requires unsafe block - .note = inline assembly is entirely unchecked and can cause undefined behavior - .label = use of inline assembly - -mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe = - use of mutable static is unsafe and requires unsafe block - .note = mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior - .label = use of mutable static - -mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe = - mutation of layout constrained field is unsafe and requires unsafe block - .note = mutating layout constrained fields cannot statically be checked for valid values - .label = mutation of layout constrained field - -mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe = - access to union field is unsafe and requires unsafe block - .note = the field may not be properly initialized: using uninitialized data will cause undefined behavior - .label = access to union field - -mir_build_unsafe_op_in_unsafe_fn_unsafe_field_requires_unsafe = - use of unsafe field is unsafe and requires unsafe block - .note = unsafe fields may carry library invariants - .label = use of unsafe field - -mir_build_unsized_pattern = cannot use unsized non-slice type `{$non_sm_ty}` in constant patterns - -mir_build_unused_unsafe = unnecessary `unsafe` block - .label = unnecessary `unsafe` block - -mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block - -mir_build_upper_range_bound_cannot_be_min = exclusive upper bound for a range bound cannot be the minimum - -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/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 64e2bb3207c8..f51e130ea47a 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1,7 +1,7 @@ use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, - MultiSpan, Subdiagnostic, + MultiSpan, Subdiagnostic, inline_fluent, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; @@ -9,12 +9,10 @@ use rustc_pattern_analysis::errors::Uncovered; use rustc_pattern_analysis::rustc::RustcPatCtxt; use rustc_span::{Ident, Span, Symbol}; -use crate::fluent_generated as fluent; - #[derive(LintDiagnostic)] -#[diag(mir_build_call_to_deprecated_safe_fn_requires_unsafe)] +#[diag("call to deprecated safe function `{$function}` is unsafe and requires unsafe block")] pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe { - #[label] + #[label("call to unsafe function")] pub(crate) span: Span, pub(crate) function: String, pub(crate) guarantee: String, @@ -23,7 +21,10 @@ pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe { } #[derive(Subdiagnostic)] -#[multipart_suggestion(mir_build_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "you can wrap the call in an `unsafe` block if you can guarantee that the environment access only happens in single-threaded code", + applicability = "machine-applicable" +)] pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafeSub { pub(crate) start_of_line_suggestion: String, #[suggestion_part(code = "{start_of_line_suggestion}")] @@ -35,10 +36,10 @@ pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafeSub { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe, code = E0133)] -#[note] +#[diag("call to unsafe function `{$function}` is unsafe and requires unsafe block", code = E0133)] +#[note("consult the function's documentation for information on how to avoid undefined behavior")] pub(crate) struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { - #[label] + #[label("call to unsafe function")] pub(crate) span: Span, pub(crate) function: String, #[subdiagnostic] @@ -46,90 +47,100 @@ pub(crate) struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless, code = E0133)] -#[note] +#[diag("call to unsafe function is unsafe and requires unsafe block", code = E0133)] +#[note("consult the function's documentation for information on how to avoid undefined behavior")] pub(crate) struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { - #[label] + #[label("call to unsafe function")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe, code = E0133)] -#[note] +#[diag("use of inline assembly is unsafe and requires unsafe block", code = E0133)] +#[note("inline assembly is entirely unchecked and can cause undefined behavior")] pub(crate) struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { - #[label] + #[label("use of inline assembly")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe, code = E0133)] -#[note] +#[diag("initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block", code = E0133)] +#[note( + "initializing a layout restricted type's field with a value outside the valid range is undefined behavior" +)] pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { - #[label] + #[label("initializing type with `rustc_layout_scalar_valid_range` attr")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_unsafe_field_requires_unsafe, code = E0133)] -#[note] +#[diag("initializing type with an unsafe field is unsafe and requires unsafe block", code = E0133)] +#[note("unsafe fields may carry library invariants")] pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithUnsafeFieldRequiresUnsafe { - #[label] + #[label("initialization of struct with unsafe field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe, code = E0133)] -#[note] +#[diag("use of mutable static is unsafe and requires unsafe block", code = E0133)] +#[note( + "mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior" +)] pub(crate) struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { - #[label] + #[label("use of mutable static")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe, code = E0133)] -#[note] +#[diag("use of extern static is unsafe and requires unsafe block", code = E0133)] +#[note( + "extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior" +)] pub(crate) struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { - #[label] + #[label("use of extern static")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_unsafe_field_requires_unsafe, code = E0133)] -#[note] +#[diag("use of unsafe field is unsafe and requires unsafe block", code = E0133)] +#[note("unsafe fields may carry library invariants")] pub(crate) struct UnsafeOpInUnsafeFnUseOfUnsafeFieldRequiresUnsafe { - #[label] + #[label("use of unsafe field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe, code = E0133)] -#[note] +#[diag("dereference of raw pointer is unsafe and requires unsafe block", code = E0133)] +#[note( + "raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior" +)] pub(crate) struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { - #[label] + #[label("dereference of raw pointer")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe, code = E0133)] -#[note] +#[diag("access to union field is unsafe and requires unsafe block", code = E0133)] +#[note( + "the field may not be properly initialized: using uninitialized data will cause undefined behavior" +)] pub(crate) struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { - #[label] + #[label("access to union field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -137,12 +148,12 @@ pub(crate) struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { #[derive(LintDiagnostic)] #[diag( - mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe, + "mutation of layout constrained field is unsafe and requires unsafe block", code = E0133 )] -#[note] +#[note("mutating layout constrained fields cannot statically be checked for valid values")] pub(crate) struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { - #[label] + #[label("mutation of layout constrained field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -150,11 +161,11 @@ pub(crate) struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsa #[derive(LintDiagnostic)] #[diag( - mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe, + "borrow of layout constrained field with interior mutability is unsafe and requires unsafe block", code = E0133, )] pub(crate) struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { - #[label] + #[label("borrow of layout constrained field with interior mutability")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -162,26 +173,37 @@ pub(crate) struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe #[derive(LintDiagnostic)] #[diag( - mir_build_unsafe_binder_cast_requires_unsafe, + "unsafe binder cast is unsafe and requires unsafe block information that may be required to uphold safety guarantees of a type", code = E0133, )] pub(crate) struct UnsafeOpInUnsafeFnUnsafeBinderCastRequiresUnsafe { - #[label] + #[label("unsafe binder cast")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe, code = E0133)] -#[help] +#[diag("call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block", code = E0133)] +#[help( + "in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> + [1] feature + *[count] features + }: {$missing_target_features}" +)] pub(crate) struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { - #[label] + #[label("call to function with `#[target_feature]`")] pub(crate) span: Span, pub(crate) function: String, pub(crate) missing_target_features: DiagArgValue, pub(crate) missing_target_features_count: usize, - #[note] + #[note("the {$build_target_features} target {$build_target_features_count -> + [1] feature + *[count] features + } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it +*[count] them +} in `#[target_feature]`")] pub(crate) note: bool, pub(crate) build_target_features: DiagArgValue, pub(crate) build_target_features_count: usize, @@ -190,11 +212,11 @@ pub(crate) struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { } #[derive(Diagnostic)] -#[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = E0133)] -#[note] +#[diag("call to unsafe function `{$function}` is unsafe and requires unsafe block", code = E0133)] +#[note("consult the function's documentation for information on how to avoid undefined behavior")] pub(crate) struct CallToUnsafeFunctionRequiresUnsafe { #[primary_span] - #[label] + #[label("call to unsafe function")] pub(crate) span: Span, pub(crate) function: String, #[subdiagnostic] @@ -202,22 +224,22 @@ pub(crate) struct CallToUnsafeFunctionRequiresUnsafe { } #[derive(Diagnostic)] -#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_nameless, code = E0133)] -#[note] +#[diag("call to unsafe function is unsafe and requires unsafe block", code = E0133)] +#[note("consult the function's documentation for information on how to avoid undefined behavior")] pub(crate) struct CallToUnsafeFunctionRequiresUnsafeNameless { #[primary_span] - #[label] + #[label("call to unsafe function")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[note] +#[diag("call to unsafe function `{$function}` is unsafe and requires unsafe function or block", code = E0133)] +#[note("consult the function's documentation for information on how to avoid undefined behavior")] pub(crate) struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("call to unsafe function")] pub(crate) span: Span, pub(crate) function: String, #[subdiagnostic] @@ -226,57 +248,59 @@ pub(crate) struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[derive(Diagnostic)] #[diag( - mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed, + "call to unsafe function is unsafe and requires unsafe function or block", code = E0133 )] -#[note] +#[note("consult the function's documentation for information on how to avoid undefined behavior")] pub(crate) struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("call to unsafe function")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_inline_assembly_requires_unsafe, code = E0133)] -#[note] +#[diag("use of inline assembly is unsafe and requires unsafe block", code = E0133)] +#[note("inline assembly is entirely unchecked and can cause undefined behavior")] pub(crate) struct UseOfInlineAssemblyRequiresUnsafe { #[primary_span] - #[label] + #[label("use of inline assembly")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[note] +#[diag("use of inline assembly is unsafe and requires unsafe function or block", code = E0133)] +#[note("inline assembly is entirely unchecked and can cause undefined behavior")] pub(crate) struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("use of inline assembly")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_initializing_type_with_requires_unsafe, code = E0133)] -#[note] +#[diag("initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe block", code = E0133)] +#[note( + "initializing a layout restricted type's field with a value outside the valid range is undefined behavior" +)] pub(crate) struct InitializingTypeWithRequiresUnsafe { #[primary_span] - #[label] + #[label("initializing type with `rustc_layout_scalar_valid_range` attr")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_initializing_type_with_unsafe_field_requires_unsafe, code = E0133)] -#[note] +#[diag("initializing type with an unsafe field is unsafe and requires unsafe block", code = E0133)] +#[note("unsafe fields may carry library invariants")] pub(crate) struct InitializingTypeWithUnsafeFieldRequiresUnsafe { #[primary_span] - #[label] + #[label("initialization of struct with unsafe field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -284,13 +308,15 @@ pub(crate) struct InitializingTypeWithUnsafeFieldRequiresUnsafe { #[derive(Diagnostic)] #[diag( - mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + "initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block", code = E0133 )] -#[note] +#[note( + "initializing a layout restricted type's field with a value outside the valid range is undefined behavior" +)] pub(crate) struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("initializing type with `rustc_layout_scalar_valid_range` attr")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -298,134 +324,150 @@ pub(crate) struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[derive(Diagnostic)] #[diag( - mir_build_initializing_type_with_unsafe_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + "initializing type with an unsafe field is unsafe and requires unsafe block", code = E0133 )] -#[note] +#[note("unsafe fields may carry library invariants")] pub(crate) struct InitializingTypeWithUnsafeFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("initialization of struct with unsafe field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_mutable_static_requires_unsafe, code = E0133)] -#[note] +#[diag("use of mutable static is unsafe and requires unsafe block", code = E0133)] +#[note( + "mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior" +)] pub(crate) struct UseOfMutableStaticRequiresUnsafe { #[primary_span] - #[label] + #[label("use of mutable static")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[note] +#[diag("use of mutable static is unsafe and requires unsafe function or block", code = E0133)] +#[note( + "mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior" +)] pub(crate) struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("use of mutable static")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_extern_static_requires_unsafe, code = E0133)] -#[note] +#[diag("use of extern static is unsafe and requires unsafe block", code = E0133)] +#[note( + "extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior" +)] pub(crate) struct UseOfExternStaticRequiresUnsafe { #[primary_span] - #[label] + #[label("use of extern static")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[note] +#[diag("use of extern static is unsafe and requires unsafe function or block", code = E0133)] +#[note( + "extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior" +)] pub(crate) struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("use of extern static")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_unsafe_field_requires_unsafe, code = E0133)] -#[note] +#[diag("use of unsafe field is unsafe and requires unsafe block", code = E0133)] +#[note("unsafe fields may carry library invariants")] pub(crate) struct UseOfUnsafeFieldRequiresUnsafe { #[primary_span] - #[label] + #[label("use of unsafe field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_unsafe_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[note] +#[diag("use of unsafe field is unsafe and requires unsafe block", code = E0133)] +#[note("unsafe fields may carry library invariants")] pub(crate) struct UseOfUnsafeFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("use of unsafe field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_deref_raw_pointer_requires_unsafe, code = E0133)] -#[note] +#[diag("dereference of raw pointer is unsafe and requires unsafe block", code = E0133)] +#[note( + "raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior" +)] pub(crate) struct DerefOfRawPointerRequiresUnsafe { #[primary_span] - #[label] + #[label("dereference of raw pointer")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[note] +#[diag("dereference of raw pointer is unsafe and requires unsafe function or block", code = E0133)] +#[note( + "raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior" +)] pub(crate) struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("dereference of raw pointer")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_union_field_requires_unsafe, code = E0133)] -#[note] +#[diag("access to union field is unsafe and requires unsafe block", code = E0133)] +#[note( + "the field may not be properly initialized: using uninitialized data will cause undefined behavior" +)] pub(crate) struct AccessToUnionFieldRequiresUnsafe { #[primary_span] - #[label] + #[label("access to union field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[note] +#[diag("access to union field is unsafe and requires unsafe function or block", code = E0133)] +#[note( + "the field may not be properly initialized: using uninitialized data will cause undefined behavior" +)] pub(crate) struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("access to union field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_mutation_of_layout_constrained_field_requires_unsafe, code = E0133)] -#[note] +#[diag("mutation of layout constrained field is unsafe and requires unsafe block", code = E0133)] +#[note("mutating layout constrained fields cannot statically be checked for valid values")] pub(crate) struct MutationOfLayoutConstrainedFieldRequiresUnsafe { #[primary_span] - #[label] + #[label("mutation of layout constrained field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -433,24 +475,26 @@ pub(crate) struct MutationOfLayoutConstrainedFieldRequiresUnsafe { #[derive(Diagnostic)] #[diag( - mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + "mutation of layout constrained field is unsafe and requires unsafe function or block", code = E0133 )] -#[note] +#[note("mutating layout constrained fields cannot statically be checked for valid values")] pub(crate) struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("mutation of layout constrained field")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_borrow_of_layout_constrained_field_requires_unsafe, code = E0133)] -#[note] +#[diag("borrow of layout constrained field with interior mutability is unsafe and requires unsafe block", code = E0133)] +#[note( + "references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values" +)] pub(crate) struct BorrowOfLayoutConstrainedFieldRequiresUnsafe { #[primary_span] - #[label] + #[label("borrow of layout constrained field with interior mutability")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -458,47 +502,42 @@ pub(crate) struct BorrowOfLayoutConstrainedFieldRequiresUnsafe { #[derive(Diagnostic)] #[diag( - mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + "borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block", code = E0133 )] -#[note] +#[note( + "references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values" +)] pub(crate) struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("borrow of layout constrained field with interior mutability")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] -#[diag(mir_build_call_to_fn_with_requires_unsafe, code = E0133)] -#[help] +#[diag("call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block", code = E0133)] +#[help( + "in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> + [1] feature + *[count] features +}: {$missing_target_features}" +)] pub(crate) struct CallToFunctionWithRequiresUnsafe { #[primary_span] - #[label] + #[label("call to function with `#[target_feature]`")] pub(crate) span: Span, pub(crate) function: String, pub(crate) missing_target_features: DiagArgValue, pub(crate) missing_target_features_count: usize, - #[note] - pub(crate) note: bool, - pub(crate) build_target_features: DiagArgValue, - pub(crate) build_target_features_count: usize, - #[subdiagnostic] - pub(crate) unsafe_not_inherited_note: Option, -} - -#[derive(Diagnostic)] -#[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] -#[help] -pub(crate) struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { - #[primary_span] - #[label] - pub(crate) span: Span, - pub(crate) function: String, - pub(crate) missing_target_features: DiagArgValue, - pub(crate) missing_target_features_count: usize, - #[note] + #[note("the {$build_target_features} target {$build_target_features_count -> + [1] feature + *[count] features +} being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it + *[count] them +} in `#[target_feature]`")] pub(crate) note: bool, pub(crate) build_target_features: DiagArgValue, pub(crate) build_target_features_count: usize, @@ -508,12 +547,44 @@ pub(crate) struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[derive(Diagnostic)] #[diag( - mir_build_unsafe_binder_cast_requires_unsafe, + "call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe function or block", + code = E0133, +)] +#[help( + "in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> + [1] feature + *[count] features +}: {$missing_target_features}" +)] +pub(crate) struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + #[primary_span] + #[label("call to function with `#[target_feature]`")] + pub(crate) span: Span, + pub(crate) function: String, + pub(crate) missing_target_features: DiagArgValue, + pub(crate) missing_target_features_count: usize, + #[note("the {$build_target_features} target {$build_target_features_count -> + [1] feature + *[count] features + } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it + *[count] them + } in `#[target_feature]`")] + pub(crate) note: bool, + pub(crate) build_target_features: DiagArgValue, + pub(crate) build_target_features_count: usize, + #[subdiagnostic] + pub(crate) unsafe_not_inherited_note: Option, +} + +#[derive(Diagnostic)] +#[diag( + "unsafe binder cast is unsafe and requires unsafe block information that may be required to uphold safety guarantees of a type", code = E0133, )] pub(crate) struct UnsafeBinderCastRequiresUnsafe { #[primary_span] - #[label] + #[label("unsafe binder cast")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, @@ -521,19 +592,19 @@ pub(crate) struct UnsafeBinderCastRequiresUnsafe { #[derive(Diagnostic)] #[diag( - mir_build_unsafe_binder_cast_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, + "unsafe binder cast is unsafe and requires unsafe block or unsafe fn information that may be required to uphold safety guarantees of a type", code = E0133, )] pub(crate) struct UnsafeBinderCastRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] - #[label] + #[label("unsafe binder cast")] pub(crate) span: Span, #[subdiagnostic] pub(crate) unsafe_not_inherited_note: Option, } #[derive(Subdiagnostic)] -#[label(mir_build_unsafe_not_inherited)] +#[label("items do not inherit unsafety from separate enclosing items")] pub(crate) struct UnsafeNotInheritedNote { #[primary_span] pub(crate) span: Span, @@ -546,11 +617,16 @@ pub(crate) struct UnsafeNotInheritedLintNote { impl Subdiagnostic for UnsafeNotInheritedLintNote { fn add_to_diag(self, diag: &mut Diag<'_, G>) { - diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body); + diag.span_note( + self.signature_span, + inline_fluent!( + "an unsafe function restricts its caller, but its body is safe by default" + ), + ); 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, + inline_fluent!("consider wrapping the function body in an unsafe block"), vec![(body_start, "{ unsafe ".into()), (body_end, "}".into())], Applicability::MachineApplicable, ); @@ -558,9 +634,9 @@ impl Subdiagnostic for UnsafeNotInheritedLintNote { } #[derive(LintDiagnostic)] -#[diag(mir_build_unused_unsafe)] +#[diag("unnecessary `unsafe` block")] pub(crate) struct UnusedUnsafe { - #[label] + #[label("unnecessary `unsafe` block")] pub(crate) span: Span, #[subdiagnostic] pub(crate) enclosing: Option, @@ -568,7 +644,7 @@ pub(crate) struct UnusedUnsafe { #[derive(Subdiagnostic)] pub(crate) enum UnusedUnsafeEnclosing { - #[label(mir_build_unused_unsafe_enclosing_block_label)] + #[label("because it's nested under this `unsafe` block")] Block { #[primary_span] span: Span, @@ -584,8 +660,11 @@ pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { - let mut diag = - Diag::new(dcx, level, fluent::mir_build_non_exhaustive_patterns_type_not_empty); + let mut diag = Diag::new( + dcx, + level, + inline_fluent!("non-exhaustive patterns: type `{$ty}` is non-empty"), + ); diag.span(self.scrut_span); diag.code(E0004); let peeled_ty = self.ty.peel_refs(); @@ -605,20 +684,22 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo let mut span: MultiSpan = def_span.into(); span.push_span_label(def_span, ""); - diag.span_note(span, fluent::mir_build_def_note); + diag.span_note(span, inline_fluent!("`{$peeled_ty}` defined here")); } let is_non_exhaustive = matches!(self.ty.kind(), ty::Adt(def, _) if def.variant_list_has_applicable_non_exhaustive()); if is_non_exhaustive { - diag.note(fluent::mir_build_non_exhaustive_type_note); + diag.note(inline_fluent!( + "the matched value is of type `{$ty}`, which is marked as non-exhaustive" + )); } else { - diag.note(fluent::mir_build_type_note); + diag.note(inline_fluent!("the matched value is of type `{$ty}`")); } if let ty::Ref(_, sub_ty, _) = self.ty.kind() { if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.typing_env) { - diag.note(fluent::mir_build_reference_note); + diag.note(inline_fluent!("references are always considered inhabited")); } } @@ -633,12 +714,14 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo }; diag.span_suggestion_verbose( braces_span, - fluent::mir_build_suggestion, + inline_fluent!("ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown"), format!(" {{{indentation}{more}_ => todo!(),{indentation}}}"), Applicability::HasPlaceholders, ); } else { - diag.help(fluent::mir_build_help); + diag.help(inline_fluent!( + "ensure that all possible cases are being handled by adding a match arm with a wildcard pattern" + )); } diag @@ -646,69 +729,80 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo } #[derive(Subdiagnostic)] -#[note(mir_build_non_exhaustive_match_all_arms_guarded)] +#[note("match arms with guards don't count towards exhaustivity")] pub(crate) struct NonExhaustiveMatchAllArmsGuarded; #[derive(Diagnostic)] -#[diag(mir_build_static_in_pattern, code = E0158)] +#[diag("statics cannot be referenced in patterns", code = E0158)] pub(crate) struct StaticInPattern { #[primary_span] - #[label] + #[label("can't be used in patterns")] pub(crate) span: Span, - #[label(mir_build_static_in_pattern_def)] + #[label("`static` defined here")] pub(crate) static_span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_const_param_in_pattern, code = E0158)] +#[diag("constant parameters cannot be referenced in patterns", code = E0158)] pub(crate) struct ConstParamInPattern { #[primary_span] - #[label] + #[label("can't be used in patterns")] pub(crate) span: Span, - #[label(mir_build_const_param_in_pattern_def)] + #[label("constant defined here")] pub(crate) const_span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_non_const_path, code = E0080)] +#[diag("runtime values cannot be referenced in patterns", code = E0080)] pub(crate) struct NonConstPath { #[primary_span] - #[label] + #[label("references a runtime value")] pub(crate) span: Span, } #[derive(LintDiagnostic)] -#[diag(mir_build_unreachable_pattern)] +#[diag("unreachable pattern")] pub(crate) struct UnreachablePattern<'tcx> { - #[label] + #[label("no value can reach this")] pub(crate) span: Option, - #[label(mir_build_unreachable_matches_no_values)] + #[label("matches no values because `{$matches_no_values_ty}` is uninhabited")] pub(crate) matches_no_values: Option, pub(crate) matches_no_values_ty: Ty<'tcx>, - #[note(mir_build_unreachable_uninhabited_note)] + #[note( + "to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types" + )] pub(crate) uninhabited_note: Option<()>, - #[label(mir_build_unreachable_covered_by_catchall)] + #[label("matches any value")] pub(crate) covered_by_catchall: Option, #[subdiagnostic] pub(crate) wanted_constant: Option, - #[note(mir_build_unreachable_pattern_const_reexport_accessible)] + #[note( + "there is a constant of the same name imported in another scope, which could have been used to pattern match against its value instead of introducing a new catch-all binding, but it needs to be imported in the pattern's scope" + )] pub(crate) accessible_constant: Option, - #[note(mir_build_unreachable_pattern_const_inaccessible)] + #[note( + "there is a constant of the same name, which could have been used to pattern match against its value instead of introducing a new catch-all binding, but it is not accessible from this scope" + )] pub(crate) inaccessible_constant: Option, - #[note(mir_build_unreachable_pattern_let_binding)] + #[note( + "there is a binding of the same name; if you meant to pattern match against the value of that binding, that is a feature of constants that is not available for `let` bindings" + )] pub(crate) pattern_let_binding: Option, - #[label(mir_build_unreachable_covered_by_one)] + #[label("matches all the relevant values")] pub(crate) covered_by_one: Option, - #[note(mir_build_unreachable_covered_by_many)] + #[note("multiple earlier patterns match some of the same values")] pub(crate) covered_by_many: Option, pub(crate) covered_by_many_n_more_count: usize, - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove the match arm", code = "", applicability = "machine-applicable")] pub(crate) suggest_remove: Option, } #[derive(Subdiagnostic)] #[suggestion( - mir_build_unreachable_pattern_wanted_const, + "you might have meant to pattern match against the value of {$is_typo -> + [true] similarly named constant + *[false] constant + } `{$const_name}` instead of introducing a new catch-all binding", code = "{const_path}", applicability = "machine-applicable" )] @@ -721,48 +815,50 @@ pub(crate) struct WantedConstant { } #[derive(LintDiagnostic)] -#[diag(mir_build_unreachable_due_to_uninhabited)] +#[diag("unreachable {$descr}")] pub(crate) struct UnreachableDueToUninhabited<'desc, 'tcx> { pub descr: &'desc str, - #[label] + #[label("unreachable {$descr}")] pub expr: Span, - #[label(mir_build_label_orig)] - #[note] + #[label("any code following this expression is unreachable")] + #[note("this expression has type `{$ty}`, which is uninhabited")] pub orig: Span, pub ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(mir_build_const_pattern_depends_on_generic_parameter, code = E0158)] +#[diag("constant pattern cannot depend on generic parameters", code = E0158)] pub(crate) struct ConstPatternDependsOnGenericParameter { #[primary_span] - #[label] + #[label("`const` depends on a generic parameter")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_could_not_eval_const_pattern)] +#[diag("could not evaluate constant pattern")] pub(crate) struct CouldNotEvalConstPattern { #[primary_span] - #[label] + #[label("could not evaluate constant")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper, code = E0030)] +#[diag("lower bound for range pattern must be less than or equal to upper bound", code = E0030)] pub(crate) struct LowerRangeBoundMustBeLessThanOrEqualToUpper { #[primary_span] - #[label] + #[label("lower bound larger than upper bound")] pub(crate) span: Span, - #[note(mir_build_teach_note)] + #[note( + "When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range." + )] pub(crate) teach: bool, } #[derive(Diagnostic)] -#[diag(mir_build_literal_in_range_out_of_bounds)] +#[diag("literal out of range for `{$ty}`")] pub(crate) struct LiteralOutOfRange<'tcx> { #[primary_span] - #[label] + #[label("this value does not fit into the type `{$ty}` whose range is `{$min}..={$max}`")] pub(crate) span: Span, pub(crate) ty: Ty<'tcx>, pub(crate) min: i128, @@ -770,93 +866,173 @@ pub(crate) struct LiteralOutOfRange<'tcx> { } #[derive(Diagnostic)] -#[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = E0579)] +#[diag("lower bound for range pattern must be less than upper bound", code = E0579)] pub(crate) struct LowerRangeBoundMustBeLessThanUpper { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_upper_range_bound_cannot_be_min, code = E0579)] +#[diag("exclusive upper bound for a range bound cannot be the minimum", code = E0579)] pub(crate) struct UpperRangeBoundCannotBeMin { #[primary_span] pub(crate) span: Span, } #[derive(LintDiagnostic)] -#[diag(mir_build_leading_irrefutable_let_patterns)] -#[note] -#[help] +#[diag( + "leading irrefutable {$count -> + [one] pattern + *[other] patterns +} in let chain" +)] +#[note( + "{$count -> + [one] this pattern + *[other] these patterns +} will always match" +)] +#[help( + "consider moving {$count -> + [one] it + *[other] them +} outside of the construct" +)] pub(crate) struct LeadingIrrefutableLetPatterns { pub(crate) count: usize, } #[derive(LintDiagnostic)] -#[diag(mir_build_trailing_irrefutable_let_patterns)] -#[note] -#[help] +#[diag( + "trailing irrefutable {$count -> + [one] pattern + *[other] patterns +} in let chain" +)] +#[note( + "{$count -> + [one] this pattern + *[other] these patterns +} will always match" +)] +#[help( + "consider moving {$count -> + [one] it + *[other] them +} into the body" +)] pub(crate) struct TrailingIrrefutableLetPatterns { pub(crate) count: usize, } #[derive(LintDiagnostic)] -#[diag(mir_build_bindings_with_variant_name, code = E0170)] +#[diag("pattern binding `{$name}` is named the same as one of the variants of the type `{$ty_path}`", code = E0170)] pub(crate) struct BindingsWithVariantName { - #[suggestion(code = "{ty_path}::{name}", applicability = "machine-applicable")] + #[suggestion( + "to match on the variant, qualify the path", + code = "{ty_path}::{name}", + applicability = "machine-applicable" + )] pub(crate) suggestion: Option, pub(crate) ty_path: String, pub(crate) name: Ident, } #[derive(LintDiagnostic)] -#[diag(mir_build_irrefutable_let_patterns_if_let)] -#[note] -#[help] +#[diag( + "irrefutable `if let` {$count -> + [one] pattern + *[other] patterns +}" +)] +#[note( + "{$count -> + [one] this pattern + *[other] these patterns +} will always match, so the `if let` is useless" +)] +#[help("consider replacing the `if let` with a `let`")] pub(crate) struct IrrefutableLetPatternsIfLet { pub(crate) count: usize, } #[derive(LintDiagnostic)] -#[diag(mir_build_irrefutable_let_patterns_if_let_guard)] -#[note] -#[help] +#[diag( + "irrefutable `if let` guard {$count -> + [one] pattern + *[other] patterns +}" +)] +#[note( + "{$count -> + [one] this pattern + *[other] these patterns +} will always match, so the guard is useless" +)] +#[help("consider removing the guard and adding a `let` inside the match arm")] pub(crate) struct IrrefutableLetPatternsIfLetGuard { pub(crate) count: usize, } #[derive(LintDiagnostic)] -#[diag(mir_build_irrefutable_let_patterns_let_else)] -#[note] -#[help] +#[diag( + "irrefutable `let...else` {$count -> + [one] pattern + *[other] patterns +}" +)] +#[note( + "{$count -> + [one] this pattern + *[other] these patterns +} will always match, so the `else` clause is useless" +)] +#[help("consider removing the `else` clause")] pub(crate) struct IrrefutableLetPatternsLetElse { pub(crate) count: usize, } #[derive(LintDiagnostic)] -#[diag(mir_build_irrefutable_let_patterns_while_let)] -#[note] -#[help] +#[diag( + "irrefutable `while let` {$count -> + [one] pattern + *[other] patterns +}" +)] +#[note( + "{$count -> + [one] this pattern + *[other] these patterns +} will always match, so the loop will never exit" +)] +#[help("consider instead using a `loop {\"{\"} ... {\"}\"}` with a `let` inside it")] pub(crate) struct IrrefutableLetPatternsWhileLet { pub(crate) count: usize, } #[derive(Diagnostic)] -#[diag(mir_build_borrow_of_moved_value)] +#[diag("borrow of moved value")] pub(crate) struct BorrowOfMovedValue<'tcx> { #[primary_span] - #[label] - #[label(mir_build_occurs_because_label)] + #[label("value moved into `{$name}` here")] + #[label( + "move occurs because `{$name}` has type `{$ty}`, which does not implement the `Copy` trait" + )] pub(crate) binding_span: Span, - #[label(mir_build_value_borrowed_label)] + #[label("value borrowed here after move")] pub(crate) conflicts_ref: Vec, pub(crate) name: Ident, pub(crate) ty: Ty<'tcx>, - #[suggestion(code = "ref ", applicability = "machine-applicable")] + #[suggestion( + "borrow this binding in the pattern to avoid moving the value", + code = "ref ", + applicability = "machine-applicable" + )] pub(crate) suggest_borrowing: Option, } #[derive(Diagnostic)] -#[diag(mir_build_multiple_mut_borrows)] +#[diag("cannot borrow value as mutable more than once at a time")] pub(crate) struct MultipleMutBorrows { #[primary_span] pub(crate) span: Span, @@ -865,7 +1041,7 @@ pub(crate) struct MultipleMutBorrows { } #[derive(Diagnostic)] -#[diag(mir_build_already_borrowed)] +#[diag("cannot borrow value as mutable because it is also borrowed as immutable")] pub(crate) struct AlreadyBorrowed { #[primary_span] pub(crate) span: Span, @@ -874,7 +1050,7 @@ pub(crate) struct AlreadyBorrowed { } #[derive(Diagnostic)] -#[diag(mir_build_already_mut_borrowed)] +#[diag("cannot borrow value as immutable because it is also borrowed as mutable")] pub(crate) struct AlreadyMutBorrowed { #[primary_span] pub(crate) span: Span, @@ -883,7 +1059,7 @@ pub(crate) struct AlreadyMutBorrowed { } #[derive(Diagnostic)] -#[diag(mir_build_moved_while_borrowed)] +#[diag("cannot move out of value because it is borrowed")] pub(crate) struct MovedWhileBorrowed { #[primary_span] pub(crate) span: Span, @@ -893,19 +1069,19 @@ pub(crate) struct MovedWhileBorrowed { #[derive(Subdiagnostic)] pub(crate) enum Conflict { - #[label(mir_build_mutable_borrow)] + #[label("value is mutably borrowed by `{$name}` here")] Mut { #[primary_span] span: Span, name: Symbol, }, - #[label(mir_build_borrow)] + #[label("value is borrowed by `{$name}` here")] Ref { #[primary_span] span: Span, name: Symbol, }, - #[label(mir_build_moved)] + #[label("value is moved into `{$name}` here")] Moved { #[primary_span] span: Span, @@ -914,50 +1090,56 @@ pub(crate) enum Conflict { } #[derive(Diagnostic)] -#[diag(mir_build_union_pattern)] +#[diag("cannot use unions in constant patterns")] pub(crate) struct UnionPattern { #[primary_span] - #[label] + #[label("can't use a `union` here")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_type_not_structural)] +#[diag("constant of non-structural type `{$ty}` in a pattern")] pub(crate) struct TypeNotStructural<'tcx> { #[primary_span] - #[label] + #[label("constant of non-structural type")] pub(crate) span: Span, - #[label(mir_build_type_not_structural_def)] + #[label("`{$ty}` must be annotated with `#[derive(PartialEq)]` to be usable in patterns")] pub(crate) ty_def_span: Span, pub(crate) ty: Ty<'tcx>, - #[note(mir_build_type_not_structural_tip)] + #[note( + "the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details" + )] pub(crate) manual_partialeq_impl_span: Option, - #[note(mir_build_type_not_structural_more_info)] + #[note( + "see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details" + )] pub(crate) manual_partialeq_impl_note: bool, } #[derive(Diagnostic)] -#[diag(mir_build_non_partial_eq_match)] -#[note(mir_build_type_not_structural_more_info)] +#[diag("constant of non-structural type `{$ty}` in a pattern")] +#[note( + "see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details" +)] pub(crate) struct TypeNotPartialEq<'tcx> { #[primary_span] - #[label] + #[label("constant of non-structural type")] pub(crate) span: Span, pub(crate) ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(mir_build_invalid_pattern)] +#[diag("{$prefix} `{$non_sm_ty}` cannot be used in patterns")] pub(crate) struct InvalidPattern<'tcx> { #[primary_span] - #[label] + #[label("{$prefix} can't be used in patterns")] pub(crate) span: Span, pub(crate) non_sm_ty: Ty<'tcx>, pub(crate) prefix: String, } #[derive(Diagnostic)] -#[diag(mir_build_unsized_pattern)] +#[diag("cannot use unsized non-slice type `{$non_sm_ty}` in constant patterns")] pub(crate) struct UnsizedPattern<'tcx> { #[primary_span] pub(crate) span: Span, @@ -965,36 +1147,38 @@ pub(crate) struct UnsizedPattern<'tcx> { } #[derive(Diagnostic)] -#[diag(mir_build_nan_pattern)] -#[note] -#[help] +#[diag("cannot use NaN in patterns")] +#[note("NaNs compare inequal to everything, even themselves, so this pattern would never match")] +#[help("try using the `is_nan` method instead")] pub(crate) struct NaNPattern { #[primary_span] - #[label] + #[label("evaluates to `NaN`, which is not allowed in patterns")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_pointer_pattern)] -#[note] +#[diag( + "function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon" +)] +#[note("see https://github.com/rust-lang/rust/issues/70861 for details")] pub(crate) struct PointerPattern { #[primary_span] - #[label] + #[label("can't be used in patterns")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_non_empty_never_pattern)] -#[note] +#[diag("mismatched types")] +#[note("the matched value is of type `{$ty}`")] pub(crate) struct NonEmptyNeverPattern<'tcx> { #[primary_span] - #[label] + #[label("a never pattern must be used on an uninhabited type")] pub(crate) span: Span, pub(crate) ty: Ty<'tcx>, } #[derive(Diagnostic)] -#[diag(mir_build_pattern_not_covered, code = E0005)] +#[diag("refutable pattern in {$origin}", code = E0005)] pub(crate) struct PatternNotCovered<'s, 'tcx> { #[primary_span] pub(crate) span: Span, @@ -1009,10 +1193,12 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> { pub(crate) interpreted_as_const_sugg: Option, #[subdiagnostic] pub(crate) adt_defined_here: Option>, - #[note(mir_build_privately_uninhabited)] + #[note( + "pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future" + )] pub(crate) witness_1_is_privately_uninhabited: bool, pub(crate) witness_1: String, - #[note(mir_build_pattern_ty)] + #[note("the matched value is of type `{$pattern_ty}`")] pub(crate) _p: (), pub(crate) pattern_ty: Ty<'tcx>, #[subdiagnostic] @@ -1022,12 +1208,16 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> { } #[derive(Subdiagnostic)] -#[note(mir_build_inform_irrefutable)] -#[note(mir_build_more_information)] +#[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/ch19-02-refutability.html")] pub(crate) struct Inform; #[derive(Subdiagnostic)] -#[label(mir_build_confused)] +#[label( + "missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable" +)] pub(crate) struct InterpretedAsConst { #[primary_span] pub(crate) span: Span, @@ -1050,16 +1240,16 @@ impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> { let mut spans = MultiSpan::from(self.adt_def_span); for Variant { span } in self.variants { - spans.push_span_label(span, fluent::mir_build_variant_defined_here); + spans.push_span_label(span, inline_fluent!("not covered")); } - diag.span_note(spans, fluent::mir_build_adt_defined_here); + diag.span_note(spans, inline_fluent!("`{$ty}` defined here")); } } #[derive(Subdiagnostic)] #[suggestion( - mir_build_interpreted_as_const, + "introduce a variable instead", code = "{variable}_var", applicability = "maybe-incorrect", style = "verbose" @@ -1072,7 +1262,13 @@ pub(crate) struct InterpretedAsConstSugg { #[derive(Subdiagnostic)] pub(crate) enum SuggestLet { - #[multipart_suggestion(mir_build_suggest_if_let, applicability = "has-placeholders")] + #[multipart_suggestion( + "you might want to use `if let` to ignore the {$count -> +[one] variant that isn't +*[other] variants that aren't +} matched", + applicability = "has-placeholders" + )] If { #[suggestion_part(code = "if ")] start_span: Span, @@ -1081,7 +1277,10 @@ pub(crate) enum SuggestLet { count: usize, }, #[suggestion( - mir_build_suggest_let_else, + "you might want to use `let...else` to handle the {$count -> +[one] variant that isn't +*[other] variants that aren't +} matched", code = " else {{ todo!() }}", applicability = "has-placeholders" )] @@ -1095,7 +1294,7 @@ pub(crate) enum SuggestLet { #[derive(Subdiagnostic)] pub(crate) enum MiscPatternSuggestion { #[suggestion( - mir_build_suggest_attempted_int_lit, + "alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits", code = "_", applicability = "maybe-incorrect" )] @@ -1106,25 +1305,25 @@ pub(crate) enum MiscPatternSuggestion { } #[derive(Diagnostic)] -#[diag(mir_build_loop_match_invalid_update)] +#[diag("invalid update of the `#[loop_match]` state")] pub(crate) struct LoopMatchInvalidUpdate { #[primary_span] pub lhs: Span, - #[label] + #[label("the assignment must update this variable")] pub scrutinee: Span, } #[derive(Diagnostic)] -#[diag(mir_build_loop_match_invalid_match)] -#[note] +#[diag("invalid match on `#[loop_match]` state")] +#[note("a local variable must be the scrutinee within a `#[loop_match]`")] pub(crate) struct LoopMatchInvalidMatch { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_loop_match_unsupported_type)] -#[note] +#[diag("this `#[loop_match]` state value has type `{$ty}`, which is not supported")] +#[note("only integers, floats, bool, char, and enums without fields are supported")] pub(crate) struct LoopMatchUnsupportedType<'tcx> { #[primary_span] pub span: Span, @@ -1132,36 +1331,36 @@ pub(crate) struct LoopMatchUnsupportedType<'tcx> { } #[derive(Diagnostic)] -#[diag(mir_build_loop_match_bad_statements)] +#[diag("statements are not allowed in this position within a `#[loop_match]`")] pub(crate) struct LoopMatchBadStatements { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_loop_match_bad_rhs)] +#[diag("this expression must be a single `match` wrapped in a labeled block")] pub(crate) struct LoopMatchBadRhs { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_loop_match_missing_assignment)] +#[diag("expected a single assignment expression")] pub(crate) struct LoopMatchMissingAssignment { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_loop_match_arm_with_guard)] +#[diag("match arms that are part of a `#[loop_match]` cannot have guards")] pub(crate) struct LoopMatchArmWithGuard { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_const_continue_not_const)] -#[help] +#[diag("could not determine the target branch for this `#[const_continue]`")] +#[help("try extracting the expression into a `const` item")] pub(crate) struct ConstContinueNotMonomorphicConst { #[primary_span] pub span: Span, @@ -1172,19 +1371,19 @@ pub(crate) struct ConstContinueNotMonomorphicConst { #[derive(Subdiagnostic)] pub(crate) enum ConstContinueNotMonomorphicConstReason { - #[label(mir_build_const_continue_not_const_constant_parameter)] + #[label("constant parameters may use generics, and are not evaluated early enough")] ConstantParameter { #[primary_span] span: Span, }, - #[label(mir_build_const_continue_not_const_const_block)] + #[label("`const` blocks may use generics, and are not evaluated early enough")] ConstBlock { #[primary_span] span: Span, }, - #[label(mir_build_const_continue_not_const_const_other)] + #[label("this value must be a literal or a monomorphic const")] Other { #[primary_span] span: Span, @@ -1192,22 +1391,22 @@ pub(crate) enum ConstContinueNotMonomorphicConstReason { } #[derive(Diagnostic)] -#[diag(mir_build_const_continue_bad_const)] +#[diag("could not determine the target branch for this `#[const_continue]`")] pub(crate) struct ConstContinueBadConst { #[primary_span] - #[label] + #[label("this value is too generic")] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_const_continue_missing_label_or_value)] +#[diag("a `#[const_continue]` must break to a label with a value")] pub(crate) struct ConstContinueMissingLabelOrValue { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(mir_build_const_continue_unknown_jump_target)] +#[diag("the target of this `#[const_continue]` is not statically known")] pub(crate) struct ConstContinueUnknownJumpTarget { #[primary_span] pub span: Span, diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 5c5d979306bf..cc8035e2b0ac 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -18,8 +18,6 @@ pub mod thir; use rustc_middle::util::Providers; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn provide(providers: &mut Providers) { providers.queries.check_match = thir::pattern::check_match; providers.queries.lit_to_const = thir::constant::lit_to_const; 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 290d4ab2bfbb..4eb7b3671e9c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -3,7 +3,9 @@ use rustc_ast::Mutability; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::codes::*; -use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, struct_span_code_err}; +use rustc_errors::{ + Applicability, ErrorGuaranteed, MultiSpan, inline_fluent, struct_span_code_err, +}; use rustc_hir::def::*; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, BindingMode, ByRef, HirId, MatchSource}; @@ -29,7 +31,6 @@ use rustc_trait_selection::infer::InferCtxtExt; use tracing::instrument; use crate::errors::*; -use crate::fluent_generated as fluent; pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { let typeck_results = tcx.typeck(def_id); @@ -988,20 +989,20 @@ fn report_unreachable_pattern<'p, 'tcx>( for p in iter.by_ref().take(CAP_COVERED_BY_MANY) { multispan.push_span_label( p.data().span, - fluent::mir_build_unreachable_matches_same_values, + inline_fluent!("matches some of the same values"), ); } let remain = iter.count(); if remain == 0 { multispan.push_span_label( pat_span, - fluent::mir_build_unreachable_making_this_unreachable, + inline_fluent!("collectively making this unreachable"), ); } else { lint.covered_by_many_n_more_count = remain; multispan.push_span_label( pat_span, - fluent::mir_build_unreachable_making_this_unreachable_n_more, + inline_fluent!("...and {$covered_by_many_n_more_count} other patterns collectively make this unreachable"), ); } lint.covered_by_many = Some(multispan); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 0a0e0d06061e..6f0f6478f2d7 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 @@ -3,7 +3,7 @@ use core::ops::ControlFlow; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_apfloat::Float; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::Diag; +use rustc_errors::{Diag, inline_fluent}; use rustc_hir as hir; use rustc_hir::attrs::AttributeKind; use rustc_hir::find_attr; @@ -82,10 +82,7 @@ impl<'tcx> ConstToPat<'tcx> { err.span_label(self.tcx.def_span(self.tcx.local_parent(def_id)), ""); } if let hir::def::DefKind::Const | hir::def::DefKind::AssocConst = def_kind { - err.span_label( - self.tcx.def_span(uv.def), - crate::fluent_generated::mir_build_const_defined_here, - ); + err.span_label(self.tcx.def_span(uv.def), inline_fluent!("constant defined here")); } } Box::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit()), extra: None }) From 1a03742c252f651c0d909fbff24595d855e48249 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 5 Feb 2026 11:40:31 +0000 Subject: [PATCH 628/978] simplify some other generics --- library/proc_macro/src/bridge/mod.rs | 10 ++++++---- library/proc_macro/src/bridge/server.rs | 4 +--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index d9529b63e8e4..12af785df238 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -173,7 +173,7 @@ impl Mark for Marked { self.value } } -impl<'a, T, M> Mark for &'a Marked { +impl<'a, T> Mark for &'a Marked { type Unmarked = &'a T; fn mark(_: Self::Unmarked) -> Self { unreachable!() @@ -220,6 +220,8 @@ mark_noop! { Delimiter, LitKind, Level, + Bound, + Range, } rpc_encode_decode!( @@ -318,7 +320,7 @@ macro_rules! compound_traits { }; } -compound_traits!( +rpc_encode_decode!( enum Bound { Included(x), Excluded(x), @@ -390,7 +392,7 @@ pub struct Literal { pub span: Span, } -compound_traits!(struct Literal { kind, symbol, suffix, span }); +compound_traits!(struct Literal { kind, symbol, suffix, span }); #[derive(Clone)] pub enum TokenTree { @@ -434,6 +436,6 @@ compound_traits!( struct ExpnGlobals { def_site, call_site, mixed_site } ); -compound_traits!( +rpc_encode_decode!( struct Range { start, end } ); diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index 073ddb554994..a107657d2f61 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -63,7 +63,7 @@ macro_rules! define_server_dispatcher_impl { $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)* ) => { pub trait Server { - type TokenStream: 'static + Clone; + type TokenStream: 'static + Clone + Default; type Span: 'static + Copy + Eq + Hash; type Symbol: 'static; @@ -312,7 +312,6 @@ impl client::Client { ) -> Result where S: Server, - S::TokenStream: Default, { let client::Client { handle_counters, run, _marker } = *self; run_server( @@ -338,7 +337,6 @@ impl client::Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream ) -> Result where S: Server, - S::TokenStream: Default, { let client::Client { handle_counters, run, _marker } = *self; run_server( From 18996c698570bc1b2aa0e0989b306531e6ebe86b Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 5 Feb 2026 12:09:42 +0000 Subject: [PATCH 629/978] make `with_api!` take explicit type paths --- library/proc_macro/src/bridge/client.rs | 2 +- library/proc_macro/src/bridge/mod.rs | 92 ++++++++++++------------- library/proc_macro/src/bridge/server.rs | 20 +++--- 3 files changed, 54 insertions(+), 60 deletions(-) diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index ddc9e0d4dee0..02a408802b6f 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -121,7 +121,7 @@ macro_rules! define_client_side { } } } -with_api!(self, define_client_side); +with_api!(define_client_side, TokenStream, Span, Symbol); struct Bridge<'a> { /// Reusable buffer (only `clear`-ed, never shrunk), primarily diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 12af785df238..6a9027046af0 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -18,71 +18,67 @@ use crate::{Delimiter, Level}; /// Higher-order macro describing the server RPC API, allowing automatic /// generation of type-safe Rust APIs, both client-side and server-side. /// -/// `with_api!(MySelf, my_macro)` expands to: +/// `with_api!(my_macro, MyTokenStream, MySpan, MySymbol)` expands to: /// ```rust,ignore (pseudo-code) /// my_macro! { -/// fn lit_character(ch: char) -> MySelf::Literal; -/// fn lit_span(lit: &MySelf::Literal) -> MySelf::Span; -/// fn lit_set_span(lit: &mut MySelf::Literal, span: MySelf::Span); +/// fn ts_clone(stream: &MyTokenStream) -> MyTokenStream; +/// fn span_debug(span: &MySpan) -> String; /// // ... /// } /// ``` /// -/// The first argument serves to customize the argument/return types, -/// to enable several different usecases: -/// -/// If `MySelf` is just `Self`, then the types are only valid inside -/// a trait or a trait impl, where the trait has associated types -/// for each of the API types. If non-associated types are desired, -/// a module name (`self` in practice) can be used instead of `Self`. +/// The second (`TokenStream`), third (`Span`) and fourth (`Symbol`) +/// argument serve to customize the argument/return types that need +/// special handling, to enable several different representations of +/// these types. macro_rules! with_api { - ($S:ident, $m:ident) => { + ($m:ident, $TokenStream: path, $Span: path, $Symbol: path) => { $m! { fn injected_env_var(var: &str) -> Option; fn track_env_var(var: &str, value: Option<&str>); fn track_path(path: &str); - fn literal_from_str(s: &str) -> Result, ()>; - fn emit_diagnostic(diagnostic: Diagnostic<$S::Span>); + fn literal_from_str(s: &str) -> Result, ()>; + fn emit_diagnostic(diagnostic: Diagnostic<$Span>); - fn ts_drop(stream: $S::TokenStream); - fn ts_clone(stream: &$S::TokenStream) -> $S::TokenStream; - fn ts_is_empty(stream: &$S::TokenStream) -> bool; - fn ts_expand_expr(stream: &$S::TokenStream) -> Result<$S::TokenStream, ()>; - fn ts_from_str(src: &str) -> $S::TokenStream; - fn ts_to_string(stream: &$S::TokenStream) -> String; + fn ts_drop(stream: $TokenStream); + fn ts_clone(stream: &$TokenStream) -> $TokenStream; + fn ts_is_empty(stream: &$TokenStream) -> bool; + fn ts_expand_expr(stream: &$TokenStream) -> Result<$TokenStream, ()>; + fn ts_from_str(src: &str) -> $TokenStream; + fn ts_to_string(stream: &$TokenStream) -> String; fn ts_from_token_tree( - tree: TokenTree<$S::TokenStream, $S::Span, $S::Symbol>, - ) -> $S::TokenStream; + tree: TokenTree<$TokenStream, $Span, $Symbol>, + ) -> $TokenStream; fn ts_concat_trees( - base: Option<$S::TokenStream>, - trees: Vec>, - ) -> $S::TokenStream; + base: Option<$TokenStream>, + trees: Vec>, + ) -> $TokenStream; fn ts_concat_streams( - base: Option<$S::TokenStream>, - streams: Vec<$S::TokenStream>, - ) -> $S::TokenStream; + base: Option<$TokenStream>, + streams: Vec<$TokenStream>, + ) -> $TokenStream; fn ts_into_trees( - stream: $S::TokenStream - ) -> Vec>; + stream: $TokenStream + ) -> Vec>; - fn span_debug(span: $S::Span) -> String; - fn span_parent(span: $S::Span) -> Option<$S::Span>; - fn span_source(span: $S::Span) -> $S::Span; - fn span_byte_range(span: $S::Span) -> Range; - fn span_start(span: $S::Span) -> $S::Span; - fn span_end(span: $S::Span) -> $S::Span; - fn span_line(span: $S::Span) -> usize; - fn span_column(span: $S::Span) -> usize; - fn span_file(span: $S::Span) -> String; - fn span_local_file(span: $S::Span) -> Option; - fn span_join(span: $S::Span, other: $S::Span) -> Option<$S::Span>; - fn span_subspan(span: $S::Span, start: Bound, end: Bound) -> Option<$S::Span>; - fn span_resolved_at(span: $S::Span, at: $S::Span) -> $S::Span; - fn span_source_text(span: $S::Span) -> Option; - fn span_save_span(span: $S::Span) -> usize; - fn span_recover_proc_macro_span(id: usize) -> $S::Span; + fn span_debug(span: $Span) -> String; + fn span_parent(span: $Span) -> Option<$Span>; + fn span_source(span: $Span) -> $Span; + fn span_byte_range(span: $Span) -> Range; + fn span_start(span: $Span) -> $Span; + fn span_end(span: $Span) -> $Span; + fn span_line(span: $Span) -> usize; + fn span_column(span: $Span) -> usize; + fn span_file(span: $Span) -> String; + fn span_local_file(span: $Span) -> Option; + fn span_join(span: $Span, other: $Span) -> Option<$Span>; + fn span_subspan(span: $Span, start: Bound, end: Bound) -> Option<$Span>; + fn span_resolved_at(span: $Span, at: $Span) -> $Span; + fn span_source_text(span: $Span) -> Option; + fn span_save_span(span: $Span) -> usize; + fn span_recover_proc_macro_span(id: usize) -> $Span; - fn symbol_normalize_and_validate_ident(string: &str) -> Result<$S::Symbol, ()>; + fn symbol_normalize_and_validate_ident(string: &str) -> Result<$Symbol, ()>; } }; } @@ -146,7 +142,7 @@ macro_rules! declare_tags { rpc_encode_decode!(enum ApiTags { $($method),* }); } } -with_api!(self, declare_tags); +with_api!(declare_tags, __, __, __); /// Helper to wrap associated types to allow trait impl dispatch. /// That is, normally a pair of impls for `T::Foo` and `T::Bar` diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index a107657d2f61..a3c6a232264e 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -58,7 +58,7 @@ struct Dispatcher { server: S, } -macro_rules! define_server_dispatcher_impl { +macro_rules! define_server { ( $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)* ) => { @@ -77,22 +77,20 @@ macro_rules! define_server_dispatcher_impl { $(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)?;)* } + } +} +with_api!(define_server, Self::TokenStream, Self::Span, Self::Symbol); +macro_rules! define_dispatcher { + ( + $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)* + ) => { // FIXME(eddyb) `pub` only for `ExecutionStrategy` below. pub trait DispatcherTrait { - // HACK(eddyb) these are here to allow `Self::$name` to work below. - type TokenStream; - type Span; - type Symbol; - fn dispatch(&mut self, buf: Buffer) -> Buffer; } impl DispatcherTrait for Dispatcher { - type TokenStream = MarkedTokenStream; - type Span = MarkedSpan; - type Symbol = MarkedSymbol; - fn dispatch(&mut self, mut buf: Buffer) -> Buffer { let Dispatcher { handle_store, server } = self; @@ -127,7 +125,7 @@ macro_rules! define_server_dispatcher_impl { } } } -with_api!(Self, define_server_dispatcher_impl); +with_api!(define_dispatcher, MarkedTokenStream, MarkedSpan, MarkedSymbol); pub trait ExecutionStrategy { fn run_bridge_and_client( From a6062a84bc0c55d00f068afc79f8a40ba756c977 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 5 Feb 2026 14:33:30 +0000 Subject: [PATCH 630/978] use `mem::conjure_zst` directly --- library/proc_macro/src/bridge/selfless_reify.rs | 2 +- library/proc_macro/src/lib.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/library/proc_macro/src/bridge/selfless_reify.rs b/library/proc_macro/src/bridge/selfless_reify.rs index 9d565485bbdd..1a9951af8c9f 100644 --- a/library/proc_macro/src/bridge/selfless_reify.rs +++ b/library/proc_macro/src/bridge/selfless_reify.rs @@ -55,7 +55,7 @@ pub(super) const fn reify_to_extern_c_fn_hrt_bridge< let f = unsafe { // SAFETY: `F` satisfies all criteria for "out of thin air" // reconstructability (see module-level doc comment). - mem::MaybeUninit::::uninit().assume_init() + mem::conjure_zst::() }; f(bridge) } diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 49b6f2ae41f8..e2f39c015bdd 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -27,6 +27,7 @@ #![feature(restricted_std)] #![feature(rustc_attrs)] #![feature(extend_one)] +#![feature(mem_conjure_zst)] #![recursion_limit = "256"] #![allow(internal_features)] #![deny(ffi_unwind_calls)] From 74d2616efc34b46dda95821274cd527a019dc4f3 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Fri, 6 Feb 2026 13:52:21 +0000 Subject: [PATCH 631/978] deduplicate `Tag` enum --- library/proc_macro/src/bridge/rpc.rs | 58 ++++++++++++---------------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/library/proc_macro/src/bridge/rpc.rs b/library/proc_macro/src/bridge/rpc.rs index 63329c8c0260..7fee8654bc78 100644 --- a/library/proc_macro/src/bridge/rpc.rs +++ b/library/proc_macro/src/bridge/rpc.rs @@ -52,45 +52,37 @@ macro_rules! rpc_encode_decode { } }; (enum $name:ident $(<$($T:ident),+>)? { $($variant:ident $(($field:ident))*),* $(,)? }) => { - impl),+)?> Encode for $name $(<$($T),+>)? { - fn encode(self, w: &mut Buffer, s: &mut S) { - // HACK(eddyb): `Tag` enum duplicated between the - // two impls as there's no other place to stash it. - #[allow(non_camel_case_types)] - #[repr(u8)] - enum Tag { $($variant),* } + #[allow(non_upper_case_globals, non_camel_case_types)] + const _: () = { + #[repr(u8)] enum Tag { $($variant),* } - match self { - $($name::$variant $(($field))* => { - (Tag::$variant as u8).encode(w, s); - $($field.encode(w, s);)* - })* + $(const $variant: u8 = Tag::$variant as u8;)* + + impl),+)?> Encode for $name $(<$($T),+>)? { + fn encode(self, w: &mut Buffer, s: &mut S) { + match self { + $($name::$variant $(($field))* => { + $variant.encode(w, s); + $($field.encode(w, s);)* + })* + } } } - } - impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S> - for $name $(<$($T),+>)? - { - fn decode(r: &mut &'a [u8], s: &mut S) -> Self { - // HACK(eddyb): `Tag` enum duplicated between the - // two impls as there's no other place to stash it. - #[allow(non_upper_case_globals, non_camel_case_types)] - mod tag { - #[repr(u8)] enum Tag { $($variant),* } - - $(pub(crate) const $variant: u8 = Tag::$variant as u8;)* - } - - match u8::decode(r, s) { - $(tag::$variant => { - $(let $field = Decode::decode(r, s);)* - $name::$variant $(($field))* - })* - _ => unreachable!(), + impl<'a, S, $($($T: for<'s> Decode<'a, 's, S>),+)?> Decode<'a, '_, S> + for $name $(<$($T),+>)? + { + fn decode(r: &mut &'a [u8], s: &mut S) -> Self { + match u8::decode(r, s) { + $($variant => { + $(let $field = Decode::decode(r, s);)* + $name::$variant $(($field))* + })* + _ => unreachable!(), + } } } - } + }; } } From c6829020b0c0878633f72e592d6a25d7687b6d3e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 5 Feb 2026 22:25:42 +0100 Subject: [PATCH 632/978] Convert to inline diagnostics in `rustc_const_eval` --- Cargo.lock | 1 - compiler/rustc_const_eval/Cargo.toml | 1 - compiler/rustc_const_eval/messages.ftl | 507 ------------ .../rustc_const_eval/src/check_consts/ops.rs | 8 +- .../rustc_const_eval/src/const_eval/error.rs | 44 +- .../src/const_eval/eval_queries.rs | 16 +- .../src/const_eval/machine.rs | 18 +- compiler/rustc_const_eval/src/errors.rs | 747 +++++++++++++----- .../rustc_const_eval/src/interpret/call.rs | 22 +- .../rustc_const_eval/src/interpret/cast.rs | 7 +- .../src/interpret/eval_context.rs | 8 +- .../src/interpret/intrinsics.rs | 42 +- .../rustc_const_eval/src/interpret/memory.rs | 71 +- compiler/rustc_const_eval/src/lib.rs | 2 - compiler/rustc_driver_impl/src/lib.rs | 1 - tests/ui/consts/const-try-feature-gate.stderr | 1 + 16 files changed, 736 insertions(+), 760 deletions(-) delete mode 100644 compiler/rustc_const_eval/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 430a1d149a2b..05c00f6e3987 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3703,7 +3703,6 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_infer", diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml index 51dcee8d8822..aa013cf61f48 100644 --- a/compiler/rustc_const_eval/Cargo.toml +++ b/compiler/rustc_const_eval/Cargo.toml @@ -11,7 +11,6 @@ rustc_apfloat = "0.2.0" rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl deleted file mode 100644 index 4aa0a0b2a96f..000000000000 --- a/compiler/rustc_const_eval/messages.ftl +++ /dev/null @@ -1,507 +0,0 @@ -const_eval_address_space_full = - there are no more free addresses in the address space - -const_eval_alignment_check_failed = - {$msg -> - [AccessedPtr] accessing memory - *[other] accessing memory based on pointer - } with alignment {$has}, but alignment {$required} is required - -const_eval_already_reported = - an error has already been reported elsewhere (this should not usually be printed) -const_eval_assume_false = - `assume` called with `false` - -const_eval_bad_pointer_op = {$operation -> - [MemoryAccess] memory access failed - [InboundsPointerArithmetic] in-bounds pointer arithmetic failed - *[Dereferenceable] pointer not dereferenceable -} -const_eval_bad_pointer_op_attempting = {const_eval_bad_pointer_op}: {$operation -> - [MemoryAccess] attempting to access {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - *[Dereferenceable] pointer must {$inbounds_size -> - [0] point to some allocation - [1] be dereferenceable for 1 byte - *[x] be dereferenceable for {$inbounds_size} bytes - } - } - -const_eval_bounds_check_failed = - indexing out of bounds: the len is {$len} but the index is {$index} -const_eval_call_nonzero_intrinsic = - `{$name}` called on 0 - -const_eval_closure_call = - closures need an RFC before allowed to be called in {const_eval_const_context}s -const_eval_closure_fndef_not_const = - function defined here, but it is not `const` - -const_eval_consider_dereferencing = - consider dereferencing here - -const_eval_const_accesses_mut_global = - constant accesses mutable global memory - -const_eval_const_context = {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -} - -const_eval_const_heap_ptr_in_final = encountered `const_allocate` pointer in final value that was not made global - .note = use `const_make_global` to turn allocated pointers into immutable globals before returning - -const_eval_const_make_global_ptr_already_made_global = attempting to call `const_make_global` twice on the same allocation {$alloc} - -const_eval_const_make_global_ptr_is_non_heap = pointer passed to `const_make_global` does not point to a heap allocation: {$ptr} - -const_eval_const_make_global_with_dangling_ptr = pointer passed to `const_make_global` is dangling: {$ptr} - -const_eval_const_make_global_with_offset = making {$ptr} global which does not point to the beginning of an object - -const_eval_copy_nonoverlapping_overlapping = - `copy_nonoverlapping` called on overlapping ranges - -const_eval_dangling_int_pointer = - {const_eval_bad_pointer_op_attempting}, but got {$pointer} which is a dangling pointer (it has no provenance) -const_eval_dangling_null_pointer = - {const_eval_bad_pointer_op_attempting}, but got null pointer - -const_eval_dangling_ptr_in_final = encountered dangling pointer in final value of {const_eval_intern_kind} -const_eval_dead_local = - accessing a dead local variable -const_eval_dealloc_immutable = - deallocating immutable allocation {$alloc} - -const_eval_dealloc_incorrect_layout = - incorrect layout on deallocation: {$alloc} has size {$size} and alignment {$align}, but gave size {$size_found} and alignment {$align_found} - -const_eval_dealloc_kind_mismatch = - deallocating {$alloc}, which is {$alloc_kind} memory, using {$kind} deallocation operation - -const_eval_deref_function_pointer = - accessing {$allocation} which contains a function -const_eval_deref_typeid_pointer = - accessing {$allocation} which contains a `TypeId` -const_eval_deref_vtable_pointer = - accessing {$allocation} which contains a vtable -const_eval_division_by_zero = - dividing by zero -const_eval_division_overflow = - overflow in signed division (dividing MIN by -1) - -const_eval_dyn_call_not_a_method = - `dyn` call trying to call something that is not a method - -const_eval_error = evaluation of `{$instance}` failed {$num_frames -> - [0] here - *[other] inside this call -} - -const_eval_exact_div_has_remainder = - exact_div: {$a} cannot be divided by {$b} without remainder - -const_eval_extern_static = - cannot access extern static `{$did}` -const_eval_extern_type_field = `extern type` field does not have a known offset - -const_eval_fn_ptr_call = - function pointers need an RFC before allowed to be called in {const_eval_const_context}s -const_eval_frame_note = {$times -> - [0] {const_eval_frame_note_inner} - *[other] [... {$times} additional calls {const_eval_frame_note_inner} ...] -} - -const_eval_frame_note_inner = inside {$where_ -> - [closure] closure - [instance] `{$instance}` - *[other] {""} -} - -const_eval_frame_note_last = the failure occurred here - -const_eval_incompatible_arg_types = - calling a function whose parameter #{$arg_idx} has type {$callee_ty} passing argument of type {$caller_ty} - -const_eval_incompatible_calling_conventions = - calling a function with calling convention "{$callee_conv}" using calling convention "{$caller_conv}" - -const_eval_incompatible_return_types = - calling a function with return type {$callee_ty} passing return place of type {$caller_ty} - -const_eval_interior_mutable_borrow_escaping = - interior mutable shared borrows of temporaries that have their lifetime extended until the end of the program are not allowed - .label = this borrow of an interior mutable value refers to such a temporary - .note = temporaries in constants and statics can have their lifetime extended until the end of the program - .note2 = to avoid accidentally creating global mutable state, such temporaries must be immutable - .help = if you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut` - -const_eval_intern_kind = {$kind -> - [static] static - [static_mut] mutable static - [const] constant - [promoted] promoted - *[other] {""} -} - -const_eval_interrupted = compilation was interrupted - -const_eval_invalid_align_details = - invalid align passed to `{$name}`: {$align} is {$err_kind -> - [not_power_of_two] not a power of 2 - [too_large] too large - *[other] {""} - } - -const_eval_invalid_bool = - interpreting an invalid 8-bit value as a bool: 0x{$value} -const_eval_invalid_char = - interpreting an invalid 32-bit value as a char: 0x{$value} -const_eval_invalid_dealloc = - deallocating {$alloc_id}, which is {$kind -> - [fn] a function - [vtable] a vtable - [static_mem] static memory - *[other] {""} - } - -const_eval_invalid_function_pointer = - using {$pointer} as function pointer but it does not point to a function -const_eval_invalid_meta = - invalid metadata in wide pointer: total size is bigger than largest supported object -const_eval_invalid_meta_slice = - invalid metadata in wide pointer: slice is bigger than largest supported object - -const_eval_invalid_niched_enum_variant_written = - trying to set discriminant of a {$ty} to the niched variant, but the value does not match - -const_eval_invalid_str = - this string is not valid UTF-8: {$err} -const_eval_invalid_tag = - enum value has invalid tag: {$tag} -const_eval_invalid_transmute = - transmuting from {$src_bytes}-byte type to {$dest_bytes}-byte type: `{$src}` -> `{$dest}` - -const_eval_invalid_uninit_bytes = - reading memory at {$alloc}{$access}, but memory is uninitialized at {$uninit}, and this operation requires initialized memory -const_eval_invalid_uninit_bytes_unknown = - using uninitialized data, but this operation requires initialized memory - -const_eval_invalid_vtable_pointer = - using {$pointer} as vtable pointer but it does not point to a vtable - -const_eval_invalid_vtable_trait = - using vtable for `{$vtable_dyn_type}` but `{$expected_dyn_type}` was expected - -const_eval_lazy_lock = - consider wrapping this expression in `std::sync::LazyLock::new(|| ...)` - -const_eval_live_drop = - destructor of `{$dropped_ty}` cannot be evaluated at compile-time - .label = the destructor for this type cannot be evaluated in {const_eval_const_context}s - .dropped_at_label = value is dropped here - -const_eval_long_running = - constant evaluation is taking a long time - .note = this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. - .label = the const evaluator is currently interpreting this expression - .help = the constant being evaluated - -const_eval_memory_exhausted = - tried to allocate more memory than available to compiler - -const_eval_modified_global = - modifying a static's initial value from another static's initializer - -const_eval_mutable_borrow_escaping = - mutable borrows of temporaries that have their lifetime extended until the end of the program are not allowed - .label = this mutable borrow refers to such a temporary - .note = temporaries in constants and statics can have their lifetime extended until the end of the program - .note2 = to avoid accidentally creating global mutable state, such temporaries must be immutable - .help = if you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut` - -const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind} - -const_eval_nested_static_in_thread_local = #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead - -const_eval_non_const_await = - cannot convert `{$ty}` into a future in {const_eval_const_context}s - -const_eval_non_const_closure = - cannot call {$non_or_conditionally}-const closure in {const_eval_const_context}s - -const_eval_non_const_deref_coercion = - cannot perform {$non_or_conditionally}-const deref coercion on `{$ty}` in {const_eval_const_context}s - .note = attempting to deref into `{$target_ty}` - .target_note = deref defined here - -const_eval_non_const_fmt_macro_call = - cannot call {$non_or_conditionally}-const formatting macro in {const_eval_const_context}s - -const_eval_non_const_fn_call = - cannot call {$non_or_conditionally}-const {$def_descr} `{$def_path_str}` in {const_eval_const_context}s - -const_eval_non_const_for_loop_into_iter = - cannot use `for` loop on `{$ty}` in {const_eval_const_context}s - -const_eval_non_const_impl = - impl defined here, but it is not `const` - -const_eval_non_const_intrinsic = - cannot call non-const intrinsic `{$name}` in {const_eval_const_context}s - -const_eval_non_const_match_eq = cannot match on `{$ty}` in {const_eval_const_context}s - .note = `{$ty}` cannot be compared in compile-time, and therefore cannot be used in `match`es - -const_eval_non_const_operator = - cannot call {$non_or_conditionally}-const operator in {const_eval_const_context}s - -const_eval_non_const_question_branch = - `?` is not allowed on `{$ty}` in {const_eval_const_context}s -const_eval_non_const_question_from_residual = - `?` is not allowed on `{$ty}` in {const_eval_const_context}s - -const_eval_non_const_try_block_from_output = - `try` block cannot convert `{$ty}` to the result in {const_eval_const_context}s - -const_eval_not_enough_caller_args = - calling a function with fewer arguments than it requires - -const_eval_offset_from_different_allocations = - `{$name}` called on two different pointers that are not both derived from the same allocation -const_eval_offset_from_out_of_bounds = - `{$name}` called on two different pointers where the memory range between them is not in-bounds of an allocation -const_eval_offset_from_overflow = - `{$name}` called when first pointer is too far ahead of second -const_eval_offset_from_underflow = - `{$name}` called when first pointer is too far before second -const_eval_offset_from_unsigned_overflow = - `ptr_offset_from_unsigned` called when first pointer has smaller {$is_addr -> - [true] address - *[false] offset - } than second: {$a_offset} < {$b_offset} - -const_eval_overflow_arith = - arithmetic overflow in `{$intrinsic}` -const_eval_overflow_shift = - overflowing shift by {$shift_amount} in `{$intrinsic}` - -const_eval_panic = evaluation panicked: {$msg} - -const_eval_panic_non_str = argument to `panic!()` in a const context must have type `&str` - -const_eval_partial_pointer_in_final = encountered partial pointer in final value of {const_eval_intern_kind} - .note = while pointers can be broken apart into individual bytes during const-evaluation, only complete pointers (with all their bytes in the right order) are supported in the final value - -const_eval_partial_pointer_read = - unable to read parts of a pointer from memory at {$ptr} -const_eval_pointer_arithmetic_overflow = - overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize` - -const_eval_pointer_out_of_bounds = - {const_eval_bad_pointer_op_attempting}, but got {$pointer} which {$ptr_offset_is_neg -> - [true] points to before the beginning of the allocation - *[false] {$inbounds_size_is_neg -> - [false] {$alloc_size_minus_ptr_offset -> - [0] is at or beyond the end of the allocation of size {$alloc_size -> - [1] 1 byte - *[x] {$alloc_size} bytes - } - [1] is only 1 byte from the end of the allocation - *[x] is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation - } - *[true] {$ptr_offset_abs -> - [0] is at the beginning of the allocation - *[other] is only {$ptr_offset_abs} bytes from the beginning of the allocation - } - } - } - -const_eval_pointer_use_after_free = - {const_eval_bad_pointer_op}: {$alloc_id} has been freed, so this pointer is dangling -const_eval_ptr_as_bytes_1 = - this code performed an operation that depends on the underlying bytes representing a pointer -const_eval_ptr_as_bytes_2 = - the absolute address of a pointer is not known at compile-time, so such operations are not supported - -const_eval_range = in the range {$lo}..={$hi} -const_eval_range_lower = greater or equal to {$lo} -const_eval_range_singular = equal to {$lo} -const_eval_range_upper = less or equal to {$hi} -const_eval_range_wrapping = less or equal to {$hi}, or greater or equal to {$lo} -const_eval_raw_bytes = the raw bytes of the constant (size: {$size}, align: {$align}) {"{"}{$bytes}{"}"} - -const_eval_raw_ptr_comparison = - pointers cannot be reliably compared during const eval - .note = see issue #53020 for more information - -const_eval_raw_ptr_to_int = - pointers cannot be cast to integers during const eval - .note = at compile-time, pointers do not have an integer value - .note2 = avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior - -const_eval_read_pointer_as_int = - unable to turn pointer into integer -const_eval_realloc_or_alloc_with_offset = - {$kind -> - [dealloc] deallocating - [realloc] reallocating - *[other] {""} - } {$ptr} which does not point to the beginning of an object - -const_eval_recursive_static = encountered static that tried to access itself during initialization - -const_eval_remainder_by_zero = - calculating the remainder with a divisor of zero -const_eval_remainder_overflow = - overflow in signed remainder (dividing MIN by -1) -const_eval_scalar_size_mismatch = - scalar size mismatch: expected {$target_size} bytes but got {$data_size} bytes instead -const_eval_size_overflow = - overflow computing total size of `{$name}` - -const_eval_stack_frame_limit_reached = - reached the configured maximum number of stack frames - -const_eval_thread_local_access = - thread-local statics cannot be accessed at compile-time - -const_eval_thread_local_static = - cannot access thread local static `{$did}` -const_eval_too_generic = - encountered overly generic constant -const_eval_too_many_caller_args = - calling a function with more arguments than it expected - -const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {const_eval_const_context}s - -const_eval_unallowed_heap_allocations = - allocations are not allowed in {const_eval_const_context}s - .label = allocation not allowed in {const_eval_const_context}s - .teach_note = - The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created. - -const_eval_unallowed_inline_asm = - inline assembly is not allowed in {const_eval_const_context}s - -const_eval_unallowed_op_in_const_context = - {$msg} - -const_eval_uninhabited_enum_variant_read = - read discriminant of an uninhabited enum variant -const_eval_uninhabited_enum_variant_written = - writing discriminant of an uninhabited enum variant - -const_eval_unmarked_const_item_exposed = `{$def_path}` cannot be (indirectly) exposed to stable - .help = either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]` -const_eval_unmarked_intrinsic_exposed = intrinsic `{$def_path}` cannot be (indirectly) exposed to stable - .help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_intrinsic_const_stable_indirect]` (but this requires team approval) - -const_eval_unreachable = entering unreachable code -const_eval_unreachable_unwind = - unwinding past a stack frame that does not allow unwinding - -const_eval_unsized_local = unsized locals are not supported -const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn -const_eval_unstable_const_trait = `{$def_path}` is not yet stable as a const trait -const_eval_unstable_in_stable_exposed = - const function that might be (indirectly) exposed to stable cannot use `#[feature({$gate})]` - .is_function_call = mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features - .unstable_sugg = if the {$is_function_call2 -> - [true] caller - *[false] function - } is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]` - -const_eval_unstable_intrinsic = `{$name}` is not yet stable as a const intrinsic -const_eval_unstable_intrinsic_suggestion = add `#![feature({$feature})]` to the crate attributes to enable - -const_eval_unterminated_c_string = - reading a null-terminated string starting at {$pointer} with no null found before end of allocation - -const_eval_unwind_past_top = - unwinding past the topmost frame of the stack - -## The `front_matter`s here refer to either `const_eval_front_matter_invalid_value` or `const_eval_front_matter_invalid_value_with_path`. -## (We'd love to sort this differently to make that more clear but tidy won't let us...) -const_eval_validation_box_to_uninhabited = {$front_matter}: encountered a box pointing to uninhabited type {$ty} - -const_eval_validation_dangling_box_no_provenance = {$front_matter}: encountered a dangling box ({$pointer} has no provenance) -const_eval_validation_dangling_box_out_of_bounds = {$front_matter}: encountered a dangling box (going beyond the bounds of its allocation) -const_eval_validation_dangling_box_use_after_free = {$front_matter}: encountered a dangling box (use-after-free) -const_eval_validation_dangling_ref_no_provenance = {$front_matter}: encountered a dangling reference ({$pointer} has no provenance) -const_eval_validation_dangling_ref_out_of_bounds = {$front_matter}: encountered a dangling reference (going beyond the bounds of its allocation) -const_eval_validation_dangling_ref_use_after_free = {$front_matter}: encountered a dangling reference (use-after-free) - -const_eval_validation_expected_bool = expected a boolean -const_eval_validation_expected_box = expected a box -const_eval_validation_expected_char = expected a unicode scalar value -const_eval_validation_expected_enum_tag = expected a valid enum tag -const_eval_validation_expected_float = expected a floating point number -const_eval_validation_expected_fn_ptr = expected a function pointer -const_eval_validation_expected_init_scalar = expected initialized scalar value -const_eval_validation_expected_int = expected an integer -const_eval_validation_expected_raw_ptr = expected a raw pointer -const_eval_validation_expected_ref = expected a reference -const_eval_validation_expected_str = expected a string - -const_eval_validation_failure = - it is undefined behavior to use this value - -const_eval_validation_failure_note = - the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - -const_eval_validation_front_matter_invalid_value = constructing invalid value -const_eval_validation_front_matter_invalid_value_with_path = constructing invalid value at {$path} - -const_eval_validation_invalid_bool = {$front_matter}: encountered {$value}, but expected a boolean -const_eval_validation_invalid_box_meta = {$front_matter}: encountered invalid box metadata: total size is bigger than largest supported object -const_eval_validation_invalid_box_slice_meta = {$front_matter}: encountered invalid box metadata: slice is bigger than largest supported object -const_eval_validation_invalid_char = {$front_matter}: encountered {$value}, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) - -const_eval_validation_invalid_enum_tag = {$front_matter}: encountered {$value}, but expected a valid enum tag -const_eval_validation_invalid_fn_ptr = {$front_matter}: encountered {$value}, but expected a function pointer -const_eval_validation_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object -const_eval_validation_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object -const_eval_validation_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer -const_eval_validation_invalid_vtable_trait = {$front_matter}: wrong trait in wide pointer vtable: expected `{$expected_dyn_type}`, but encountered `{$vtable_dyn_type}` -const_eval_validation_mutable_ref_to_immutable = {$front_matter}: encountered mutable reference or box pointing to read-only memory -const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!` -const_eval_validation_nonnull_ptr_out_of_range = {$front_matter}: encountered a maybe-null pointer, but expected something that is definitely non-zero -const_eval_validation_null_box = {$front_matter}: encountered a {$maybe -> - [true] maybe-null - *[false] null - } box -const_eval_validation_null_fn_ptr = {$front_matter}: encountered a {$maybe -> - [true] maybe-null - *[false] null - } function pointer -const_eval_validation_null_ref = {$front_matter}: encountered a {$maybe -> - [true] maybe-null - *[false] null - } reference -const_eval_validation_out_of_range = {$front_matter}: encountered {$value}, but expected something {$in_range} -const_eval_validation_partial_pointer = {$front_matter}: encountered a partial pointer or a mix of pointers -const_eval_validation_pointer_as_int = {$front_matter}: encountered a pointer, but {$expected} -const_eval_validation_ptr_out_of_range = {$front_matter}: encountered a pointer with unknown absolute address, but expected something that is definitely {$in_range} -const_eval_validation_ref_to_uninhabited = {$front_matter}: encountered a reference pointing to uninhabited type {$ty} -const_eval_validation_unaligned_box = {$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes}) -const_eval_validation_unaligned_ref = {$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes}) -const_eval_validation_uninhabited_enum_variant = {$front_matter}: encountered an uninhabited enum variant -const_eval_validation_uninhabited_val = {$front_matter}: encountered a value of uninhabited type `{$ty}` -const_eval_validation_uninit = {$front_matter}: encountered uninitialized memory, but {$expected} -const_eval_validation_unsafe_cell = {$front_matter}: encountered `UnsafeCell` in read-only memory - -const_eval_write_through_immutable_pointer = - writing through a pointer that was derived from a shared (immutable) reference - -const_eval_write_to_read_only = - writing to {$allocation} which is read-only diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index a9366bf29fbe..ecf52e4aa605 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -2,7 +2,7 @@ use hir::{ConstContext, LangItem}; use rustc_errors::codes::*; -use rustc_errors::{Applicability, Diag, MultiSpan}; +use rustc_errors::{Applicability, Diag, MultiSpan, inline_fluent}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; @@ -23,7 +23,7 @@ use rustc_trait_selection::traits::SelectionContext; use tracing::debug; use super::ConstCx; -use crate::{errors, fluent_generated}; +use crate::errors; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Status { @@ -181,7 +181,9 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { ); if let ConstContext::Static(_) = ccx.const_kind() { - err.note(fluent_generated::const_eval_lazy_lock); + err.note(inline_fluent!( + "consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`" + )); } err diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 69a8f163ca93..e87d2cbb20de 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -43,21 +43,41 @@ pub enum ConstEvalErrKind { impl MachineStopType for ConstEvalErrKind { fn diagnostic_message(&self) -> DiagMessage { use ConstEvalErrKind::*; + use rustc_errors::inline_fluent; - use crate::fluent_generated::*; match self { - ConstAccessesMutGlobal => const_eval_const_accesses_mut_global, - ModifiedGlobal => const_eval_modified_global, - Panic { .. } => const_eval_panic, - RecursiveStatic => const_eval_recursive_static, - AssertFailure(x) => x.diagnostic_message(), - WriteThroughImmutablePointer => const_eval_write_through_immutable_pointer, - ConstMakeGlobalPtrAlreadyMadeGlobal { .. } => { - const_eval_const_make_global_ptr_already_made_global + ConstAccessesMutGlobal => "constant accesses mutable global memory".into(), + ModifiedGlobal => { + "modifying a static's initial value from another static's initializer".into() + } + Panic { .. } => inline_fluent!("evaluation panicked: {$msg}"), + RecursiveStatic => { + "encountered static that tried to access itself during initialization".into() + } + AssertFailure(x) => x.diagnostic_message(), + WriteThroughImmutablePointer => { + inline_fluent!( + "writing through a pointer that was derived from a shared (immutable) reference" + ) + } + ConstMakeGlobalPtrAlreadyMadeGlobal { .. } => { + inline_fluent!( + "attempting to call `const_make_global` twice on the same allocation {$alloc}" + ) + } + ConstMakeGlobalPtrIsNonHeap(_) => { + inline_fluent!( + "pointer passed to `const_make_global` does not point to a heap allocation: {$ptr}" + ) + } + ConstMakeGlobalWithDanglingPtr(_) => { + inline_fluent!("pointer passed to `const_make_global` is dangling: {$ptr}") + } + ConstMakeGlobalWithOffset(_) => { + inline_fluent!( + "making {$ptr} global which does not point to the beginning of an object" + ) } - ConstMakeGlobalPtrIsNonHeap(_) => const_eval_const_make_global_ptr_is_non_heap, - ConstMakeGlobalWithDanglingPtr(_) => const_eval_const_make_global_with_dangling_ptr, - ConstMakeGlobalWithOffset(_) => const_eval_const_make_global_with_offset, } } fn add_args(self: Box, adder: &mut dyn FnMut(DiagArgName, DiagArgValue)) { diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 5383ab3547af..25da90298791 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -2,7 +2,7 @@ use std::sync::atomic::Ordering::Relaxed; use either::{Left, Right}; use rustc_abi::{self as abi, BackendRepr}; -use rustc_errors::E0080; +use rustc_errors::{E0080, inline_fluent}; use rustc_hir::def::DefKind; use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo, ReportedErrorInfo}; use rustc_middle::mir::{self, ConstAlloc, ConstValue}; @@ -467,7 +467,15 @@ fn report_eval_error<'tcx>( let num_frames = frames.len(); // FIXME(oli-obk): figure out how to use structured diagnostics again. diag.code(E0080); - diag.span_label(span, crate::fluent_generated::const_eval_error); + diag.span_label( + span, + inline_fluent!( + "evaluation of `{$instance}` failed {$num_frames -> + [0] here + *[other] inside this call +}" + ), + ); for frame in frames { diag.subdiagnostic(frame); } @@ -506,8 +514,8 @@ fn report_validation_error<'tcx>( move |diag, span, frames| { // FIXME(oli-obk): figure out how to use structured diagnostics again. diag.code(E0080); - diag.span_label(span, crate::fluent_generated::const_eval_validation_failure); - diag.note(crate::fluent_generated::const_eval_validation_failure_note); + diag.span_label(span, "it is undefined behavior to use this value"); + diag.note("the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior."); for frame in frames { diag.subdiagnostic(frame); } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 719187b99012..da4f97db1c59 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -5,6 +5,7 @@ use std::hash::Hash; use rustc_abi::{Align, Size}; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; +use rustc_errors::inline_fluent; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, CRATE_HIR_ID, LangItem}; use rustc_middle::mir::AssertMessage; @@ -19,7 +20,6 @@ use tracing::debug; use super::error::*; use crate::errors::{LongRunning, LongRunningWarn}; -use crate::fluent_generated as fluent; use crate::interpret::{ self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, RangeSet, Scalar, @@ -489,7 +489,13 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { let align = match Align::from_bytes(align) { Ok(a) => a, Err(err) => throw_ub_custom!( - fluent::const_eval_invalid_align_details, + inline_fluent!( + "invalid align passed to `{$name}`: {$align} is {$err_kind -> + [not_power_of_two] not a power of 2 + [too_large] too large + *[other] {\"\"} +}" + ), name = "const_allocate", err_kind = err.diag_ident(), align = err.align() @@ -513,7 +519,13 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { let align = match Align::from_bytes(align) { Ok(a) => a, Err(err) => throw_ub_custom!( - fluent::const_eval_invalid_align_details, + inline_fluent!( + "invalid align passed to `{$name}`: {$align} is {$err_kind -> + [not_power_of_two] not a power of 2 + [too_large] too large + *[other] {\"\"} +}" + ), name = "const_deallocate", err_kind = err.diag_ident(), align = err.align() diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 50f5448ec20a..39f98b844920 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -5,7 +5,8 @@ use either::Either; use rustc_abi::WrappingRange; use rustc_errors::codes::*; use rustc_errors::{ - Diag, DiagArgValue, DiagMessage, Diagnostic, EmissionGuarantee, Level, MultiSpan, Subdiagnostic, + Diag, DiagArgValue, DiagMessage, Diagnostic, EmissionGuarantee, Level, MultiSpan, + Subdiagnostic, inline_fluent, }; use rustc_hir::ConstContext; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -17,11 +18,18 @@ use rustc_middle::mir::interpret::{ use rustc_middle::ty::{self, Mutability, Ty}; use rustc_span::{Span, Symbol}; -use crate::fluent_generated as fluent; use crate::interpret::InternKind; #[derive(Diagnostic)] -#[diag(const_eval_dangling_ptr_in_final)] +#[diag( + r#"encountered dangling pointer in final value of {$kind -> + [static] static + [static_mut] mutable static + [const] constant + [promoted] promoted + *[other] {""} +}"# +)] pub(crate) struct DanglingPtrInFinal { #[primary_span] pub span: Span, @@ -29,14 +37,24 @@ pub(crate) struct DanglingPtrInFinal { } #[derive(Diagnostic)] -#[diag(const_eval_nested_static_in_thread_local)] +#[diag( + "#[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead" +)] pub(crate) struct NestedStaticInThreadLocal { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(const_eval_mutable_ptr_in_final)] +#[diag( + r#"encountered mutable pointer in final value of {$kind -> + [static] static + [static_mut] mutable static + [const] constant + [promoted] promoted + *[other] {""} +}"# +)] pub(crate) struct MutablePtrInFinal { #[primary_span] pub span: Span, @@ -44,16 +62,28 @@ pub(crate) struct MutablePtrInFinal { } #[derive(Diagnostic)] -#[diag(const_eval_const_heap_ptr_in_final)] -#[note] +#[diag("encountered `const_allocate` pointer in final value that was not made global")] +#[note( + "use `const_make_global` to turn allocated pointers into immutable globals before returning" +)] pub(crate) struct ConstHeapPtrInFinal { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(const_eval_partial_pointer_in_final)] -#[note] +#[diag( + r#"encountered partial pointer in final value of {$kind -> + [static] static + [static_mut] mutable static + [const] constant + [promoted] promoted + *[other] {""} +}"# +)] +#[note( + "while pointers can be broken apart into individual bytes during const-evaluation, only complete pointers (with all their bytes in the right order) are supported in the final value" +)] pub(crate) struct PartialPtrInFinal { #[primary_span] pub span: Span, @@ -61,17 +91,24 @@ pub(crate) struct PartialPtrInFinal { } #[derive(Diagnostic)] -#[diag(const_eval_unstable_in_stable_exposed)] +#[diag( + "const function that might be (indirectly) exposed to stable cannot use `#[feature({$gate})]`" +)] pub(crate) struct UnstableInStableExposed { pub gate: String, #[primary_span] pub span: Span, - #[help(const_eval_is_function_call)] + #[help( + "mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features" + )] pub is_function_call: bool, /// Need to duplicate the field so that fluent also provides it as a variable... pub is_function_call2: bool, #[suggestion( - const_eval_unstable_sugg, + "if the {$is_function_call2 -> + [true] caller + *[false] function +} is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`", code = "#[rustc_const_unstable(feature = \"...\", issue = \"...\")]\n", applicability = "has-placeholders" )] @@ -79,38 +116,47 @@ pub(crate) struct UnstableInStableExposed { } #[derive(Diagnostic)] -#[diag(const_eval_thread_local_access, code = E0625)] +#[diag("thread-local statics cannot be accessed at compile-time", code = E0625)] pub(crate) struct ThreadLocalAccessErr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(const_eval_raw_ptr_to_int)] -#[note] -#[note(const_eval_note2)] +#[diag("pointers cannot be cast to integers during const eval")] +#[note("at compile-time, pointers do not have an integer value")] +#[note( + "avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior" +)] pub(crate) struct RawPtrToIntErr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(const_eval_raw_ptr_comparison)] -#[note] +#[diag("pointers cannot be reliably compared during const eval")] +#[note("see issue #53020 for more information")] pub(crate) struct RawPtrComparisonErr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(const_eval_panic_non_str)] +#[diag("argument to `panic!()` in a const context must have type `&str`")] pub(crate) struct PanicNonStrErr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_fn_pointer_call)] +#[diag( + r#"function pointer calls are not allowed in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"# +)] pub(crate) struct UnallowedFnPointerCall { #[primary_span] pub span: Span, @@ -118,7 +164,7 @@ pub(crate) struct UnallowedFnPointerCall { } #[derive(Diagnostic)] -#[diag(const_eval_unstable_const_fn)] +#[diag("`{$def_path}` is not yet stable as a const fn")] pub(crate) struct UnstableConstFn { #[primary_span] pub span: Span, @@ -126,7 +172,7 @@ pub(crate) struct UnstableConstFn { } #[derive(Diagnostic)] -#[diag(const_eval_unstable_const_trait)] +#[diag("`{$def_path}` is not yet stable as a const trait")] pub(crate) struct UnstableConstTrait { #[primary_span] pub span: Span, @@ -134,14 +180,14 @@ pub(crate) struct UnstableConstTrait { } #[derive(Diagnostic)] -#[diag(const_eval_unstable_intrinsic)] +#[diag("`{$name}` is not yet stable as a const intrinsic")] pub(crate) struct UnstableIntrinsic { #[primary_span] pub span: Span, pub name: Symbol, pub feature: Symbol, #[suggestion( - const_eval_unstable_intrinsic_suggestion, + "add `#![feature({$feature})]` to the crate attributes to enable", code = "#![feature({feature})]\n", applicability = "machine-applicable" )] @@ -149,8 +195,10 @@ pub(crate) struct UnstableIntrinsic { } #[derive(Diagnostic)] -#[diag(const_eval_unmarked_const_item_exposed)] -#[help] +#[diag("`{$def_path}` cannot be (indirectly) exposed to stable")] +#[help( + "either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`" +)] pub(crate) struct UnmarkedConstItemExposed { #[primary_span] pub span: Span, @@ -158,8 +206,10 @@ pub(crate) struct UnmarkedConstItemExposed { } #[derive(Diagnostic)] -#[diag(const_eval_unmarked_intrinsic_exposed)] -#[help] +#[diag("intrinsic `{$def_path}` cannot be (indirectly) exposed to stable")] +#[help( + "mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_intrinsic_const_stable_indirect]` (but this requires team approval)" +)] pub(crate) struct UnmarkedIntrinsicExposed { #[primary_span] pub span: Span, @@ -167,19 +217,31 @@ pub(crate) struct UnmarkedIntrinsicExposed { } #[derive(Diagnostic)] -#[diag(const_eval_mutable_borrow_escaping, code = E0764)] -#[note] -#[note(const_eval_note2)] -#[help] +#[diag("mutable borrows of temporaries that have their lifetime extended until the end of the program are not allowed", code = E0764)] +#[note( + "temporaries in constants and statics can have their lifetime extended until the end of the program" +)] +#[note("to avoid accidentally creating global mutable state, such temporaries must be immutable")] +#[help( + "if you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut`" +)] pub(crate) struct MutableBorrowEscaping { #[primary_span] - #[label] + #[label("this mutable borrow refers to such a temporary")] pub span: Span, pub kind: ConstContext, } #[derive(Diagnostic)] -#[diag(const_eval_non_const_fmt_macro_call, code = E0015)] +#[diag( + r#"cannot call {$non_or_conditionally}-const formatting macro in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, + code = E0015, +)] pub(crate) struct NonConstFmtMacroCall { #[primary_span] pub span: Span, @@ -188,7 +250,12 @@ pub(crate) struct NonConstFmtMacroCall { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_fn_call, code = E0015)] +#[diag(r#"cannot call {$non_or_conditionally}-const {$def_descr} `{$def_path_str}` in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub(crate) struct NonConstFnCall { #[primary_span] pub span: Span, @@ -199,7 +266,14 @@ pub(crate) struct NonConstFnCall { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_intrinsic)] +#[diag( + r#"cannot call non-const intrinsic `{$name}` in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"# +)] pub(crate) struct NonConstIntrinsic { #[primary_span] pub span: Span, @@ -208,7 +282,7 @@ pub(crate) struct NonConstIntrinsic { } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_op_in_const_context)] +#[diag("{$msg}")] pub(crate) struct UnallowedOpInConstContext { #[primary_span] pub span: Span, @@ -216,18 +290,37 @@ pub(crate) struct UnallowedOpInConstContext { } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_heap_allocations, code = E0010)] +#[diag(r#"allocations are not allowed in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0010)] pub(crate) struct UnallowedHeapAllocations { #[primary_span] - #[label] + #[label( + r#"allocation not allowed in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"# + )] pub span: Span, pub kind: ConstContext, - #[note(const_eval_teach_note)] + #[note( + "The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created." + )] pub teach: bool, } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_inline_asm, code = E0015)] +#[diag(r#"inline assembly is not allowed in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub(crate) struct UnallowedInlineAsm { #[primary_span] pub span: Span, @@ -235,39 +328,46 @@ pub(crate) struct UnallowedInlineAsm { } #[derive(Diagnostic)] -#[diag(const_eval_interior_mutable_borrow_escaping, code = E0492)] -#[note] -#[note(const_eval_note2)] -#[help] +#[diag("interior mutable shared borrows of temporaries that have their lifetime extended until the end of the program are not allowed", code = E0492)] +#[note( + "temporaries in constants and statics can have their lifetime extended until the end of the program" +)] +#[note("to avoid accidentally creating global mutable state, such temporaries must be immutable")] +#[help( + "if you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut`" +)] pub(crate) struct InteriorMutableBorrowEscaping { #[primary_span] - #[label] + #[label("this borrow of an interior mutable value refers to such a temporary")] pub span: Span, pub kind: ConstContext, } #[derive(LintDiagnostic)] -#[diag(const_eval_long_running)] -#[note] +#[diag("constant evaluation is taking a long time")] +#[note( + "this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. + If your compilation actually takes a long time, you can safely allow the lint." +)] pub struct LongRunning { - #[help] + #[help("the constant being evaluated")] pub item_span: Span, } #[derive(Diagnostic)] -#[diag(const_eval_long_running)] +#[diag("constant evaluation is taking a long time")] pub struct LongRunningWarn { #[primary_span] - #[label] + #[label("the const evaluator is currently interpreting this expression")] pub span: Span, - #[help] + #[help("the constant being evaluated")] pub item_span: Span, // Used for evading `-Z deduplicate-diagnostics`. pub force_duplicate: usize, } #[derive(Subdiagnostic)] -#[note(const_eval_non_const_impl)] +#[note("impl defined here, but it is not `const`")] pub(crate) struct NonConstImplNote { #[primary_span] pub span: Span, @@ -289,9 +389,21 @@ impl Subdiagnostic for FrameNote { diag.arg("instance", self.instance); let mut span: MultiSpan = self.span.into(); if self.has_label && !self.span.is_dummy() { - span.push_span_label(self.span, fluent::const_eval_frame_note_last); + span.push_span_label(self.span, inline_fluent!("the failure occurred here")); } - let msg = diag.eagerly_translate(fluent::const_eval_frame_note); + let msg = diag.eagerly_translate(inline_fluent!( + r#"{$times -> + [0] {const_eval_frame_note_inner} + *[other] [... {$times} additional calls {const_eval_frame_note_inner} ...] +} + +const_eval_frame_note_inner = inside {$where_ -> + [closure] closure + [instance] `{$instance}` + *[other] {""} +} +"# + )); diag.remove_arg("times"); diag.remove_arg("where_"); diag.remove_arg("instance"); @@ -300,7 +412,7 @@ impl Subdiagnostic for FrameNote { } #[derive(Subdiagnostic)] -#[note(const_eval_raw_bytes)] +#[note(r#"the raw bytes of the constant (size: {$size}, align: {$align}) {"{"}{$bytes}{"}"}"#)] pub struct RawBytesNote { pub size: u64, pub align: u64, @@ -310,8 +422,15 @@ pub struct RawBytesNote { // FIXME(fee1-dead) do not use stringly typed `ConstContext` #[derive(Diagnostic)] -#[diag(const_eval_non_const_match_eq, code = E0015)] -#[note] +#[diag( + r#"cannot match on `{$ty}` in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"# +)] +#[note("`{$ty}` cannot be compared in compile-time, and therefore cannot be used in `match`es")] pub struct NonConstMatchEq<'tcx> { #[primary_span] pub span: Span, @@ -321,7 +440,12 @@ pub struct NonConstMatchEq<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_for_loop_into_iter, code = E0015)] +#[diag(r#"cannot use `for` loop on `{$ty}` in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub struct NonConstForLoopIntoIter<'tcx> { #[primary_span] pub span: Span, @@ -331,7 +455,12 @@ pub struct NonConstForLoopIntoIter<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_question_branch, code = E0015)] +#[diag(r#"`?` is not allowed on `{$ty}` in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub struct NonConstQuestionBranch<'tcx> { #[primary_span] pub span: Span, @@ -341,7 +470,12 @@ pub struct NonConstQuestionBranch<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_question_from_residual, code = E0015)] +#[diag(r#"`?` is not allowed on `{$ty}` in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub struct NonConstQuestionFromResidual<'tcx> { #[primary_span] pub span: Span, @@ -351,7 +485,12 @@ pub struct NonConstQuestionFromResidual<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_try_block_from_output, code = E0015)] +#[diag(r#"`try` block cannot convert `{$ty}` to the result in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub struct NonConstTryBlockFromOutput<'tcx> { #[primary_span] pub span: Span, @@ -361,7 +500,12 @@ pub struct NonConstTryBlockFromOutput<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_await, code = E0015)] +#[diag(r#"cannot convert `{$ty}` into a future in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub struct NonConstAwait<'tcx> { #[primary_span] pub span: Span, @@ -371,7 +515,12 @@ pub struct NonConstAwait<'tcx> { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_closure, code = E0015)] +#[diag(r#"cannot call {$non_or_conditionally}-const closure in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub struct NonConstClosure { #[primary_span] pub span: Span, @@ -383,19 +532,33 @@ pub struct NonConstClosure { #[derive(Subdiagnostic)] pub enum NonConstClosureNote { - #[note(const_eval_closure_fndef_not_const)] + #[note("function defined here, but it is not `const`")] FnDef { #[primary_span] span: Span, }, - #[note(const_eval_fn_ptr_call)] + #[note( + r#"function pointers need an RFC before allowed to be called in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"# + )] FnPtr, - #[note(const_eval_closure_call)] + #[note( + r#"closures need an RFC before allowed to be called in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"# + )] Closure, } #[derive(Subdiagnostic)] -#[multipart_suggestion(const_eval_consider_dereferencing, applicability = "machine-applicable")] +#[multipart_suggestion("consider dereferencing here", applicability = "machine-applicable")] pub struct ConsiderDereferencing { pub deref: String, #[suggestion_part(code = "{deref}")] @@ -405,7 +568,12 @@ pub struct ConsiderDereferencing { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_operator, code = E0015)] +#[diag(r#"cannot call {$non_or_conditionally}-const operator in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] pub struct NonConstOperator { #[primary_span] pub span: Span, @@ -416,28 +584,40 @@ pub struct NonConstOperator { } #[derive(Diagnostic)] -#[diag(const_eval_non_const_deref_coercion, code = E0015)] -#[note] +#[diag(r#"cannot perform {$non_or_conditionally}-const deref coercion on `{$ty}` in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"#, code = E0015)] +#[note("attempting to deref into `{$target_ty}`")] pub struct NonConstDerefCoercion<'tcx> { #[primary_span] pub span: Span, pub ty: Ty<'tcx>, pub kind: ConstContext, pub target_ty: Ty<'tcx>, - #[note(const_eval_target_note)] + #[note("deref defined here")] pub deref_target: Option, pub non_or_conditionally: &'static str, } #[derive(Diagnostic)] -#[diag(const_eval_live_drop, code = E0493)] +#[diag("destructor of `{$dropped_ty}` cannot be evaluated at compile-time", code = E0493)] pub struct LiveDrop<'tcx> { #[primary_span] - #[label] + #[label( + r#"the destructor for this type cannot be evaluated in {$kind -> + [const] constant + [static] static + [const_fn] constant function + *[other] {""} +}s"# + )] pub span: Span, pub kind: ConstContext, pub dropped_ty: Ty<'tcx>, - #[label(const_eval_dropped_at_label)] + #[label("value is dropped here")] pub dropped_at: Span, } @@ -466,51 +646,128 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { fn diagnostic_message(&self) -> DiagMessage { use UndefinedBehaviorInfo::*; - use crate::fluent_generated::*; match self { Ub(msg) => msg.clone().into(), Custom(x) => (x.msg)(), ValidationError(e) => e.diagnostic_message(), - Unreachable => const_eval_unreachable, - BoundsCheckFailed { .. } => const_eval_bounds_check_failed, - DivisionByZero => const_eval_division_by_zero, - RemainderByZero => const_eval_remainder_by_zero, - DivisionOverflow => const_eval_division_overflow, - RemainderOverflow => const_eval_remainder_overflow, - PointerArithOverflow => const_eval_pointer_arithmetic_overflow, - ArithOverflow { .. } => const_eval_overflow_arith, - ShiftOverflow { .. } => const_eval_overflow_shift, - InvalidMeta(InvalidMetaKind::SliceTooBig) => const_eval_invalid_meta_slice, - InvalidMeta(InvalidMetaKind::TooBig) => const_eval_invalid_meta, - UnterminatedCString(_) => const_eval_unterminated_c_string, - PointerUseAfterFree(_, _) => const_eval_pointer_use_after_free, - PointerOutOfBounds { .. } => const_eval_pointer_out_of_bounds, - DanglingIntPointer { addr: 0, .. } => const_eval_dangling_null_pointer, - DanglingIntPointer { .. } => const_eval_dangling_int_pointer, - AlignmentCheckFailed { .. } => const_eval_alignment_check_failed, - WriteToReadOnly(_) => const_eval_write_to_read_only, - DerefFunctionPointer(_) => const_eval_deref_function_pointer, - DerefVTablePointer(_) => const_eval_deref_vtable_pointer, - DerefTypeIdPointer(_) => const_eval_deref_typeid_pointer, - InvalidBool(_) => const_eval_invalid_bool, - InvalidChar(_) => const_eval_invalid_char, - InvalidTag(_) => const_eval_invalid_tag, - InvalidFunctionPointer(_) => const_eval_invalid_function_pointer, - InvalidVTablePointer(_) => const_eval_invalid_vtable_pointer, - InvalidVTableTrait { .. } => const_eval_invalid_vtable_trait, - InvalidStr(_) => const_eval_invalid_str, - InvalidUninitBytes(None) => const_eval_invalid_uninit_bytes_unknown, - InvalidUninitBytes(Some(_)) => const_eval_invalid_uninit_bytes, - DeadLocal => const_eval_dead_local, - ScalarSizeMismatch(_) => const_eval_scalar_size_mismatch, - UninhabitedEnumVariantWritten(_) => const_eval_uninhabited_enum_variant_written, - UninhabitedEnumVariantRead(_) => const_eval_uninhabited_enum_variant_read, - InvalidNichedEnumVariantWritten { .. } => { - const_eval_invalid_niched_enum_variant_written + Unreachable => "entering unreachable code".into(), + BoundsCheckFailed { .. } => inline_fluent!("indexing out of bounds: the len is {$len} but the index is {$index}"), + DivisionByZero => "dividing by zero".into(), + RemainderByZero => "calculating the remainder with a divisor of zero".into(), + DivisionOverflow => "overflow in signed division (dividing MIN by -1)".into(), + RemainderOverflow => "overflow in signed remainder (dividing MIN by -1)".into(), + PointerArithOverflow => "overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`".into(), + ArithOverflow { .. } => inline_fluent!("arithmetic overflow in `{$intrinsic}`"), + ShiftOverflow { .. } => inline_fluent!("overflowing shift by {$shift_amount} in `{$intrinsic}`"), + InvalidMeta(InvalidMetaKind::SliceTooBig) => "invalid metadata in wide pointer: slice is bigger than largest supported object".into(), + InvalidMeta(InvalidMetaKind::TooBig) => "invalid metadata in wide pointer: total size is bigger than largest supported object".into(), + UnterminatedCString(_) => "reading a null-terminated string starting at {$pointer} with no null found before end of allocation".into(), + PointerUseAfterFree(_, _) => inline_fluent!("{$operation -> + [MemoryAccess] memory access failed + [InboundsPointerArithmetic] in-bounds pointer arithmetic failed + *[Dereferenceable] pointer not dereferenceable +}: {$alloc_id} has been freed, so this pointer is dangling"), + PointerOutOfBounds { .. } => inline_fluent!("{$operation -> + [MemoryAccess] memory access failed + [InboundsPointerArithmetic] in-bounds pointer arithmetic failed + *[Dereferenceable] pointer not dereferenceable +}: {$operation -> + [MemoryAccess] attempting to access {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + *[Dereferenceable] pointer must {$inbounds_size -> + [0] point to some allocation + [1] be dereferenceable for 1 byte + *[x] be dereferenceable for {$inbounds_size} bytes + } +}, but got {$pointer} which {$ptr_offset_is_neg -> + [true] points to before the beginning of the allocation + *[false] {$inbounds_size_is_neg -> + [false] {$alloc_size_minus_ptr_offset -> + [0] is at or beyond the end of the allocation of size {$alloc_size -> + [1] 1 byte + *[x] {$alloc_size} bytes } - AbiMismatchArgument { .. } => const_eval_incompatible_arg_types, - AbiMismatchReturn { .. } => const_eval_incompatible_return_types, + [1] is only 1 byte from the end of the allocation + *[x] is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation + } + *[true] {$ptr_offset_abs -> + [0] is at the beginning of the allocation + *[other] is only {$ptr_offset_abs} bytes from the beginning of the allocation + } + } +} +"), + DanglingIntPointer { addr: 0, .. } => inline_fluent!("{$operation -> + [MemoryAccess] memory access failed + [InboundsPointerArithmetic] in-bounds pointer arithmetic failed + *[Dereferenceable] pointer not dereferenceable +}: {$operation -> + [MemoryAccess] attempting to access {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + *[Dereferenceable] pointer must {$inbounds_size -> + [0] point to some allocation + [1] be dereferenceable for 1 byte + *[x] be dereferenceable for {$inbounds_size} bytes + } +}, but got null pointer"), + DanglingIntPointer { .. } => inline_fluent!("{$operation -> + [MemoryAccess] memory access failed + [InboundsPointerArithmetic] in-bounds pointer arithmetic failed + *[Dereferenceable] pointer not dereferenceable +}: {$operation -> + [MemoryAccess] attempting to access {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + *[Dereferenceable] pointer must {$inbounds_size -> + [0] point to some allocation + [1] be dereferenceable for 1 byte + *[x] be dereferenceable for {$inbounds_size} bytes + } +}, but got {$pointer} which is a dangling pointer (it has no provenance)"), + AlignmentCheckFailed { .. } => inline_fluent!("{$msg -> + [AccessedPtr] accessing memory + *[other] accessing memory based on pointer +} with alignment {$has}, but alignment {$required} is required"), + WriteToReadOnly(_) => inline_fluent!("writing to {$allocation} which is read-only"), + DerefFunctionPointer(_) => inline_fluent!("accessing {$allocation} which contains a function"), + DerefVTablePointer(_) => inline_fluent!("accessing {$allocation} which contains a vtable"), + DerefTypeIdPointer(_) => inline_fluent!("accessing {$allocation} which contains a `TypeId`"), + InvalidBool(_) => inline_fluent!("interpreting an invalid 8-bit value as a bool: 0x{$value}"), + InvalidChar(_) => inline_fluent!("interpreting an invalid 32-bit value as a char: 0x{$value}"), + InvalidTag(_) => inline_fluent!("enum value has invalid tag: {$tag}"), + InvalidFunctionPointer(_) => inline_fluent!("using {$pointer} as function pointer but it does not point to a function"), + InvalidVTablePointer(_) => inline_fluent!("using {$pointer} as vtable pointer but it does not point to a vtable"), + InvalidVTableTrait { .. } => inline_fluent!("using vtable for `{$vtable_dyn_type}` but `{$expected_dyn_type}` was expected"), + InvalidStr(_) => inline_fluent!("this string is not valid UTF-8: {$err}"), + InvalidUninitBytes(None) => "using uninitialized data, but this operation requires initialized memory".into(), + InvalidUninitBytes(Some(_)) => inline_fluent!("reading memory at {$alloc}{$access}, but memory is uninitialized at {$uninit}, and this operation requires initialized memory"), + DeadLocal => "accessing a dead local variable".into(), + ScalarSizeMismatch(_) => inline_fluent!("scalar size mismatch: expected {$target_size} bytes but got {$data_size} bytes instead"), + UninhabitedEnumVariantWritten(_) => "writing discriminant of an uninhabited enum variant".into(), + UninhabitedEnumVariantRead(_) => "read discriminant of an uninhabited enum variant".into(), + InvalidNichedEnumVariantWritten { .. } => { + inline_fluent!("trying to set discriminant of a {$ty} to the niched variant, but the value does not match") + } + AbiMismatchArgument { .. } => inline_fluent!("calling a function whose parameter #{$arg_idx} has type {$callee_ty} passing argument of type {$caller_ty}"), + AbiMismatchReturn { .. } => inline_fluent!("calling a function with return type {$callee_ty} passing return place of type {$caller_ty}"), } } @@ -653,92 +910,189 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { fn diagnostic_message(&self) -> DiagMessage { use rustc_middle::mir::interpret::ValidationErrorKind::*; - use crate::fluent_generated::*; match self.kind { PtrToUninhabited { ptr_kind: PointerKind::Box, .. } => { - const_eval_validation_box_to_uninhabited + inline_fluent!( + "{$front_matter}: encountered a box pointing to uninhabited type {$ty}" + ) } PtrToUninhabited { ptr_kind: PointerKind::Ref(_), .. } => { - const_eval_validation_ref_to_uninhabited + inline_fluent!( + "{$front_matter}: encountered a reference pointing to uninhabited type {$ty}" + ) } - PointerAsInt { .. } => const_eval_validation_pointer_as_int, - PartialPointer => const_eval_validation_partial_pointer, - MutableRefToImmutable => const_eval_validation_mutable_ref_to_immutable, - NullFnPtr { .. } => const_eval_validation_null_fn_ptr, - NeverVal => const_eval_validation_never_val, - NonnullPtrMaybeNull { .. } => const_eval_validation_nonnull_ptr_out_of_range, - PtrOutOfRange { .. } => const_eval_validation_ptr_out_of_range, - OutOfRange { .. } => const_eval_validation_out_of_range, - UnsafeCellInImmutable => const_eval_validation_unsafe_cell, - UninhabitedVal { .. } => const_eval_validation_uninhabited_val, - InvalidEnumTag { .. } => const_eval_validation_invalid_enum_tag, - UninhabitedEnumVariant => const_eval_validation_uninhabited_enum_variant, - Uninit { .. } => const_eval_validation_uninit, - InvalidVTablePtr { .. } => const_eval_validation_invalid_vtable_ptr, - InvalidMetaWrongTrait { .. } => const_eval_validation_invalid_vtable_trait, + PointerAsInt { .. } => { + inline_fluent!("{$front_matter}: encountered a pointer, but {$expected}") + } + PartialPointer => inline_fluent!( + "{$front_matter}: encountered a partial pointer or a mix of pointers" + ), + MutableRefToImmutable => { + inline_fluent!( + "{$front_matter}: encountered mutable reference or box pointing to read-only memory" + ) + } + NullFnPtr { .. } => { + inline_fluent!( + "{$front_matter}: encountered a {$maybe -> + [true] maybe-null + *[false] null +} function pointer" + ) + } + NeverVal => { + inline_fluent!("{$front_matter}: encountered a value of the never type `!`") + } + NonnullPtrMaybeNull { .. } => { + inline_fluent!( + "{$front_matter}: encountered a maybe-null pointer, but expected something that is definitely non-zero" + ) + } + PtrOutOfRange { .. } => { + inline_fluent!( + "{$front_matter}: encountered a pointer with unknown absolute address, but expected something that is definitely {$in_range}" + ) + } + OutOfRange { .. } => { + inline_fluent!( + "{$front_matter}: encountered {$value}, but expected something {$in_range}" + ) + } + UnsafeCellInImmutable => { + inline_fluent!("{$front_matter}: encountered `UnsafeCell` in read-only memory") + } + UninhabitedVal { .. } => { + inline_fluent!("{$front_matter}: encountered a value of uninhabited type `{$ty}`") + } + InvalidEnumTag { .. } => { + inline_fluent!( + "{$front_matter}: encountered {$value}, but expected a valid enum tag" + ) + } + UninhabitedEnumVariant => { + inline_fluent!("{$front_matter}: encountered an uninhabited enum variant") + } + Uninit { .. } => { + inline_fluent!("{$front_matter}: encountered uninitialized memory, but {$expected}") + } + InvalidVTablePtr { .. } => { + inline_fluent!( + "{$front_matter}: encountered {$value}, but expected a vtable pointer" + ) + } + InvalidMetaWrongTrait { .. } => { + inline_fluent!( + "{$front_matter}: wrong trait in wide pointer vtable: expected `{$expected_dyn_type}`, but encountered `{$vtable_dyn_type}`" + ) + } InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Box } => { - const_eval_validation_invalid_box_slice_meta + inline_fluent!( + "{$front_matter}: encountered invalid box metadata: slice is bigger than largest supported object" + ) } InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Ref(_) } => { - const_eval_validation_invalid_ref_slice_meta + inline_fluent!( + "{$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object" + ) } InvalidMetaTooLarge { ptr_kind: PointerKind::Box } => { - const_eval_validation_invalid_box_meta + inline_fluent!( + "{$front_matter}: encountered invalid box metadata: total size is bigger than largest supported object" + ) } InvalidMetaTooLarge { ptr_kind: PointerKind::Ref(_) } => { - const_eval_validation_invalid_ref_meta + inline_fluent!( + "{$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object" + ) } UnalignedPtr { ptr_kind: PointerKind::Ref(_), .. } => { - const_eval_validation_unaligned_ref + inline_fluent!( + "{$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes})" + ) + } + UnalignedPtr { ptr_kind: PointerKind::Box, .. } => { + inline_fluent!( + "{$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes})" + ) } - UnalignedPtr { ptr_kind: PointerKind::Box, .. } => const_eval_validation_unaligned_box, - NullPtr { ptr_kind: PointerKind::Box, .. } => const_eval_validation_null_box, - NullPtr { ptr_kind: PointerKind::Ref(_), .. } => const_eval_validation_null_ref, + NullPtr { ptr_kind: PointerKind::Box, .. } => { + inline_fluent!( + "{$front_matter}: encountered a {$maybe -> + [true] maybe-null + *[false] null +} box" + ) + } + NullPtr { ptr_kind: PointerKind::Ref(_), .. } => { + inline_fluent!( + "{$front_matter}: encountered a {$maybe -> + [true] maybe-null + *[false] null +} reference" + ) + } DanglingPtrNoProvenance { ptr_kind: PointerKind::Box, .. } => { - const_eval_validation_dangling_box_no_provenance + inline_fluent!( + "{$front_matter}: encountered a dangling box ({$pointer} has no provenance)" + ) } DanglingPtrNoProvenance { ptr_kind: PointerKind::Ref(_), .. } => { - const_eval_validation_dangling_ref_no_provenance + inline_fluent!( + "{$front_matter}: encountered a dangling reference ({$pointer} has no provenance)" + ) } DanglingPtrOutOfBounds { ptr_kind: PointerKind::Box } => { - const_eval_validation_dangling_box_out_of_bounds + inline_fluent!( + "{$front_matter}: encountered a dangling box (going beyond the bounds of its allocation)" + ) } DanglingPtrOutOfBounds { ptr_kind: PointerKind::Ref(_) } => { - const_eval_validation_dangling_ref_out_of_bounds + inline_fluent!( + "{$front_matter}: encountered a dangling reference (going beyond the bounds of its allocation)" + ) } DanglingPtrUseAfterFree { ptr_kind: PointerKind::Box } => { - const_eval_validation_dangling_box_use_after_free + inline_fluent!("{$front_matter}: encountered a dangling box (use-after-free)") } DanglingPtrUseAfterFree { ptr_kind: PointerKind::Ref(_) } => { - const_eval_validation_dangling_ref_use_after_free + inline_fluent!("{$front_matter}: encountered a dangling reference (use-after-free)") + } + InvalidBool { .. } => { + inline_fluent!("{$front_matter}: encountered {$value}, but expected a boolean") + } + InvalidChar { .. } => { + inline_fluent!( + "{$front_matter}: encountered {$value}, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)" + ) + } + InvalidFnPtr { .. } => { + inline_fluent!( + "{$front_matter}: encountered {$value}, but expected a function pointer" + ) } - InvalidBool { .. } => const_eval_validation_invalid_bool, - InvalidChar { .. } => const_eval_validation_invalid_char, - InvalidFnPtr { .. } => const_eval_validation_invalid_fn_ptr, } } fn add_args(self, err: &mut Diag<'_, G>) { + use rustc_errors::inline_fluent; use rustc_middle::mir::interpret::ValidationErrorKind::*; - use crate::fluent_generated as fluent; - if let PointerAsInt { .. } | PartialPointer = self.kind { - err.help(fluent::const_eval_ptr_as_bytes_1); - err.help(fluent::const_eval_ptr_as_bytes_2); + err.help(inline_fluent!("this code performed an operation that depends on the underlying bytes representing a pointer")); + err.help(inline_fluent!("the absolute address of a pointer is not known at compile-time, so such operations are not supported")); } let message = if let Some(path) = self.path { err.dcx.eagerly_translate_to_string( - fluent::const_eval_validation_front_matter_invalid_value_with_path, + inline_fluent!("constructing invalid value at {$path}"), [("path".into(), DiagArgValue::Str(path.into()))].iter().map(|(a, b)| (a, b)), ) } else { err.dcx.eagerly_translate_to_string( - fluent::const_eval_validation_front_matter_invalid_value, + inline_fluent!("constructing invalid value"), [].into_iter(), ) }; @@ -753,17 +1107,17 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { let WrappingRange { start: lo, end: hi } = r; assert!(hi <= max_hi); let msg = if lo > hi { - fluent::const_eval_range_wrapping + inline_fluent!("less or equal to {$hi}, or greater or equal to {$lo}") } else if lo == hi { - fluent::const_eval_range_singular + inline_fluent!("equal to {$lo}") } else if lo == 0 { assert!(hi < max_hi, "should not be printing if the range covers everything"); - fluent::const_eval_range_upper + inline_fluent!("less or equal to {$hi}") } else if hi == max_hi { assert!(lo > 0, "should not be printing if the range covers everything"); - fluent::const_eval_range_lower + inline_fluent!("greater or equal to {$lo}") } else { - fluent::const_eval_range + inline_fluent!("in the range {$lo}..={$hi}") }; let args = [ @@ -781,17 +1135,17 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { } PointerAsInt { expected } | Uninit { expected } => { let msg = match expected { - ExpectedKind::Reference => fluent::const_eval_validation_expected_ref, - ExpectedKind::Box => fluent::const_eval_validation_expected_box, - ExpectedKind::RawPtr => fluent::const_eval_validation_expected_raw_ptr, - ExpectedKind::InitScalar => fluent::const_eval_validation_expected_init_scalar, - ExpectedKind::Bool => fluent::const_eval_validation_expected_bool, - ExpectedKind::Char => fluent::const_eval_validation_expected_char, - ExpectedKind::Float => fluent::const_eval_validation_expected_float, - ExpectedKind::Int => fluent::const_eval_validation_expected_int, - ExpectedKind::FnPtr => fluent::const_eval_validation_expected_fn_ptr, - ExpectedKind::EnumTag => fluent::const_eval_validation_expected_enum_tag, - ExpectedKind::Str => fluent::const_eval_validation_expected_str, + ExpectedKind::Reference => inline_fluent!("expected a reference"), + ExpectedKind::Box => inline_fluent!("expected a box"), + ExpectedKind::RawPtr => inline_fluent!("expected a raw pointer"), + ExpectedKind::InitScalar => inline_fluent!("expected initialized scalar value"), + ExpectedKind::Bool => inline_fluent!("expected a boolean"), + ExpectedKind::Char => inline_fluent!("expected a unicode scalar value"), + ExpectedKind::Float => inline_fluent!("expected a floating point number"), + ExpectedKind::Int => inline_fluent!("expected an integer"), + ExpectedKind::FnPtr => inline_fluent!("expected a function pointer"), + ExpectedKind::EnumTag => inline_fluent!("expected a valid enum tag"), + ExpectedKind::Str => inline_fluent!("expected a string"), }; let msg = err.dcx.eagerly_translate_to_string(msg, [].into_iter()); err.arg("expected", msg); @@ -838,25 +1192,32 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { impl ReportErrorExt for UnsupportedOpInfo { fn diagnostic_message(&self) -> DiagMessage { - use crate::fluent_generated::*; match self { UnsupportedOpInfo::Unsupported(s) => s.clone().into(), - UnsupportedOpInfo::ExternTypeField => const_eval_extern_type_field, - UnsupportedOpInfo::UnsizedLocal => const_eval_unsized_local, - UnsupportedOpInfo::ReadPartialPointer(_) => const_eval_partial_pointer_read, - UnsupportedOpInfo::ReadPointerAsInt(_) => const_eval_read_pointer_as_int, - UnsupportedOpInfo::ThreadLocalStatic(_) => const_eval_thread_local_static, - UnsupportedOpInfo::ExternStatic(_) => const_eval_extern_static, + UnsupportedOpInfo::ExternTypeField => { + "`extern type` field does not have a known offset".into() + } + UnsupportedOpInfo::UnsizedLocal => "unsized locals are not supported".into(), + UnsupportedOpInfo::ReadPartialPointer(_) => { + inline_fluent!("unable to read parts of a pointer from memory at {$ptr}") + } + UnsupportedOpInfo::ReadPointerAsInt(_) => "unable to turn pointer into integer".into(), + UnsupportedOpInfo::ThreadLocalStatic(_) => { + inline_fluent!("cannot access thread local static `{$did}`") + } + UnsupportedOpInfo::ExternStatic(_) => { + inline_fluent!("cannot access extern static `{$did}`") + } } + .into() } fn add_args(self, diag: &mut Diag<'_, G>) { use UnsupportedOpInfo::*; - use crate::fluent_generated::*; if let ReadPointerAsInt(_) | ReadPartialPointer(_) = self { - diag.help(const_eval_ptr_as_bytes_1); - diag.help(const_eval_ptr_as_bytes_2); + diag.help("this code performed an operation that depends on the underlying bytes representing a pointer"); + diag.help("the absolute address of a pointer is not known at compile-time, so such operations are not supported"); } match self { // `ReadPointerAsInt(Some(info))` is never printed anyway, it only serves as an error to @@ -901,10 +1262,12 @@ impl<'tcx> ReportErrorExt for InterpErrorKind<'tcx> { impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { fn diagnostic_message(&self) -> DiagMessage { - use crate::fluent_generated::*; match self { - InvalidProgramInfo::TooGeneric => const_eval_too_generic, - InvalidProgramInfo::AlreadyReported(_) => const_eval_already_reported, + InvalidProgramInfo::TooGeneric => "encountered overly generic constant".into(), + InvalidProgramInfo::AlreadyReported(_) => { + "an error has already been reported elsewhere (this should not usually be printed)" + .into() + } InvalidProgramInfo::Layout(e) => e.diagnostic_message(), } } @@ -926,13 +1289,19 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { impl ReportErrorExt for ResourceExhaustionInfo { fn diagnostic_message(&self) -> DiagMessage { - use crate::fluent_generated::*; match self { - ResourceExhaustionInfo::StackFrameLimitReached => const_eval_stack_frame_limit_reached, - ResourceExhaustionInfo::MemoryExhausted => const_eval_memory_exhausted, - ResourceExhaustionInfo::AddressSpaceFull => const_eval_address_space_full, - ResourceExhaustionInfo::Interrupted => const_eval_interrupted, + ResourceExhaustionInfo::StackFrameLimitReached => { + "reached the configured maximum number of stack frames" + } + ResourceExhaustionInfo::MemoryExhausted => { + "tried to allocate more memory than available to compiler" + } + ResourceExhaustionInfo::AddressSpaceFull => { + "there are no more free addresses in the address space" + } + ResourceExhaustionInfo::Interrupted => "compilation was interrupted", } + .into() } fn add_args(self, _: &mut Diag<'_, G>) {} } diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 9c8ca44c5e8f..c7ddcaa73157 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -1,10 +1,12 @@ //! Manages calling a concrete function (with known MIR body) with argument passing, //! and returning the return value to the caller. + use std::borrow::Cow; use either::{Left, Right}; use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx}; use rustc_data_structures::assert_matches; +use rustc_errors::inline_fluent; use rustc_hir::def_id::DefId; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, Instance, Ty, VariantDef}; @@ -19,8 +21,8 @@ use super::{ Projectable, Provenance, ReturnAction, ReturnContinuation, Scalar, StackPopInfo, interp_ok, throw_ub, throw_ub_custom, throw_unsup_format, }; +use crate::enter_trace_span; use crate::interpret::EnteredTraceSpan; -use crate::{enter_trace_span, fluent_generated as fluent}; /// An argument passed to a function. #[derive(Clone, Debug)] @@ -292,7 +294,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } // Find next caller arg. let Some((caller_arg, caller_abi)) = caller_args.next() else { - throw_ub_custom!(fluent::const_eval_not_enough_caller_args); + throw_ub_custom!(inline_fluent!( + "calling a function with fewer arguments than it requires" + )); }; assert_eq!(caller_arg.layout().layout, caller_abi.layout.layout); // Sadly we cannot assert that `caller_arg.layout().ty` and `caller_abi.layout.ty` are @@ -359,7 +363,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if caller_fn_abi.conv != callee_fn_abi.conv { throw_ub_custom!( - fluent::const_eval_incompatible_calling_conventions, + rustc_errors::inline_fluent!( + "calling a function with calling convention \"{$callee_conv}\" using calling convention \"{$caller_conv}\"" + ), callee_conv = format!("{}", callee_fn_abi.conv), caller_conv = format!("{}", caller_fn_abi.conv), ) @@ -490,7 +496,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { "mismatch between callee ABI and callee body arguments" ); if caller_args.next().is_some() { - throw_ub_custom!(fluent::const_eval_too_many_caller_args); + throw_ub_custom!(inline_fluent!( + "calling a function with more arguments than it expected" + )); } // Don't forget to check the return type! if !self.check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret)? { @@ -690,7 +698,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let vtable_entries = self.vtable_entries(receiver_trait.principal(), dyn_ty); let Some(ty::VtblEntry::Method(fn_inst)) = vtable_entries.get(idx).copied() else { // FIXME(fee1-dead) these could be variants of the UB info enum instead of this - throw_ub_custom!(fluent::const_eval_dyn_call_not_a_method); + throw_ub_custom!(inline_fluent!( + "`dyn` call trying to call something that is not a method" + )); }; trace!("Virtual call dispatches to {fn_inst:#?}"); // We can also do the lookup based on `def_id` and `dyn_ty`, and check that that @@ -887,7 +897,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } ); if unwinding && self.frame_idx() == 0 { - throw_ub_custom!(fluent::const_eval_unwind_past_top); + throw_ub_custom!(inline_fluent!("unwinding past the topmost frame of the stack")); } // Get out the return value. Must happen *before* the frame is popped as we have to get the diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 43de2e7f078a..44ca20ab4c03 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -2,6 +2,7 @@ use rustc_abi::{FieldIdx, Integer}; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_apfloat::{Float, FloatConvert}; use rustc_data_structures::assert_matches; +use rustc_errors::inline_fluent; use rustc_middle::mir::CastKind; use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; use rustc_middle::ty::adjustment::PointerCoercion; @@ -15,8 +16,8 @@ use super::{ FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy, err_inval, interp_ok, throw_ub, throw_ub_custom, }; +use crate::enter_trace_span; use crate::interpret::Writeable; -use crate::{enter_trace_span, fluent_generated as fluent}; impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub fn cast( @@ -138,7 +139,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { assert_eq!(cast_ty, dest.layout.ty); // we otherwise ignore `cast_ty` enirely... if src.layout.size != dest.layout.size { throw_ub_custom!( - fluent::const_eval_invalid_transmute, + inline_fluent!( + "transmuting from {$src_bytes}-byte type to {$dest_bytes}-byte type: `{$src}` -> `{$dest}`" + ), src_bytes = src.layout.size.bytes(), dest_bytes = dest.layout.size.bytes(), src = src.layout.ty, diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index b72a50a0bfce..8c9a79abe48d 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -1,7 +1,7 @@ use either::{Left, Right}; use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout}; use rustc_data_structures::debug_assert_matches; -use rustc_errors::DiagCtxtHandle; +use rustc_errors::{DiagCtxtHandle, inline_fluent}; use rustc_hir::def_id::DefId; use rustc_hir::limit::Limit; use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo}; @@ -23,7 +23,7 @@ use super::{ MemPlaceMeta, Memory, OpTy, Place, PlaceTy, PointerArithmetic, Projectable, Provenance, err_inval, interp_ok, throw_inval, throw_ub, throw_ub_custom, }; -use crate::{ReportErrorExt, enter_trace_span, fluent_generated as fluent, util}; +use crate::{ReportErrorExt, enter_trace_span, util}; pub struct InterpCx<'tcx, M: Machine<'tcx>> { /// Stores the `Machine` instance. @@ -555,7 +555,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { mir::UnwindAction::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }), mir::UnwindAction::Continue => Right(self.frame_mut().body.span), mir::UnwindAction::Unreachable => { - throw_ub_custom!(fluent::const_eval_unreachable_unwind); + throw_ub_custom!(inline_fluent!( + "unwinding past a stack frame that does not allow unwinding" + )); } mir::UnwindAction::Terminate(reason) => { self.frame_mut().loc = Right(self.frame_mut().body.span); diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index e526f6120689..2ea5e4a25c11 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -7,6 +7,7 @@ mod simd; use rustc_abi::{FIRST_VARIANT, FieldIdx, HasDataLayout, Size, VariantIdx}; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_data_structures::assert_matches; +use rustc_errors::inline_fluent; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, read_target_uint, write_target_uint}; @@ -25,7 +26,6 @@ use super::{ PointerArithmetic, Provenance, Scalar, err_ub_custom, err_unsup_format, interp_ok, throw_inval, throw_ub_custom, throw_ub_format, }; -use crate::fluent_generated as fluent; use crate::interpret::Writeable; #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -438,7 +438,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { _ => { // Not into the same allocation -- this is UB. throw_ub_custom!( - fluent::const_eval_offset_from_different_allocations, + inline_fluent!( + "`{$name}` called on two different pointers that are not both derived from the same allocation" + ), name = intrinsic_name, ); } @@ -459,7 +461,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // a < b if intrinsic_name == sym::ptr_offset_from_unsigned { throw_ub_custom!( - fluent::const_eval_offset_from_unsigned_overflow, + inline_fluent!("`ptr_offset_from_unsigned` called when first pointer has smaller {$is_addr -> + [true] address + *[false] offset +} than second: {$a_offset} < {$b_offset}"), a_offset = a_offset, b_offset = b_offset, is_addr = is_addr, @@ -471,7 +476,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let dist = val.to_target_isize(self)?; if dist >= 0 || i128::from(dist) == self.pointer_size().signed_int_min() { throw_ub_custom!( - fluent::const_eval_offset_from_underflow, + inline_fluent!( + "`{$name}` called when first pointer is too far before second" + ), name = intrinsic_name, ); } @@ -483,7 +490,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // because they were more than isize::MAX apart. if dist < 0 { throw_ub_custom!( - fluent::const_eval_offset_from_overflow, + inline_fluent!( + "`{$name}` called when first pointer is too far ahead of second" + ), name = intrinsic_name, ); } @@ -502,12 +511,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { && a_alloc_id == b_alloc_id { err_ub_custom!( - fluent::const_eval_offset_from_out_of_bounds, + inline_fluent!("`{$name}` called on two different pointers where the memory range between them is not in-bounds of an allocation"), name = intrinsic_name, ) } else { err_ub_custom!( - fluent::const_eval_offset_from_different_allocations, + inline_fluent!("`{$name}` called on two different pointers that are not both derived from the same allocation"), name = intrinsic_name, ) } @@ -522,7 +531,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .map_err_kind(|_| { // Make the error more specific. err_ub_custom!( - fluent::const_eval_offset_from_different_allocations, + inline_fluent!("`{$name}` called on two different pointers that are not both derived from the same allocation"), name = intrinsic_name, ) })?; @@ -752,7 +761,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let op = self.eval_operand(op, None)?; let cond = self.read_scalar(&op)?.to_bool()?; if !cond { - throw_ub_custom!(fluent::const_eval_assume_false); + throw_ub_custom!(inline_fluent!("`assume` called with `false`")); } interp_ok(()) } @@ -782,7 +791,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let bits_out = match name { sym::ctpop => u128::from(bits.count_ones()), sym::ctlz_nonzero | sym::cttz_nonzero if bits == 0 => { - throw_ub_custom!(fluent::const_eval_call_nonzero_intrinsic, name = name,); + throw_ub_custom!(inline_fluent!("`{$name}` called on 0"), name = name,); } sym::ctlz | sym::ctlz_nonzero => u128::from(bits.leading_zeros()) - extra, sym::cttz | sym::cttz_nonzero => u128::from((bits << extra).trailing_zeros()) - extra, @@ -815,7 +824,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // sign does not matter for 0 test, so `to_bits` is fine if rem.to_scalar().to_bits(a.layout.size)? != 0 { throw_ub_custom!( - fluent::const_eval_exact_div_has_remainder, + inline_fluent!("exact_div: {$a} cannot be divided by {$b} without remainder"), a = format!("{a}"), b = format!("{b}") ) @@ -900,7 +909,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let size = self.compute_size_in_bytes(size, count).ok_or_else(|| { err_ub_custom!( - fluent::const_eval_size_overflow, + inline_fluent!("overflow computing total size of `{$name}`"), name = if nonoverlapping { "copy_nonoverlapping" } else { "copy" } ) })?; @@ -963,9 +972,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max), // but no actual allocation can be big enough for the difference to be noticeable. - let len = self - .compute_size_in_bytes(layout.size, count) - .ok_or_else(|| err_ub_custom!(fluent::const_eval_size_overflow, name = name))?; + let len = self.compute_size_in_bytes(layout.size, count).ok_or_else(|| { + err_ub_custom!( + inline_fluent!("overflow computing total size of `{$name}`"), + name = name + ) + })?; let bytes = std::iter::repeat_n(byte, len.bytes_usize()); self.write_bytes_ptr(dst, bytes) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index a6c8b28cce9f..28dae2ef3b8b 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -15,6 +15,7 @@ use rustc_abi::{Align, HasDataLayout, Size}; use rustc_ast::Mutability; use rustc_data_structures::assert_matches; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_errors::inline_fluent; use rustc_middle::mir::display_allocation; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::{bug, throw_ub_format}; @@ -27,7 +28,6 @@ use super::{ err_ub_custom, interp_ok, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format, }; use crate::const_eval::ConstEvalErrKind; -use crate::fluent_generated as fluent; #[derive(Debug, PartialEq, Copy, Clone)] pub enum MemoryKind { @@ -291,7 +291,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr, 0)?; if offset.bytes() != 0 { throw_ub_custom!( - fluent::const_eval_realloc_or_alloc_with_offset, + inline_fluent!( + "{$kind -> + [dealloc] deallocating + [realloc] reallocating + *[other] {\"\"} +} {$ptr} which does not point to the beginning of an object" + ), ptr = format!("{ptr:?}"), kind = "realloc" ); @@ -371,7 +377,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if offset.bytes() != 0 { throw_ub_custom!( - fluent::const_eval_realloc_or_alloc_with_offset, + inline_fluent!( + "{$kind -> + [dealloc] deallocating + [realloc] reallocating + *[other] {\"\"} +} {$ptr} which does not point to the beginning of an object" + ), ptr = format!("{ptr:?}"), kind = "dealloc", ); @@ -382,28 +394,56 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { return Err(match self.tcx.try_get_global_alloc(alloc_id) { Some(GlobalAlloc::Function { .. }) => { err_ub_custom!( - fluent::const_eval_invalid_dealloc, + inline_fluent!( + "deallocating {$alloc_id}, which is {$kind -> + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} +}" + ), alloc_id = alloc_id, kind = "fn", ) } Some(GlobalAlloc::VTable(..)) => { err_ub_custom!( - fluent::const_eval_invalid_dealloc, + inline_fluent!( + "deallocating {$alloc_id}, which is {$kind -> + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} +}" + ), alloc_id = alloc_id, kind = "vtable", ) } Some(GlobalAlloc::TypeId { .. }) => { err_ub_custom!( - fluent::const_eval_invalid_dealloc, + inline_fluent!( + "deallocating {$alloc_id}, which is {$kind -> + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} +}" + ), alloc_id = alloc_id, kind = "typeid", ) } Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => { err_ub_custom!( - fluent::const_eval_invalid_dealloc, + inline_fluent!( + "deallocating {$alloc_id}, which is {$kind -> + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} +}" + ), alloc_id = alloc_id, kind = "static_mem" ) @@ -414,11 +454,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; if alloc.mutability.is_not() { - throw_ub_custom!(fluent::const_eval_dealloc_immutable, alloc = alloc_id,); + throw_ub_custom!( + inline_fluent!("deallocating immutable allocation {$alloc}"), + alloc = alloc_id, + ); } if alloc_kind != kind { throw_ub_custom!( - fluent::const_eval_dealloc_kind_mismatch, + inline_fluent!( + "deallocating {$alloc}, which is {$alloc_kind} memory, using {$kind} deallocation operation" + ), alloc = alloc_id, alloc_kind = format!("{alloc_kind}"), kind = format!("{kind}"), @@ -427,7 +472,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if let Some((size, align)) = old_size_and_align { if size != alloc.size() || align != alloc.align { throw_ub_custom!( - fluent::const_eval_dealloc_incorrect_layout, + inline_fluent!( + "incorrect layout on deallocation: {$alloc} has size {$size} and alignment {$align}, but gave size {$size_found} and alignment {$align_found}" + ), alloc = alloc_id, size = alloc.size().bytes(), align = alloc.align.bytes(), @@ -1546,7 +1593,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if (src_offset <= dest_offset && src_offset + size > dest_offset) || (dest_offset <= src_offset && dest_offset + size > src_offset) { - throw_ub_custom!(fluent::const_eval_copy_nonoverlapping_overlapping); + throw_ub_custom!(inline_fluent!( + "`copy_nonoverlapping` called on overlapping ranges" + )); } } } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 1266e15c682f..cccebded4b0b 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -26,8 +26,6 @@ use rustc_middle::util::Providers; pub use self::errors::ReportErrorExt; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn provide(providers: &mut Providers) { const_eval::provide(&mut providers.queries); providers.queries.tag_for_variant = const_eval::tag_for_variant_provider; diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 72831a8d8ff6..d31d7b55d535 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -113,7 +113,6 @@ pub fn default_translator() -> Translator { pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ // tidy-alphabetical-start - rustc_const_eval::DEFAULT_LOCALE_RESOURCE, rustc_lint::DEFAULT_LOCALE_RESOURCE, rustc_mir_build::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE, diff --git a/tests/ui/consts/const-try-feature-gate.stderr b/tests/ui/consts/const-try-feature-gate.stderr index 62a4a5fba4ff..eb5728aaaa78 100644 --- a/tests/ui/consts/const-try-feature-gate.stderr +++ b/tests/ui/consts/const-try-feature-gate.stderr @@ -30,6 +30,7 @@ LL | Some(())?; = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `FromResidual` is not yet stable as a const trait --> $DIR/const-try-feature-gate.rs:4:5 From 5ea37f7addca91f4034d5c5ace26b3daa27b233a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Fri, 6 Feb 2026 23:45:57 +0100 Subject: [PATCH 633/978] Introduce helper `ty::Generics::has_own_self` --- .../rustc_hir_analysis/src/hir_ty_lowering/generics.rs | 3 +-- compiler/rustc_middle/src/ty/generics.rs | 8 ++++++-- .../src/error_reporting/infer/need_type_info.rs | 2 +- src/librustdoc/clean/utils.rs | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index cbd0bec38d57..ff0a5a8df0fa 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -393,8 +393,7 @@ pub fn check_generic_arg_count_for_call( IsMethodCall::Yes => GenericArgPosition::MethodCall, IsMethodCall::No => GenericArgPosition::Value, }; - let has_self = generics.parent.is_none() && generics.has_self; - check_generic_arg_count(cx, def_id, seg, generics, gen_pos, has_self) + check_generic_arg_count(cx, def_id, seg, generics, gen_pos, generics.has_own_self()) } /// Checks that the correct number of generic arguments have been provided. diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index b6b10e245857..ed587cbc3c28 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -284,7 +284,7 @@ impl<'tcx> Generics { args: &'a [ty::GenericArg<'tcx>], ) -> &'a [ty::GenericArg<'tcx>] { let mut own_params = self.parent_count..self.count(); - if self.has_self && self.parent.is_none() { + if self.has_own_self() { own_params.start = 1; } @@ -316,7 +316,7 @@ impl<'tcx> Generics { args: &'tcx [ty::GenericArg<'tcx>], ) -> &'tcx [ty::GenericArg<'tcx>] { let own = &args[self.parent_count..][..self.own_params.len()]; - if self.has_self && self.parent.is_none() { &own[1..] } else { own } + if self.has_own_self() { &own[1..] } else { own } } /// Returns true if a concrete type is specified after a default type. @@ -350,6 +350,10 @@ impl<'tcx> Generics { pub fn is_own_empty(&'tcx self) -> bool { self.own_params.is_empty() } + + pub fn has_own_self(&'tcx self) -> bool { + self.has_self && self.parent.is_none() + } } /// Bounds on generics. diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index e3c8bfe4a452..f7c6b1722ade 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -1263,7 +1263,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { .iter() .position(|&arg| self.generic_arg_contains_target(arg)) { - if generics.parent.is_none() && generics.has_self { + if generics.has_own_self() { argument_index += 1; } let args = self.tecx.resolve_vars_if_possible(args); diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 9dc4b1ec4e9a..bd83c6ea6b83 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -105,7 +105,7 @@ pub(crate) fn clean_middle_generic_args<'tcx>( // to align the arguments and parameters for the iteration below and to enable us to correctly // instantiate the generic parameter default later. let generics = cx.tcx.generics_of(owner); - let args = if !has_self && generics.parent.is_none() && generics.has_self { + let args = if !has_self && generics.has_own_self() { has_self = true; [cx.tcx.types.trait_object_dummy_self.into()] .into_iter() From 345acb1afda663de14f74dc9b617b91b8e989139 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 6 Feb 2026 22:39:43 +0000 Subject: [PATCH 634/978] ci: Temporarily disable native PPC and s390x jobs There are some permission changes that are causing the runners to fail to launch. Link: https://github.com/IBM/actionspz/issues/75 --- .../compiler-builtins/.github/workflows/main.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/compiler-builtins/.github/workflows/main.yaml b/library/compiler-builtins/.github/workflows/main.yaml index 1572a8ec6cd1..3fed58f2a207 100644 --- a/library/compiler-builtins/.github/workflows/main.yaml +++ b/library/compiler-builtins/.github/workflows/main.yaml @@ -70,14 +70,14 @@ jobs: os: ubuntu-24.04 - target: powerpc64le-unknown-linux-gnu os: ubuntu-24.04 - - target: powerpc64le-unknown-linux-gnu - os: ubuntu-24.04-ppc64le - # FIXME(rust#151807): remove once PPC builds work again. - channel: nightly-2026-01-23 + # - target: powerpc64le-unknown-linux-gnu + # os: ubuntu-24.04-ppc64le + # # FIXME(rust#151807): remove once PPC builds work again. + # channel: nightly-2026-01-23 - target: riscv64gc-unknown-linux-gnu os: ubuntu-24.04 - - target: s390x-unknown-linux-gnu - os: ubuntu-24.04-s390x + # - target: s390x-unknown-linux-gnu + # os: ubuntu-24.04-s390x - target: thumbv6m-none-eabi os: ubuntu-24.04 - target: thumbv7em-none-eabi From a47510aa0f13ec8e76c4c4ca904e96b85cbd5126 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 6 Feb 2026 22:14:58 +0000 Subject: [PATCH 635/978] Allow unstable_name_collisions In recent nightlies we are hitting errors like the following: error: an associated constant with this name may be added to the standard library in the future --> libm/src/math/support/float_traits.rs:248:48 | 248 | const SIGN_MASK: Self::Int = 1 << (Self::BITS - 1); | ^^^^^^^^^^ ... 324 | / float_impl!( 325 | | f32, 326 | | u32, 327 | | i32, ... | 333 | | fmaf32 334 | | ); | |_- in this macro invocation | = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior! = note: for more information, see issue #48919 = note: `-D unstable-name-collisions` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(unstable_name_collisions)]` = note: this error originates in the macro `float_impl` (in Nightly builds, run with -Z macro-backtrace for more info) help: use the fully qualified path to the associated const | 248 - const SIGN_MASK: Self::Int = 1 << (Self::BITS - 1); 248 + const SIGN_MASK: Self::Int = 1 << (::BITS - 1); | help: add `#![feature(float_bits_const)]` to the crate attributes to enable `core::f32::::BITS` --> libm/src/lib.rs:26:1 | 26 + #![feature(float_bits_const)] | Using fully qualified syntax is verbose and `BITS` only exists since recently, so allow this lint instead. --- library/compiler-builtins/compiler-builtins/src/lib.rs | 2 +- library/compiler-builtins/libm-test/src/lib.rs | 1 + library/compiler-builtins/libm/src/lib.rs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/library/compiler-builtins/compiler-builtins/src/lib.rs b/library/compiler-builtins/compiler-builtins/src/lib.rs index a9a9cccfa163..80395a4738eb 100644 --- a/library/compiler-builtins/compiler-builtins/src/lib.rs +++ b/library/compiler-builtins/compiler-builtins/src/lib.rs @@ -11,11 +11,11 @@ #![feature(repr_simd)] #![feature(macro_metavar_expr_concat)] #![feature(rustc_attrs)] -#![feature(float_bits_const)] #![cfg_attr(f16_enabled, feature(f16))] #![cfg_attr(f128_enabled, feature(f128))] #![no_builtins] #![no_std] +#![allow(unstable_name_collisions)] // FIXME(float_bits_const): remove when stable #![allow(unused_features)] #![allow(internal_features)] // `mem::swap` cannot be used because it may generate references to memcpy in unoptimized code. diff --git a/library/compiler-builtins/libm-test/src/lib.rs b/library/compiler-builtins/libm-test/src/lib.rs index accb39654d15..60d96ae9bcee 100644 --- a/library/compiler-builtins/libm-test/src/lib.rs +++ b/library/compiler-builtins/libm-test/src/lib.rs @@ -1,6 +1,7 @@ #![cfg_attr(f16_enabled, feature(f16))] #![cfg_attr(f128_enabled, feature(f128))] #![allow(clippy::unusual_byte_groupings)] // sometimes we group by sign_exp_sig +#![allow(unstable_name_collisions)] // FIXME(float_bits_const): remove when stable pub mod domain; mod f8_impl; diff --git a/library/compiler-builtins/libm/src/lib.rs b/library/compiler-builtins/libm/src/lib.rs index 31b12235314c..85ed5e2c9fc6 100644 --- a/library/compiler-builtins/libm/src/lib.rs +++ b/library/compiler-builtins/libm/src/lib.rs @@ -8,6 +8,7 @@ )] #![cfg_attr(f128_enabled, feature(f128))] #![cfg_attr(f16_enabled, feature(f16))] +#![allow(unstable_name_collisions)] // FIXME(float_bits_const): remove when stable #![allow(clippy::assign_op_pattern)] #![allow(clippy::deprecated_cfg_attr)] #![allow(clippy::eq_op)] From 10f0c2d5790ab7fc9b2b0cb2ca9fd70813a24812 Mon Sep 17 00:00:00 2001 From: Edvin Bryntesson Date: Sun, 11 Jan 2026 01:59:43 +0100 Subject: [PATCH 636/978] Port `#[rustc_symbol_name]` and `#[rustc_def_path]` to attr parser --- .../src/attributes/rustc_internal.rs | 50 +++++++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 2 + .../rustc_hir/src/attrs/data_structures.rs | 6 +++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 2 + compiler/rustc_passes/src/check_attr.rs | 4 +- compiler/rustc_symbol_mangling/src/test.rs | 25 ++++++---- 6 files changed, 77 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index bde4904e9655..3b7d25b43ba2 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -760,3 +760,53 @@ impl NoArgsAttributeParser for RustcEffectiveVisibilityParser { ]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEffectiveVisibility; } + +pub(crate) struct RustcSymbolName; + +impl SingleAttributeParser for RustcSymbolName { + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::ForeignFn), + Allow(Target::ForeignStatic), + Allow(Target::Impl { of_trait: false }), + ]); + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const PATH: &[Symbol] = &[sym::rustc_symbol_name]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; + const TEMPLATE: AttributeTemplate = template!(Word); + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + return None; + } + Some(AttributeKind::RustcSymbolName(cx.attr_span)) + } +} + +pub(crate) struct RustcDefPath; + +impl SingleAttributeParser for RustcDefPath { + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::ForeignFn), + Allow(Target::ForeignStatic), + Allow(Target::Impl { of_trait: false }), + ]); + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const PATH: &[Symbol] = &[sym::rustc_def_path]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; + const TEMPLATE: AttributeTemplate = template!(Word); + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + if let Err(span) = args.no_args() { + cx.expected_no_args(span); + return None; + } + Some(AttributeKind::RustcDefPath(cx.attr_span)) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 9008e9edf965..5b489d306499 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -194,6 +194,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, @@ -204,6 +205,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 426363dcd725..fa781a74c9e2 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1081,6 +1081,9 @@ pub enum AttributeKind { /// Represents `#[rustc_deallocator]` RustcDeallocator, + /// Represents `#[rustc_def_path]` + RustcDefPath(Span), + /// Represents `#[rustc_deny_explicit_impl]`. RustcDenyExplicitImpl(Span), @@ -1218,6 +1221,9 @@ pub enum AttributeKind { /// Represents `#[rustc_std_internal_symbol]`. RustcStdInternalSymbol(Span), + /// Represents `#[rustc_symbol_name]` + RustcSymbolName(Span), + /// Represents `#[rustc_then_this_would_need]` RustcThenThisWouldNeed(Span, ThinVec), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index eb1e35ed9b25..14b54c129d3e 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -105,6 +105,7 @@ impl AttributeKind { RustcConstStability { .. } => Yes, RustcConstStabilityIndirect => No, RustcDeallocator => No, + RustcDefPath(..) => No, RustcDenyExplicitImpl(..) => No, RustcDummy => No, RustcDumpDefParents => No, @@ -149,6 +150,7 @@ impl AttributeKind { RustcSkipDuringMethodDispatch { .. } => No, RustcSpecializationTrait(..) => No, RustcStdInternalSymbol(..) => No, + RustcSymbolName(..) => Yes, RustcThenThisWouldNeed(..) => No, RustcUnsafeSpecializationMarker(..) => No, RustcVariance => No, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c207d7455f74..680a93908354 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -300,6 +300,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcConfusables { .. } | AttributeKind::RustcConstStabilityIndirect | AttributeKind::RustcDeallocator + | AttributeKind::RustcDefPath(..) | AttributeKind::RustcDenyExplicitImpl(..) | AttributeKind::RustcDummy | AttributeKind::RustcDumpDefParents @@ -340,6 +341,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcSkipDuringMethodDispatch { .. } | AttributeKind::RustcSpecializationTrait(..) | AttributeKind::RustcStdInternalSymbol (..) + | AttributeKind::RustcSymbolName(..) | AttributeKind::RustcThenThisWouldNeed(..) | AttributeKind::RustcUnsafeSpecializationMarker(..) | AttributeKind::RustcVariance @@ -403,10 +405,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_strict_coherence | sym::rustc_mir | sym::rustc_outlives - | sym::rustc_symbol_name | sym::rustc_evaluate_where_clauses | sym::rustc_delayed_bug_from_inside_query - | sym::rustc_def_path | sym::rustc_partition_reused | sym::rustc_partition_codegened | sym::rustc_expected_cgu_reuse diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index 50935e7caf33..8f842e030011 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -4,16 +4,14 @@ //! def-path. This is used for unit testing the code that generates //! paths etc in all kinds of annoying scenarios. +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::LocalDefId; +use rustc_hir::find_attr; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{GenericArgs, Instance, TyCtxt}; -use rustc_span::{Symbol, sym}; use crate::errors::{Kind, TestOutput}; -const SYMBOL_NAME: Symbol = sym::rustc_symbol_name; -const DEF_PATH: Symbol = sym::rustc_def_path; - pub fn report_symbol_names(tcx: TyCtxt<'_>) { // if the `rustc_attrs` feature is not enabled, then the // attributes we are interested in cannot be present anyway, so @@ -54,7 +52,11 @@ impl SymbolNamesTest<'_> { // The formatting of `tag({})` is chosen so that tests can elect // to test the entirety of the string, if they choose, or else just // some subset. - for attr in tcx.get_attrs(def_id, SYMBOL_NAME) { + + if let Some(attr_span) = find_attr!( + tcx.get_all_attrs(def_id), + AttributeKind::RustcSymbolName(span) => span + ) { let def_id = def_id.to_def_id(); let instance = Instance::new_raw( def_id, @@ -62,27 +64,30 @@ impl SymbolNamesTest<'_> { ); let mangled = tcx.symbol_name(instance); tcx.dcx().emit_err(TestOutput { - span: attr.span(), + span: *attr_span, kind: Kind::SymbolName, content: format!("{mangled}"), }); if let Ok(demangling) = rustc_demangle::try_demangle(mangled.name) { tcx.dcx().emit_err(TestOutput { - span: attr.span(), + span: *attr_span, kind: Kind::Demangling, content: format!("{demangling}"), }); tcx.dcx().emit_err(TestOutput { - span: attr.span(), + span: *attr_span, kind: Kind::DemanglingAlt, content: format!("{demangling:#}"), }); } } - for attr in tcx.get_attrs(def_id, DEF_PATH) { + if let Some(attr_span) = find_attr!( + tcx.get_all_attrs(def_id), + AttributeKind::RustcDefPath(span) => span + ) { tcx.dcx().emit_err(TestOutput { - span: attr.span(), + span: *attr_span, kind: Kind::DefPath, content: with_no_trimmed_paths!(tcx.def_path_str(def_id)), }); From 8aea4b17751d19abbef91c72aa59c25671711acb Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 9 Dec 2025 19:34:29 +0100 Subject: [PATCH 637/978] add `unreachable_cfg_select_predicates` lint This is emitted on branches of a `cfg_select!` that are statically known to be unreachable. --- .../src/attributes/cfg_select.rs | 25 +++++++++++ .../rustc_builtin_macros/src/cfg_select.rs | 18 +------- compiler/rustc_builtin_macros/src/errors.rs | 11 ----- compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_lint/messages.ftl | 4 ++ compiler/rustc_lint/src/early/diagnostics.rs | 4 ++ compiler/rustc_lint/src/lib.rs | 3 ++ compiler/rustc_lint/src/lints.rs | 10 +++++ compiler/rustc_lint_defs/src/builtin.rs | 29 ++++++++++++ compiler/rustc_lint_defs/src/lib.rs | 4 ++ .../feature-gates/feature-gate-cfg-select.rs | 11 +++++ .../feature-gate-cfg-select.stderr | 25 +++++++++++ tests/ui/macros/cfg_select.rs | 3 +- tests/ui/macros/cfg_select.stderr | 44 +++++++++++-------- 14 files changed, 146 insertions(+), 47 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-cfg-select.rs create mode 100644 tests/ui/feature-gates/feature-gate-cfg-select.stderr diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs index 4005ad2cba11..f978d7af67c4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -7,6 +7,8 @@ use rustc_hir::{AttrPath, Target}; use rustc_parse::exp; use rustc_parse::parser::{Parser, Recovery}; use rustc_session::Session; +use rustc_session::lint::BuiltinLintDiag; +use rustc_session::lint::builtin::UNREACHABLE_CFG_SELECT_PREDICATES; use rustc_span::{ErrorGuaranteed, Span, sym}; use crate::parser::MetaItemOrLitParser; @@ -17,6 +19,15 @@ pub enum CfgSelectPredicate { Wildcard(Token), } +impl CfgSelectPredicate { + fn span(&self) -> Span { + match self { + CfgSelectPredicate::Cfg(cfg_entry) => cfg_entry.span(), + CfgSelectPredicate::Wildcard(token) => token.span, + } + } +} + #[derive(Default)] pub struct CfgSelectBranches { /// All the conditional branches. @@ -115,5 +126,19 @@ pub fn parse_cfg_select( } } + if let Some((underscore, _, _)) = branches.wildcard + && features.map_or(false, |f| f.enabled(rustc_span::sym::cfg_select)) + { + for (predicate, _, _) in &branches.unreachable { + let span = predicate.span(); + p.psess.buffer_lint( + UNREACHABLE_CFG_SELECT_PREDICATES, + span, + lint_node_id, + BuiltinLintDiag::UnreachableCfg { span, wildcard_span: underscore.span }, + ); + } + } + Ok(branches) } diff --git a/compiler/rustc_builtin_macros/src/cfg_select.rs b/compiler/rustc_builtin_macros/src/cfg_select.rs index f11190b28105..35098722a910 100644 --- a/compiler/rustc_builtin_macros/src/cfg_select.rs +++ b/compiler/rustc_builtin_macros/src/cfg_select.rs @@ -1,14 +1,12 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::{Expr, ast}; use rustc_attr_parsing as attr; -use rustc_attr_parsing::{ - CfgSelectBranches, CfgSelectPredicate, EvalConfigResult, parse_cfg_select, -}; +use rustc_attr_parsing::{CfgSelectBranches, EvalConfigResult, parse_cfg_select}; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult}; use rustc_span::{Ident, Span, sym}; use smallvec::SmallVec; -use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable}; +use crate::errors::CfgSelectNoMatches; /// This intermediate structure is used to emit parse errors for the branches that are not chosen. /// The `MacResult` instance below parses all branches, emitting any errors it encounters, but only @@ -75,18 +73,6 @@ pub(super) fn expand_cfg_select<'cx>( ecx.current_expansion.lint_node_id, ) { Ok(mut branches) => { - if let Some((underscore, _, _)) = branches.wildcard { - // Warn for every unreachable predicate. We store the fully parsed branch for rustfmt. - for (predicate, _, _) in &branches.unreachable { - let span = match predicate { - CfgSelectPredicate::Wildcard(underscore) => underscore.span, - CfgSelectPredicate::Cfg(cfg) => cfg.span(), - }; - let err = CfgSelectUnreachable { span, wildcard_span: underscore.span }; - ecx.dcx().emit_warn(err); - } - } - if let Some((selected_tts, selected_span)) = branches.pop_first_match(|cfg| { matches!(attr::eval_config_entry(&ecx.sess, cfg), EvalConfigResult::True) }) { diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index d3f7e1c5d8e3..43bade3c43ac 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1086,17 +1086,6 @@ pub(crate) struct CfgSelectNoMatches { pub span: Span, } -#[derive(Diagnostic)] -#[diag("unreachable predicate")] -pub(crate) struct CfgSelectUnreachable { - #[primary_span] - #[label("this predicate is never reached")] - pub span: Span, - - #[label("always matches")] - pub wildcard_span: Span, -} - #[derive(Diagnostic)] #[diag("`#[eii_declaration(...)]` is only valid on macros")] pub(crate) struct EiiExternTargetExpectedMacro { diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index c99af9658cde..6bdf9f04405f 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -392,6 +392,8 @@ declare_features! ( (unstable, cfg_sanitize, "1.41.0", Some(39699)), /// Allows `cfg(sanitizer_cfi_generalize_pointers)` and `cfg(sanitizer_cfi_normalize_integers)`. (unstable, cfg_sanitizer_cfi, "1.77.0", Some(89653)), + /// Provides a native way to easily manage multiple conditional flags without having to rewrite each clause multiple times. + (unstable, cfg_select, "CURRENT_RUSTC_VERSION", Some(115585)), /// Allows `cfg(target(abi = "..."))`. (unstable, cfg_target_compact, "1.63.0", Some(96901)), /// Allows `cfg(target_has_atomic_load_store = "...")`. diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 2f5b7ed26952..2699889c3730 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -998,6 +998,10 @@ lint_unpredictable_fn_pointer_comparisons = function pointer comparisons do not lint_unqualified_local_imports = `use` of a local item without leading `self::`, `super::`, or `crate::` +lint_unreachable_cfg_select_predicate = unreachable configuration predicate + .label = always matches + .label2 = this configuration predicate is never reached + lint_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe .label = usage of unsafe attribute lint_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)` diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index c0ab0d1f0040..b93453d29bea 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -293,6 +293,10 @@ pub fn decorate_builtin_lint( } .decorate_lint(diag); } + BuiltinLintDiag::UnreachableCfg { span, wildcard_span } => { + lints::UnreachableCfgSelectPredicate { span, wildcard_span }.decorate_lint(diag); + } + BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => { lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag) } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 80b32645a895..ea31a6373cbc 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -297,6 +297,9 @@ fn register_builtins(store: &mut LintStore) { UNUSED_ASSIGNMENTS, DEAD_CODE, UNUSED_MUT, + // FIXME: add this lint when it becomes stable, + // see https://github.com/rust-lang/rust/issues/115585. + // UNREACHABLE_CFG_SELECT_PREDICATES, UNREACHABLE_CODE, UNREACHABLE_PATTERNS, UNUSED_MUST_USE, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 1a87cc013e79..210bcddcca22 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3340,3 +3340,13 @@ pub(crate) struct UnknownCrateTypesSuggestion { pub span: Span, pub snippet: Symbol, } + +#[derive(LintDiagnostic)] +#[diag(lint_unreachable_cfg_select_predicate)] +pub(crate) struct UnreachableCfgSelectPredicate { + #[label(lint_label2)] + pub span: Span, + + #[label] + pub wildcard_span: Span, +} diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index f4e6e93356c7..488e3a70b669 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -123,6 +123,7 @@ declare_lint_pass! { UNKNOWN_LINTS, UNNAMEABLE_TEST_ITEMS, UNNAMEABLE_TYPES, + UNREACHABLE_CFG_SELECT_PREDICATES, UNREACHABLE_CODE, UNREACHABLE_PATTERNS, UNSAFE_ATTR_OUTSIDE_UNSAFE, @@ -855,6 +856,34 @@ declare_lint! { "detects unreachable patterns" } +declare_lint! { + /// The `unreachable_cfg_select_predicates` lint detects unreachable configuration + /// predicates in the `cfg_select!` macro. + /// + /// ### Example + /// + /// ```rust + /// #![feature(cfg_select)] + /// cfg_select! { + /// _ => (), + /// windows => (), + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// This usually indicates a mistake in how the predicates are specified or + /// ordered. In this example, the `_` predicate will always match, so the + /// `windows` is impossible to reach. Remember, arms match in order, you + /// probably wanted to put the `windows` case above the `_` case. + pub UNREACHABLE_CFG_SELECT_PREDICATES, + Warn, + "detects unreachable configuration predicates in the cfg_select macro", + @feature_gate = cfg_select; +} + declare_lint! { /// The `overlapping_range_endpoints` lint detects `match` arms that have [range patterns] that /// overlap on their endpoints. diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index b3e5b93cf2fc..76126c96b72a 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -748,6 +748,10 @@ pub enum BuiltinLintDiag { }, UnusedVisibility(Span), AttributeLint(AttributeLintKind), + UnreachableCfg { + span: Span, + wildcard_span: Span, + }, } #[derive(Debug, HashStable_Generic)] diff --git a/tests/ui/feature-gates/feature-gate-cfg-select.rs b/tests/ui/feature-gates/feature-gate-cfg-select.rs new file mode 100644 index 000000000000..0963ed001508 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-select.rs @@ -0,0 +1,11 @@ +#![warn(unreachable_cfg_select_predicates)] +//~^ WARN unknown lint: `unreachable_cfg_select_predicates` + +cfg_select! { + //~^ ERROR use of unstable library feature `cfg_select` + _ => {} + // With the feature enabled, this branch would trip the unreachable_cfg_select_predicate lint. + true => {} +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-cfg-select.stderr b/tests/ui/feature-gates/feature-gate-cfg-select.stderr new file mode 100644 index 000000000000..0fdce4975164 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-select.stderr @@ -0,0 +1,25 @@ +error[E0658]: use of unstable library feature `cfg_select` + --> $DIR/feature-gate-cfg-select.rs:4:1 + | +LL | cfg_select! { + | ^^^^^^^^^^ + | + = note: see issue #115585 for more information + = help: add `#![feature(cfg_select)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +warning: unknown lint: `unreachable_cfg_select_predicates` + --> $DIR/feature-gate-cfg-select.rs:1:9 + | +LL | #![warn(unreachable_cfg_select_predicates)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the `unreachable_cfg_select_predicates` lint is unstable + = note: see issue #115585 for more information + = help: add `#![feature(cfg_select)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: `#[warn(unknown_lints)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs index 2369158ba82a..ecdeb006edf5 100644 --- a/tests/ui/macros/cfg_select.rs +++ b/tests/ui/macros/cfg_select.rs @@ -1,5 +1,6 @@ #![feature(cfg_select)] #![crate_type = "lib"] +#![warn(unreachable_cfg_select_predicates)] // Unused warnings are disabled by default in UI tests. fn print() { println!(cfg_select! { @@ -133,7 +134,7 @@ extern "C" { cfg_select! { _ => {} true => {} - //~^ WARN unreachable predicate + //~^ WARN unreachable configuration predicate } cfg_select! { diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index ffd8540425ab..7ef4ec06d93b 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -1,13 +1,5 @@ -warning: unreachable predicate - --> $DIR/cfg_select.rs:135:5 - | -LL | _ => {} - | - always matches -LL | true => {} - | ^^^^ this predicate is never reached - error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:139:1 + --> $DIR/cfg_select.rs:140:1 | LL | / cfg_select! { LL | | @@ -16,55 +8,69 @@ LL | | } | |_^ error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:144:1 + --> $DIR/cfg_select.rs:145:1 | LL | cfg_select! {} | ^^^^^^^^^^^^^^ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `=>` - --> $DIR/cfg_select.rs:148:5 + --> $DIR/cfg_select.rs:149:5 | LL | => {} | ^^ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression - --> $DIR/cfg_select.rs:153:5 + --> $DIR/cfg_select.rs:154:5 | LL | () => {} | ^^ expressions are not allowed here error[E0539]: malformed `cfg_select` macro input - --> $DIR/cfg_select.rs:158:5 + --> $DIR/cfg_select.rs:159:5 | LL | "str" => {} | ^^^^^ expected a valid identifier here error[E0539]: malformed `cfg_select` macro input - --> $DIR/cfg_select.rs:163:5 + --> $DIR/cfg_select.rs:164:5 | LL | a::b => {} | ^^^^ expected a valid identifier here error[E0537]: invalid predicate `a` - --> $DIR/cfg_select.rs:168:5 + --> $DIR/cfg_select.rs:169:5 | LL | a() => {} | ^^^ error: expected one of `(`, `::`, `=>`, or `=`, found `+` - --> $DIR/cfg_select.rs:173:7 + --> $DIR/cfg_select.rs:174:7 | LL | a + 1 => {} | ^ expected one of `(`, `::`, `=>`, or `=` error: expected one of `(`, `::`, `=>`, or `=`, found `!` - --> $DIR/cfg_select.rs:179:8 + --> $DIR/cfg_select.rs:180:8 | LL | cfg!() => {} | ^ expected one of `(`, `::`, `=>`, or `=` +warning: unreachable configuration predicate + --> $DIR/cfg_select.rs:136:5 + | +LL | _ => {} + | - always matches +LL | true => {} + | ^^^^ this configuration predicate is never reached + | +note: the lint level is defined here + --> $DIR/cfg_select.rs:3:9 + | +LL | #![warn(unreachable_cfg_select_predicates)] // Unused warnings are disabled by default in UI tests. + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + warning: unexpected `cfg` condition name: `a` - --> $DIR/cfg_select.rs:173:5 + --> $DIR/cfg_select.rs:174:5 | LL | a + 1 => {} | ^ help: found config with similar value: `target_feature = "a"` @@ -75,7 +81,7 @@ LL | a + 1 => {} = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `cfg` - --> $DIR/cfg_select.rs:179:5 + --> $DIR/cfg_select.rs:180:5 | LL | cfg!() => {} | ^^^ From a6bd7cc54e193021a3401a627ce573e2a265d11c Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 6 Feb 2026 19:48:33 +0100 Subject: [PATCH 638/978] make the lint more sophisticated --- Cargo.lock | 1 + compiler/rustc_attr_parsing/Cargo.toml | 1 + .../src/attributes/cfg_select.rs | 107 ++++++++++++++++-- compiler/rustc_lint/messages.ftl | 3 + compiler/rustc_lint/src/early/diagnostics.rs | 10 +- compiler/rustc_lint/src/lints.rs | 7 ++ compiler/rustc_lint_defs/src/lib.rs | 2 +- tests/ui/check-cfg/cfg-select.rs | 4 +- tests/ui/macros/cfg_select.rs | 69 +++++++---- tests/ui/macros/cfg_select.stderr | 44 +++++-- 10 files changed, 194 insertions(+), 54 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9ea22911d515..2a4db6d4de4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3539,6 +3539,7 @@ dependencies = [ "rustc_abi", "rustc_ast", "rustc_ast_pretty", + "rustc_data_structures", "rustc_errors", "rustc_feature", "rustc_hir", diff --git a/compiler/rustc_attr_parsing/Cargo.toml b/compiler/rustc_attr_parsing/Cargo.toml index 411f3f5ccbd1..0a11a2da0dcf 100644 --- a/compiler/rustc_attr_parsing/Cargo.toml +++ b/compiler/rustc_attr_parsing/Cargo.toml @@ -8,6 +8,7 @@ edition = "2024" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } +rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs index f978d7af67c4..b6cb5b4504ee 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -1,6 +1,7 @@ use rustc_ast::token::Token; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{AttrStyle, NodeId, token}; +use rustc_data_structures::fx::FxHashMap; use rustc_feature::{AttributeTemplate, Features}; use rustc_hir::attrs::CfgEntry; use rustc_hir::{AttrPath, Target}; @@ -9,11 +10,12 @@ use rustc_parse::parser::{Parser, Recovery}; use rustc_session::Session; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::UNREACHABLE_CFG_SELECT_PREDICATES; -use rustc_span::{ErrorGuaranteed, Span, sym}; +use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; use crate::parser::MetaItemOrLitParser; use crate::{AttributeParser, ParsedDescription, ShouldEmit, parse_cfg_entry}; +#[derive(Clone)] pub enum CfgSelectPredicate { Cfg(CfgEntry), Wildcard(Token), @@ -126,19 +128,102 @@ pub fn parse_cfg_select( } } - if let Some((underscore, _, _)) = branches.wildcard - && features.map_or(false, |f| f.enabled(rustc_span::sym::cfg_select)) + if let Some(features) = features + && features.enabled(sym::cfg_select) { - for (predicate, _, _) in &branches.unreachable { - let span = predicate.span(); - p.psess.buffer_lint( - UNREACHABLE_CFG_SELECT_PREDICATES, - span, - lint_node_id, - BuiltinLintDiag::UnreachableCfg { span, wildcard_span: underscore.span }, + let it = branches + .reachable + .iter() + .map(|(entry, _, _)| CfgSelectPredicate::Cfg(entry.clone())) + .chain(branches.wildcard.as_ref().map(|(t, _, _)| CfgSelectPredicate::Wildcard(*t))) + .chain( + branches.unreachable.iter().map(|(entry, _, _)| CfgSelectPredicate::clone(entry)), ); - } + + lint_unreachable(p, it, lint_node_id); } Ok(branches) } + +fn lint_unreachable( + p: &mut Parser<'_>, + predicates: impl Iterator, + lint_node_id: NodeId, +) { + // Symbols that have a known value. + let mut known = FxHashMap::::default(); + let mut wildcard_span = None; + let mut it = predicates; + + let branch_is_unreachable = |predicate: CfgSelectPredicate, wildcard_span| { + let span = predicate.span(); + p.psess.buffer_lint( + UNREACHABLE_CFG_SELECT_PREDICATES, + span, + lint_node_id, + BuiltinLintDiag::UnreachableCfg { span, wildcard_span }, + ); + }; + + for predicate in &mut it { + let CfgSelectPredicate::Cfg(ref cfg_entry) = predicate else { + wildcard_span = Some(predicate.span()); + break; + }; + + match cfg_entry { + CfgEntry::Bool(true, _) => { + wildcard_span = Some(predicate.span()); + break; + } + CfgEntry::Bool(false, _) => continue, + CfgEntry::NameValue { name, value, .. } => match value { + None => { + // `name` will be false in all subsequent branches. + let current = known.insert(*name, false); + + match current { + None => continue, + Some(false) => { + branch_is_unreachable(predicate, None); + break; + } + Some(true) => { + // this branch will be taken, so all subsequent branches are unreachable. + break; + } + } + } + Some(_) => { /* for now we don't bother solving these */ } + }, + CfgEntry::Not(inner, _) => match &**inner { + CfgEntry::NameValue { name, value: None, .. } => { + // `name` will be true in all subsequent branches. + let current = known.insert(*name, true); + + match current { + None => continue, + Some(true) => { + branch_is_unreachable(predicate, None); + break; + } + Some(false) => { + // this branch will be taken, so all subsequent branches are unreachable. + break; + } + } + } + _ => { /* for now we don't bother solving these */ } + }, + CfgEntry::All(_, _) | CfgEntry::Any(_, _) => { + /* for now we don't bother solving these */ + } + CfgEntry::Version(..) => { /* don't bother solving these */ } + } + } + + for predicate in it { + branch_is_unreachable(predicate, wildcard_span) + } +} diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 2699889c3730..ff771532ae49 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -999,6 +999,9 @@ lint_unpredictable_fn_pointer_comparisons = function pointer comparisons do not lint_unqualified_local_imports = `use` of a local item without leading `self::`, `super::`, or `crate::` lint_unreachable_cfg_select_predicate = unreachable configuration predicate + .label = this configuration predicate is never reached + +lint_unreachable_cfg_select_predicate_wildcard = unreachable configuration predicate .label = always matches .label2 = this configuration predicate is never reached diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index b93453d29bea..7681eedc75ed 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -293,9 +293,13 @@ pub fn decorate_builtin_lint( } .decorate_lint(diag); } - BuiltinLintDiag::UnreachableCfg { span, wildcard_span } => { - lints::UnreachableCfgSelectPredicate { span, wildcard_span }.decorate_lint(diag); - } + BuiltinLintDiag::UnreachableCfg { span, wildcard_span } => match wildcard_span { + Some(wildcard_span) => { + lints::UnreachableCfgSelectPredicateWildcard { span, wildcard_span } + .decorate_lint(diag) + } + None => lints::UnreachableCfgSelectPredicate { span }.decorate_lint(diag), + }, BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => { lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 210bcddcca22..bdc171f11e3b 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3344,6 +3344,13 @@ pub(crate) struct UnknownCrateTypesSuggestion { #[derive(LintDiagnostic)] #[diag(lint_unreachable_cfg_select_predicate)] pub(crate) struct UnreachableCfgSelectPredicate { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_unreachable_cfg_select_predicate_wildcard)] +pub(crate) struct UnreachableCfgSelectPredicateWildcard { #[label(lint_label2)] pub span: Span, diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 76126c96b72a..0c454ec60f4a 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -750,7 +750,7 @@ pub enum BuiltinLintDiag { AttributeLint(AttributeLintKind), UnreachableCfg { span: Span, - wildcard_span: Span, + wildcard_span: Option, }, } diff --git a/tests/ui/check-cfg/cfg-select.rs b/tests/ui/check-cfg/cfg-select.rs index 39703489818d..ffa5e40bff08 100644 --- a/tests/ui/check-cfg/cfg-select.rs +++ b/tests/ui/check-cfg/cfg-select.rs @@ -4,7 +4,7 @@ #![crate_type = "lib"] cfg_select! { - true => {} + false => {} invalid_cfg1 => {} //~^ WARN unexpected `cfg` condition name _ => {} @@ -13,6 +13,6 @@ cfg_select! { cfg_select! { invalid_cfg2 => {} //~^ WARN unexpected `cfg` condition name - true => {} + false => {} _ => {} } diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs index ecdeb006edf5..09d2c116a86d 100644 --- a/tests/ui/macros/cfg_select.rs +++ b/tests/ui/macros/cfg_select.rs @@ -24,40 +24,40 @@ fn arm_rhs_expr_1() -> i32 { fn arm_rhs_expr_2() -> i32 { cfg_select! { - true => 1, - false => 2 + false => 2, + true => 1 } } fn arm_rhs_expr_3() -> i32 { cfg_select! { - true => 1, - false => 2, - true => { 42 } - false => -1 as i32, - true => 2 + 2, - false => "", - true => if true { 42 } else { 84 } - false => if true { 42 } else { 84 }, - true => return 42, - false => loop {} - true => (1, 2), - false => (1, 2,), - true => todo!(), - false => println!("hello"), + any(true) => 1, + any(false) => 2, + any(true) => { 42 } + any(false) => -1 as i32, + any(true) => 2 + 2, + any(false) => "", + any(true) => if true { 42 } else { 84 } + any(false) => if true { 42 } else { 84 }, + any(true) => return 42, + any(false) => loop {} + any(true) => (1, 2), + any(false) => (1, 2,), + any(true) => todo!(), + any(false) => println!("hello"), } } fn expand_to_statements() -> i32 { cfg_select! { - true => { - let a = 1; - a + 1 - } false => { let b = 2; b + 1 } + true => { + let a = 1; + a + 1 + } } } @@ -77,7 +77,7 @@ fn expand_to_pattern(x: Option) -> bool { } cfg_select! { - true => { + false => { fn foo() {} } _ => { @@ -89,7 +89,7 @@ struct S; impl S { cfg_select! { - true => { + false => { fn foo() {} } _ => { @@ -100,7 +100,7 @@ impl S { trait T { cfg_select! { - true => { + false => { fn a(); } _ => { @@ -111,7 +111,7 @@ trait T { impl T for S { cfg_select! { - true => { + false => { fn a() {} } _ => { @@ -122,7 +122,7 @@ impl T for S { extern "C" { cfg_select! { - true => { + false => { fn puts(s: *const i8) -> i32; } _ => { @@ -137,6 +137,25 @@ cfg_select! { //~^ WARN unreachable configuration predicate } +cfg_select! { + true => {} + _ => {} + //~^ WARN unreachable configuration predicate +} + +cfg_select! { + unix => {} + not(unix) => {} + _ => {} + //~^ WARN unreachable configuration predicate +} + +cfg_select! { + unix => {} + unix => {} + //~^ WARN unreachable configuration predicate +} + cfg_select! { //~^ ERROR none of the predicates in this `cfg_select` evaluated to true false => {} diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index 7ef4ec06d93b..be238e0a65e5 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -1,5 +1,5 @@ error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:140:1 + --> $DIR/cfg_select.rs:159:1 | LL | / cfg_select! { LL | | @@ -8,49 +8,49 @@ LL | | } | |_^ error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:145:1 + --> $DIR/cfg_select.rs:164:1 | LL | cfg_select! {} | ^^^^^^^^^^^^^^ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `=>` - --> $DIR/cfg_select.rs:149:5 + --> $DIR/cfg_select.rs:168:5 | LL | => {} | ^^ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression - --> $DIR/cfg_select.rs:154:5 + --> $DIR/cfg_select.rs:173:5 | LL | () => {} | ^^ expressions are not allowed here error[E0539]: malformed `cfg_select` macro input - --> $DIR/cfg_select.rs:159:5 + --> $DIR/cfg_select.rs:178:5 | LL | "str" => {} | ^^^^^ expected a valid identifier here error[E0539]: malformed `cfg_select` macro input - --> $DIR/cfg_select.rs:164:5 + --> $DIR/cfg_select.rs:183:5 | LL | a::b => {} | ^^^^ expected a valid identifier here error[E0537]: invalid predicate `a` - --> $DIR/cfg_select.rs:169:5 + --> $DIR/cfg_select.rs:188:5 | LL | a() => {} | ^^^ error: expected one of `(`, `::`, `=>`, or `=`, found `+` - --> $DIR/cfg_select.rs:174:7 + --> $DIR/cfg_select.rs:193:7 | LL | a + 1 => {} | ^ expected one of `(`, `::`, `=>`, or `=` error: expected one of `(`, `::`, `=>`, or `=`, found `!` - --> $DIR/cfg_select.rs:180:8 + --> $DIR/cfg_select.rs:199:8 | LL | cfg!() => {} | ^ expected one of `(`, `::`, `=>`, or `=` @@ -69,8 +69,28 @@ note: the lint level is defined here LL | #![warn(unreachable_cfg_select_predicates)] // Unused warnings are disabled by default in UI tests. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: unreachable configuration predicate + --> $DIR/cfg_select.rs:142:5 + | +LL | true => {} + | ---- always matches +LL | _ => {} + | ^ this configuration predicate is never reached + +warning: unreachable configuration predicate + --> $DIR/cfg_select.rs:149:5 + | +LL | _ => {} + | ^ this configuration predicate is never reached + +warning: unreachable configuration predicate + --> $DIR/cfg_select.rs:155:5 + | +LL | unix => {} + | ^^^^ this configuration predicate is never reached + warning: unexpected `cfg` condition name: `a` - --> $DIR/cfg_select.rs:174:5 + --> $DIR/cfg_select.rs:193:5 | LL | a + 1 => {} | ^ help: found config with similar value: `target_feature = "a"` @@ -81,7 +101,7 @@ LL | a + 1 => {} = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `cfg` - --> $DIR/cfg_select.rs:180:5 + --> $DIR/cfg_select.rs:199:5 | LL | cfg!() => {} | ^^^ @@ -89,7 +109,7 @@ LL | cfg!() => {} = help: to expect this configuration use `--check-cfg=cfg(cfg)` = note: see for more information about checking conditional configuration -error: aborting due to 9 previous errors; 3 warnings emitted +error: aborting due to 9 previous errors; 6 warnings emitted Some errors have detailed explanations: E0537, E0539. For more information about an error, try `rustc --explain E0537`. From b29a9b6920d89b61319544ac0fafe796fff88d2d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 7 Feb 2026 14:06:46 +1100 Subject: [PATCH 639/978] Move `rustc_query_system::cache` to `rustc_middle::traits`. --- .../src => rustc_middle/src/traits}/cache.rs | 0 compiler/rustc_middle/src/traits/mod.rs | 1 + compiler/rustc_middle/src/traits/select.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_query_system/src/lib.rs | 1 - 5 files changed, 3 insertions(+), 3 deletions(-) rename compiler/{rustc_query_system/src => rustc_middle/src/traits}/cache.rs (100%) diff --git a/compiler/rustc_query_system/src/cache.rs b/compiler/rustc_middle/src/traits/cache.rs similarity index 100% rename from compiler/rustc_query_system/src/cache.rs rename to compiler/rustc_middle/src/traits/cache.rs diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 3a1682614cbf..75323bf5c8cc 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -2,6 +2,7 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html +pub mod cache; pub mod query; pub mod select; pub mod solve; diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 3861efd36428..f151a6e4567e 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -5,12 +5,12 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, TypeVisitable}; -use rustc_query_system::cache::Cache; use rustc_type_ir::solve::AliasBoundKind; use self::EvaluationResult::*; use super::{SelectionError, SelectionResult}; use crate::ty; +use crate::traits::cache::Cache; pub type SelectionCache<'tcx, ENV> = Cache<(ENV, ty::TraitPredicate<'tcx>), SelectionResult<'tcx, SelectionCandidate<'tcx>>>; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 41e1388e3146..b283c08b90de 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -40,7 +40,6 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::limit::Limit; use rustc_hir::{self as hir, HirId, Node, TraitCandidate, find_attr}; use rustc_index::IndexVec; -use rustc_query_system::cache::WithDepNode; use rustc_query_system::dep_graph::DepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; @@ -71,6 +70,7 @@ use crate::query::plumbing::QuerySystem; use crate::query::{IntoQueryParam, LocalCrate, Providers, TyCtxtAt}; use crate::thir::Thir; use crate::traits; +use crate::traits::cache::WithDepNode; use crate::traits::solve::{ self, CanonicalInput, ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, QueryResult, inspect, diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index 61edf397886b..b61b9b71b528 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -5,7 +5,6 @@ #![feature(min_specialization)] // tidy-alphabetical-end -pub mod cache; pub mod dep_graph; mod error; pub mod ich; From b49ab57d6b0f0aefe71a0ef4aa57043d975f7341 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 7 Feb 2026 14:14:16 +1100 Subject: [PATCH 640/978] Rename `Cache` as `WithDepNodeCache`. Because `Cache` is unhelpfully vague. --- compiler/rustc_middle/src/traits/cache.rs | 8 ++++---- compiler/rustc_middle/src/traits/select.rs | 11 +++++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_middle/src/traits/cache.rs b/compiler/rustc_middle/src/traits/cache.rs index 4217d0a49b91..ed41a69f9714 100644 --- a/compiler/rustc_middle/src/traits/cache.rs +++ b/compiler/rustc_middle/src/traits/cache.rs @@ -7,23 +7,23 @@ use rustc_data_structures::sync::Lock; use crate::dep_graph::{DepContext, DepNodeIndex}; -pub struct Cache { +pub struct WithDepNodeCache { hashmap: Lock>>, } -impl Clone for Cache { +impl Clone for WithDepNodeCache { fn clone(&self) -> Self { Self { hashmap: Lock::new(self.hashmap.borrow().clone()) } } } -impl Default for Cache { +impl Default for WithDepNodeCache { fn default() -> Self { Self { hashmap: Default::default() } } } -impl Cache { +impl WithDepNodeCache { pub fn get(&self, key: &Key, tcx: Tcx) -> Option { Some(self.hashmap.borrow().get(key)?.get(tcx)) } diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index f151a6e4567e..3a32029c60bd 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -9,13 +9,16 @@ use rustc_type_ir::solve::AliasBoundKind; use self::EvaluationResult::*; use super::{SelectionError, SelectionResult}; +use crate::traits::cache::WithDepNodeCache; use crate::ty; -use crate::traits::cache::Cache; -pub type SelectionCache<'tcx, ENV> = - Cache<(ENV, ty::TraitPredicate<'tcx>), SelectionResult<'tcx, SelectionCandidate<'tcx>>>; +pub type SelectionCache<'tcx, ENV> = WithDepNodeCache< + (ENV, ty::TraitPredicate<'tcx>), + SelectionResult<'tcx, SelectionCandidate<'tcx>>, +>; -pub type EvaluationCache<'tcx, ENV> = Cache<(ENV, ty::PolyTraitPredicate<'tcx>), EvaluationResult>; +pub type EvaluationCache<'tcx, ENV> = + WithDepNodeCache<(ENV, ty::PolyTraitPredicate<'tcx>), EvaluationResult>; /// The selection process begins by considering all impls, where /// clauses, and so forth that might resolve an obligation. Sometimes From d2020fbf7c5ac729e28993a10d12ade7d0604ff5 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Tue, 30 Dec 2025 13:43:43 -0700 Subject: [PATCH 641/978] stabilize new inclusive range type and iter stabilizes `core::range::RangeInclusive` and `core::range::RangeInclusiveIter` and the `core::range` module --- library/core/src/index.rs | 4 +- library/core/src/lib.rs | 2 +- library/core/src/random.rs | 2 +- library/core/src/range.rs | 58 +++++++++++++---------- library/core/src/range/iter.rs | 15 +++--- library/core/src/slice/index.rs | 4 +- library/core/src/str/traits.rs | 2 +- tests/ui/new-range/disabled.rs | 9 ++-- tests/ui/new-range/enabled.rs | 9 ++-- tests/ui/range/new_range_stability.rs | 28 +++++++++++ tests/ui/range/new_range_stability.stderr | 53 +++++++++++++++++++++ 11 files changed, 140 insertions(+), 46 deletions(-) create mode 100644 tests/ui/range/new_range_stability.rs create mode 100644 tests/ui/range/new_range_stability.stderr diff --git a/library/core/src/index.rs b/library/core/src/index.rs index 3baefdf10cec..70372163c6e1 100644 --- a/library/core/src/index.rs +++ b/library/core/src/index.rs @@ -315,7 +315,7 @@ unsafe impl SliceIndex<[T]> for Clamp> { } #[unstable(feature = "sliceindex_wrappers", issue = "146179")] -unsafe impl SliceIndex<[T]> for Clamp> { +unsafe impl SliceIndex<[T]> for Clamp> { type Output = [T]; fn get(self, slice: &[T]) -> Option<&Self::Output> { @@ -408,7 +408,7 @@ unsafe impl SliceIndex<[T]> for Clamp> { } #[unstable(feature = "sliceindex_wrappers", issue = "146179")] -unsafe impl SliceIndex<[T]> for Clamp { +unsafe impl SliceIndex<[T]> for Clamp { type Output = [T]; fn get(self, slice: &[T]) -> Option<&Self::Output> { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 432ca50b3361..17cf6b3714f5 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -324,7 +324,7 @@ pub mod pat; pub mod pin; #[unstable(feature = "random", issue = "130703")] pub mod random; -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] pub mod range; pub mod result; pub mod sync; diff --git a/library/core/src/random.rs b/library/core/src/random.rs index 8a51fb289d8f..06f4f30efe2b 100644 --- a/library/core/src/random.rs +++ b/library/core/src/random.rs @@ -1,6 +1,6 @@ //! Random value generation. -use crate::range::RangeFull; +use crate::ops::RangeFull; /// A source of randomness. #[unstable(feature = "random", issue = "130703")] diff --git a/library/core/src/range.rs b/library/core/src/range.rs index 4b87d426bda7..fe488355ad15 100644 --- a/library/core/src/range.rs +++ b/library/core/src/range.rs @@ -24,14 +24,26 @@ mod iter; #[unstable(feature = "new_range_api", issue = "125687")] pub mod legacy; -use Bound::{Excluded, Included, Unbounded}; #[doc(inline)] -pub use iter::{RangeFromIter, RangeInclusiveIter, RangeIter}; +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] +pub use iter::RangeInclusiveIter; +#[doc(inline)] +#[unstable(feature = "new_range_api", issue = "125687")] +pub use iter::{RangeFromIter, RangeIter}; -#[doc(inline)] -pub use crate::iter::Step; -#[doc(inline)] -pub use crate::ops::{Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo}; +// FIXME(#125687): re-exports temporarily removed +// Because re-exports of stable items (Bound, RangeBounds, RangeFull, RangeTo) +// can't be made unstable. +// +// #[doc(inline)] +// #[unstable(feature = "new_range_api", issue = "125687")] +// pub use crate::iter::Step; +// #[doc(inline)] +// #[unstable(feature = "new_range_api", issue = "125687")] +// pub use crate::ops::{Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo}; +use crate::iter::Step; +use crate::ops::Bound::{self, Excluded, Included, Unbounded}; +use crate::ops::{IntoBounds, RangeBounds}; /// A (half-open) range bounded inclusively below and exclusively above /// (`start..end` in a future edition). @@ -226,7 +238,6 @@ impl const From> for Range { /// The `start..=last` syntax is a `RangeInclusive`: /// /// ``` -/// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// /// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, last: 5 }); @@ -234,17 +245,17 @@ impl const From> for Range { /// ``` #[lang = "RangeInclusiveCopy"] #[derive(Clone, Copy, PartialEq, Eq, Hash)] -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] pub struct RangeInclusive { /// The lower bound of the range (inclusive). - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] pub start: Idx, /// The upper bound of the range (inclusive). - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] pub last: Idx, } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] impl fmt::Debug for RangeInclusive { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { self.start.fmt(fmt)?; @@ -260,7 +271,6 @@ impl> RangeInclusive { /// # Examples /// /// ``` - /// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// /// assert!(!RangeInclusive::from(3..=5).contains(&2)); @@ -278,7 +288,7 @@ impl> RangeInclusive { /// assert!(!RangeInclusive::from(f32::NAN..=1.0).contains(&1.0)); /// ``` #[inline] - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_range", issue = "none")] pub const fn contains(&self, item: &U) -> bool where @@ -293,7 +303,6 @@ impl> RangeInclusive { /// # Examples /// /// ``` - /// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// /// assert!(!RangeInclusive::from(3..=5).is_empty()); @@ -304,14 +313,13 @@ impl> RangeInclusive { /// The range is empty if either side is incomparable: /// /// ``` - /// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// /// assert!(!RangeInclusive::from(3.0..=5.0).is_empty()); /// assert!( RangeInclusive::from(3.0..=f32::NAN).is_empty()); /// assert!( RangeInclusive::from(f32::NAN..=5.0).is_empty()); /// ``` - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[inline] #[rustc_const_unstable(feature = "const_range", issue = "none")] pub const fn is_empty(&self) -> bool @@ -330,7 +338,6 @@ impl RangeInclusive { /// # Examples /// /// ``` - /// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// /// let mut i = RangeInclusive::from(3..=8).iter().map(|n| n*n); @@ -338,7 +345,7 @@ impl RangeInclusive { /// assert_eq!(i.next(), Some(16)); /// assert_eq!(i.next(), Some(25)); /// ``` - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn iter(&self) -> RangeInclusiveIter { self.clone().into_iter() @@ -354,7 +361,7 @@ impl RangeInclusive { } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_range", issue = "none")] impl const RangeBounds for RangeInclusive { fn start_bound(&self) -> Bound<&T> { @@ -371,7 +378,7 @@ impl const RangeBounds for RangeInclusive { /// If you need to use this implementation where `T` is unsized, /// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], /// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`. -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_range", issue = "none")] impl const RangeBounds for RangeInclusive<&T> { fn start_bound(&self) -> Bound<&T> { @@ -382,8 +389,8 @@ impl const RangeBounds for RangeInclusive<&T> { } } -// #[unstable(feature = "range_into_bounds", issue = "136903")] -#[unstable(feature = "new_range_api", issue = "125687")] +// #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] +#[unstable(feature = "range_into_bounds", issue = "136903")] #[rustc_const_unstable(feature = "const_range", issue = "none")] impl const IntoBounds for RangeInclusive { fn into_bounds(self) -> (Bound, Bound) { @@ -391,7 +398,7 @@ impl const IntoBounds for RangeInclusive { } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] impl const From> for legacy::RangeInclusive { #[inline] @@ -399,7 +406,7 @@ impl const From> for legacy::RangeInclusive { Self::new(value.start, value.last) } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] impl const From> for RangeInclusive { #[inline] @@ -650,12 +657,13 @@ impl> RangeToInclusive { } } +#[unstable(feature = "new_range_api", issue = "125687")] impl From> for RangeToInclusive { fn from(value: legacy::RangeToInclusive) -> Self { Self { last: value.end } } } - +#[unstable(feature = "new_range_api", issue = "125687")] impl From> for legacy::RangeToInclusive { fn from(value: RangeToInclusive) -> Self { Self { end: value.last } diff --git a/library/core/src/range/iter.rs b/library/core/src/range/iter.rs index 6fe5d9b34361..e722b9fa33c5 100644 --- a/library/core/src/range/iter.rs +++ b/library/core/src/range/iter.rs @@ -11,6 +11,7 @@ use crate::{intrinsics, mem}; pub struct RangeIter(legacy::Range); impl RangeIter { + #[unstable(feature = "new_range_api", issue = "125687")] /// Returns the remainder of the range being iterated over. pub fn remainder(self) -> Range { Range { start: self.0.start, end: self.0.end } @@ -152,7 +153,7 @@ impl IntoIterator for Range { } /// By-value [`RangeInclusive`] iterator. -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[derive(Debug, Clone)] pub struct RangeInclusiveIter(legacy::RangeInclusive); @@ -160,6 +161,7 @@ impl RangeInclusiveIter { /// Returns the remainder of the range being iterated over. /// /// If the iterator is exhausted or empty, returns `None`. + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] pub fn remainder(self) -> Option> { if self.0.is_empty() { return None; @@ -169,7 +171,7 @@ impl RangeInclusiveIter { } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] impl Iterator for RangeInclusiveIter { type Item = A; @@ -225,7 +227,7 @@ impl Iterator for RangeInclusiveIter { } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] impl DoubleEndedIterator for RangeInclusiveIter { #[inline] fn next_back(&mut self) -> Option { @@ -246,10 +248,10 @@ impl DoubleEndedIterator for RangeInclusiveIter { #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for RangeInclusiveIter {} -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] impl FusedIterator for RangeInclusiveIter {} -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] impl IntoIterator for RangeInclusive { type Item = A; type IntoIter = RangeInclusiveIter; @@ -276,7 +278,7 @@ macro_rules! range_exact_iter_impl { macro_rules! range_incl_exact_iter_impl { ($($t:ty)*) => ($( - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] impl ExactSizeIterator for RangeInclusiveIter<$t> { } )*) } @@ -305,6 +307,7 @@ impl RangeFromIter { /// Returns the remainder of the range being iterated over. #[inline] #[rustc_inherit_overflow_checks] + #[unstable(feature = "new_range_api", issue = "125687")] pub fn remainder(self) -> RangeFrom { if intrinsics::overflow_checks() { if !self.first { diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 59802989c18f..31d9931e474a 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -127,7 +127,7 @@ mod private_slice_index { #[unstable(feature = "new_range_api", issue = "125687")] impl Sealed for range::Range {} - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] impl Sealed for range::RangeInclusive {} #[unstable(feature = "new_range_api", issue = "125687")] impl Sealed for range::RangeToInclusive {} @@ -724,7 +724,7 @@ unsafe impl const SliceIndex<[T]> for ops::RangeInclusive { } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_index", issue = "143775")] unsafe impl const SliceIndex<[T]> for range::RangeInclusive { type Output = [T]; diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index a7cc943994c5..b63fe96ea99d 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -672,7 +672,7 @@ unsafe impl const SliceIndex for ops::RangeInclusive { } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_index", issue = "143775")] unsafe impl const SliceIndex for range::RangeInclusive { type Output = str; diff --git a/tests/ui/new-range/disabled.rs b/tests/ui/new-range/disabled.rs index 6ba29f5ca9a2..ab6fbd3276b3 100644 --- a/tests/ui/new-range/disabled.rs +++ b/tests/ui/new-range/disabled.rs @@ -4,11 +4,12 @@ fn main() { // Unchanged - let a: core::range::RangeFull = ..; - let b: core::range::RangeTo = ..2; + let a: core::ops::RangeFull = ..; + let b: core::ops::RangeTo = ..2; - let _: core::ops::RangeFull = a; - let _: core::ops::RangeTo = b; + // FIXME(#125687): re-exports temporarily removed + // let _: core::range::RangeFull = a; + // let _: core::range::RangeTo = b; // Changed let a: core::range::legacy::RangeFrom = 1..; diff --git a/tests/ui/new-range/enabled.rs b/tests/ui/new-range/enabled.rs index 140e3b648709..b49681eaacde 100644 --- a/tests/ui/new-range/enabled.rs +++ b/tests/ui/new-range/enabled.rs @@ -5,11 +5,12 @@ fn main() { // Unchanged - let a: core::range::RangeFull = ..; - let b: core::range::RangeTo = ..2; + let a: core::ops::RangeFull = ..; + let b: core::ops::RangeTo = ..2; - let _: core::ops::RangeFull = a; - let _: core::ops::RangeTo = b; + // FIXME(#125687): re-exports temporarily removed + // let _: core::range::RangeFull = a; + // let _: core::range::RangeTo = b; // Changed let a: core::range::RangeFrom = 1..; diff --git a/tests/ui/range/new_range_stability.rs b/tests/ui/range/new_range_stability.rs new file mode 100644 index 000000000000..7200e1ac95d2 --- /dev/null +++ b/tests/ui/range/new_range_stability.rs @@ -0,0 +1,28 @@ +// Stable + +use std::range::{RangeInclusive, RangeInclusiveIter}; + +fn range_inclusive(mut r: RangeInclusive) { + r.start; + r.last; + r.contains(&5); + r.is_empty(); + r.iter(); + + let mut i = r.into_iter(); + i.next(); + i.remainder(); +} + +// Unstable module + +use std::range::legacy; //~ ERROR unstable + +// Unstable types + +use std::range::RangeFrom; //~ ERROR unstable +use std::range::Range; //~ ERROR unstable +use std::range::RangeFromIter; //~ ERROR unstable +use std::range::RangeIter; //~ ERROR unstable + +fn main() {} diff --git a/tests/ui/range/new_range_stability.stderr b/tests/ui/range/new_range_stability.stderr new file mode 100644 index 000000000000..871d691794ff --- /dev/null +++ b/tests/ui/range/new_range_stability.stderr @@ -0,0 +1,53 @@ +error[E0658]: use of unstable library feature `new_range_api` + --> $DIR/new_range_stability.rs:19:5 + | +LL | use std::range::legacy; + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #125687 for more information + = help: add `#![feature(new_range_api)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `new_range_api` + --> $DIR/new_range_stability.rs:23:5 + | +LL | use std::range::RangeFrom; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #125687 for more information + = help: add `#![feature(new_range_api)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `new_range_api` + --> $DIR/new_range_stability.rs:24:5 + | +LL | use std::range::Range; + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #125687 for more information + = help: add `#![feature(new_range_api)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `new_range_api` + --> $DIR/new_range_stability.rs:25:5 + | +LL | use std::range::RangeFromIter; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #125687 for more information + = help: add `#![feature(new_range_api)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `new_range_api` + --> $DIR/new_range_stability.rs:26:5 + | +LL | use std::range::RangeIter; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #125687 for more information + = help: add `#![feature(new_range_api)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0658`. From d837cf67003c150a5adf7fd3e94ae97ca80c5b94 Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Sat, 7 Feb 2026 13:42:49 +0900 Subject: [PATCH 642/978] feat: Implement `int_from_ascii` for `NonZero` --- library/core/src/num/nonzero.rs | 120 ++++++++++++++++++++++++++--- library/coretests/tests/lib.rs | 1 + library/coretests/tests/nonzero.rs | 56 ++++++++++++++ 3 files changed, 166 insertions(+), 11 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 16de01406d8c..7876fced1c98 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1241,6 +1241,114 @@ macro_rules! nonzero_integer { unsafe { Self::new_unchecked(self.get().saturating_pow(other)) } } + /// Parses a non-zero integer from an ASCII-byte slice with decimal digits. + /// + /// The characters are expected to be an optional + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + " `+` or `-` " + } + if unsigned { + " `+` " + } + }] + /// sign followed by only digits. Leading and trailing non-digit characters (including + /// whitespace) represent an error. Underscores (which are accepted in Rust literals) + /// also represent an error. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_from_ascii)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::from_ascii(b\"+10\"), Ok(NonZero::new(10)?));")] + /// # Some(()) + /// # } + /// ``` + /// + /// Trailing space returns error: + /// + /// ``` + /// #![feature(int_from_ascii)] + /// + /// # use std::num::NonZero; + /// # + #[doc = concat!("assert!(NonZero::<", stringify!($Int), ">::from_ascii(b\"1 \").is_err());")] + /// ``` + #[unstable(feature = "int_from_ascii", issue = "134821")] + #[inline] + pub const fn from_ascii(src: &[u8]) -> Result { + Self::from_ascii_radix(src, 10) + } + + /// Parses a non-zero integer from an ASCII-byte slice with digits in a given base. + /// + /// The characters are expected to be an optional + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + " `+` or `-` " + } + if unsigned { + " `+` " + } + }] + /// sign followed by only digits. Leading and trailing non-digit characters (including + /// whitespace) represent an error. Underscores (which are accepted in Rust literals) + /// also represent an error. + /// + /// Digits are a subset of these characters, depending on `radix`: + /// + /// - `0-9` + /// - `a-z` + /// - `A-Z` + /// + /// # Panics + /// + /// This method panics if `radix` is not in the range from 2 to 36. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_from_ascii)] + /// + /// # use std::num::NonZero; + /// # + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::from_ascii_radix(b\"A\", 16), Ok(NonZero::new(10)?));")] + /// # Some(()) + /// # } + /// ``` + /// + /// Trailing space returns error: + /// + /// ``` + /// #![feature(int_from_ascii)] + /// + /// # use std::num::NonZero; + /// # + #[doc = concat!("assert!(NonZero::<", stringify!($Int), ">::from_ascii_radix(b\"1 \", 10).is_err());")] + /// ``` + #[unstable(feature = "int_from_ascii", issue = "134821")] + #[inline] + pub const fn from_ascii_radix(src: &[u8], radix: u32) -> Result { + let n = match <$Int>::from_ascii_radix(src, radix) { + Ok(n) => n, + Err(err) => return Err(err), + }; + if let Some(n) = Self::new(n) { + Ok(n) + } else { + Err(ParseIntError { kind: IntErrorKind::Zero }) + } + } + /// Parses a non-zero integer from a string slice with digits in a given base. /// /// The string is expected to be an optional @@ -1269,8 +1377,6 @@ macro_rules! nonzero_integer { /// /// # Examples /// - /// Basic usage: - /// /// ``` /// #![feature(nonzero_from_str_radix)] /// @@ -1295,15 +1401,7 @@ macro_rules! nonzero_integer { #[unstable(feature = "nonzero_from_str_radix", issue = "152193")] #[inline] pub const fn from_str_radix(src: &str, radix: u32) -> Result { - let n = match <$Int>::from_str_radix(src, radix) { - Ok(n) => n, - Err(err) => return Err(err), - }; - if let Some(n) = Self::new(n) { - Ok(n) - } else { - Err(ParseIntError { kind: IntErrorKind::Zero }) - } + Self::from_ascii_radix(src.as_bytes(), radix) } } diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 91a7c898b299..592332865552 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -66,6 +66,7 @@ #![feature(generic_assert_internals)] #![feature(hasher_prefixfree_extras)] #![feature(hashmap_internals)] +#![feature(int_from_ascii)] #![feature(int_lowest_highest_one)] #![feature(int_roundings)] #![feature(ip)] diff --git a/library/coretests/tests/nonzero.rs b/library/coretests/tests/nonzero.rs index 134f875925f9..861e9e05081f 100644 --- a/library/coretests/tests/nonzero.rs +++ b/library/coretests/tests/nonzero.rs @@ -124,6 +124,62 @@ fn test_from_signed_nonzero() { assert_eq!(num, 1i32); } +#[test] +fn test_from_ascii_radix() { + assert_eq!(NonZero::::from_ascii_radix(b"123", 10), Ok(NonZero::new(123).unwrap())); + assert_eq!(NonZero::::from_ascii_radix(b"1001", 2), Ok(NonZero::new(9).unwrap())); + assert_eq!(NonZero::::from_ascii_radix(b"123", 8), Ok(NonZero::new(83).unwrap())); + assert_eq!(NonZero::::from_ascii_radix(b"123", 16), Ok(NonZero::new(291).unwrap())); + assert_eq!(NonZero::::from_ascii_radix(b"ffff", 16), Ok(NonZero::new(65535).unwrap())); + assert_eq!(NonZero::::from_ascii_radix(b"z", 36), Ok(NonZero::new(35).unwrap())); + assert_eq!( + NonZero::::from_ascii_radix(b"0", 10).err().map(|e| e.kind().clone()), + Some(IntErrorKind::Zero) + ); + assert_eq!( + NonZero::::from_ascii_radix(b"-1", 10).err().map(|e| e.kind().clone()), + Some(IntErrorKind::InvalidDigit) + ); + assert_eq!( + NonZero::::from_ascii_radix(b"-129", 10).err().map(|e| e.kind().clone()), + Some(IntErrorKind::NegOverflow) + ); + assert_eq!( + NonZero::::from_ascii_radix(b"257", 10).err().map(|e| e.kind().clone()), + Some(IntErrorKind::PosOverflow) + ); + + assert_eq!( + NonZero::::from_ascii_radix(b"Z", 10).err().map(|e| e.kind().clone()), + Some(IntErrorKind::InvalidDigit) + ); + assert_eq!( + NonZero::::from_ascii_radix(b"_", 2).err().map(|e| e.kind().clone()), + Some(IntErrorKind::InvalidDigit) + ); +} + +#[test] +fn test_from_ascii() { + assert_eq!(NonZero::::from_ascii(b"123"), Ok(NonZero::new(123).unwrap())); + assert_eq!( + NonZero::::from_ascii(b"0").err().map(|e| e.kind().clone()), + Some(IntErrorKind::Zero) + ); + assert_eq!( + NonZero::::from_ascii(b"-1").err().map(|e| e.kind().clone()), + Some(IntErrorKind::InvalidDigit) + ); + assert_eq!( + NonZero::::from_ascii(b"-129").err().map(|e| e.kind().clone()), + Some(IntErrorKind::NegOverflow) + ); + assert_eq!( + NonZero::::from_ascii(b"257").err().map(|e| e.kind().clone()), + Some(IntErrorKind::PosOverflow) + ); +} + #[test] fn test_from_str_radix() { assert_eq!(NonZero::::from_str_radix("123", 10), Ok(NonZero::new(123).unwrap())); From cd50e622774cf7c2698bddec184cafaeaad66444 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" Date: Sun, 1 Feb 2026 03:13:55 +0100 Subject: [PATCH 643/978] Linker-plugin-based LTO: Give explanation how to use linker-plugin-lto with full LTO --- src/doc/rustc/src/linker-plugin-lto.md | 80 +++++++++++++++++++++----- 1 file changed, 66 insertions(+), 14 deletions(-) diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md index 32e712a48d76..1502e694bba5 100644 --- a/src/doc/rustc/src/linker-plugin-lto.md +++ b/src/doc/rustc/src/linker-plugin-lto.md @@ -3,20 +3,35 @@ The `-C linker-plugin-lto` flag allows for deferring the LTO optimization to the actual linking step, which in turn allows for performing interprocedural optimizations across programming language boundaries if -all the object files being linked were created by LLVM based toolchains. -The prime example here would be linking Rust code together with -Clang-compiled C/C++ code. +all the object files being linked were created by LLVM-based toolchains +using the **same** LTO mode: either thin LTO or fat LTO. +The examples would be linking Rust code together with +Clang-compiled C/C++ code and LLVM Flang-compiled Fortran code. ## Usage -There are two main cases how linker plugin based LTO can be used: +There are two main cases how linker-plugin-based LTO can be used: - compiling a Rust `staticlib` that is used as a C ABI dependency - compiling a Rust binary where `rustc` invokes the linker -In both cases the Rust code has to be compiled with `-C linker-plugin-lto` and -the C/C++ code with `-flto` or `-flto=thin` so that object files are emitted -as LLVM bitcode. +In both cases, the Rust code must be compiled with `-C linker-plugin-lto`. +By default, this enables thin LTO, so any interoperable language code must +also be compiled in thin LTO mode. To use fat LTO with linker-plugin-based LTO, +the `rustc` compiler requires the additional `-C lto=fat` flag, and the +interoperable language must likewise be compiled in fat LTO mode. Note that +interoperable language must be compiled using the LLVM infrastructure +(see more details in [toolchain compability](#toolchain-compatibility)). + +The following table summarizes how to enable thin LTO and fat LTO in +different compilers: + +| Compiler | Thin LTO | Fat LTO | +|:---------|-----------------:|---------------:| +| rustc | -Clto=thin | -Clto=fat | +| clang | -flto=thin | -flto=full | +| clang++ | -flto=thin | -flto=full | +| flang | -flto=thin (WIP) | -flto=full | ### Rust `staticlib` as dependency in C/C++ program @@ -54,7 +69,7 @@ that an appropriate linker is used. Using `rustc` directly: ```bash -# Compile C code with `-flto` +# Compile C code with `-flto=thin` clang ./clib.c -flto=thin -c -o ./clib.o -O2 # Create a static library from the C code ar crus ./libxyz.a ./clib.o @@ -66,7 +81,7 @@ rustc -Clinker-plugin-lto -L. -Copt-level=2 -Clinker=clang -Clink-arg=-fuse-ld=l Using `cargo` directly: ```bash -# Compile C code with `-flto` +# Compile C code with `-flto=thin` clang ./clib.c -flto=thin -c -o ./clib.o -O2 # Create a static library from the C code ar crus ./libxyz.a ./clib.o @@ -75,6 +90,41 @@ ar crus ./libxyz.a ./clib.o RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build --release ``` +### Fortran code as a dependency in Rust + +Rust code can also be linked together with Fortran code compiled by LLVM `flang`. +The following examples demonstrate fat LTO usage, as LLVM `flang` has WIP status for +thin LTO. The same approach can be applied to compile C and C++ code with fat LTO. + +Using `rustc` directly: + +```bash +# Compile Fortran code with `-flto=full` +flang ./ftnlib.f90 -flto=full -c -o ./ftnlib.f90.o -O3 +# Create a static library from the Fortran code +ar crus ./libftn.a ./ftnlib.f90.o + +# Invoke `rustc` with the additional arguments, `-Clto=fat` is mandatory +rustc -Clinker-plugin-lto -Clto=fat -Clink-arg=path/to/libftn.a -Copt-level=3 -Clinker=flang -C default-linker-libraries=yes -Clink-arg=-fuse-ld=lld ./main.rs +``` + +Using `cargo` directly: + +```bash +# Compile Fortran code with `-flto=full` +flang ./ftnlib.f90 -flto=full -c -o ./ftnlib.f90.o -O3 +# Create a static library from the Fortran code +ar crus ./libftn.a ./ftnlib.f90.o + +# Set the linking arguments via RUSTFLAGS, `-Clto=fat` is mandatory +RUSTFLAGS="-Clinker-plugin-lto -Clto=fat -Clink-arg=path/to/libftn.a -Clinker=flang -C default-linker-libraries=yes -Clink-arg=-fuse-ld=lld" cargo build --release +``` + +Note, LLVM `flang` can be used as a linker driver starting from flang 21.1.8. +The `-C default-linker-libraries=yes` option may be omitted if the Fortran +runtime is not required; however, most Fortran code depends on the runtime, +so enabling default linker libraries is usually necessary. + ### Explicitly specifying the linker plugin to be used by `rustc` If one wants to use a linker other than LLD, the LLVM linker plugin has to be @@ -179,11 +229,13 @@ for clang, rust in sorted(version_map.items()): --> In order for this kind of LTO to work, the LLVM linker plugin must be able to -handle the LLVM bitcode produced by both `rustc` and `clang`. +handle the LLVM bitcode produced by `rustc` and by compilers of all +interoperable languages. A good rule of thumb is to use an LLVM linker plugin +whose version is at least as new as the newest compiler involved. -Best results are achieved by using a `rustc` and `clang` that are based on the -exact same version of LLVM. One can use `rustc -vV` in order to view the LLVM -used by a given `rustc` version. Note that the version number given +Best results are achieved by using a `rustc` and LLVM compilers that are based +on the exact same version of LLVM. One can use `rustc -vV` in order to view +the LLVM used by a given `rustc` version. Note that the version number given here is only an approximation as Rust sometimes uses unstable revisions of LLVM. However, the approximation is usually reliable. @@ -204,6 +256,6 @@ The following table shows known good combinations of toolchain versions. | 1.78 - 1.81 | 18 | | 1.82 - 1.86 | 19 | | 1.87 - 1.90 | 20 | -| 1.91 - 1.92 | 21 | +| 1.91 - 1.93 | 21 | Note that the compatibility policy for this feature might change in the future. From 5db03861b063bad596fef43759df988c6e7e28c1 Mon Sep 17 00:00:00 2001 From: Juho Kahala <57393910+quaternic@users.noreply.github.com> Date: Tue, 3 Feb 2026 00:35:17 +0200 Subject: [PATCH 644/978] libm-test: Remove exception for fmaximum_num tests This was left over from f6a23a78c44e ("fmaximum,fminimum: Fix incorrect result and add tests"). [ added context to body - Trevor ] --- library/compiler-builtins/libm-test/src/precision.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/library/compiler-builtins/libm-test/src/precision.rs b/library/compiler-builtins/libm-test/src/precision.rs index 7887c032394b..5f7bdd20b18d 100644 --- a/library/compiler-builtins/libm-test/src/precision.rs +++ b/library/compiler-builtins/libm-test/src/precision.rs @@ -401,14 +401,6 @@ fn binop_common( return SKIP; } - // FIXME(#939): this should not be skipped, there is a bug in our implementationi. - if ctx.base_name == BaseName::FmaximumNum - && ctx.basis == CheckBasis::Mpfr - && ((input.0.is_nan() && actual.is_nan() && expected.is_nan()) || input.1.is_nan()) - { - return XFAIL_NOCHECK; - } - /* FIXME(#439): our fmin and fmax do not compare signed zeros */ if ctx.base_name == BaseName::Fmin From 2f06c639c3014cdf3260133a72b4eebd4c924f3d Mon Sep 17 00:00:00 2001 From: Juho Kahala <57393910+quaternic@users.noreply.github.com> Date: Tue, 3 Feb 2026 01:14:54 +0200 Subject: [PATCH 645/978] libm: Fix acoshf and acosh for negative inputs The acosh functions were incorrectly returning finite values for some negative inputs (should be NaN for any `x < 1.0`) The bug was inherited when originally ported from musl, and this patch follows their fix for single-precision acoshf in [1]. A similar fix is applied to acosh, though musl still has an incorrect implementation requiring tests against that basis to be skipped. [1]: https://git.musl-libc.org/cgit/musl/commit/?id=c4c38e6364323b6d83ba3428464e19987b981d7a [ added context to message - Trevor ] --- .../libm-test/src/precision.rs | 22 +++++++--------- .../compiler-builtins/libm/src/math/acosh.rs | 26 +++++++++---------- .../compiler-builtins/libm/src/math/acoshf.rs | 25 +++++++++--------- 3 files changed, 35 insertions(+), 38 deletions(-) diff --git a/library/compiler-builtins/libm-test/src/precision.rs b/library/compiler-builtins/libm-test/src/precision.rs index 5f7bdd20b18d..897f21da78e7 100644 --- a/library/compiler-builtins/libm-test/src/precision.rs +++ b/library/compiler-builtins/libm-test/src/precision.rs @@ -266,6 +266,15 @@ impl MaybeOverride<(f64,)> for SpecialCase { return XFAIL_NOCHECK; } + if ctx.base_name == BaseName::Acosh + && input.0 < 1.0 + && actual.is_nan() + && ctx.basis == CheckBasis::Musl + { + // Musl sometimes evaluates acosh(negative) to a numeric value + return XFAIL_NOCHECK; + } + // maybe_check_nan_bits(actual, expected, ctx) unop_common(input, actual, expected, ctx) } @@ -295,19 +304,6 @@ fn unop_common( expected: F2, ctx: &CheckCtx, ) -> CheckAction { - if ctx.base_name == BaseName::Acosh - && input.0 < F1::NEG_ONE - && !(expected.is_nan() && actual.is_nan()) - { - // acoshf is undefined for x <= 1.0, but we return a random result at lower values. - - if ctx.basis == CheckBasis::Musl { - return XFAIL_NOCHECK; - } - - return XFAIL("acoshf undefined"); - } - if (ctx.base_name == BaseName::Lgamma || ctx.base_name == BaseName::LgammaR) && input.0 < F1::ZERO && !input.0.is_infinite() diff --git a/library/compiler-builtins/libm/src/math/acosh.rs b/library/compiler-builtins/libm/src/math/acosh.rs index 8737bad012c8..2904fc0ed520 100644 --- a/library/compiler-builtins/libm/src/math/acosh.rs +++ b/library/compiler-builtins/libm/src/math/acosh.rs @@ -1,4 +1,4 @@ -use super::{log, log1p, sqrt}; +use super::{Float, log, log1p, sqrt}; const LN2: f64 = 0.693147180559945309417232121458176568; /* 0x3fe62e42, 0xfefa39ef*/ @@ -9,19 +9,19 @@ const LN2: f64 = 0.693147180559945309417232121458176568; /* 0x3fe62e42, 0xfefa3 /// `x` must be a number greater than or equal to 1. #[cfg_attr(assert_no_panic, no_panic::no_panic)] pub fn acosh(x: f64) -> f64 { - let u = x.to_bits(); - let e = ((u >> 52) as usize) & 0x7ff; + let ux = x.to_bits(); /* x < 1 domain error is handled in the called functions */ - - if e < 0x3ff + 1 { - /* |x| < 2, up to 2ulp error in [1,1.125] */ - return log1p(x - 1.0 + sqrt((x - 1.0) * (x - 1.0) + 2.0 * (x - 1.0))); + if (ux & !f64::SIGN_MASK) < 2_f64.to_bits() { + /* |x| < 2, invalid if x < 1 */ + /* up to 2ulp error in [1,1.125] */ + let x_1 = x - 1.0; + log1p(x_1 + sqrt(x_1 * x_1 + 2.0 * x_1)) + } else if ux < ((1 << 26) as f64).to_bits() { + /* 2 <= x < 0x1p26 */ + log(2.0 * x - 1.0 / (x + sqrt(x * x - 1.0))) + } else { + /* x >= 0x1p26 or x <= -2 or nan */ + log(x) + LN2 } - if e < 0x3ff + 26 { - /* |x| < 0x1p26 */ - return log(2.0 * x - 1.0 / (x + sqrt(x * x - 1.0))); - } - /* |x| >= 0x1p26 or nan */ - return log(x) + LN2; } diff --git a/library/compiler-builtins/libm/src/math/acoshf.rs b/library/compiler-builtins/libm/src/math/acoshf.rs index 432fa03f1163..d9aafaabdef4 100644 --- a/library/compiler-builtins/libm/src/math/acoshf.rs +++ b/library/compiler-builtins/libm/src/math/acoshf.rs @@ -1,4 +1,4 @@ -use super::{log1pf, logf, sqrtf}; +use super::{Float, log1pf, logf, sqrtf}; const LN2: f32 = 0.693147180559945309417232121458176568; @@ -9,18 +9,19 @@ const LN2: f32 = 0.693147180559945309417232121458176568; /// `x` must be a number greater than or equal to 1. #[cfg_attr(assert_no_panic, no_panic::no_panic)] pub fn acoshf(x: f32) -> f32 { - let u = x.to_bits(); - let a = u & 0x7fffffff; + let ux = x.to_bits(); - if a < 0x3f800000 + (1 << 23) { - /* |x| < 2, invalid if x < 1 or nan */ + /* x < 1 domain error is handled in the called functions */ + if (ux & !f32::SIGN_MASK) < 2_f32.to_bits() { + /* |x| < 2, invalid if x < 1 */ /* up to 2ulp error in [1,1.125] */ - return log1pf(x - 1.0 + sqrtf((x - 1.0) * (x - 1.0) + 2.0 * (x - 1.0))); + let x_1 = x - 1.0; + log1pf(x_1 + sqrtf(x_1 * x_1 + 2.0 * x_1)) + } else if ux < ((1 << 12) as f32).to_bits() { + /* 2 <= x < 0x1p12 */ + logf(2.0 * x - 1.0 / (x + sqrtf(x * x - 1.0))) + } else { + /* x >= 0x1p12 or x <= -2 or nan */ + logf(x) + LN2 } - if a < 0x3f800000 + (12 << 23) { - /* |x| < 0x1p12 */ - return logf(2.0 * x - 1.0 / (x + sqrtf(x * x - 1.0))); - } - /* x >= 0x1p12 */ - return logf(x) + LN2; } From 7183f983b2c621b8b19d63bb3619339e9251ac16 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 7 Feb 2026 06:40:01 +0000 Subject: [PATCH 646/978] ci: Enable verbose output for josh-sync --- library/compiler-builtins/.github/workflows/rustc-pull.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/compiler-builtins/.github/workflows/rustc-pull.yml b/library/compiler-builtins/.github/workflows/rustc-pull.yml index 617db14f46ee..8e88213332de 100644 --- a/library/compiler-builtins/.github/workflows/rustc-pull.yml +++ b/library/compiler-builtins/.github/workflows/rustc-pull.yml @@ -7,6 +7,9 @@ on: # Run at 04:00 UTC every Monday and Thursday - cron: '0 4 * * 1,4' +env: + JOSH_SYNC_VERBOSE: true + jobs: pull: if: github.repository == 'rust-lang/compiler-builtins' From b5cd820ef421f710a73a196ec85f5a2198427cc3 Mon Sep 17 00:00:00 2001 From: lapla Date: Sat, 7 Feb 2026 11:42:53 +0900 Subject: [PATCH 647/978] Use `.map.collect` to aggregate in `.to_ty` of tuples --- compiler/rustc_ast/src/ast.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 591abdaa2683..fea87c2360f1 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -656,11 +656,7 @@ impl Pat { // A tuple pattern `(P0, .., Pn)` can be reparsed as `(T0, .., Tn)` // assuming `T0` to `Tn` are all syntactically valid as types. PatKind::Tuple(pats) => { - let mut tys = ThinVec::with_capacity(pats.len()); - // FIXME(#48994) - could just be collected into an Option - for pat in pats { - tys.push(pat.to_ty()?); - } + let tys = pats.iter().map(|pat| pat.to_ty()).collect::>>()?; TyKind::Tup(tys) } _ => return None, From f71347c611fde0b28699c85db0858f52ff2e5002 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 19:28:22 +0100 Subject: [PATCH 648/978] Remove tidy fluent file checks --- src/tools/tidy/src/fluent_alphabetical.rs | 125 ---------------------- src/tools/tidy/src/fluent_lowercase.rs | 65 ----------- src/tools/tidy/src/fluent_period.rs | 88 --------------- src/tools/tidy/src/fluent_used.rs | 42 -------- src/tools/tidy/src/lib.rs | 4 - src/tools/tidy/src/main.rs | 3 - 6 files changed, 327 deletions(-) delete mode 100644 src/tools/tidy/src/fluent_alphabetical.rs delete mode 100644 src/tools/tidy/src/fluent_lowercase.rs delete mode 100644 src/tools/tidy/src/fluent_period.rs delete mode 100644 src/tools/tidy/src/fluent_used.rs diff --git a/src/tools/tidy/src/fluent_alphabetical.rs b/src/tools/tidy/src/fluent_alphabetical.rs deleted file mode 100644 index 7583241ea638..000000000000 --- a/src/tools/tidy/src/fluent_alphabetical.rs +++ /dev/null @@ -1,125 +0,0 @@ -//! Checks that all Flunt files have messages in alphabetical order - -use std::collections::HashMap; -use std::fs::OpenOptions; -use std::io::Write; -use std::path::Path; - -use fluent_syntax::ast::Entry; -use fluent_syntax::parser; -use regex::Regex; - -use crate::diagnostics::{CheckId, RunningCheck, TidyCtx}; -use crate::walk::{filter_dirs, walk}; - -fn message() -> &'static Regex { - static_regex!(r#"(?m)^([a-zA-Z0-9_]+)\s*=\s*"#) -} - -fn is_fluent(path: &Path) -> bool { - path.extension().is_some_and(|ext| ext == "ftl") -} - -fn check_alphabetic( - filename: &str, - fluent: &str, - check: &mut RunningCheck, - all_defined_msgs: &mut HashMap, -) { - let Ok(resource) = parser::parse(fluent) else { - panic!("Errors encountered while parsing fluent file `{filename}`"); - }; - - let mut prev: Option<&str> = None; - - for entry in &resource.body { - if let Entry::Message(msg) = entry { - let name: &str = msg.id.name; - if let Some(defined_filename) = all_defined_msgs.get(name) { - check.error(format!( - "{filename}: message `{name}` is already defined in {defined_filename}", - )); - } else { - all_defined_msgs.insert(name.to_string(), filename.to_owned()); - } - if let Some(prev) = prev - && prev > name - { - check.error(format!( - "{filename}: message `{prev}` appears before `{name}`, but is alphabetically \ -later than it. Run `./x.py test tidy --bless` to sort the file correctly", - )); - } - prev = Some(name); - } - } -} - -fn sort_messages( - filename: &str, - fluent: &str, - check: &mut RunningCheck, - all_defined_msgs: &mut HashMap, -) -> String { - let mut chunks = vec![]; - let mut cur = String::new(); - for line in fluent.lines() { - if let Some(name) = message().find(line) { - if let Some(defined_filename) = all_defined_msgs.get(name.as_str()) { - check.error(format!( - "{filename}: message `{}` is already defined in {defined_filename}", - name.as_str(), - )); - } - - all_defined_msgs.insert(name.as_str().to_owned(), filename.to_owned()); - chunks.push(std::mem::take(&mut cur)); - } - - cur += line; - cur.push('\n'); - } - chunks.push(cur); - chunks.sort(); - let mut out = chunks.join(""); - out = out.trim().to_string(); - out.push('\n'); - out -} - -pub fn check(path: &Path, tidy_ctx: TidyCtx) { - let mut check = tidy_ctx.start_check(CheckId::new("fluent_alphabetical").path(path)); - let bless = tidy_ctx.is_bless_enabled(); - - let mut all_defined_msgs = HashMap::new(); - walk( - path, - |path, is_dir| filter_dirs(path) || (!is_dir && !is_fluent(path)), - &mut |ent, contents| { - if bless { - let sorted = sort_messages( - ent.path().to_str().unwrap(), - contents, - &mut check, - &mut all_defined_msgs, - ); - if sorted != contents { - let mut f = - OpenOptions::new().write(true).truncate(true).open(ent.path()).unwrap(); - f.write_all(sorted.as_bytes()).unwrap(); - } - } else { - check_alphabetic( - ent.path().to_str().unwrap(), - contents, - &mut check, - &mut all_defined_msgs, - ); - } - }, - ); - - assert!(!all_defined_msgs.is_empty()); - - crate::fluent_used::check(path, all_defined_msgs, tidy_ctx); -} diff --git a/src/tools/tidy/src/fluent_lowercase.rs b/src/tools/tidy/src/fluent_lowercase.rs deleted file mode 100644 index 690b733a5b64..000000000000 --- a/src/tools/tidy/src/fluent_lowercase.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! Checks that the error messages start with a lowercased letter (except when allowed to). - -use std::path::Path; - -use fluent_syntax::ast::{Entry, Message, PatternElement}; - -use crate::diagnostics::{CheckId, RunningCheck, TidyCtx}; -use crate::walk::{filter_dirs, walk}; - -#[rustfmt::skip] -const ALLOWED_CAPITALIZED_WORDS: &[&str] = &[ - // tidy-alphabetical-start - "ABI", - "ABIs", - "ADT", - "C", - "CGU", - "Ferris", - "MIR", - "OK", - "Rust", - "VS", // VS Code - // tidy-alphabetical-end -]; - -fn filter_fluent(path: &Path) -> bool { - if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true } -} - -fn is_allowed_capitalized_word(msg: &str) -> bool { - ALLOWED_CAPITALIZED_WORDS.iter().any(|word| { - msg.strip_prefix(word) - .map(|tail| tail.chars().next().map(|c| c == '-' || c.is_whitespace()).unwrap_or(true)) - .unwrap_or_default() - }) -} - -fn check_lowercase(filename: &str, contents: &str, check: &mut RunningCheck) { - let (Ok(parse) | Err((parse, _))) = fluent_syntax::parser::parse(contents); - - for entry in &parse.body { - if let Entry::Message(msg) = entry - && let Message { value: Some(pattern), .. } = msg - && let [first_pattern, ..] = &pattern.elements[..] - && let PatternElement::TextElement { value } = first_pattern - && value.chars().next().is_some_and(char::is_uppercase) - && !is_allowed_capitalized_word(value) - { - check.error(format!( - "{filename}: message `{value}` starts with an uppercase letter. Fix it or add it to `ALLOWED_CAPITALIZED_WORDS`" - )); - } - } -} - -pub fn check(path: &Path, tidy_ctx: TidyCtx) { - let mut check = tidy_ctx.start_check(CheckId::new("fluent_lowercase").path(path)); - walk( - path, - |path, is_dir| filter_dirs(path) || (!is_dir && filter_fluent(path)), - &mut |ent, contents| { - check_lowercase(ent.path().to_str().unwrap(), contents, &mut check); - }, - ); -} diff --git a/src/tools/tidy/src/fluent_period.rs b/src/tools/tidy/src/fluent_period.rs deleted file mode 100644 index e7d59e2ce2a9..000000000000 --- a/src/tools/tidy/src/fluent_period.rs +++ /dev/null @@ -1,88 +0,0 @@ -//! Checks that no Fluent messages or attributes end in periods (except ellipses) - -use std::path::Path; - -use fluent_syntax::ast::{Entry, PatternElement}; - -use crate::diagnostics::{CheckId, RunningCheck, TidyCtx}; -use crate::walk::{filter_dirs, walk}; - -fn filter_fluent(path: &Path) -> bool { - if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true } -} - -/// Messages allowed to have `.` at their end. -/// -/// These should probably be reworked eventually. -const ALLOWLIST: &[&str] = &[ - "const_eval_long_running", - "const_eval_validation_failure_note", - "driver_impl_ice", - "incremental_corrupt_file", -]; - -fn check_period(filename: &str, contents: &str, check: &mut RunningCheck) { - if filename.contains("codegen") { - // FIXME: Too many codegen messages have periods right now... - return; - } - - let (Ok(parse) | Err((parse, _))) = fluent_syntax::parser::parse(contents); - for entry in &parse.body { - if let Entry::Message(m) = entry { - if ALLOWLIST.contains(&m.id.name) { - continue; - } - - if let Some(pat) = &m.value - && let Some(PatternElement::TextElement { value }) = pat.elements.last() - { - // We don't care about ellipses. - if value.ends_with(".") && !value.ends_with("...") { - let ll = find_line(contents, value); - let name = m.id.name; - check.error(format!("{filename}:{ll}: message `{name}` ends in a period")); - } - } - - for attr in &m.attributes { - // Teach notes usually have long messages. - if attr.id.name == "teach_note" { - continue; - } - - if let Some(PatternElement::TextElement { value }) = attr.value.elements.last() - && value.ends_with(".") - && !value.ends_with("...") - { - let ll = find_line(contents, value); - let name = attr.id.name; - check.error(format!("{filename}:{ll}: attr `{name}` ends in a period")); - } - } - } - } -} - -/// Evil cursed bad hack. Requires that `value` be a substr (in memory) of `contents`. -fn find_line(haystack: &str, needle: &str) -> usize { - for (ll, line) in haystack.lines().enumerate() { - if line.as_ptr() > needle.as_ptr() { - return ll; - } - } - - 1 -} - -pub fn check(path: &Path, tidy_ctx: TidyCtx) { - let mut check = tidy_ctx.start_check(CheckId::new("fluent_period").path(path)); - - walk( - path, - |path, is_dir| filter_dirs(path) || (!is_dir && filter_fluent(path)), - &mut |ent, contents| { - check_period(ent.path().to_str().unwrap(), contents, &mut check); - }, - ); -} diff --git a/src/tools/tidy/src/fluent_used.rs b/src/tools/tidy/src/fluent_used.rs deleted file mode 100644 index 75da1d7ea49d..000000000000 --- a/src/tools/tidy/src/fluent_used.rs +++ /dev/null @@ -1,42 +0,0 @@ -//! Checks that all Fluent messages appear at least twice - -use std::collections::HashMap; -use std::path::Path; - -use crate::diagnostics::{CheckId, TidyCtx}; -use crate::walk::{filter_dirs, walk}; - -fn filter_used_messages( - contents: &str, - msgs_not_appeared_yet: &mut HashMap, - msgs_appeared_only_once: &mut HashMap, -) { - // we don't just check messages never appear in Rust files, - // because messages can be used as parts of other fluent messages in Fluent files, - // so we check messages appear only once in all Rust and Fluent files. - let matches = static_regex!(r"\w+").find_iter(contents); - for name in matches { - if let Some((name, filename)) = msgs_not_appeared_yet.remove_entry(name.as_str()) { - // if one msg appears for the first time, - // remove it from `msgs_not_appeared_yet` and insert it into `msgs_appeared_only_once`. - msgs_appeared_only_once.insert(name, filename); - } else { - // if one msg appears for the second time, - // remove it from `msgs_appeared_only_once`. - msgs_appeared_only_once.remove(name.as_str()); - } - } -} - -pub fn check(path: &Path, mut all_defined_msgs: HashMap, tidy_ctx: TidyCtx) { - let mut check = tidy_ctx.start_check(CheckId::new("fluent_used").path(path)); - - let mut msgs_appear_only_once = HashMap::new(); - walk(path, |path, _| filter_dirs(path), &mut |_, contents| { - filter_used_messages(contents, &mut all_defined_msgs, &mut msgs_appear_only_once); - }); - - for (name, filename) in msgs_appear_only_once { - check.error(format!("{filename}: message `{name}` is not used")); - } -} diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 19a9fa80d9f0..ed41130f5d29 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -168,10 +168,6 @@ pub mod extdeps; pub mod extra_checks; pub mod features; pub mod filenames; -pub mod fluent_alphabetical; -pub mod fluent_lowercase; -pub mod fluent_period; -mod fluent_used; pub mod gcc_submodule; pub(crate) mod iter_header; pub mod known_bug; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 2485dc802ed5..09c08e1baf50 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -107,9 +107,6 @@ fn main() { // Checks that only make sense for the compiler. check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], &ci_info); - check!(fluent_alphabetical, &compiler_path); - check!(fluent_period, &compiler_path); - check!(fluent_lowercase, &compiler_path); check!(target_policy, &root_path); check!(gcc_submodule, &root_path, &compiler_path); From ca9c2277008aee9310155c5e6131f0f93f67e3ad Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 21:15:02 +0100 Subject: [PATCH 649/978] Check style of messages in `rustc_macros` --- .../rustc_macros/src/diagnostics/message.rs | 71 +++++++++++++++---- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/message.rs b/compiler/rustc_macros/src/diagnostics/message.rs index 6c8aded89f16..16ee3c657611 100644 --- a/compiler/rustc_macros/src/diagnostics/message.rs +++ b/compiler/rustc_macros/src/diagnostics/message.rs @@ -23,9 +23,7 @@ impl Message { quote! { crate::fluent_generated::#slug } } Message::Inline(message_span, message) => { - if let Some(variant) = variant { - verify_fluent_message(*message_span, &message, variant); - } + verify_fluent_message(*message_span, &message, variant); quote! { rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed(#message)) } } } @@ -86,30 +84,37 @@ impl Message { } } -fn verify_fluent_message(msg_span: Span, message: &str, variant: &VariantInfo<'_>) { +fn verify_fluent_message(msg_span: Span, message_str: &str, variant: Option<&VariantInfo<'_>>) { // Parse the fluent message const GENERATED_MSG_ID: &str = "generated_msg"; - let resource = FluentResource::try_new(format!("{GENERATED_MSG_ID} = {message}\n")).unwrap(); + let resource = + FluentResource::try_new(format!("{GENERATED_MSG_ID} = {message_str}\n")).unwrap(); assert_eq!(resource.entries().count(), 1); let Some(fluent_syntax::ast::Entry::Message(message)) = resource.get_entry(0) else { panic!("Did not parse into a message") }; // Check if all variables are used - let fields: Vec = variant - .bindings() - .iter() - .flat_map(|b| b.ast().ident.as_ref()) - .map(|id| id.to_string()) - .collect(); - for variable in variable_references(&message) { - if !fields.iter().any(|f| f == variable) { - span_err(msg_span.unwrap(), format!("Variable `{variable}` not found in diagnostic ")) + if let Some(variant) = variant { + let fields: Vec = variant + .bindings() + .iter() + .flat_map(|b| b.ast().ident.as_ref()) + .map(|id| id.to_string()) + .collect(); + for variable in variable_references(&message) { + if !fields.iter().any(|f| f == variable) { + span_err( + msg_span.unwrap(), + format!("Variable `{variable}` not found in diagnostic "), + ) .help(format!("Available fields: {:?}", fields.join(", "))) .emit(); + } } - // assert!(, ); } + + verify_message_style(msg_span, message_str); } fn variable_references<'a>(msg: &fluent_syntax::ast::Message<&'a str>) -> Vec<&'a str> { @@ -136,3 +141,39 @@ fn variable_references<'a>(msg: &fluent_syntax::ast::Message<&'a str>) -> Vec<&' } refs } + +const ALLOWED_CAPITALIZED_WORDS: &[&str] = &[ + // tidy-alphabetical-start + "ABI", + "ABIs", + "ADT", + "C-variadic", + "CGU-reuse", + "Cargo", + "Ferris", + "GCC", + "MIR", + "OK", + "VS", + // tidy-alphabetical-end +]; + +/// See: https://rustc-dev-guide.rust-lang.org/diagnostics.html#diagnostic-output-style-guide +fn verify_message_style(msg_span: Span, message: &str) { + // Verify that message starts with lowercase char + let Some(first_word) = message.split_whitespace().next() else { + span_err(msg_span.unwrap(), "message must not be empty").emit(); + return; + }; + let first_char = first_word.chars().next().expect("Word is not empty"); + if first_char.is_uppercase() && !ALLOWED_CAPITALIZED_WORDS.contains(&first_word) { + span_err(msg_span.unwrap(), "message `{value}` starts with an uppercase letter. Fix it or add it to `ALLOWED_CAPITALIZED_WORDS`").emit(); + return; + } + + // Verify that message does not end in `.` + if message.ends_with(".") && !message.ends_with("...") { + span_err(msg_span.unwrap(), "message `{value}` ends with a period").emit(); + return; + } +} From edd43c9e1f9fbca3e7f95447fbade7cb1bf11d7c Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 21:16:48 +0100 Subject: [PATCH 650/978] Fix existing messages in the diag structs --- compiler/rustc_codegen_llvm/src/errors.rs | 2 +- compiler/rustc_codegen_ssa/src/errors.rs | 10 +++++----- compiler/rustc_const_eval/src/errors.rs | 4 ++-- compiler/rustc_driver_impl/src/session_diagnostics.rs | 2 +- compiler/rustc_hir_typeck/src/errors.rs | 2 +- compiler/rustc_incremental/src/errors.rs | 2 +- compiler/rustc_macros/src/diagnostics/message.rs | 1 + compiler/rustc_mir_build/src/errors.rs | 2 +- 8 files changed, 13 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 23fa05f3d02f..20eba352bc41 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -214,5 +214,5 @@ pub(crate) struct FixedX18InvalidArch<'a> { } #[derive(Diagnostic)] -#[diag("`-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later.")] +#[diag("`-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later")] pub(crate) struct SanitizerKcfiArityRequiresLLVM2100; diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 742e05973ee5..82a6525adcc9 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -59,7 +59,7 @@ pub(crate) struct MissingQueryDepGraph { #[derive(Diagnostic)] #[diag( - "found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case)." + "found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case)" )] pub(crate) struct MalformedCguName { #[primary_span] @@ -562,12 +562,12 @@ pub(crate) struct SelfContainedLinkerMissing; #[derive(Diagnostic)] #[diag( - "please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option." + "please ensure that Visual Studio 2017 or later, or Build Tools for Visual Studio were installed with the Visual C++ option" )] pub(crate) struct CheckInstalledVisualStudio; #[derive(Diagnostic)] -#[diag("VS Code is a different product, and is not sufficient.")] +#[diag("VS Code is a different product, and is not sufficient")] pub(crate) struct InsufficientVSCodeProduct; #[derive(Diagnostic)] @@ -610,13 +610,13 @@ pub(crate) struct LinkerFileStem; #[derive(Diagnostic)] #[diag( - "link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms." + "link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms" )] pub(crate) struct StaticLibraryNativeArtifacts; #[derive(Diagnostic)] #[diag( - "native artifacts to link against have been written to {$path}. The order and any duplication can be significant on some platforms." + "native artifacts to link against have been written to {$path}. The order and any duplication can be significant on some platforms" )] pub(crate) struct StaticLibraryNativeArtifactsToFile<'a> { pub path: &'a Path, diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 39f98b844920..3b49dbd907c8 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -309,7 +309,7 @@ pub(crate) struct UnallowedHeapAllocations { pub span: Span, pub kind: ConstContext, #[note( - "The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created." + "the runtime heap is not yet available at compile-time, so no runtime heap allocations can be created" )] pub teach: bool, } @@ -347,7 +347,7 @@ pub(crate) struct InteriorMutableBorrowEscaping { #[diag("constant evaluation is taking a long time")] #[note( "this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint." + If your compilation actually takes a long time, you can safely allow the lint" )] pub struct LongRunning { #[help("the constant being evaluated")] diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs index 565c176645de..97972185ebc4 100644 --- a/compiler/rustc_driver_impl/src/session_diagnostics.rs +++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs @@ -51,7 +51,7 @@ pub(crate) struct RlinkCorruptFile<'a> { } #[derive(Diagnostic)] -#[diag("the compiler unexpectedly panicked. this is a bug.")] +#[diag("the compiler unexpectedly panicked. This is a bug")] pub(crate) struct Ice; #[derive(Diagnostic)] diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 0f330c3021c0..a5de1014dd7a 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -1145,7 +1145,7 @@ pub(crate) struct CastThinPointerToWidePointer<'tcx> { pub expr_ty: Ty<'tcx>, pub cast_ty: Ty<'tcx>, #[note( - "Thin pointers are \"simple\" pointers: they are purely a reference to a + "thin pointers are \"simple\" pointers: they are purely a reference to a memory address. Wide pointers are pointers referencing \"Dynamically Sized Types\" (also diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs index 9b33b49d4406..3354689d0ca3 100644 --- a/compiler/rustc_incremental/src/errors.rs +++ b/compiler/rustc_incremental/src/errors.rs @@ -281,7 +281,7 @@ pub(crate) struct DeleteWorkProduct<'a> { #[derive(Diagnostic)] #[diag( - "corrupt incremental compilation artifact found at `{$path}`. This file will automatically be ignored and deleted. If you see this message repeatedly or can provoke it without manually manipulating the compiler's artifacts, please file an issue. The incremental compilation system relies on hardlinks and filesystem locks behaving correctly, and may not deal well with OS crashes, so whatever information you can provide about your filesystem or other state may be very relevant." + "corrupt incremental compilation artifact found at `{$path}`. This file will automatically be ignored and deleted. If you see this message repeatedly or can provoke it without manually manipulating the compiler's artifacts, please file an issue. The incremental compilation system relies on hardlinks and filesystem locks behaving correctly, and may not deal well with OS crashes, so whatever information you can provide about your filesystem or other state may be very relevant" )] pub(crate) struct CorruptFile<'a> { pub path: &'a Path, diff --git a/compiler/rustc_macros/src/diagnostics/message.rs b/compiler/rustc_macros/src/diagnostics/message.rs index 16ee3c657611..948cc9e93064 100644 --- a/compiler/rustc_macros/src/diagnostics/message.rs +++ b/compiler/rustc_macros/src/diagnostics/message.rs @@ -153,6 +153,7 @@ const ALLOWED_CAPITALIZED_WORDS: &[&str] = &[ "Ferris", "GCC", "MIR", + "NaNs", "OK", "VS", // tidy-alphabetical-end diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index f51e130ea47a..13d8211999e6 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -849,7 +849,7 @@ pub(crate) struct LowerRangeBoundMustBeLessThanOrEqualToUpper { #[label("lower bound larger than upper bound")] pub(crate) span: Span, #[note( - "When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range." + "when matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range" )] pub(crate) teach: bool, } From c1091da34c052b2260c7d4d5e0d4c6a63a34a0b8 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 21:16:53 +0100 Subject: [PATCH 651/978] Fix existing messages in stderrs --- tests/rustdoc-ui/ice-bug-report-url.stderr | 2 +- .../field-access-after-const-eval-fail-in-ty.stderr | 2 +- tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr | 2 +- tests/ui/consts/const-eval/infinite_loop.no_ice.stderr | 2 +- tests/ui/consts/const-eval/issue-52475.stderr | 2 +- tests/ui/consts/const-eval/issue-70723.stderr | 2 +- tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr | 2 +- .../consts/const-eval/stable-metric/ctfe-labelled-loop.stderr | 2 +- .../ui/consts/const-eval/stable-metric/ctfe-recursion.stderr | 2 +- .../const-eval/stable-metric/ctfe-simple-loop.warn.stderr | 4 ++-- .../do-not-ice-long-constant-evaluation-in-for-loop.stderr | 2 +- tests/ui/consts/do-not-ice-on-field-access-of-err-type.stderr | 2 +- tests/ui/consts/timeout.stderr | 2 +- tests/ui/error-codes/E0010-teach.stderr | 2 +- tests/ui/error-codes/E0030-teach.stderr | 2 +- .../ui/explicit-tail-calls/infinite-recursion-in-ctfe.stderr | 2 +- tests/ui/layout/valid_range_oob.stderr | 2 +- tests/ui/mir/lint/storage-live.stderr | 2 +- tests/ui/panics/default-backtrace-ice.stderr | 2 +- tests/ui/privacy/no-ice-on-inference-failure.stderr | 2 +- tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.rs | 2 +- tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.stderr | 2 +- tests/ui/treat-err-as-bug/err.stderr | 2 +- tests/ui/treat-err-as-bug/span_delayed_bug.stderr | 2 +- 24 files changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/rustdoc-ui/ice-bug-report-url.stderr b/tests/rustdoc-ui/ice-bug-report-url.stderr index b6eb8a1792df..bc46b226a703 100644 --- a/tests/rustdoc-ui/ice-bug-report-url.stderr +++ b/tests/rustdoc-ui/ice-bug-report-url.stderr @@ -9,7 +9,7 @@ LL | fn wrong() aborting due to `-Z treat-err-as-bug=1` stack backtrace: -error: the compiler unexpectedly panicked. this is a bug. +error: the compiler unexpectedly panicked. This is a bug note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md diff --git a/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.stderr b/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.stderr index 9d62bbc2187f..735409b77953 100644 --- a/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.stderr +++ b/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.stderr @@ -5,7 +5,7 @@ LL | [(); loop {}].field; | ^^^^^^^ | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. + If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated --> $DIR/field-access-after-const-eval-fail-in-ty.rs:4:10 | diff --git a/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr b/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr index f326da8e26af..a11915d47861 100644 --- a/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr +++ b/tests/ui/consts/const-eval/infinite_loop.eval_limit.stderr @@ -8,7 +8,7 @@ LL | | } | |_________^ | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. + If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated --> $DIR/infinite_loop.rs:13:18 | diff --git a/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr b/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr index f326da8e26af..a11915d47861 100644 --- a/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr +++ b/tests/ui/consts/const-eval/infinite_loop.no_ice.stderr @@ -8,7 +8,7 @@ LL | | } | |_________^ | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. + If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated --> $DIR/infinite_loop.rs:13:18 | diff --git a/tests/ui/consts/const-eval/issue-52475.stderr b/tests/ui/consts/const-eval/issue-52475.stderr index daaee03787f4..5ba0f8732d80 100644 --- a/tests/ui/consts/const-eval/issue-52475.stderr +++ b/tests/ui/consts/const-eval/issue-52475.stderr @@ -9,7 +9,7 @@ LL | | } | |_________^ | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. + If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated --> $DIR/issue-52475.rs:2:18 | diff --git a/tests/ui/consts/const-eval/issue-70723.stderr b/tests/ui/consts/const-eval/issue-70723.stderr index 7cece4ed5d6c..50faa3353e91 100644 --- a/tests/ui/consts/const-eval/issue-70723.stderr +++ b/tests/ui/consts/const-eval/issue-70723.stderr @@ -5,7 +5,7 @@ LL | static _X: () = loop {}; | ^^^^^^^ | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. + If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated --> $DIR/issue-70723.rs:1:1 | diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr index f087c9960c28..47e26c3ed935 100644 --- a/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr +++ b/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr @@ -5,7 +5,7 @@ LL | foo(); | ^^^^^ | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. + If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated --> $DIR/ctfe-fn-call.rs:32:1 | diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr index ecb48fc62a3d..95e280398050 100644 --- a/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr +++ b/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr @@ -11,7 +11,7 @@ LL | | } | |_____^ | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. + If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated --> $DIR/ctfe-labelled-loop.rs:16:1 | diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr index a05d792c95ca..25928b766bda 100644 --- a/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr +++ b/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr @@ -5,7 +5,7 @@ LL | recurse(n - 1) | ^^^^^^^^^^^^^^ | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. + If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated --> $DIR/ctfe-recursion.rs:13:1 | diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr index 2bb9a8a98ec4..44abf8be6bdf 100644 --- a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr +++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr @@ -7,7 +7,7 @@ LL | | } | |_____^ | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. + If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated --> $DIR/ctfe-simple-loop.rs:19:1 | @@ -28,7 +28,7 @@ LL | | } | |_____^ | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. + If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated --> $DIR/ctfe-simple-loop.rs:20:1 | diff --git a/tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.stderr b/tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.stderr index 32a18469ab9e..c28f37bc1670 100644 --- a/tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.stderr +++ b/tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.stderr @@ -5,7 +5,7 @@ LL | [(); loop {}]; | ^^^^^^^ | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. + If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated --> $DIR/do-not-ice-long-constant-evaluation-in-for-loop.rs:10:14 | diff --git a/tests/ui/consts/do-not-ice-on-field-access-of-err-type.stderr b/tests/ui/consts/do-not-ice-on-field-access-of-err-type.stderr index 02b8904fbded..ebf659814e73 100644 --- a/tests/ui/consts/do-not-ice-on-field-access-of-err-type.stderr +++ b/tests/ui/consts/do-not-ice-on-field-access-of-err-type.stderr @@ -5,7 +5,7 @@ LL | let array = [(); { loop {} }]; | ^^^^^^^ | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. + If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated --> $DIR/do-not-ice-on-field-access-of-err-type.rs:5:22 | diff --git a/tests/ui/consts/timeout.stderr b/tests/ui/consts/timeout.stderr index 6afb317c3aff..e96e5875058a 100644 --- a/tests/ui/consts/timeout.stderr +++ b/tests/ui/consts/timeout.stderr @@ -7,7 +7,7 @@ error: constant evaluation is taking a long time = note: in this macro invocation | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. + If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated --> $DIR/timeout.rs:7:1 | diff --git a/tests/ui/error-codes/E0010-teach.stderr b/tests/ui/error-codes/E0010-teach.stderr index 9318e8df7e25..b035cf343e95 100644 --- a/tests/ui/error-codes/E0010-teach.stderr +++ b/tests/ui/error-codes/E0010-teach.stderr @@ -4,7 +4,7 @@ error[E0010]: allocations are not allowed in constants LL | const CON: Vec = vec![1, 2, 3]; | ^^^^^^^^^^^^^ allocation not allowed in constants | - = note: The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created. + = note: the runtime heap is not yet available at compile-time, so no runtime heap allocations can be created error[E0015]: cannot call non-const method `slice::::into_vec::` in constants --> $DIR/E0010-teach.rs:5:23 diff --git a/tests/ui/error-codes/E0030-teach.stderr b/tests/ui/error-codes/E0030-teach.stderr index 50c7d1eee1f4..81c9236b0037 100644 --- a/tests/ui/error-codes/E0030-teach.stderr +++ b/tests/ui/error-codes/E0030-teach.stderr @@ -4,7 +4,7 @@ error[E0030]: lower bound for range pattern must be less than or equal to upper LL | 1000 ..= 5 => {} | ^^^^^^^^^^ lower bound larger than upper bound | - = note: When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range. + = note: when matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range error: aborting due to 1 previous error diff --git a/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.stderr b/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.stderr index b5a96114a583..7bc6281c4674 100644 --- a/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.stderr +++ b/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.stderr @@ -5,7 +5,7 @@ LL | become f(); | ^^^^^^^^^^ | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. + If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated --> $DIR/infinite-recursion-in-ctfe.rs:4:1 | diff --git a/tests/ui/layout/valid_range_oob.stderr b/tests/ui/layout/valid_range_oob.stderr index 1a0c38412503..fc6ebcf1692f 100644 --- a/tests/ui/layout/valid_range_oob.stderr +++ b/tests/ui/layout/valid_range_oob.stderr @@ -1,6 +1,6 @@ 257 > 255 -error: the compiler unexpectedly panicked. this is a bug. +error: the compiler unexpectedly panicked. This is a bug query stack during panic: #0 [layout_of] computing layout of `Foo` diff --git a/tests/ui/mir/lint/storage-live.stderr b/tests/ui/mir/lint/storage-live.stderr index ef0d253b15a8..c8d07314f075 100644 --- a/tests/ui/mir/lint/storage-live.stderr +++ b/tests/ui/mir/lint/storage-live.stderr @@ -13,7 +13,7 @@ LL | StorageLive(a); aborting due to `-Z treat-err-as-bug=1` -error: the compiler unexpectedly panicked. this is a bug. +error: the compiler unexpectedly panicked. This is a bug query stack during panic: end of query stack diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr index a7d99e325d9b..4e48e769d9d5 100644 --- a/tests/ui/panics/default-backtrace-ice.stderr +++ b/tests/ui/panics/default-backtrace-ice.stderr @@ -13,7 +13,7 @@ stack backtrace: (end_short_backtrace) (begin_short_backtrace) -error: the compiler unexpectedly panicked. this is a bug. +error: the compiler unexpectedly panicked. This is a bug diff --git a/tests/ui/privacy/no-ice-on-inference-failure.stderr b/tests/ui/privacy/no-ice-on-inference-failure.stderr index 67476e6e2189..91b99c2890b8 100644 --- a/tests/ui/privacy/no-ice-on-inference-failure.stderr +++ b/tests/ui/privacy/no-ice-on-inference-failure.stderr @@ -8,7 +8,7 @@ LL | | } | |_________^ | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. - If your compilation actually takes a long time, you can safely allow the lint. + If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated --> $DIR/no-ice-on-inference-failure.rs:2:22 | diff --git a/tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.rs b/tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.rs index 8a724b853e13..c3046708e4eb 100644 --- a/tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.rs +++ b/tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.rs @@ -5,7 +5,7 @@ //@ build-fail //@ max-llvm-major-version: 20 -//~? ERROR `-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later. +//~? ERROR `-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later #![feature(no_core)] #![no_core] #![no_main] diff --git a/tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.stderr b/tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.stderr index ac6bd7411fd8..c5f886e3a390 100644 --- a/tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.stderr +++ b/tests/ui/sanitizer/kcfi-arity-requires-llvm-21-0-0.stderr @@ -1,4 +1,4 @@ -error: `-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later. +error: `-Zsanitizer-kcfi-arity` requires LLVM 21.0.0 or later error: aborting due to 1 previous error diff --git a/tests/ui/treat-err-as-bug/err.stderr b/tests/ui/treat-err-as-bug/err.stderr index 2a9935c5d22b..8ff267deacef 100644 --- a/tests/ui/treat-err-as-bug/err.stderr +++ b/tests/ui/treat-err-as-bug/err.stderr @@ -5,7 +5,7 @@ LL | pub static C: u32 = 0 - 1; | ^^^^^ evaluation of `C` failed here -error: the compiler unexpectedly panicked. this is a bug. +error: the compiler unexpectedly panicked. This is a bug query stack during panic: #0 [eval_static_initializer] evaluating initializer of static `C` diff --git a/tests/ui/treat-err-as-bug/span_delayed_bug.stderr b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr index 88983e95cee7..ae1bad55960e 100644 --- a/tests/ui/treat-err-as-bug/span_delayed_bug.stderr +++ b/tests/ui/treat-err-as-bug/span_delayed_bug.stderr @@ -5,7 +5,7 @@ LL | fn main() {} | ^^^^^^^^^ -error: the compiler unexpectedly panicked. this is a bug. +error: the compiler unexpectedly panicked. This is a bug query stack during panic: #0 [trigger_delayed_bug] triggering a delayed bug for testing incremental From 9a114c686f9e618a217f54920530bcbe66cb8a04 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 17:13:30 +0100 Subject: [PATCH 652/978] Convert to inline diagnostics in `rustc_parse` --- Cargo.lock | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_interface/src/interface.rs | 14 +- .../rustc_macros/src/diagnostics/message.rs | 3 +- compiler/rustc_parse/Cargo.toml | 1 - compiler/rustc_parse/messages.ftl | 1043 --------- compiler/rustc_parse/src/errors.rs | 2012 +++++++++++------ compiler/rustc_parse/src/lib.rs | 2 - compiler/rustc_parse/src/parser/attr.rs | 54 +- .../rustc_parse/src/parser/diagnostics.rs | 6 +- compiler/rustc_parse/src/parser/item.rs | 6 +- compiler/rustc_parse/src/parser/tests.rs | 24 +- compiler/rustc_session/src/parse.rs | 4 +- .../ui-fulldeps/mod_dir_path_canonicalized.rs | 2 +- tests/ui-fulldeps/pprust-expr-roundtrip.rs | 2 +- .../pprust-parenthesis-insertion.rs | 2 +- 16 files changed, 1401 insertions(+), 1776 deletions(-) delete mode 100644 compiler/rustc_parse/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 1d2289357300..54822628ca45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4381,7 +4381,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_index", "rustc_lexer", "rustc_macros", diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 3685d4ee7ebb..315b11056085 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -114,7 +114,6 @@ pub fn default_translator() -> Translator { pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ // tidy-alphabetical-start rustc_lint::DEFAULT_LOCALE_RESOURCE, - rustc_parse::DEFAULT_LOCALE_RESOURCE, // tidy-alphabetical-end ]; diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 3dbe1057c19d..722e9a420540 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -53,10 +53,9 @@ pub struct Compiler { pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec) -> Cfg { cfgs.into_iter() .map(|s| { - let psess = ParseSess::emitter_with_note( - vec![rustc_parse::DEFAULT_LOCALE_RESOURCE], - format!("this occurred on the command line: `--cfg={s}`"), - ); + let psess = ParseSess::emitter_with_note(format!( + "this occurred on the command line: `--cfg={s}`" + )); let filename = FileName::cfg_spec_source_code(&s); macro_rules! error { @@ -125,10 +124,9 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec) -> Ch let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() }; for s in specs { - let psess = ParseSess::emitter_with_note( - vec![rustc_parse::DEFAULT_LOCALE_RESOURCE], - format!("this occurred on the command line: `--check-cfg={s}`"), - ); + let psess = ParseSess::emitter_with_note(format!( + "this occurred on the command line: `--check-cfg={s}`" + )); let filename = FileName::cfg_spec_source_code(&s); const VISIT: &str = diff --git a/compiler/rustc_macros/src/diagnostics/message.rs b/compiler/rustc_macros/src/diagnostics/message.rs index 948cc9e93064..ad3ca4d1f8ea 100644 --- a/compiler/rustc_macros/src/diagnostics/message.rs +++ b/compiler/rustc_macros/src/diagnostics/message.rs @@ -3,6 +3,7 @@ use fluent_syntax::ast::{Expression, InlineExpression, Pattern, PatternElement}; use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::Path; +use syn::ext::IdentExt; use synstructure::{Structure, VariantInfo}; use crate::diagnostics::error::span_err; @@ -100,7 +101,7 @@ fn verify_fluent_message(msg_span: Span, message_str: &str, variant: Option<&Var .bindings() .iter() .flat_map(|b| b.ast().ident.as_ref()) - .map(|id| id.to_string()) + .map(|id| id.unraw().to_string()) .collect(); for variable in variable_references(&message) { if !fields.iter().any(|f| f == variable) { diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index f0c84e07a56f..28a67ae12126 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -12,7 +12,6 @@ rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_index = { path = "../rustc_index" } rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl deleted file mode 100644 index 3f3300117460..000000000000 --- a/compiler/rustc_parse/messages.ftl +++ /dev/null @@ -1,1043 +0,0 @@ -parse_add_paren = try adding parentheses - -parse_ambiguous_range_pattern = the range pattern here has ambiguous interpretation -parse_ambiguous_range_pattern_suggestion = add parentheses to clarify the precedence - -parse_array_brackets_instead_of_braces = this is a block expression, not an array - .suggestion = to make an array, use square brackets instead of curly braces - -parse_array_index_offset_of = array indexing not supported in offset_of - -parse_asm_expected_comma = expected token: `,` - .label = expected `,` - -parse_asm_expected_other = expected operand, {$is_inline_asm -> - [false] options - *[true] clobber_abi, options - }, or additional template string - -parse_asm_expected_register_class_or_explicit_register = expected register class or explicit register - -parse_asm_expected_string_literal = expected string literal - .label = not a string literal - -parse_asm_non_abi = at least one abi must be provided as an argument to `clobber_abi` - -parse_asm_requires_template = requires at least a template string argument - -parse_asm_sym_no_path = expected a path for argument to `sym` - -parse_asm_underscore_input = _ cannot be used for input operands - -parse_asm_unsupported_operand = the `{$symbol}` operand cannot be used with `{$macro_name}!` - .label = the `{$symbol}` operand is not meaningful for global-scoped inline assembly, remove it - -parse_assignment_else_not_allowed = ... else {"{"} ... {"}"} is not allowed - -parse_associated_static_item_not_allowed = associated `static` items are not allowed - -parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later - -parse_async_bound_modifier_in_2015 = `async` trait bounds are only allowed in Rust 2018 or later - -parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015 - .label = to use `async fn`, switch to Rust 2018 or later - -parse_async_impl = `async` trait implementations are unsupported - -parse_async_move_block_in_2015 = `async move` blocks are only allowed in Rust 2018 or later - -parse_async_move_order_incorrect = the order of `move` and `async` is incorrect - .suggestion = try switching the order - -parse_async_use_block_in_2015 = `async use` blocks are only allowed in Rust 2018 or later - -parse_async_use_order_incorrect = the order of `use` and `async` is incorrect - .suggestion = try switching the order - -parse_at_dot_dot_in_struct_pattern = `@ ..` is not supported in struct patterns - .suggestion = bind to each field separately or, if you don't need them, just remove `{$ident} @` - -parse_at_in_struct_pattern = unexpected `@` in struct pattern - .note = struct patterns use `field: pattern` syntax to bind to fields - .help = consider replacing `new_name @ field_name` with `field_name: new_name` if that is what you intended - -parse_attr_after_generic = trailing attribute after generic parameter - .label = attributes must go before parameters - -parse_attr_without_generics = attribute without generic parameters - .label = attributes are only permitted when preceding parameters - -parse_attribute_on_empty_type = attributes cannot be applied here - .label = attributes are not allowed here - -parse_attribute_on_generic_arg = attributes cannot be applied to generic arguments - .label = attributes are not allowed here - .suggestion = remove attribute from here - -parse_attribute_on_param_type = attributes cannot be applied to a function parameter's type - .label = attributes are not allowed here - -parse_attribute_on_type = attributes cannot be applied to types - .label = attributes are not allowed here - .suggestion = remove attribute from here - -parse_bad_assoc_type_bounds = bounds on associated types do not belong here - .label = belongs in `where` clause - -parse_bad_item_kind = {$descr} is not supported in {$ctx} - .help = consider moving the {$descr} out to a nearby module scope - -parse_bad_return_type_notation_output = - return type not allowed with return type notation - .suggestion = remove the return type - -parse_bare_cr = {$double_quotes -> - [true] bare CR not allowed in string, use `\r` instead - *[false] character constant must be escaped: `\r` - } - .escape = escape the character - -parse_bare_cr_in_frontmatter = bare CR not allowed in frontmatter - -parse_bare_cr_in_raw_string = bare CR not allowed in raw string - -parse_binder_and_polarity = `for<...>` binder not allowed with `{$polarity}` trait polarity modifier - .label = there is not a well-defined meaning for a higher-ranked `{$polarity}` trait - -parse_binder_before_modifiers = `for<...>` binder should be placed before trait bound modifiers - .label = place the `for<...>` binder before any modifiers - -parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases - -parse_box_not_pat = expected pattern, found {$descr} - .note = `box` is a reserved keyword - .suggestion = escape `box` to use it as an identifier - -parse_box_syntax_removed = `box_syntax` has been removed -parse_box_syntax_removed_suggestion = use `Box::new()` instead - -parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier - -parse_cannot_be_raw_lifetime = `{$ident}` cannot be a raw lifetime - -parse_catch_after_try = keyword `catch` cannot follow a `try` block - .help = try using `match` on the result of the `try` block instead - -parse_colon_as_semi = statements are terminated with a semicolon - .suggestion = use a semicolon instead - -parse_comma_after_base_struct = cannot use a comma after the base struct - .note = the base struct must always be the last field - .suggestion = remove this comma - -parse_comparison_interpreted_as_generic = - `<` is interpreted as a start of generic arguments for `{$type}`, not a comparison - .label_args = interpreted as generic arguments - .label_comparison = not interpreted as comparison - .suggestion = try comparing the cast value - -parse_comparison_operators_cannot_be_chained = comparison operators cannot be chained - .sugg_parentheses_for_function_args = or use `(...)` if you meant to specify fn arguments - .sugg_split_comparison = split the comparison into two - .sugg_parenthesize = parenthesize the comparison -parse_compound_assignment_expression_in_let = can't reassign to an uninitialized variable - .suggestion = initialize the variable - .help = if you meant to overwrite, remove the `let` binding - -parse_const_generic_without_braces = expressions must be enclosed in braces to be used as const generic arguments - .suggestion = enclose the `const` expression in braces - -parse_const_global_cannot_be_mutable = const globals cannot be mutable - .label = cannot be mutable - .suggestion = you might want to declare a static instead - -parse_const_let_mutually_exclusive = `const` and `let` are mutually exclusive - .suggestion = remove `let` - -parse_cr_doc_comment = bare CR not allowed in {$block -> - [true] block doc-comment - *[false] doc-comment -} - -parse_default_not_followed_by_item = `default` is not followed by an item - .label = the `default` qualifier - .note = only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` - -parse_delegation_non_trait_impl_reuse = only trait impls can be reused - -parse_do_catch_syntax_removed = found removed `do catch` syntax - .note = following RFC #2388, the new non-placeholder syntax is `try` - .suggestion = replace with the new syntax - -parse_doc_comment_does_not_document_anything = found a documentation comment that doesn't document anything - .help = doc comments must come before what they document, if a comment was intended use `//` - .suggestion = missing comma here - -parse_doc_comment_on_param_type = documentation comments cannot be applied to a function parameter's type - .label = doc comments are not allowed here - -parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_str}` - .suggestion = to omit remaining fields, use `..` - -parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` are not allowed - .suggestion = use `..=` instead - -parse_dot_dot_range_attribute = attributes are not allowed on range expressions starting with `..` - -parse_dotdotdot = unexpected token: `...` - .suggest_exclusive_range = use `..` for an exclusive range - .suggest_inclusive_range = or `..=` for an inclusive range - -parse_dotdotdot_rest_pattern = unexpected `...` - .label = not a valid pattern - .suggestion = for a rest pattern, use `..` instead of `...` - .note = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list - -parse_dotdotdot_rest_type = unexpected `...` - .note = only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list - -parse_double_colon_in_bound = expected `:` followed by trait or lifetime - .suggestion = use single colon - -parse_dyn_after_mut = `mut` must precede `dyn` - .suggestion = place `mut` before `dyn` - -parse_empty_exponent_float = expected at least one digit in exponent - -parse_empty_unicode_escape = empty unicode escape - .label = this escape must have at least 1 hex digit - -parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern - -parse_enum_struct_mutually_exclusive = `enum` and `struct` are mutually exclusive - .suggestion = replace `enum struct` with - -parse_eq_field_init = expected `:`, found `=` - .suggestion = replace equals symbol with a colon - -parse_escape_only_char = {$byte -> - [true] byte - *[false] character - } constant must be escaped: `{$escaped_msg}` - .escape = escape the character - -parse_expect_dotdot_not_dotdotdot = expected `..`, found `...` - .suggestion = use `..` to fill in the rest of the fields - -parse_expect_eq_instead_of_eqeq = expected `=`, found `==` - .suggestion = consider using `=` here - -parse_expect_label_found_ident = expected a label, found an identifier - .suggestion = labels start with a tick - -parse_expect_path = expected a path - -parse_expected_binding_left_of_at = left-hand side of `@` must be a binding - .label_lhs = interpreted as a pattern, not a binding - .label_rhs = also a pattern - .note = bindings are `x`, `mut x`, `ref x`, and `ref mut x` - -parse_expected_builtin_ident = expected identifier after `builtin #` - -parse_expected_comma_after_pattern_field = expected `,` - -parse_expected_else_block = expected `{"{"}`, found {$first_tok} - .label = expected an `if` or a block after this `else` - .suggestion = add an `if` if this is the condition of a chained `else if` statement - -parse_expected_expression_found_let = expected expression, found `let` statement - .note = only supported directly in conditions of `if` and `while` expressions - .not_supported_or = `||` operators are not supported in let chain expressions - .not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains - -parse_expected_fn_path_found_fn_keyword = expected identifier, found keyword `fn` - .suggestion = use `Fn` to refer to the trait - -parse_expected_identifier = expected identifier - -parse_expected_identifier_found_doc_comment = expected identifier, found doc comment -parse_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token}` -parse_expected_identifier_found_keyword = expected identifier, found keyword -parse_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token}` -parse_expected_identifier_found_metavar = expected identifier, found metavariable -# This one deliberately doesn't print a token. -parse_expected_identifier_found_metavar_str = expected identifier, found metavariable -parse_expected_identifier_found_reserved_identifier = expected identifier, found reserved identifier -parse_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token}` -parse_expected_identifier_found_reserved_keyword = expected identifier, found reserved keyword -parse_expected_identifier_found_reserved_keyword_str = expected identifier, found reserved keyword `{$token}` -parse_expected_identifier_found_str = expected identifier, found `{$token}` - -parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyword in raw pointer type - .suggestion = add `mut` or `const` here - -parse_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token}` -parse_expected_semi_found_keyword_str = expected `;`, found keyword `{$token}` -# This one deliberately doesn't print a token. -parse_expected_semi_found_metavar_str = expected `;`, found metavariable -parse_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token}` -parse_expected_semi_found_reserved_keyword_str = expected `;`, found reserved keyword `{$token}` -parse_expected_semi_found_str = expected `;`, found `{$token}` - -parse_expected_statement_after_outer_attr = expected statement after outer attribute - -parse_expected_struct_field = expected one of `,`, `:`, or `{"}"}`, found `{$token}` - .label = expected one of `,`, `:`, or `{"}"}` - .ident_label = while parsing this struct field - -parse_expected_trait_in_trait_impl_found_type = expected a trait, found type - -parse_expr_rarrow_call = `->` is not valid syntax for field accesses and method calls - .suggestion = try using `.` instead - .help = the `.` operator will automatically dereference the value, except if the value is a raw pointer - -parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements - .label = dash-separated idents are not valid - .suggestion = if the original crate name uses dashes you need to use underscores in the code - -parse_extern_item_cannot_be_const = extern items cannot be `const` - .suggestion = try using a static value - .note = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html - -parse_extra_if_in_let_else = remove the `if` if you meant to write a `let...else` statement - -parse_extra_impl_keyword_in_trait_impl = unexpected `impl` keyword - .suggestion = remove the extra `impl` - .note = this is parsed as an `impl Trait` type, but a trait is expected at this position - - -parse_field_expression_with_generic = field expressions cannot have generic arguments - -parse_float_literal_requires_integer_part = float literals must have an integer part - .suggestion = must have an integer part - -parse_float_literal_unsupported_base = {$base} float literal is not supported - -parse_fn_pointer_cannot_be_async = an `fn` pointer type cannot be `async` - .label = `async` because of this - .suggestion = remove the `async` qualifier - .note = allowed qualifiers are: `unsafe` and `extern` - -parse_fn_pointer_cannot_be_const = an `fn` pointer type cannot be `const` - .label = `const` because of this - .suggestion = remove the `const` qualifier - .note = allowed qualifiers are: `unsafe` and `extern` - -parse_fn_ptr_with_generics = function pointer types may not have generic parameters - .suggestion = consider moving the lifetime {$arity -> - [one] parameter - *[other] parameters - } to {$for_param_list_exists -> - [true] the - *[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}` - .label = expected expression - -parse_frontmatter_extra_characters_after_close = extra characters after frontmatter close are not allowed -parse_frontmatter_invalid_close_preceding_whitespace = invalid preceding whitespace for frontmatter close - .note = frontmatter close should not be preceded by whitespace -parse_frontmatter_invalid_infostring = invalid infostring for frontmatter - .note = frontmatter infostrings must be a single identifier immediately following the opening -parse_frontmatter_invalid_opening_preceding_whitespace = invalid preceding whitespace for frontmatter opening - .note = frontmatter opening should not be preceded by whitespace -parse_frontmatter_length_mismatch = frontmatter close does not match the opening - .label_opening = the opening here has {$len_opening} dashes... - .label_close = ...while the close has {$len_close} dashes -parse_frontmatter_too_many_dashes = too many `-` symbols: frontmatter openings may be delimited by up to 255 `-` symbols, but found {$len_opening} -parse_frontmatter_unclosed = unclosed frontmatter - .note = frontmatter opening here was not closed -parse_function_body_equals_expr = function body cannot be `= expression;` - .suggestion = surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;` - -parse_generic_args_in_pat_require_turbofish_syntax = generic args in patterns require the turbofish syntax - -parse_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets - .suggestion = surround the type parameters with angle brackets - -parse_generics_in_path = unexpected generic arguments in path - -parse_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml` -parse_help_set_edition_standalone = pass `--edition {$edition}` to `rustc` - -parse_hidden_unicode_codepoints = unicode codepoint changing visible direction of text present in {$label} - .label = this {$label} contains {$count -> - [one] an invisible - *[other] invisible - } unicode text flow control {$count -> - [one] codepoint - *[other] codepoints - } - .note = these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen - .suggestion_remove = if their presence wasn't intentional, you can remove them - .suggestion_escape = if you want to keep them but make them visible in your source code, you can escape them - .no_suggestion_note_escape = if you want to keep them but make them visible in your source code, you can escape them: {$escaped} - -parse_if_expression_missing_condition = missing condition for `if` expression - .condition_label = expected condition here - .block_label = if this block is the condition of the `if` expression, then it must be followed by another block - -parse_if_expression_missing_then_block = this `if` expression is missing a block after the condition - .add_then_block = add a block here - .condition_possibly_unfinished = this binary operation is possibly unfinished - -parse_in_in_typo = - expected iterable, found keyword `in` - .suggestion = remove the duplicated `in` - -parse_inappropriate_default = {$article} {$descr} cannot be `default` - .label = `default` because of this - .note = only associated `fn`, `const`, and `type` items can be `default` - -parse_inclusive_range_extra_equals = unexpected `=` after inclusive range - .suggestion_remove_eq = use `..=` instead - .note = inclusive ranges end with a single equals sign (`..=`) - -parse_inclusive_range_match_arrow = unexpected `>` after inclusive range - .label = this is parsed as an inclusive range `..=` - .suggestion = add a space between the pattern and `=>` - -parse_inclusive_range_no_end = inclusive range with no end - .suggestion_open_range = use `..` instead - .note = inclusive ranges must be bounded at the end (`..=b` or `a..=b`) - -parse_incorrect_parens_trait_bounds = incorrect parentheses around trait bounds -parse_incorrect_parens_trait_bounds_sugg = fix the parentheses - -parse_incorrect_semicolon = - expected item, found `;` - .suggestion = remove this semicolon - .help = {$name} declarations are not followed by a semicolon - -parse_incorrect_type_on_self = type not allowed for shorthand `self` parameter - .suggestion = move the modifiers on `self` to the type - -parse_incorrect_use_of_await = incorrect use of `await` - .parentheses_suggestion = `await` is not a method call, remove the parentheses - -parse_incorrect_use_of_await_postfix_suggestion = `await` is a postfix operation - -parse_incorrect_use_of_use = incorrect use of `use` - .parentheses_suggestion = `use` is not a method call, try removing the parentheses - -parse_incorrect_visibility_restriction = incorrect visibility restriction - .help = some possible visibility restrictions are: - `pub(crate)`: visible only on the current crate - `pub(super)`: visible only in the current module's parent - `pub(in path::to::module)`: visible only on the specified path - .suggestion = make this visible only to module `{$inner_str}` with `in` - -parse_inner_attr_explanation = inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -parse_inner_attr_not_permitted = an inner attribute is not permitted in this context - .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this} - .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer} - -parse_inner_attr_not_permitted_after_outer_attr = an inner attribute is not permitted following an outer attribute - .label_attr = not permitted following an outer attribute - .label_prev_attr = previous outer attribute - .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this} - .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer} - -parse_inner_attr_not_permitted_after_outer_doc_comment = an inner attribute is not permitted following an outer doc comment - .label_attr = not permitted following an outer doc comment - .label_prev_doc_comment = previous doc comment - .label_does_not_annotate_this = {parse_label_inner_attr_does_not_annotate_this} - .sugg_change_inner_to_outer = {parse_sugg_change_inner_attr_to_outer} - -parse_inner_doc_comment_not_permitted = expected outer doc comment - .note = inner doc comments like this (starting with `//!` or `/*!`) can only appear before items - .suggestion = you might have meant to write a regular comment - .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item} - .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style - -parse_invalid_block_macro_segment = cannot use a `block` macro fragment here - .label = the `block` fragment is within this context - .suggestion = wrap this in another block - -parse_invalid_char_in_escape = {parse_invalid_char_in_escape_msg}: `{$ch}` - .label = {parse_invalid_char_in_escape_msg} - -parse_invalid_char_in_escape_msg = invalid character in {$is_hex -> - [true] numeric character - *[false] unicode - } escape - - -parse_invalid_comparison_operator = invalid comparison operator `{$invalid}` - .use_instead = `{$invalid}` is not a valid comparison operator, use `{$correct}` - .spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering` - -parse_invalid_curly_in_let_else = right curly brace `{"}"}` before `else` in a `let...else` statement not allowed -parse_invalid_digit_literal = invalid digit for a base {$base} literal - -parse_invalid_dyn_keyword = invalid `dyn` keyword - .help = `dyn` is only needed at the start of a trait `+`-separated list - .suggestion = remove this keyword - -parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else` -parse_invalid_identifier_with_leading_number = identifiers cannot start with a number - -parse_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are invalid - .label = invalid suffix `{$suffix}` - -parse_invalid_logical_operator = `{$incorrect}` is not a logical operator - .note = unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators - .use_amp_amp_for_conjunction = use `&&` to perform logical conjunction - .use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction - -parse_invalid_meta_item = expected unsuffixed literal, found {$descr} - .quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal - -parse_invalid_offset_of = offset_of expects dot-separated field and variant names - -parse_invalid_path_sep_in_fn_definition = invalid path separator in function definition - .suggestion = remove invalid path separator - -parse_invalid_unicode_escape = invalid unicode character escape - .label = invalid escape - .help = unicode escape must {$surrogate -> - [true] not be a surrogate - *[false] be at most 10FFFF - } - -parse_invalid_variable_declaration = - invalid variable declaration - -parse_keyword_label = labels cannot use keyword names - -parse_keyword_lifetime = - lifetimes cannot use keyword names - -parse_kw_bad_case = keyword `{$kw}` is written in the wrong case - .suggestion = write it in {$case} - -parse_label_inner_attr_does_not_annotate_this = the inner attribute doesn't annotate this {$item} -parse_label_unexpected_token = unexpected token - -parse_label_while_parsing_or_pattern_here = while parsing this or-pattern starting here - -parse_labeled_loop_in_break = parentheses are required around this expression to avoid confusion with a labeled break expression - -parse_leading_plus_not_supported = leading `+` is not supported - .label = unexpected `+` - .suggestion_remove_plus = try removing the `+` - -parse_leading_underscore_unicode_escape = {parse_leading_underscore_unicode_escape_label}: `_` -parse_leading_underscore_unicode_escape_label = invalid start of unicode escape - -parse_left_arrow_operator = unexpected token: `<-` - .suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-` - -parse_let_chain_pre_2024 = let chains are only allowed in Rust 2024 or later - -parse_lifetime_after_mut = lifetime must precede `mut` - .suggestion = place the lifetime before `mut` - -parse_lifetime_in_borrow_expression = borrow expressions cannot be annotated with lifetimes - .suggestion = remove the lifetime annotation - .label = annotated with lifetime here - -parse_lifetime_in_eq_constraint = lifetimes are not permitted in this context - .label = lifetime is not allowed here - .context_label = this introduces an associated item binding - .help = if you meant to specify a trait object, write `dyn /* Trait */ + {$lifetime}` - .colon_sugg = you might have meant to write a bound here - -parse_lone_slash = invalid trailing slash in literal - .label = {parse_lone_slash} - -parse_loop_else = `{$loop_kind}...else` loops are not supported - .note = consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run - .loop_keyword = `else` is attached to this loop - -parse_macro_expands_to_adt_field = macros cannot expand to {$adt_ty} fields - -parse_macro_expands_to_enum_variant = macros cannot expand to enum variants - -parse_macro_invocation_visibility = can't qualify macro invocation with `pub` - .suggestion = remove the visibility - .help = try adjusting the macro to put `{$vis}` inside the invocation - -parse_macro_invocation_with_qualified_path = macros cannot use qualified paths - -parse_macro_name_remove_bang = macro names aren't followed by a `!` - .suggestion = remove the `!` - -parse_macro_rules_missing_bang = expected `!` after `macro_rules` - .suggestion = add a `!` - -parse_macro_rules_visibility = can't qualify macro_rules invocation with `{$vis}` - .suggestion = try exporting the macro - -parse_malformed_loop_label = malformed loop label - .suggestion = use the correct loop label format - -parse_match_arm_body_without_braces = `match` arm body without braces - .label_statements = {$num_statements -> - [one] this statement is not surrounded by a body - *[other] these statements are not surrounded by a body - } - .label_arrow = while parsing the `match` arm starting here - .suggestion_add_braces = surround the {$num_statements -> - [one] statement - *[other] statements - } with a body - .suggestion_use_comma_not_semicolon = replace `;` with `,` to end a `match` arm expression - -parse_maybe_comparison = you might have meant to compare for equality - -parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn` - .suggestion = replace `fn` with `impl` here - -parse_maybe_missing_let = you might have meant to continue the let-chain - -parse_maybe_recover_from_bad_qpath_stage_2 = - missing angle brackets in associated item path - .suggestion = types that don't start with an identifier need to be surrounded with angle brackets in qualified paths - -parse_maybe_recover_from_bad_type_plus = - expected a path on the left-hand side of `+` - -parse_maybe_report_ambiguous_plus = - ambiguous `+` in a type - .suggestion = use parentheses to disambiguate - -parse_mismatched_closing_delimiter = mismatched closing delimiter: `{$delimiter}` - .label_unmatched = mismatched closing delimiter - .label_opening_candidate = closing delimiter possibly meant for this - .label_unclosed = unclosed delimiter - -parse_misplaced_return_type = place the return type after the function parameters - -parse_missing_comma_after_match_arm = expected `,` following `match` arm - .suggestion = missing a comma here to end this `match` arm - -parse_missing_const_type = missing type for `{$kind}` item - .suggestion = provide a type for the item - -parse_missing_enum_for_enum_definition = missing `enum` for enum definition - .suggestion = add `enum` here to parse `{$ident}` as an enum - -parse_missing_enum_or_struct_for_item_definition = missing `enum` or `struct` for enum or struct definition - -parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop - .suggestion = try adding an expression to the `for` loop - -parse_missing_fn_for_function_definition = missing `fn` for function definition - .suggestion = add `fn` here to parse `{$ident}` as a function - -parse_missing_fn_for_method_definition = missing `fn` for method definition - .suggestion = add `fn` here to parse `{$ident}` as a method - -parse_missing_fn_or_struct_for_item_definition = missing `fn` or `struct` for function or struct definition - .suggestion = if you meant to call a macro, try - .help = if you meant to call a macro, remove the `pub` and add a trailing `!` after the identifier - -parse_missing_fn_params = missing parameters for function definition - .suggestion = add a parameter list - -parse_missing_for_in_trait_impl = missing `for` in a trait impl - .suggestion = add `for` here - -parse_missing_in_in_for_loop = missing `in` in `for` loop - .use_in = try using `in` here instead - .add_in = try adding `in` here - -parse_missing_let_before_mut = missing keyword -parse_missing_plus_in_bounds = expected `+` between lifetime and {$sym} - .suggestion = add `+` - -parse_missing_semicolon_before_array = expected `;`, found `[` - .suggestion = consider adding `;` here - -parse_missing_struct_for_struct_definition = missing `struct` for struct definition - .suggestion = add `struct` here to parse `{$ident}` as a struct - -parse_missing_trait_in_trait_impl = missing trait in a trait impl - .suggestion_add_trait = add a trait here - .suggestion_remove_for = for an inherent impl, drop this `for` - -parse_misspelled_kw = {$is_incorrect_case -> - [true] write keyword `{$similar_kw}` in lowercase - *[false] there is a keyword `{$similar_kw}` with a similar name -} - -parse_modifier_lifetime = `{$modifier}` may only modify trait bounds, not lifetime bounds - .suggestion = remove the `{$modifier}` - -parse_modifiers_and_polarity = `{$modifiers_concatenated}` trait not allowed with `{$polarity}` trait polarity modifier - .label = there is not a well-defined meaning for a `{$modifiers_concatenated} {$polarity}` trait - -parse_more_than_one_char = character literal may only contain one codepoint - .followed_by = this `{$chr}` is followed by the combining {$len -> - [one] mark - *[other] marks - } `{$escaped_marks}` - .non_printing = there are non-printing characters, the full sequence is `{$escaped}` - .consider_normalized = consider using the normalized form `{$ch}` of this character - .remove_non = consider removing the non-printing characters - .use_double_quotes = if you meant to write a {$is_byte -> - [true] byte string - *[false] string - } literal, use double quotes - -parse_multiple_skipped_lines = multiple lines skipped by escaped newline - .label = skipping everything up to and including this point - -parse_multiple_where_clauses = cannot define duplicate `where` clauses on an item - .label = previous `where` clause starts here - .suggestion = consider joining the two `where` clauses into one - -parse_mut_on_nested_ident_pattern = `mut` must be attached to each individual binding - .suggestion = add `mut` to each binding -parse_mut_on_non_ident_pattern = `mut` must be followed by a named binding - .suggestion = remove the `mut` prefix - -parse_need_plus_after_trait_object_lifetime = lifetimes must be followed by `+` to form a trait object type - .suggestion = consider adding a trait bound after the potential lifetime bound - -parse_nested_adt = `{$kw_str}` definition cannot be nested inside `{$keyword}` - .suggestion = consider creating a new `{$kw_str}` definition instead of nesting - -parse_nested_c_variadic_type = C-variadic type `...` may not be nested inside another type - -parse_no_brace_unicode_escape = incorrect unicode escape sequence - .label = {parse_no_brace_unicode_escape} - .use_braces = format of unicode escape sequences uses braces - .format_of_unicode = format of unicode escape sequences is `\u{"{...}"}` - -parse_no_digits_literal = no valid digits found for number - -parse_non_string_abi_literal = non-string ABI literal - .suggestion = specify the ABI with a string literal - -parse_nonterminal_expected_ident = expected ident, found `{$token}` -parse_nonterminal_expected_item_keyword = expected an item keyword -parse_nonterminal_expected_lifetime = expected a lifetime, found `{$token}` - -parse_nonterminal_expected_statement = expected a statement - -parse_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide - -parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable @ pattern` - -parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||` - -parse_nul_in_c_str = null characters in C string literals are not supported - -parse_or_in_let_chain = `||` operators are not supported in let chain conditions - -parse_or_pattern_not_allowed_in_fn_parameters = function parameters require top-level or-patterns in parentheses -parse_or_pattern_not_allowed_in_let_binding = `let` bindings require top-level or-patterns in parentheses - -parse_outer_attr_explanation = outer attributes, like `#[test]`, annotate the item following them - -parse_outer_attribute_not_allowed_on_if_else = outer attributes are not allowed on `if` and `else` branches - .branch_label = the attributes are attached to this branch - .ctx_label = the branch belongs to this `{$ctx}` - .suggestion = remove the attributes - -parse_overlong_unicode_escape = overlong unicode escape - .label = must have at most 6 hex digits - -parse_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call arguments - .suggestion_braces_for_struct = if `{$type}` is a struct, use braces as delimiters - .suggestion_no_fields_for_fn = if `{$type}` is a function, use the arguments directly - -parse_path_double_colon = path separator must be a double colon - .suggestion = use a double colon instead - - -parse_path_found_attribute_in_params = `Trait(...)` syntax does not support attributes in parameters - .suggestion = remove the attributes - -parse_path_found_c_variadic_params = `Trait(...)` syntax does not support c_variadic parameters - .suggestion = remove the `...` - -parse_path_found_named_params = `Trait(...)` syntax does not support named parameters - .suggestion = remove the parameter name - -parse_pattern_method_param_without_body = patterns aren't allowed in methods without bodies - .suggestion = give this argument a name or use an underscore to ignore it - -parse_pattern_on_wrong_side_of_at = pattern on wrong side of `@` - .label_pattern = pattern on the left, should be on the right - .label_binding = binding on the right, should be on the left - .suggestion = switch the order - -parse_question_mark_in_type = invalid `?` in type - .label = `?` is only allowed on expressions, not types - .suggestion = if you meant to express that the type might not contain a value, use the `Option` wrapper type - -parse_recover_import_as_use = expected item, found {$token_name} - .suggestion = items are imported using the `use` keyword - -parse_remove_let = expected pattern, found `let` - .suggestion = remove the unnecessary `let` keyword - -parse_repeated_mut_in_pattern = `mut` on a binding may not be repeated - .suggestion = remove the additional `mut`s - -parse_require_colon_after_labeled_expression = labeled expression must be followed by `:` - .note = labels are used before loops and blocks, allowing e.g., `break 'label` to them - .label = the label - .suggestion = add `:` after the label - -parse_reserved_multihash = reserved multi-hash token is forbidden - .note = sequences of two or more # are reserved for future use since Rust 2024 - .suggestion_whitespace = consider inserting whitespace here - -parse_reserved_string = invalid string literal - .note = unprefixed guarded string literals are reserved for future use since Rust 2024 - .suggestion_whitespace = consider inserting whitespace here - -parse_return_types_use_thin_arrow = return types are denoted using `->` - .suggestion = use `->` instead - -parse_self_argument_pointer = cannot pass `self` by raw pointer - .label = cannot pass `self` by raw pointer - -parse_self_param_not_first = unexpected `self` parameter in function - .label = must be the first parameter of an associated function - -parse_shift_interpreted_as_generic = - `<<` is interpreted as a start of generic arguments for `{$type}`, not a shift - .label_args = interpreted as generic arguments - .label_comparison = not interpreted as shift - .suggestion = try shifting the cast value - -parse_single_colon_import_path = expected `::`, found `:` - .suggestion = use double colon - .note = import paths are delimited using `::` - -parse_static_with_generics = static items may not have generic parameters - -parse_struct_literal_body_without_path = - struct literal body without path - .suggestion = you might have forgotten to add the struct literal inside the block - -parse_struct_literal_body_without_path_late = - struct literal body without path - .label = struct name missing for struct literal - .suggestion = add the correct type - -parse_struct_literal_not_allowed_here = struct literals are not allowed here - .suggestion = surround the struct literal with parentheses - -parse_struct_literal_placeholder_path = - placeholder `_` is not allowed for the path in struct literals - .label = not allowed in struct literals - .suggestion = replace it with the correct type - -parse_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes - .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) - -parse_sugg_add_let_for_stmt = you might have meant to introduce a new binding - -parse_sugg_add_semi = add `;` here -parse_sugg_change_inner_attr_to_outer = to annotate the {$item}, change the attribute from inner to outer style - -parse_sugg_change_this_to_semi = change this to `;` -parse_sugg_escape_identifier = escape `{$ident_name}` to use it as an identifier - -parse_sugg_remove_comma = remove this comma -parse_sugg_remove_leading_vert_in_pattern = remove the `|` -parse_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments - -parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses - -parse_sugg_wrap_macro_in_parentheses = use parentheses instead of braces for this macro - -parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses - -parse_switch_mut_let_order = - switch the order of `mut` and `let` - -parse_switch_ref_box_order = switch the order of `ref` and `box` - .suggestion = swap them - -parse_ternary_operator = Rust has no ternary operator - -parse_tilde_is_not_unary_operator = `~` cannot be used as a unary operator - .suggestion = use `!` to perform bitwise not - -parse_too_many_hashes = too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found {$num} - -parse_too_short_hex_escape = numeric character escape is too short - -parse_trailing_vert_not_allowed = a trailing `{$token}` is not allowed in an or-pattern - -parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto` -parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe` - -parse_trait_impl_modifier_in_inherent_impl = inherent impls cannot be {$modifier_name} - .because = {$modifier_name} because of this - .type = inherent impl for this type - .note = only trait implementations may be annotated with `{$modifier}` - -parse_transpose_dyn_or_impl = `for<...>` expected after `{$kw}`, not before - .suggestion = move `{$kw}` before the `for<...>` - -parse_unclosed_unicode_escape = unterminated unicode escape - .label = missing a closing `{"}"}` - .terminate = terminate the unicode escape - -parse_underscore_literal_suffix = underscore literal suffix is not allowed - -parse_unexpected_const_in_generic_param = expected lifetime, type, or constant, found keyword `const` - .suggestion = the `const` keyword is only needed in the definition of the type - -parse_unexpected_const_param_declaration = unexpected `const` parameter declaration - .label = expected a `const` expression, not a parameter declaration - .suggestion = `const` parameters must be declared for the `impl` - -parse_unexpected_default_value_for_lifetime_in_generic_parameters = unexpected default lifetime parameter - .label = lifetime parameters cannot have default values - -parse_unexpected_expr_in_pat = - expected {$is_bound -> - [true] a pattern range bound - *[false] a pattern - }, found an expression - - .label = not a pattern - .note = arbitrary expressions are not allowed in patterns: - -parse_unexpected_expr_in_pat_const_sugg = consider extracting the expression into a `const` - -parse_unexpected_expr_in_pat_create_guard_sugg = consider moving the expression to a match arm guard - -parse_unexpected_expr_in_pat_update_guard_sugg = consider moving the expression to the match arm guard - -parse_unexpected_if_with_if = unexpected `if` in the condition expression - .suggestion = remove the `if` - -parse_unexpected_lifetime_in_pattern = unexpected lifetime `{$symbol}` in pattern - .suggestion = remove the lifetime - -parse_unexpected_paren_in_range_pat = range pattern bounds cannot have parentheses -parse_unexpected_paren_in_range_pat_sugg = remove these parentheses - -parse_unexpected_parentheses_in_for_head = unexpected parentheses surrounding `for` loop head - .suggestion = remove parentheses in `for` loop - -parse_unexpected_parentheses_in_match_arm_pattern = unexpected parentheses surrounding `match` arm pattern - .suggestion = remove parentheses surrounding the pattern - -parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters - .note = you cannot use `Self` as a generic parameter because it is reserved for associated items - -parse_unexpected_token_after_dot = unexpected token: {$actual} - -parse_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label - .suggestion_remove_label = consider removing the label - .suggestion_enclose_in_block = consider enclosing expression in a block - -parse_unexpected_token_after_not = unexpected {$negated_desc} after identifier -parse_unexpected_token_after_not_bitwise = use `!` to perform bitwise not -parse_unexpected_token_after_not_default = use `!` to perform logical negation or bitwise not - -parse_unexpected_token_after_not_logical = use `!` to perform logical negation -parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name -parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}` -parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}` -# This one deliberately doesn't print a token. -parse_unexpected_token_after_struct_name_found_metavar = expected `where`, `{"{"}`, `(`, or `;` after struct name, found metavar -parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}` - -parse_unexpected_token_after_struct_name_found_reserved_identifier = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved identifier `{$token}` -parse_unexpected_token_after_struct_name_found_reserved_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved keyword `{$token}` -parse_unexpected_vert_vert_before_function_parameter = unexpected `||` before function parameter - .suggestion = remove the `||` - -parse_unexpected_vert_vert_in_pattern = unexpected token `||` in pattern - .suggestion = use a single `|` to separate multiple alternative patterns - -parse_unicode_escape_in_byte = unicode escape in byte string - .label = {parse_unicode_escape_in_byte} - .help = unicode escape sequences cannot be used as a byte or in a byte string - -parse_unknown_builtin_construct = unknown `builtin #` construct `{$name}` - -parse_unknown_prefix = prefix `{$prefix}` is unknown - .label = unknown prefix - .note = prefixed identifiers and literals are reserved since Rust 2021 - .suggestion_br = use `br` for a raw byte string - .suggestion_cr = use `cr` for a raw C-string - .suggestion_str = if you meant to write a string literal, use double quotes - .suggestion_whitespace = consider inserting whitespace here - -parse_unknown_start_of_token = unknown start of token: {$escaped} - .sugg_quotes = Unicode characters '“' (Left Double Quotation Mark) and '”' (Right Double Quotation Mark) look like '{$ascii_str}' ({$ascii_name}), but are not - .sugg_other = Unicode character '{$ch}' ({$u_name}) looks like '{$ascii_str}' ({$ascii_name}), but it is not - .help_null = source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used - .help_invisible_char = invisible characters like '{$escaped}' are not usually visible in text editors - .note_repeats = character appears {$repeats -> - [one] once more - *[other] {$repeats} more times - } - -parse_unmatched_angle = unmatched angle {$plural -> - [true] brackets - *[false] bracket - } - .suggestion = remove extra angle {$plural -> - [true] brackets - *[false] bracket - } - -parse_unmatched_angle_brackets = {$num_extra_brackets -> - [one] unmatched angle bracket - *[other] unmatched angle brackets - } - .suggestion = {$num_extra_brackets -> - [one] remove extra angle bracket - *[other] remove extra angle brackets - } - - -parse_unskipped_whitespace = whitespace symbol '{$ch}' is not skipped - .label = {parse_unskipped_whitespace} - -parse_use_empty_block_not_semi = expected { "`{}`" }, found `;` - .suggestion = try using { "`{}`" } instead - -parse_use_eq_instead = unexpected `==` - .suggestion = try using `=` instead - -parse_use_if_else = use an `if-else` expression instead - -parse_use_let_not_auto = write `let` instead of `auto` to introduce a new variable -parse_use_let_not_var = write `let` instead of `var` to introduce a new variable - -parse_varargs_without_pattern = missing pattern for `...` argument - .suggestion = name the argument, or use `_` to continue ignoring it - -parse_visibility_not_followed_by_item = visibility `{$vis}` is not followed by an item - .label = the visibility - .help = you likely meant to define an item, e.g., `{$vis} fn foo() {"{}"}` - -parse_where_clause_before_const_body = where clauses are not allowed before const item bodies - .label = unexpected where clause - .name_label = while parsing this const item - .body_label = the item body - .suggestion = move the body before the where clause - -parse_where_clause_before_tuple_struct_body = where clauses are not allowed before tuple struct bodies - .label = unexpected where clause - .name_label = while parsing this tuple struct - .body_label = the struct body - .suggestion = move the body before the where clause - -parse_where_generics = generic parameters on `where` clauses are reserved for future use - .label = currently unsupported - -parse_zero_chars = empty character literal - .label = {parse_zero_chars} diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 8991e3b9d502..4a7031257700 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -9,17 +9,15 @@ use rustc_ast::{Path, Visibility}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, - Level, Subdiagnostic, SuggestionStyle, + Level, Subdiagnostic, SuggestionStyle, inline_fluent, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; use rustc_span::{Ident, Span, Symbol}; -use crate::fluent_generated as fluent; - #[derive(Diagnostic)] -#[diag(parse_maybe_report_ambiguous_plus)] +#[diag("ambiguous `+` in a type")] pub(crate) struct AmbiguousPlus { #[primary_span] pub span: Span, @@ -28,7 +26,7 @@ pub(crate) struct AmbiguousPlus { } #[derive(Diagnostic)] -#[diag(parse_maybe_recover_from_bad_type_plus, code = E0178)] +#[diag("expected a path on the left-hand side of `+`", code = E0178)] pub(crate) struct BadTypePlus { #[primary_span] pub span: Span, @@ -37,7 +35,7 @@ pub(crate) struct BadTypePlus { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_add_paren, applicability = "machine-applicable")] +#[multipart_suggestion("try adding parentheses", applicability = "machine-applicable")] pub(crate) struct AddParen { #[suggestion_part(code = "(")] pub lo: Span, @@ -51,12 +49,12 @@ pub(crate) enum BadTypePlusSub { #[subdiagnostic] suggestion: AddParen, }, - #[label(parse_forgot_paren)] + #[label("perhaps you forgot parentheses?")] ForgotParen { #[primary_span] span: Span, }, - #[label(parse_expect_path)] + #[label("expected a path")] ExpectPath { #[primary_span] span: Span, @@ -64,7 +62,7 @@ pub(crate) enum BadTypePlusSub { } #[derive(Diagnostic)] -#[diag(parse_maybe_recover_from_bad_qpath_stage_2)] +#[diag("missing angle brackets in associated item path")] pub(crate) struct BadQPathStage2 { #[primary_span] pub span: Span, @@ -73,21 +71,24 @@ pub(crate) struct BadQPathStage2 { } #[derive(Diagnostic)] -#[diag(parse_trait_impl_modifier_in_inherent_impl)] -#[note] +#[diag("inherent impls cannot be {$modifier_name}")] +#[note("only trait implementations may be annotated with `{$modifier}`")] pub(crate) struct TraitImplModifierInInherentImpl { #[primary_span] pub span: Span, pub modifier: &'static str, pub modifier_name: &'static str, - #[label(parse_because)] + #[label("{$modifier_name} because of this")] pub modifier_span: Span, - #[label(parse_type)] + #[label("inherent impl for this type")] pub self_ty: Span, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "types that don't start with an identifier need to be surrounded with angle brackets in qualified paths", + applicability = "machine-applicable" +)] pub(crate) struct WrapType { #[suggestion_part(code = "<")] pub lo: Span, @@ -96,22 +97,27 @@ pub(crate) struct WrapType { } #[derive(Diagnostic)] -#[diag(parse_incorrect_semicolon)] +#[diag("expected item, found `;`")] pub(crate) struct IncorrectSemicolon<'a> { #[primary_span] - #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] + #[suggestion( + "remove this semicolon", + style = "verbose", + code = "", + applicability = "machine-applicable" + )] pub span: Span, - #[help] + #[help("{$name} declarations are not followed by a semicolon")] pub show_help: bool, pub name: &'a str, } #[derive(Diagnostic)] -#[diag(parse_incorrect_use_of_await)] +#[diag("incorrect use of `await`")] pub(crate) struct IncorrectUseOfAwait { #[primary_span] #[suggestion( - parse_parentheses_suggestion, + "`await` is not a method call, remove the parentheses", style = "verbose", code = "", applicability = "machine-applicable" @@ -120,11 +126,11 @@ pub(crate) struct IncorrectUseOfAwait { } #[derive(Diagnostic)] -#[diag(parse_incorrect_use_of_use)] +#[diag("incorrect use of `use`")] pub(crate) struct IncorrectUseOfUse { #[primary_span] #[suggestion( - parse_parentheses_suggestion, + "`use` is not a method call, try removing the parentheses", style = "verbose", code = "", applicability = "machine-applicable" @@ -133,10 +139,7 @@ pub(crate) struct IncorrectUseOfUse { } #[derive(Subdiagnostic)] -#[multipart_suggestion( - parse_incorrect_use_of_await_postfix_suggestion, - applicability = "machine-applicable" -)] +#[multipart_suggestion("`await` is a postfix operation", applicability = "machine-applicable")] pub(crate) struct AwaitSuggestion { #[suggestion_part(code = "")] pub removal: Span, @@ -146,7 +149,7 @@ pub(crate) struct AwaitSuggestion { } #[derive(Diagnostic)] -#[diag(parse_incorrect_use_of_await)] +#[diag("incorrect use of `await`")] pub(crate) struct IncorrectAwait { #[primary_span] pub span: Span, @@ -155,16 +158,21 @@ pub(crate) struct IncorrectAwait { } #[derive(Diagnostic)] -#[diag(parse_in_in_typo)] +#[diag("expected iterable, found keyword `in`")] pub(crate) struct InInTypo { #[primary_span] pub span: Span, - #[suggestion(code = "", style = "verbose", applicability = "machine-applicable")] + #[suggestion( + "remove the duplicated `in`", + code = "", + style = "verbose", + applicability = "machine-applicable" + )] pub sugg_span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_variable_declaration)] +#[diag("invalid variable declaration")] pub(crate) struct InvalidVariableDeclaration { #[primary_span] pub span: Span, @@ -175,28 +183,28 @@ pub(crate) struct InvalidVariableDeclaration { #[derive(Subdiagnostic)] pub(crate) enum InvalidVariableDeclarationSub { #[suggestion( - parse_switch_mut_let_order, + "switch the order of `mut` and `let`", style = "verbose", applicability = "maybe-incorrect", code = "let mut" )] SwitchMutLetOrder(#[primary_span] Span), #[suggestion( - parse_missing_let_before_mut, + "missing keyword", applicability = "machine-applicable", style = "verbose", code = "let mut" )] MissingLet(#[primary_span] Span), #[suggestion( - parse_use_let_not_auto, + "write `let` instead of `auto` to introduce a new variable", style = "verbose", applicability = "machine-applicable", code = "let" )] UseLetNotAuto(#[primary_span] Span), #[suggestion( - parse_use_let_not_var, + "write `let` instead of `var` to introduce a new variable", style = "verbose", applicability = "machine-applicable", code = "let" @@ -205,15 +213,20 @@ pub(crate) enum InvalidVariableDeclarationSub { } #[derive(Diagnostic)] -#[diag(parse_switch_ref_box_order)] +#[diag("switch the order of `ref` and `box`")] pub(crate) struct SwitchRefBoxOrder { #[primary_span] - #[suggestion(applicability = "machine-applicable", style = "verbose", code = "box ref")] + #[suggestion( + "swap them", + applicability = "machine-applicable", + style = "verbose", + code = "box ref" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_comparison_operator)] +#[diag("invalid comparison operator `{$invalid}`")] pub(crate) struct InvalidComparisonOperator { #[primary_span] pub span: Span, @@ -225,7 +238,7 @@ pub(crate) struct InvalidComparisonOperator { #[derive(Subdiagnostic)] pub(crate) enum InvalidComparisonOperatorSub { #[suggestion( - parse_use_instead, + "`{$invalid}` is not a valid comparison operator, use `{$correct}`", style = "verbose", applicability = "machine-applicable", code = "{correct}" @@ -236,13 +249,13 @@ pub(crate) enum InvalidComparisonOperatorSub { invalid: String, correct: String, }, - #[label(parse_spaceship_operator_invalid)] + #[label("`<=>` is not a valid comparison operator, use `std::cmp::Ordering`")] Spaceship(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(parse_invalid_logical_operator)] -#[note] +#[diag("`{$incorrect}` is not a logical operator")] +#[note("unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators")] pub(crate) struct InvalidLogicalOperator { #[primary_span] pub span: Span, @@ -254,14 +267,14 @@ pub(crate) struct InvalidLogicalOperator { #[derive(Subdiagnostic)] pub(crate) enum InvalidLogicalOperatorSub { #[suggestion( - parse_use_amp_amp_for_conjunction, + "use `&&` to perform logical conjunction", style = "verbose", applicability = "machine-applicable", code = "&&" )] Conjunction(#[primary_span] Span), #[suggestion( - parse_use_pipe_pipe_for_disjunction, + "use `||` to perform logical disjunction", style = "verbose", applicability = "machine-applicable", code = "||" @@ -270,15 +283,20 @@ pub(crate) enum InvalidLogicalOperatorSub { } #[derive(Diagnostic)] -#[diag(parse_tilde_is_not_unary_operator)] +#[diag("`~` cannot be used as a unary operator")] pub(crate) struct TildeAsUnaryOperator( #[primary_span] - #[suggestion(style = "verbose", applicability = "machine-applicable", code = "!")] + #[suggestion( + "use `!` to perform bitwise not", + style = "verbose", + applicability = "machine-applicable", + code = "!" + )] pub Span, ); #[derive(Diagnostic)] -#[diag(parse_unexpected_token_after_not)] +#[diag("unexpected {$negated_desc} after identifier")] pub(crate) struct NotAsNegationOperator { #[primary_span] pub negated: Span, @@ -290,7 +308,7 @@ pub(crate) struct NotAsNegationOperator { #[derive(Subdiagnostic)] pub(crate) enum NotAsNegationOperatorSub { #[suggestion( - parse_unexpected_token_after_not_default, + "use `!` to perform logical negation or bitwise not", style = "verbose", applicability = "machine-applicable", code = "!" @@ -298,7 +316,7 @@ pub(crate) enum NotAsNegationOperatorSub { SuggestNotDefault(#[primary_span] Span), #[suggestion( - parse_unexpected_token_after_not_bitwise, + "use `!` to perform bitwise not", style = "verbose", applicability = "machine-applicable", code = "!" @@ -306,7 +324,7 @@ pub(crate) enum NotAsNegationOperatorSub { SuggestNotBitwise(#[primary_span] Span), #[suggestion( - parse_unexpected_token_after_not_logical, + "use `!` to perform logical negation", style = "verbose", applicability = "machine-applicable", code = "!" @@ -315,46 +333,59 @@ pub(crate) enum NotAsNegationOperatorSub { } #[derive(Diagnostic)] -#[diag(parse_malformed_loop_label)] +#[diag("malformed loop label")] pub(crate) struct MalformedLoopLabel { #[primary_span] pub span: Span, - #[suggestion(applicability = "machine-applicable", code = "'", style = "verbose")] + #[suggestion( + "use the correct loop label format", + applicability = "machine-applicable", + code = "'", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_lifetime_in_borrow_expression)] +#[diag("borrow expressions cannot be annotated with lifetimes")] pub(crate) struct LifetimeInBorrowExpression { #[primary_span] pub span: Span, - #[suggestion(applicability = "machine-applicable", code = "", style = "verbose")] - #[label] + #[suggestion( + "remove the lifetime annotation", + applicability = "machine-applicable", + code = "", + style = "verbose" + )] + #[label("annotated with lifetime here")] pub lifetime_span: Span, } #[derive(Diagnostic)] -#[diag(parse_field_expression_with_generic)] +#[diag("field expressions cannot have generic arguments")] pub(crate) struct FieldExpressionWithGeneric(#[primary_span] pub Span); #[derive(Diagnostic)] -#[diag(parse_macro_invocation_with_qualified_path)] +#[diag("macros cannot use qualified paths")] pub(crate) struct MacroInvocationWithQualifiedPath(#[primary_span] pub Span); #[derive(Diagnostic)] -#[diag(parse_unexpected_token_after_label)] +#[diag("expected `while`, `for`, `loop` or `{\"{\"}` after a label")] pub(crate) struct UnexpectedTokenAfterLabel { #[primary_span] - #[label(parse_unexpected_token_after_label)] + #[label("expected `while`, `for`, `loop` or `{\"{\"}` after a label")] pub span: Span, - #[suggestion(parse_suggestion_remove_label, style = "verbose", code = "")] + #[suggestion("consider removing the label", style = "verbose", code = "")] pub remove_label: Option, #[subdiagnostic] pub enclose_in_block: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion_enclose_in_block, applicability = "machine-applicable")] +#[multipart_suggestion( + "consider enclosing expression in a block", + applicability = "machine-applicable" +)] pub(crate) struct UnexpectedTokenAfterLabelSugg { #[suggestion_part(code = "{{ ")] pub left: Span, @@ -363,66 +394,91 @@ pub(crate) struct UnexpectedTokenAfterLabelSugg { } #[derive(Diagnostic)] -#[diag(parse_require_colon_after_labeled_expression)] -#[note] +#[diag("labeled expression must be followed by `:`")] +#[note("labels are used before loops and blocks, allowing e.g., `break 'label` to them")] pub(crate) struct RequireColonAfterLabeledExpression { #[primary_span] pub span: Span, - #[label] + #[label("the label")] pub label: Span, - #[suggestion(style = "verbose", applicability = "machine-applicable", code = ": ")] + #[suggestion( + "add `:` after the label", + style = "verbose", + applicability = "machine-applicable", + code = ": " + )] pub label_end: Span, } #[derive(Diagnostic)] -#[diag(parse_do_catch_syntax_removed)] -#[note] +#[diag("found removed `do catch` syntax")] +#[note("following RFC #2388, the new non-placeholder syntax is `try`")] pub(crate) struct DoCatchSyntaxRemoved { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "try", style = "verbose")] + #[suggestion( + "replace with the new syntax", + applicability = "machine-applicable", + code = "try", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_float_literal_requires_integer_part)] +#[diag("float literals must have an integer part")] pub(crate) struct FloatLiteralRequiresIntegerPart { #[primary_span] pub span: Span, - #[suggestion(applicability = "machine-applicable", code = "0", style = "verbose")] + #[suggestion( + "must have an integer part", + applicability = "machine-applicable", + code = "0", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_missing_semicolon_before_array)] +#[diag("expected `;`, found `[`")] pub(crate) struct MissingSemicolonBeforeArray { #[primary_span] pub open_delim: Span, - #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = ";")] + #[suggestion( + "consider adding `;` here", + style = "verbose", + applicability = "maybe-incorrect", + code = ";" + )] pub semicolon: Span, } #[derive(Diagnostic)] -#[diag(parse_expect_dotdot_not_dotdotdot)] +#[diag("expected `..`, found `...`")] pub(crate) struct MissingDotDot { #[primary_span] pub token_span: Span, - #[suggestion(applicability = "maybe-incorrect", code = "..", style = "verbose")] + #[suggestion( + "use `..` to fill in the rest of the fields", + applicability = "maybe-incorrect", + code = "..", + style = "verbose" + )] pub sugg_span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_block_macro_segment)] +#[diag("cannot use a `block` macro fragment here")] pub(crate) struct InvalidBlockMacroSegment { #[primary_span] pub span: Span, - #[label] + #[label("the `block` fragment is within this context")] pub context: Span, #[subdiagnostic] pub wrap: WrapInExplicitBlock, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion("wrap this in another block", applicability = "machine-applicable")] pub(crate) struct WrapInExplicitBlock { #[suggestion_part(code = "{{ ")] pub lo: Span, @@ -431,7 +487,7 @@ pub(crate) struct WrapInExplicitBlock { } #[derive(Diagnostic)] -#[diag(parse_if_expression_missing_then_block)] +#[diag("this `if` expression is missing a block after the condition")] pub(crate) struct IfExpressionMissingThenBlock { #[primary_span] pub if_span: Span, @@ -443,14 +499,14 @@ pub(crate) struct IfExpressionMissingThenBlock { #[derive(Subdiagnostic)] pub(crate) enum IfExpressionMissingThenBlockSub { - #[help(parse_condition_possibly_unfinished)] + #[help("this binary operation is possibly unfinished")] UnfinishedCondition(#[primary_span] Span), - #[help(parse_add_then_block)] + #[help("add a block here")] AddThenBlock(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(parse_ternary_operator)] +#[diag("Rust has no ternary operator")] pub(crate) struct TernaryOperator { #[primary_span] pub span: Span, @@ -458,12 +514,16 @@ pub(crate) struct TernaryOperator { #[subdiagnostic] pub sugg: Option, /// Otherwise, just print the suggestion message - #[help(parse_use_if_else)] + #[help("use an `if-else` expression instead")] pub no_sugg: bool, } #[derive(Subdiagnostic, Copy, Clone)] -#[multipart_suggestion(parse_use_if_else, applicability = "maybe-incorrect", style = "verbose")] +#[multipart_suggestion( + "use an `if-else` expression instead", + applicability = "maybe-incorrect", + style = "verbose" +)] pub(crate) struct TernaryOperatorSuggestion { #[suggestion_part(code = "if ")] pub before_cond: Span, @@ -477,7 +537,7 @@ pub(crate) struct TernaryOperatorSuggestion { #[derive(Subdiagnostic)] #[suggestion( - parse_extra_if_in_let_else, + "remove the `if` if you meant to write a `let...else` statement", applicability = "maybe-incorrect", code = "", style = "verbose" @@ -488,18 +548,20 @@ pub(crate) struct IfExpressionLetSomeSub { } #[derive(Diagnostic)] -#[diag(parse_if_expression_missing_condition)] +#[diag("missing condition for `if` expression")] pub(crate) struct IfExpressionMissingCondition { #[primary_span] - #[label(parse_condition_label)] + #[label("expected condition here")] pub if_span: Span, - #[label(parse_block_label)] + #[label( + "if this block is the condition of the `if` expression, then it must be followed by another block" + )] pub block_span: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_expression_found_let)] -#[note] +#[diag("expected expression, found `let` statement")] +#[note("only supported directly in conditions of `if` and `while` expressions")] pub(crate) struct ExpectedExpressionFoundLet { #[primary_span] pub span: Span, @@ -512,7 +574,7 @@ pub(crate) struct ExpectedExpressionFoundLet { } #[derive(Diagnostic)] -#[diag(parse_or_in_let_chain)] +#[diag("`||` operators are not supported in let chain conditions")] pub(crate) struct OrInLetChain { #[primary_span] pub span: Span, @@ -520,7 +582,7 @@ pub(crate) struct OrInLetChain { #[derive(Subdiagnostic, Clone, Copy)] #[multipart_suggestion( - parse_maybe_missing_let, + "you might have meant to continue the let-chain", applicability = "maybe-incorrect", style = "verbose" )] @@ -531,7 +593,7 @@ pub(crate) struct MaybeMissingLet { #[derive(Subdiagnostic, Clone, Copy)] #[multipart_suggestion( - parse_maybe_comparison, + "you might have meant to compare for equality", applicability = "maybe-incorrect", style = "verbose" )] @@ -541,56 +603,71 @@ pub(crate) struct MaybeComparison { } #[derive(Diagnostic)] -#[diag(parse_expect_eq_instead_of_eqeq)] +#[diag("expected `=`, found `==`")] pub(crate) struct ExpectedEqForLetExpr { #[primary_span] pub span: Span, - #[suggestion(applicability = "maybe-incorrect", code = "=", style = "verbose")] + #[suggestion( + "consider using `=` here", + applicability = "maybe-incorrect", + code = "=", + style = "verbose" + )] pub sugg_span: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_else_block)] +#[diag("expected `{\"{\"}`, found {$first_tok}")] pub(crate) struct ExpectedElseBlock { #[primary_span] pub first_tok_span: Span, pub first_tok: String, - #[label] + #[label("expected an `if` or a block after this `else`")] pub else_span: Span, - #[suggestion(applicability = "maybe-incorrect", code = "if ", style = "verbose")] + #[suggestion( + "add an `if` if this is the condition of a chained `else if` statement", + applicability = "maybe-incorrect", + code = "if ", + style = "verbose" + )] pub condition_start: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_struct_field)] +#[diag("expected one of `,`, `:`, or `{\"}\"}`, found `{$token}`")] pub(crate) struct ExpectedStructField { #[primary_span] - #[label] + #[label("expected one of `,`, `:`, or `{\"}\"}`")] pub span: Span, pub token: Token, - #[label(parse_ident_label)] + #[label("while parsing this struct field")] pub ident_span: Span, } #[derive(Diagnostic)] -#[diag(parse_outer_attribute_not_allowed_on_if_else)] +#[diag("outer attributes are not allowed on `if` and `else` branches")] pub(crate) struct OuterAttributeNotAllowedOnIfElse { #[primary_span] pub last: Span, - #[label(parse_branch_label)] + #[label("the attributes are attached to this branch")] pub branch_span: Span, - #[label(parse_ctx_label)] + #[label("the branch belongs to this `{$ctx}`")] pub ctx_span: Span, pub ctx: String, - #[suggestion(applicability = "machine-applicable", code = "", style = "verbose")] + #[suggestion( + "remove the attributes", + applicability = "machine-applicable", + code = "", + style = "verbose" + )] pub attributes: Span, } #[derive(Diagnostic)] -#[diag(parse_missing_in_in_for_loop)] +#[diag("missing `in` in `for` loop")] pub(crate) struct MissingInInForLoop { #[primary_span] pub span: Span, @@ -602,20 +679,36 @@ pub(crate) struct MissingInInForLoop { pub(crate) enum MissingInInForLoopSub { // User wrote `for pat of expr {}` // Has been misleading, at least in the past (closed Issue #48492), thus maybe-incorrect - #[suggestion(parse_use_in, style = "verbose", applicability = "maybe-incorrect", code = "in")] + #[suggestion( + "try using `in` here instead", + style = "verbose", + applicability = "maybe-incorrect", + code = "in" + )] InNotOf(#[primary_span] Span), // User wrote `for pat = expr {}` - #[suggestion(parse_use_in, style = "verbose", applicability = "maybe-incorrect", code = "in")] + #[suggestion( + "try using `in` here instead", + style = "verbose", + applicability = "maybe-incorrect", + code = "in" + )] InNotEq(#[primary_span] Span), - #[suggestion(parse_add_in, style = "verbose", applicability = "maybe-incorrect", code = " in ")] + #[suggestion( + "try adding `in` here", + style = "verbose", + applicability = "maybe-incorrect", + code = " in " + )] AddIn(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(parse_missing_expression_in_for_loop)] +#[diag("missing expression to iterate on in `for` loop")] pub(crate) struct MissingExpressionInForLoop { #[primary_span] #[suggestion( + "try adding an expression to the `for` loop", code = "/* expression */ ", applicability = "has-placeholders", style = "verbose" @@ -624,63 +717,80 @@ pub(crate) struct MissingExpressionInForLoop { } #[derive(Diagnostic)] -#[diag(parse_loop_else)] -#[note] +#[diag("`{$loop_kind}...else` loops are not supported")] +#[note( + "consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run" +)] pub(crate) struct LoopElseNotSupported { #[primary_span] pub span: Span, pub loop_kind: &'static str, - #[label(parse_loop_keyword)] + #[label("`else` is attached to this loop")] pub loop_kw: Span, } #[derive(Diagnostic)] -#[diag(parse_missing_comma_after_match_arm)] +#[diag("expected `,` following `match` arm")] pub(crate) struct MissingCommaAfterMatchArm { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = ",", style = "verbose")] + #[suggestion( + "missing a comma here to end this `match` arm", + applicability = "machine-applicable", + code = ",", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_catch_after_try)] -#[help] +#[diag("keyword `catch` cannot follow a `try` block")] +#[help("try using `match` on the result of the `try` block instead")] pub(crate) struct CatchAfterTry { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_comma_after_base_struct)] -#[note] +#[diag("cannot use a comma after the base struct")] +#[note("the base struct must always be the last field")] pub(crate) struct CommaAfterBaseStruct { #[primary_span] pub span: Span, - #[suggestion(style = "verbose", applicability = "machine-applicable", code = "")] + #[suggestion( + "remove this comma", + style = "verbose", + applicability = "machine-applicable", + code = "" + )] pub comma: Span, } #[derive(Diagnostic)] -#[diag(parse_eq_field_init)] +#[diag("expected `:`, found `=`")] pub(crate) struct EqFieldInit { #[primary_span] pub span: Span, - #[suggestion(applicability = "machine-applicable", code = ":", style = "verbose")] + #[suggestion( + "replace equals symbol with a colon", + applicability = "machine-applicable", + code = ":", + style = "verbose" + )] pub eq: Span, } #[derive(Diagnostic)] -#[diag(parse_dotdotdot)] +#[diag("unexpected token: `...`")] pub(crate) struct DotDotDot { #[primary_span] #[suggestion( - parse_suggest_exclusive_range, + "use `..` for an exclusive range", applicability = "maybe-incorrect", code = "..", style = "verbose" )] #[suggestion( - parse_suggest_inclusive_range, + "or `..=` for an inclusive range", applicability = "maybe-incorrect", code = "..=", style = "verbose" @@ -689,66 +799,86 @@ pub(crate) struct DotDotDot { } #[derive(Diagnostic)] -#[diag(parse_left_arrow_operator)] +#[diag("unexpected token: `<-`")] pub(crate) struct LeftArrowOperator { #[primary_span] - #[suggestion(applicability = "maybe-incorrect", code = "< -", style = "verbose")] + #[suggestion( + "if you meant to write a comparison against a negative value, add a space in between `<` and `-`", + applicability = "maybe-incorrect", + code = "< -", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_remove_let)] +#[diag("expected pattern, found `let`")] pub(crate) struct RemoveLet { #[primary_span] pub span: Span, - #[suggestion(applicability = "machine-applicable", code = "", style = "verbose")] + #[suggestion( + "remove the unnecessary `let` keyword", + applicability = "machine-applicable", + code = "", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_use_eq_instead)] +#[diag("unexpected `==`")] pub(crate) struct UseEqInstead { #[primary_span] - #[suggestion(style = "verbose", applicability = "machine-applicable", code = "=")] + #[suggestion( + "try using `=` instead", + style = "verbose", + applicability = "machine-applicable", + code = "=" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_use_empty_block_not_semi)] +#[diag("expected { \"`{}`\" }, found `;`")] pub(crate) struct UseEmptyBlockNotSemi { #[primary_span] - #[suggestion(style = "hidden", applicability = "machine-applicable", code = "{{}}")] + #[suggestion( + r#"try using { "`{}`" } instead"#, + style = "hidden", + applicability = "machine-applicable", + code = "{{}}" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_comparison_interpreted_as_generic)] +#[diag("`<` is interpreted as a start of generic arguments for `{$type}`, not a comparison")] pub(crate) struct ComparisonInterpretedAsGeneric { #[primary_span] - #[label(parse_label_comparison)] + #[label("not interpreted as comparison")] pub comparison: Span, pub r#type: Path, - #[label(parse_label_args)] + #[label("interpreted as generic arguments")] pub args: Span, #[subdiagnostic] pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg, } #[derive(Diagnostic)] -#[diag(parse_shift_interpreted_as_generic)] +#[diag("`<<` is interpreted as a start of generic arguments for `{$type}`, not a shift")] pub(crate) struct ShiftInterpretedAsGeneric { #[primary_span] - #[label(parse_label_comparison)] + #[label("not interpreted as shift")] pub shift: Span, pub r#type: Path, - #[label(parse_label_args)] + #[label("interpreted as generic arguments")] pub args: Span, #[subdiagnostic] pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion("BROKEN", applicability = "machine-applicable")] pub(crate) struct ComparisonOrShiftInterpretedAsGenericSugg { #[suggestion_part(code = "(")] pub left: Span, @@ -757,10 +887,10 @@ pub(crate) struct ComparisonOrShiftInterpretedAsGenericSugg { } #[derive(Diagnostic)] -#[diag(parse_found_expr_would_be_stmt)] +#[diag("expected expression, found `{$token}`")] pub(crate) struct FoundExprWouldBeStmt { #[primary_span] - #[label] + #[label("expected expression")] pub span: Span, pub token: Token, #[subdiagnostic] @@ -768,81 +898,83 @@ pub(crate) struct FoundExprWouldBeStmt { } #[derive(Diagnostic)] -#[diag(parse_frontmatter_extra_characters_after_close)] +#[diag("extra characters after frontmatter close are not allowed")] pub(crate) struct FrontmatterExtraCharactersAfterClose { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_frontmatter_invalid_infostring)] -#[note] +#[diag("invalid infostring for frontmatter")] +#[note("frontmatter infostrings must be a single identifier immediately following the opening")] pub(crate) struct FrontmatterInvalidInfostring { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_frontmatter_invalid_opening_preceding_whitespace)] +#[diag("invalid preceding whitespace for frontmatter opening")] pub(crate) struct FrontmatterInvalidOpeningPrecedingWhitespace { #[primary_span] pub span: Span, - #[note] + #[note("frontmatter opening should not be preceded by whitespace")] pub note_span: Span, } #[derive(Diagnostic)] -#[diag(parse_frontmatter_unclosed)] +#[diag("unclosed frontmatter")] pub(crate) struct FrontmatterUnclosed { #[primary_span] pub span: Span, - #[note] + #[note("frontmatter opening here was not closed")] pub note_span: Span, } #[derive(Diagnostic)] -#[diag(parse_frontmatter_invalid_close_preceding_whitespace)] +#[diag("invalid preceding whitespace for frontmatter close")] pub(crate) struct FrontmatterInvalidClosingPrecedingWhitespace { #[primary_span] pub span: Span, - #[note] + #[note("frontmatter close should not be preceded by whitespace")] pub note_span: Span, } #[derive(Diagnostic)] -#[diag(parse_frontmatter_length_mismatch)] +#[diag("frontmatter close does not match the opening")] pub(crate) struct FrontmatterLengthMismatch { #[primary_span] pub span: Span, - #[label(parse_label_opening)] + #[label("the opening here has {$len_opening} dashes...")] pub opening: Span, - #[label(parse_label_close)] + #[label("...while the close has {$len_close} dashes")] pub close: Span, pub len_opening: usize, pub len_close: usize, } #[derive(Diagnostic)] -#[diag(parse_frontmatter_too_many_dashes)] +#[diag( + "too many `-` symbols: frontmatter openings may be delimited by up to 255 `-` symbols, but found {$len_opening}" +)] pub(crate) struct FrontmatterTooManyDashes { pub len_opening: usize, } #[derive(Diagnostic)] -#[diag(parse_bare_cr_in_frontmatter)] +#[diag("bare CR not allowed in frontmatter")] pub(crate) struct BareCrFrontmatter { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_leading_plus_not_supported)] +#[diag("leading `+` is not supported")] pub(crate) struct LeadingPlusNotSupported { #[primary_span] - #[label] + #[label("unexpected `+`")] pub span: Span, #[suggestion( - parse_suggestion_remove_plus, + "try removing the `+`", style = "verbose", code = "", applicability = "machine-applicable" @@ -853,7 +985,7 @@ pub(crate) struct LeadingPlusNotSupported { } #[derive(Diagnostic)] -#[diag(parse_parentheses_with_struct_fields)] +#[diag("invalid `struct` delimiters or `fn` call arguments")] pub(crate) struct ParenthesesWithStructFields { #[primary_span] pub span: Span, @@ -865,7 +997,10 @@ pub(crate) struct ParenthesesWithStructFields { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion_braces_for_struct, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "if `{$type}` is a struct, use braces as delimiters", + applicability = "maybe-incorrect" +)] pub(crate) struct BracesForStructLiteral { #[suggestion_part(code = " {{ ")] pub first: Span, @@ -874,14 +1009,19 @@ pub(crate) struct BracesForStructLiteral { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion_no_fields_for_fn, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "if `{$type}` is a function, use the arguments directly", + applicability = "maybe-incorrect" +)] pub(crate) struct NoFieldsForFnCall { #[suggestion_part(code = "")] pub fields: Vec, } #[derive(Diagnostic)] -#[diag(parse_labeled_loop_in_break)] +#[diag( + "parentheses are required around this expression to avoid confusion with a labeled break expression" +)] pub(crate) struct LabeledLoopInBreak { #[primary_span] pub span: Span, @@ -892,7 +1032,7 @@ pub(crate) struct LabeledLoopInBreak { #[derive(Subdiagnostic)] pub(crate) enum WrapInParentheses { #[multipart_suggestion( - parse_sugg_wrap_expression_in_parentheses, + "wrap the expression in parentheses", applicability = "machine-applicable" )] Expression { @@ -902,7 +1042,7 @@ pub(crate) enum WrapInParentheses { right: Span, }, #[multipart_suggestion( - parse_sugg_wrap_macro_in_parentheses, + "use parentheses instead of braces for this macro", applicability = "machine-applicable" )] MacroArgs { @@ -914,7 +1054,7 @@ pub(crate) enum WrapInParentheses { } #[derive(Diagnostic)] -#[diag(parse_array_brackets_instead_of_braces)] +#[diag("this is a block expression, not an array")] pub(crate) struct ArrayBracketsInsteadOfBraces { #[primary_span] pub span: Span, @@ -923,7 +1063,10 @@ pub(crate) struct ArrayBracketsInsteadOfBraces { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "to make an array, use square brackets instead of curly braces", + applicability = "maybe-incorrect" +)] pub(crate) struct ArrayBracketsInsteadOfBracesSugg { #[suggestion_part(code = "[")] pub left: Span, @@ -932,12 +1075,17 @@ pub(crate) struct ArrayBracketsInsteadOfBracesSugg { } #[derive(Diagnostic)] -#[diag(parse_match_arm_body_without_braces)] +#[diag("`match` arm body without braces")] pub(crate) struct MatchArmBodyWithoutBraces { #[primary_span] - #[label(parse_label_statements)] + #[label( + "{$num_statements -> + [one] this statement is not surrounded by a body + *[other] these statements are not surrounded by a body + }" + )] pub statements: Span, - #[label(parse_label_arrow)] + #[label("while parsing the `match` arm starting here")] pub arrow: Span, pub num_statements: usize, #[subdiagnostic] @@ -945,12 +1093,12 @@ pub(crate) struct MatchArmBodyWithoutBraces { } #[derive(Diagnostic)] -#[diag(parse_inclusive_range_extra_equals)] -#[note] +#[diag("unexpected `=` after inclusive range")] +#[note("inclusive ranges end with a single equals sign (`..=`)")] pub(crate) struct InclusiveRangeExtraEquals { #[primary_span] #[suggestion( - parse_suggestion_remove_eq, + "use `..=` instead", style = "verbose", code = "..=", applicability = "maybe-incorrect" @@ -959,24 +1107,29 @@ pub(crate) struct InclusiveRangeExtraEquals { } #[derive(Diagnostic)] -#[diag(parse_inclusive_range_match_arrow)] +#[diag("unexpected `>` after inclusive range")] pub(crate) struct InclusiveRangeMatchArrow { #[primary_span] pub arrow: Span, - #[label] + #[label("this is parsed as an inclusive range `..=`")] pub span: Span, - #[suggestion(style = "verbose", code = " ", applicability = "machine-applicable")] + #[suggestion( + "add a space between the pattern and `=>`", + style = "verbose", + code = " ", + applicability = "machine-applicable" + )] pub after_pat: Span, } #[derive(Diagnostic)] -#[diag(parse_inclusive_range_no_end, code = E0586)] -#[note] +#[diag("inclusive range with no end", code = E0586)] +#[note("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)")] pub(crate) struct InclusiveRangeNoEnd { #[primary_span] pub span: Span, #[suggestion( - parse_suggestion_open_range, + "use `..` instead", code = "", applicability = "machine-applicable", style = "verbose" @@ -986,7 +1139,13 @@ pub(crate) struct InclusiveRangeNoEnd { #[derive(Subdiagnostic)] pub(crate) enum MatchArmBodyWithoutBracesSugg { - #[multipart_suggestion(parse_suggestion_add_braces, applicability = "machine-applicable")] + #[multipart_suggestion( + "surround the {$num_statements -> + [one] statement + *[other] statements + } with a body", + applicability = "machine-applicable" + )] AddBraces { #[suggestion_part(code = "{{ ")] left: Span, @@ -994,7 +1153,7 @@ pub(crate) enum MatchArmBodyWithoutBracesSugg { right: Span, }, #[suggestion( - parse_suggestion_use_comma_not_semicolon, + "replace `;` with `,` to end a `match` arm expression", code = ",", applicability = "machine-applicable", style = "verbose" @@ -1006,7 +1165,7 @@ pub(crate) enum MatchArmBodyWithoutBracesSugg { } #[derive(Diagnostic)] -#[diag(parse_struct_literal_not_allowed_here)] +#[diag("struct literals are not allowed here")] pub(crate) struct StructLiteralNotAllowedHere { #[primary_span] pub span: Span, @@ -1015,7 +1174,10 @@ pub(crate) struct StructLiteralNotAllowedHere { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "surround the struct literal with parentheses", + applicability = "machine-applicable" +)] pub(crate) struct StructLiteralNotAllowedHereSugg { #[suggestion_part(code = "(")] pub left: Span, @@ -1024,80 +1186,105 @@ pub(crate) struct StructLiteralNotAllowedHereSugg { } #[derive(Diagnostic)] -#[diag(parse_invalid_literal_suffix_on_tuple_index)] +#[diag("suffixes on a tuple index are invalid")] pub(crate) struct InvalidLiteralSuffixOnTupleIndex { #[primary_span] - #[label] + #[label("invalid suffix `{$suffix}`")] pub span: Span, pub suffix: Symbol, } #[derive(Diagnostic)] -#[diag(parse_non_string_abi_literal)] +#[diag("non-string ABI literal")] pub(crate) struct NonStringAbiLiteral { #[primary_span] - #[suggestion(code = "\"C\"", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "specify the ABI with a string literal", + code = "\"C\"", + applicability = "maybe-incorrect", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_mismatched_closing_delimiter)] +#[diag("mismatched closing delimiter: `{$delimiter}`")] pub(crate) struct MismatchedClosingDelimiter { #[primary_span] pub spans: Vec, pub delimiter: String, - #[label(parse_label_unmatched)] + #[label("mismatched closing delimiter")] pub unmatched: Span, - #[label(parse_label_opening_candidate)] + #[label("closing delimiter possibly meant for this")] pub opening_candidate: Option, - #[label(parse_label_unclosed)] + #[label("unclosed delimiter")] pub unclosed: Option, } #[derive(Diagnostic)] -#[diag(parse_incorrect_visibility_restriction, code = E0704)] -#[help] +#[diag("incorrect visibility restriction", code = E0704)] +#[help( + "some possible visibility restrictions are: + `pub(crate)`: visible only on the current crate + `pub(super)`: visible only in the current module's parent + `pub(in path::to::module)`: visible only on the specified path" +)] pub(crate) struct IncorrectVisibilityRestriction { #[primary_span] - #[suggestion(code = "in {inner_str}", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "make this visible only to module `{$inner_str}` with `in`", + code = "in {inner_str}", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, pub inner_str: String, } #[derive(Diagnostic)] -#[diag(parse_assignment_else_not_allowed)] +#[diag(" ... else {\"{\"} ... {\"}\"} is not allowed")] pub(crate) struct AssignmentElseNotAllowed { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_statement_after_outer_attr)] +#[diag("expected statement after outer attribute")] pub(crate) struct ExpectedStatementAfterOuterAttr { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_doc_comment_does_not_document_anything, code = E0585)] -#[help] +#[diag("found a documentation comment that doesn't document anything", code = E0585)] +#[help("doc comments must come before what they document, if a comment was intended use `//`")] pub(crate) struct DocCommentDoesNotDocumentAnything { #[primary_span] pub span: Span, - #[suggestion(code = ",", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "missing comma here", + code = ",", + applicability = "machine-applicable", + style = "verbose" + )] pub missing_comma: Option, } #[derive(Diagnostic)] -#[diag(parse_const_let_mutually_exclusive)] +#[diag("`const` and `let` are mutually exclusive")] pub(crate) struct ConstLetMutuallyExclusive { #[primary_span] - #[suggestion(code = "const", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "remove `let`", + code = "const", + applicability = "maybe-incorrect", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_expression_in_let_else)] +#[diag("a `{$operator}` expression cannot be directly assigned in `let...else`")] pub(crate) struct InvalidExpressionInLetElse { #[primary_span] pub span: Span, @@ -1107,7 +1294,7 @@ pub(crate) struct InvalidExpressionInLetElse { } #[derive(Diagnostic)] -#[diag(parse_invalid_curly_in_let_else)] +#[diag("right curly brace `{\"}\"}` before `else` in a `let...else` statement not allowed")] pub(crate) struct InvalidCurlyInLetElse { #[primary_span] pub span: Span, @@ -1116,25 +1303,32 @@ pub(crate) struct InvalidCurlyInLetElse { } #[derive(Diagnostic)] -#[diag(parse_compound_assignment_expression_in_let)] -#[help] +#[diag("can't reassign to an uninitialized variable")] +#[help("if you meant to overwrite, remove the `let` binding")] pub(crate) struct CompoundAssignmentExpressionInLet { #[primary_span] pub span: Span, - #[suggestion(style = "verbose", code = "", applicability = "maybe-incorrect")] + #[suggestion( + "initialize the variable", + style = "verbose", + code = "", + applicability = "maybe-incorrect" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_suffixed_literal_in_attribute)] -#[help] +#[diag("suffixed literals are not allowed in attributes")] +#[help( + "instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)" +)] pub(crate) struct SuffixedLiteralInAttribute { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_meta_item)] +#[diag("expected unsuffixed literal, found {$descr}")] pub(crate) struct InvalidMetaItem { #[primary_span] pub span: Span, @@ -1144,7 +1338,10 @@ pub(crate) struct InvalidMetaItem { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_quote_ident_sugg, applicability = "machine-applicable")] +#[multipart_suggestion( + "surround the identifier with quotation marks to make it into a string literal", + applicability = "machine-applicable" +)] pub(crate) struct InvalidMetaItemQuoteIdentSugg { #[suggestion_part(code = "\"")] pub before: Span, @@ -1154,7 +1351,7 @@ pub(crate) struct InvalidMetaItemQuoteIdentSugg { #[derive(Subdiagnostic)] #[suggestion( - parse_sugg_escape_identifier, + "escape `{$ident_name}` to use it as an identifier", style = "verbose", applicability = "maybe-incorrect", code = "r#" @@ -1167,7 +1364,7 @@ pub(crate) struct SuggEscapeIdentifier { #[derive(Subdiagnostic)] #[suggestion( - parse_sugg_remove_comma, + "remove this comma", applicability = "machine-applicable", code = "", style = "verbose" @@ -1179,7 +1376,7 @@ pub(crate) struct SuggRemoveComma { #[derive(Subdiagnostic)] #[suggestion( - parse_sugg_add_let_for_stmt, + "you might have meant to introduce a new binding", style = "verbose", applicability = "maybe-incorrect", code = "let " @@ -1191,17 +1388,17 @@ pub(crate) struct SuggAddMissingLetStmt { #[derive(Subdiagnostic)] pub(crate) enum ExpectedIdentifierFound { - #[label(parse_expected_identifier_found_reserved_identifier)] + #[label("expected identifier, found reserved identifier")] ReservedIdentifier(#[primary_span] Span), - #[label(parse_expected_identifier_found_keyword)] + #[label("expected identifier, found keyword")] Keyword(#[primary_span] Span), - #[label(parse_expected_identifier_found_reserved_keyword)] + #[label("expected identifier, found reserved keyword")] ReservedKeyword(#[primary_span] Span), - #[label(parse_expected_identifier_found_doc_comment)] + #[label("expected identifier, found doc comment")] DocComment(#[primary_span] Span), - #[label(parse_expected_identifier_found_metavar)] + #[label("expected identifier, found metavariable")] MetaVar(#[primary_span] Span), - #[label(parse_expected_identifier)] + #[label("expected identifier")] Other(#[primary_span] Span), } @@ -1239,22 +1436,22 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedIdentifier { level, match token_descr { Some(TokenDescription::ReservedIdentifier) => { - fluent::parse_expected_identifier_found_reserved_identifier_str + inline_fluent!("expected identifier, found reserved identifier `{$token}`") } Some(TokenDescription::Keyword) => { - fluent::parse_expected_identifier_found_keyword_str + inline_fluent!("expected identifier, found keyword `{$token}`") } Some(TokenDescription::ReservedKeyword) => { - fluent::parse_expected_identifier_found_reserved_keyword_str + inline_fluent!("expected identifier, found reserved keyword `{$token}`") } Some(TokenDescription::DocComment) => { - fluent::parse_expected_identifier_found_doc_comment_str + inline_fluent!("expected identifier, found doc comment `{$token}`") } Some(TokenDescription::MetaVar(_)) => { add_token = false; - fluent::parse_expected_identifier_found_metavar_str + inline_fluent!("expected identifier, found metavariable") } - None => fluent::parse_expected_identifier_found_str, + None => inline_fluent!("expected identifier, found `{$token}`"), }, ); diag.span(self.span); @@ -1281,7 +1478,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedIdentifier { } #[derive(Subdiagnostic)] -#[help(parse_invalid_identifier_with_leading_number)] +#[help("identifiers cannot start with a number")] pub(crate) struct HelpIdentifierStartsWithNumber { #[primary_span] pub num_span: Span, @@ -1306,20 +1503,22 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi { level, match token_descr { Some(TokenDescription::ReservedIdentifier) => { - fluent::parse_expected_semi_found_reserved_identifier_str + inline_fluent!("expected `;`, found reserved identifier `{$token}`") + } + Some(TokenDescription::Keyword) => { + inline_fluent!("expected `;`, found keyword `{$token}`") } - Some(TokenDescription::Keyword) => fluent::parse_expected_semi_found_keyword_str, Some(TokenDescription::ReservedKeyword) => { - fluent::parse_expected_semi_found_reserved_keyword_str + inline_fluent!("expected `;`, found reserved keyword `{$token}`") } Some(TokenDescription::DocComment) => { - fluent::parse_expected_semi_found_doc_comment_str + inline_fluent!("expected `;`, found doc comment `{$token}`") } Some(TokenDescription::MetaVar(_)) => { add_token = false; - fluent::parse_expected_semi_found_metavar_str + inline_fluent!("expected `;`, found metavariable") } - None => fluent::parse_expected_semi_found_str, + None => inline_fluent!("expected `;`, found `{$token}`"), }, ); diag.span(self.span); @@ -1328,7 +1527,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi { } if let Some(unexpected_token_label) = self.unexpected_token_label { - diag.span_label(unexpected_token_label, fluent::parse_label_unexpected_token); + diag.span_label(unexpected_token_label, inline_fluent!("unexpected token")); } self.sugg.add_to_diag(&mut diag); @@ -1340,23 +1539,18 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi { #[derive(Subdiagnostic)] pub(crate) enum ExpectedSemiSugg { #[suggestion( - parse_sugg_change_this_to_semi, + "change this to `;`", code = ";", applicability = "machine-applicable", style = "short" )] ChangeToSemi(#[primary_span] Span), - #[suggestion( - parse_sugg_add_semi, - code = ";", - applicability = "machine-applicable", - style = "short" - )] + #[suggestion("add `;` here", code = ";", applicability = "machine-applicable", style = "short")] AddSemi(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(parse_struct_literal_body_without_path)] +#[diag("struct literal body without path")] pub(crate) struct StructLiteralBodyWithoutPath { #[primary_span] pub span: Span, @@ -1365,7 +1559,10 @@ pub(crate) struct StructLiteralBodyWithoutPath { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "has-placeholders")] +#[multipart_suggestion( + "you might have forgotten to add the struct literal inside the block", + applicability = "has-placeholders" +)] pub(crate) struct StructLiteralBodyWithoutPathSugg { #[suggestion_part(code = "{{ SomeStruct ")] pub before: Span, @@ -1374,16 +1571,29 @@ pub(crate) struct StructLiteralBodyWithoutPathSugg { } #[derive(Diagnostic)] -#[diag(parse_unmatched_angle_brackets)] +#[diag( + "{$num_extra_brackets -> + [one] unmatched angle bracket + *[other] unmatched angle brackets + }" +)] pub(crate) struct UnmatchedAngleBrackets { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "{$num_extra_brackets -> + [one] remove extra angle bracket + *[other] remove extra angle brackets + }", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, pub num_extra_brackets: usize, } #[derive(Diagnostic)] -#[diag(parse_generic_parameters_without_angle_brackets)] +#[diag("generic parameters without surrounding angle brackets")] pub(crate) struct GenericParamsWithoutAngleBrackets { #[primary_span] pub span: Span, @@ -1392,7 +1602,10 @@ pub(crate) struct GenericParamsWithoutAngleBrackets { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "surround the type parameters with angle brackets", + applicability = "machine-applicable" +)] pub(crate) struct GenericParamsWithoutAngleBracketsSugg { #[suggestion_part(code = "<")] pub left: Span, @@ -1401,19 +1614,19 @@ pub(crate) struct GenericParamsWithoutAngleBracketsSugg { } #[derive(Diagnostic)] -#[diag(parse_comparison_operators_cannot_be_chained)] +#[diag("comparison operators cannot be chained")] pub(crate) struct ComparisonOperatorsCannotBeChained { #[primary_span] pub span: Vec, #[suggestion( - parse_sugg_turbofish_syntax, + "use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments", style = "verbose", code = "::", applicability = "maybe-incorrect" )] pub suggest_turbofish: Option, - #[help(parse_sugg_turbofish_syntax)] - #[help(parse_sugg_parentheses_for_function_args)] + #[help("use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments")] + #[help("or use `(...)` if you meant to specify fn arguments")] pub help_turbofish: bool, #[subdiagnostic] pub chaining_sugg: Option, @@ -1422,7 +1635,7 @@ pub(crate) struct ComparisonOperatorsCannotBeChained { #[derive(Subdiagnostic)] pub(crate) enum ComparisonOperatorsCannotBeChainedSugg { #[suggestion( - parse_sugg_split_comparison, + "split the comparison into two", style = "verbose", code = " && {middle_term}", applicability = "maybe-incorrect" @@ -1432,7 +1645,7 @@ pub(crate) enum ComparisonOperatorsCannotBeChainedSugg { span: Span, middle_term: String, }, - #[multipart_suggestion(parse_sugg_parenthesize, applicability = "maybe-incorrect")] + #[multipart_suggestion("parenthesize the comparison", applicability = "maybe-incorrect")] Parenthesize { #[suggestion_part(code = "(")] left: Span, @@ -1442,17 +1655,20 @@ pub(crate) enum ComparisonOperatorsCannotBeChainedSugg { } #[derive(Diagnostic)] -#[diag(parse_question_mark_in_type)] +#[diag("invalid `?` in type")] pub(crate) struct QuestionMarkInType { #[primary_span] - #[label] + #[label("`?` is only allowed on expressions, not types")] pub span: Span, #[subdiagnostic] pub sugg: QuestionMarkInTypeSugg, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "if you meant to express that the type might not contain a value, use the `Option` wrapper type", + applicability = "machine-applicable" +)] pub(crate) struct QuestionMarkInTypeSugg { #[suggestion_part(code = "Option<")] pub left: Span, @@ -1461,7 +1677,7 @@ pub(crate) struct QuestionMarkInTypeSugg { } #[derive(Diagnostic)] -#[diag(parse_unexpected_parentheses_in_for_head)] +#[diag("unexpected parentheses surrounding `for` loop head")] pub(crate) struct ParenthesesInForHead { #[primary_span] pub span: Vec, @@ -1470,7 +1686,7 @@ pub(crate) struct ParenthesesInForHead { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion("remove parentheses in `for` loop", applicability = "machine-applicable")] pub(crate) struct ParenthesesInForHeadSugg { #[suggestion_part(code = " ")] pub left: Span, @@ -1479,7 +1695,7 @@ pub(crate) struct ParenthesesInForHeadSugg { } #[derive(Diagnostic)] -#[diag(parse_unexpected_parentheses_in_match_arm_pattern)] +#[diag("unexpected parentheses surrounding `match` arm pattern")] pub(crate) struct ParenthesesInMatchPat { #[primary_span] pub span: Vec, @@ -1488,7 +1704,10 @@ pub(crate) struct ParenthesesInMatchPat { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "remove parentheses surrounding the pattern", + applicability = "machine-applicable" +)] pub(crate) struct ParenthesesInMatchPatSugg { #[suggestion_part(code = "")] pub left: Span, @@ -1497,67 +1716,82 @@ pub(crate) struct ParenthesesInMatchPatSugg { } #[derive(Diagnostic)] -#[diag(parse_doc_comment_on_param_type)] +#[diag("documentation comments cannot be applied to a function parameter's type")] pub(crate) struct DocCommentOnParamType { #[primary_span] - #[label] + #[label("doc comments are not allowed here")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_attribute_on_param_type)] +#[diag("attributes cannot be applied to a function parameter's type")] pub(crate) struct AttributeOnParamType { #[primary_span] - #[label] + #[label("attributes are not allowed here")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_attribute_on_type)] +#[diag("attributes cannot be applied to types")] pub(crate) struct AttributeOnType { #[primary_span] - #[label] + #[label("attributes are not allowed here")] pub span: Span, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove attribute from here", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub fix_span: Span, } #[derive(Diagnostic)] -#[diag(parse_attribute_on_generic_arg)] +#[diag("attributes cannot be applied to generic arguments")] pub(crate) struct AttributeOnGenericArg { #[primary_span] - #[label] + #[label("attributes are not allowed here")] pub span: Span, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove attribute from here", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub fix_span: Span, } #[derive(Diagnostic)] -#[diag(parse_attribute_on_empty_type)] +#[diag("attributes cannot be applied here")] pub(crate) struct AttributeOnEmptyType { #[primary_span] - #[label] + #[label("attributes are not allowed here")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_pattern_method_param_without_body, code = E0642)] +#[diag("patterns aren't allowed in methods without bodies", code = E0642)] pub(crate) struct PatternMethodParamWithoutBody { #[primary_span] - #[suggestion(code = "_", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "give this argument a name or use an underscore to ignore it", + code = "_", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_self_param_not_first)] +#[diag("unexpected `self` parameter in function")] pub(crate) struct SelfParamNotFirst { #[primary_span] - #[label] + #[label("must be the first parameter of an associated function")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_const_generic_without_braces)] +#[diag("expressions must be enclosed in braces to be used as const generic arguments")] pub(crate) struct ConstGenericWithoutBraces { #[primary_span] pub span: Span, @@ -1566,7 +1800,10 @@ pub(crate) struct ConstGenericWithoutBraces { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "enclose the `const` expression in braces", + applicability = "machine-applicable" +)] pub(crate) struct ConstGenericWithoutBracesSugg { #[suggestion_part(code = "{{ ")] pub left: Span, @@ -1575,10 +1812,10 @@ pub(crate) struct ConstGenericWithoutBracesSugg { } #[derive(Diagnostic)] -#[diag(parse_unexpected_const_param_declaration)] +#[diag("unexpected `const` parameter declaration")] pub(crate) struct UnexpectedConstParamDeclaration { #[primary_span] - #[label] + #[label("expected a `const` expression, not a parameter declaration")] pub span: Span, #[subdiagnostic] pub sugg: Option, @@ -1586,7 +1823,10 @@ pub(crate) struct UnexpectedConstParamDeclaration { #[derive(Subdiagnostic)] pub(crate) enum UnexpectedConstParamDeclarationSugg { - #[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] + #[multipart_suggestion( + "`const` parameters must be declared for the `impl`", + applicability = "machine-applicable" + )] AddParam { #[suggestion_part(code = "<{snippet}>")] impl_generics: Span, @@ -1595,7 +1835,10 @@ pub(crate) enum UnexpectedConstParamDeclarationSugg { snippet: String, ident: String, }, - #[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] + #[multipart_suggestion( + "`const` parameters must be declared for the `impl`", + applicability = "machine-applicable" + )] AppendParam { #[suggestion_part(code = ", {snippet}")] impl_generics_end: Span, @@ -1607,41 +1850,61 @@ pub(crate) enum UnexpectedConstParamDeclarationSugg { } #[derive(Diagnostic)] -#[diag(parse_unexpected_const_in_generic_param)] +#[diag("expected lifetime, type, or constant, found keyword `const`")] pub(crate) struct UnexpectedConstInGenericParam { #[primary_span] pub span: Span, - #[suggestion(style = "verbose", code = "", applicability = "maybe-incorrect")] + #[suggestion( + "the `const` keyword is only needed in the definition of the type", + style = "verbose", + code = "", + applicability = "maybe-incorrect" + )] pub to_remove: Option, } #[derive(Diagnostic)] -#[diag(parse_async_move_order_incorrect)] +#[diag("the order of `move` and `async` is incorrect")] pub(crate) struct AsyncMoveOrderIncorrect { #[primary_span] - #[suggestion(style = "verbose", code = "async move", applicability = "maybe-incorrect")] + #[suggestion( + "try switching the order", + style = "verbose", + code = "async move", + applicability = "maybe-incorrect" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_async_use_order_incorrect)] +#[diag("the order of `use` and `async` is incorrect")] pub(crate) struct AsyncUseOrderIncorrect { #[primary_span] - #[suggestion(style = "verbose", code = "async use", applicability = "maybe-incorrect")] + #[suggestion( + "try switching the order", + style = "verbose", + code = "async use", + applicability = "maybe-incorrect" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_double_colon_in_bound)] +#[diag("expected `:` followed by trait or lifetime")] pub(crate) struct DoubleColonInBound { #[primary_span] pub span: Span, - #[suggestion(code = ": ", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "use single colon", + code = ": ", + applicability = "machine-applicable", + style = "verbose" + )] pub between: Span, } #[derive(Diagnostic)] -#[diag(parse_fn_ptr_with_generics)] +#[diag("function pointer types may not have generic parameters")] pub(crate) struct FnPtrWithGenerics { #[primary_span] pub span: Span, @@ -1651,7 +1914,7 @@ pub(crate) struct FnPtrWithGenerics { #[derive(Subdiagnostic)] #[multipart_suggestion( - parse_misplaced_return_type, + "place the return type after the function parameters", style = "verbose", applicability = "maybe-incorrect" )] @@ -1664,7 +1927,16 @@ pub(crate) struct MisplacedReturnType { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "consider moving the lifetime {$arity -> + [one] parameter + *[other] parameters + } to {$for_param_list_exists -> + [true] the + *[false] a + } `for` parameter list", + applicability = "maybe-incorrect" +)] pub(crate) struct FnPtrWithGenericsSugg { #[suggestion_part(code = "{snippet}")] pub left: Span, @@ -1681,10 +1953,10 @@ pub(crate) struct FnTraitMissingParen { impl Subdiagnostic for FnTraitMissingParen { fn add_to_diag(self, diag: &mut Diag<'_, G>) { - diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren); + diag.span_label(self.span, inline_fluent!("`Fn` bounds require arguments in parentheses")); diag.span_suggestion_short( self.span.shrink_to_hi(), - crate::fluent_generated::parse_add_paren, + inline_fluent!("try adding parentheses"), "()", Applicability::MachineApplicable, ); @@ -1692,95 +1964,128 @@ impl Subdiagnostic for FnTraitMissingParen { } #[derive(Diagnostic)] -#[diag(parse_unexpected_if_with_if)] +#[diag("unexpected `if` in the condition expression")] pub(crate) struct UnexpectedIfWithIf( #[primary_span] - #[suggestion(applicability = "machine-applicable", code = " ", style = "verbose")] + #[suggestion( + "remove the `if`", + applicability = "machine-applicable", + code = " ", + style = "verbose" + )] pub Span, ); #[derive(Diagnostic)] -#[diag(parse_maybe_fn_typo_with_impl)] +#[diag("you might have meant to write `impl` instead of `fn`")] pub(crate) struct FnTypoWithImpl { #[primary_span] - #[suggestion(applicability = "maybe-incorrect", code = "impl", style = "verbose")] + #[suggestion( + "replace `fn` with `impl` here", + applicability = "maybe-incorrect", + code = "impl", + style = "verbose" + )] pub fn_span: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_fn_path_found_fn_keyword)] +#[diag("expected identifier, found keyword `fn`")] pub(crate) struct ExpectedFnPathFoundFnKeyword { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "Fn", style = "verbose")] + #[suggestion( + "use `Fn` to refer to the trait", + applicability = "machine-applicable", + code = "Fn", + style = "verbose" + )] pub fn_token_span: Span, } #[derive(Diagnostic)] -#[diag(parse_path_found_named_params)] +#[diag("`Trait(...)` syntax does not support named parameters")] pub(crate) struct FnPathFoundNamedParams { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "")] + #[suggestion("remove the parameter name", applicability = "machine-applicable", code = "")] pub named_param_span: Span, } #[derive(Diagnostic)] -#[diag(parse_path_found_c_variadic_params)] +#[diag("`Trait(...)` syntax does not support c_variadic parameters")] pub(crate) struct PathFoundCVariadicParams { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "")] + #[suggestion("remove the `...`", applicability = "machine-applicable", code = "")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_path_found_attribute_in_params)] +#[diag("`Trait(...)` syntax does not support attributes in parameters")] pub(crate) struct PathFoundAttributeInParams { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "")] + #[suggestion("remove the attributes", applicability = "machine-applicable", code = "")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_path_double_colon)] +#[diag("path separator must be a double colon")] pub(crate) struct PathSingleColon { #[primary_span] pub span: Span, - #[suggestion(applicability = "machine-applicable", code = ":", style = "verbose")] + #[suggestion( + "use a double colon instead", + applicability = "machine-applicable", + code = ":", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_path_double_colon)] +#[diag("path separator must be a double colon")] pub(crate) struct PathTripleColon { #[primary_span] - #[suggestion(applicability = "maybe-incorrect", code = "", style = "verbose")] + #[suggestion( + "use a double colon instead", + applicability = "maybe-incorrect", + code = "", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_colon_as_semi)] +#[diag("statements are terminated with a semicolon")] pub(crate) struct ColonAsSemi { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = ";", style = "verbose")] + #[suggestion( + "use a semicolon instead", + applicability = "machine-applicable", + code = ";", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_where_clause_before_tuple_struct_body)] +#[diag("where clauses are not allowed before tuple struct bodies")] pub(crate) struct WhereClauseBeforeTupleStructBody { #[primary_span] - #[label] + #[label("unexpected where clause")] pub span: Span, - #[label(parse_name_label)] + #[label("while parsing this tuple struct")] pub name: Span, - #[label(parse_body_label)] + #[label("the struct body")] pub body: Span, #[subdiagnostic] pub sugg: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "move the body before the where clause", + applicability = "machine-applicable" +)] pub(crate) struct WhereClauseBeforeTupleStructBodySugg { #[suggestion_part(code = "{snippet}")] pub left: Span, @@ -1790,38 +2095,38 @@ pub(crate) struct WhereClauseBeforeTupleStructBodySugg { } #[derive(Diagnostic)] -#[diag(parse_async_fn_in_2015, code = E0670)] +#[diag("`async fn` is not permitted in Rust 2015", code = E0670)] pub(crate) struct AsyncFnIn2015 { #[primary_span] - #[label] + #[label("to use `async fn`, switch to Rust 2018 or later")] pub span: Span, #[subdiagnostic] pub help: HelpUseLatestEdition, } #[derive(Subdiagnostic)] -#[label(parse_async_block_in_2015)] +#[label("`async` blocks are only allowed in Rust 2018 or later")] pub(crate) struct AsyncBlockIn2015 { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_async_move_block_in_2015)] +#[diag("`async move` blocks are only allowed in Rust 2018 or later")] pub(crate) struct AsyncMoveBlockIn2015 { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_async_use_block_in_2015)] +#[diag("`async use` blocks are only allowed in Rust 2018 or later")] pub(crate) struct AsyncUseBlockIn2015 { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_async_bound_modifier_in_2015)] +#[diag("`async` trait bounds are only allowed in Rust 2018 or later")] pub(crate) struct AsyncBoundModifierIn2015 { #[primary_span] pub span: Span, @@ -1830,22 +2135,22 @@ pub(crate) struct AsyncBoundModifierIn2015 { } #[derive(Diagnostic)] -#[diag(parse_let_chain_pre_2024)] +#[diag("let chains are only allowed in Rust 2024 or later")] pub(crate) struct LetChainPre2024 { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_self_argument_pointer)] +#[diag("cannot pass `self` by raw pointer")] pub(crate) struct SelfArgumentPointer { #[primary_span] - #[label] + #[label("cannot pass `self` by raw pointer")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_unexpected_token_after_dot)] +#[diag("unexpected token: {$actual}")] pub(crate) struct UnexpectedTokenAfterDot { #[primary_span] pub span: Span, @@ -1853,64 +2158,84 @@ pub(crate) struct UnexpectedTokenAfterDot { } #[derive(Diagnostic)] -#[diag(parse_visibility_not_followed_by_item)] -#[help] +#[diag("visibility `{$vis}` is not followed by an item")] +#[help("you likely meant to define an item, e.g., `{$vis} fn foo() {\"{}\"}`")] pub(crate) struct VisibilityNotFollowedByItem { #[primary_span] - #[label] + #[label("the visibility")] pub span: Span, pub vis: Visibility, } #[derive(Diagnostic)] -#[diag(parse_default_not_followed_by_item)] -#[note] +#[diag("`default` is not followed by an item")] +#[note("only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`")] pub(crate) struct DefaultNotFollowedByItem { #[primary_span] - #[label] + #[label("the `default` qualifier")] pub span: Span, } #[derive(Diagnostic)] pub(crate) enum MissingKeywordForItemDefinition { - #[diag(parse_missing_enum_for_enum_definition)] + #[diag("missing `enum` for enum definition")] Enum { #[primary_span] span: Span, - #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "enum ")] + #[suggestion( + "add `enum` here to parse `{$ident}` as an enum", + style = "verbose", + applicability = "maybe-incorrect", + code = "enum " + )] insert_span: Span, ident: Ident, }, - #[diag(parse_missing_enum_or_struct_for_item_definition)] + #[diag("missing `enum` or `struct` for enum or struct definition")] EnumOrStruct { #[primary_span] span: Span, }, - #[diag(parse_missing_struct_for_struct_definition)] + #[diag("missing `struct` for struct definition")] Struct { #[primary_span] span: Span, - #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "struct ")] + #[suggestion( + "add `struct` here to parse `{$ident}` as a struct", + style = "verbose", + applicability = "maybe-incorrect", + code = "struct " + )] insert_span: Span, ident: Ident, }, - #[diag(parse_missing_fn_for_function_definition)] + #[diag("missing `fn` for function definition")] Function { #[primary_span] span: Span, - #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "fn ")] + #[suggestion( + "add `fn` here to parse `{$ident}` as a function", + style = "verbose", + applicability = "maybe-incorrect", + code = "fn " + )] insert_span: Span, ident: Ident, }, - #[diag(parse_missing_fn_for_method_definition)] + #[diag("missing `fn` for method definition")] Method { #[primary_span] span: Span, - #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "fn ")] + #[suggestion( + "add `fn` here to parse `{$ident}` as a method", + style = "verbose", + applicability = "maybe-incorrect", + code = "fn " + )] insert_span: Span, ident: Ident, }, - #[diag(parse_missing_fn_or_struct_for_item_definition)] + #[diag("missing `fn` or `struct` for function or struct definition")] Ambiguous { #[primary_span] span: Span, @@ -1922,7 +2247,7 @@ pub(crate) enum MissingKeywordForItemDefinition { #[derive(Subdiagnostic)] pub(crate) enum AmbiguousMissingKwForItemSub { #[suggestion( - parse_suggestion, + "if you meant to call a macro, try", applicability = "maybe-incorrect", code = "{snippet}!", style = "verbose" @@ -1932,39 +2257,49 @@ pub(crate) enum AmbiguousMissingKwForItemSub { span: Span, snippet: String, }, - #[help(parse_help)] + #[help("you likely meant to define an item, e.g., `{$vis} fn foo() {\"{}\"}`")] HelpMacro, } #[derive(Diagnostic)] -#[diag(parse_missing_fn_params)] +#[diag("missing parameters for function definition")] pub(crate) struct MissingFnParams { #[primary_span] - #[suggestion(code = "()", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "add a parameter list", + code = "()", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_path_sep_in_fn_definition)] +#[diag("invalid path separator in function definition")] pub(crate) struct InvalidPathSepInFnDefinition { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove invalid path separator", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_missing_trait_in_trait_impl)] +#[diag("missing trait in a trait impl")] pub(crate) struct MissingTraitInTraitImpl { #[primary_span] #[suggestion( - parse_suggestion_add_trait, + "add a trait here", code = " Trait ", applicability = "has-placeholders", style = "verbose" )] pub span: Span, #[suggestion( - parse_suggestion_remove_for, + "for an inherent impl, drop this `for`", code = "", applicability = "maybe-incorrect", style = "verbose" @@ -1973,102 +2308,130 @@ pub(crate) struct MissingTraitInTraitImpl { } #[derive(Diagnostic)] -#[diag(parse_missing_for_in_trait_impl)] +#[diag("missing `for` in a trait impl")] pub(crate) struct MissingForInTraitImpl { #[primary_span] - #[suggestion(style = "verbose", code = " for ", applicability = "machine-applicable")] + #[suggestion( + "add `for` here", + style = "verbose", + code = " for ", + applicability = "machine-applicable" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_trait_in_trait_impl_found_type)] +#[diag("expected a trait, found type")] pub(crate) struct ExpectedTraitInTraitImplFoundType { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_extra_impl_keyword_in_trait_impl)] +#[diag("unexpected `impl` keyword")] pub(crate) struct ExtraImplKeywordInTraitImpl { #[primary_span] - #[suggestion(code = "", applicability = "maybe-incorrect", style = "short")] + #[suggestion( + "remove the extra `impl`", + code = "", + applicability = "maybe-incorrect", + style = "short" + )] pub extra_impl_kw: Span, - #[note] + #[note("this is parsed as an `impl Trait` type, but a trait is expected at this position")] pub impl_trait_span: Span, } #[derive(Diagnostic)] -#[diag(parse_bounds_not_allowed_on_trait_aliases)] +#[diag("bounds are not allowed on trait aliases")] pub(crate) struct BoundsNotAllowedOnTraitAliases { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_trait_alias_cannot_be_auto)] +#[diag("trait aliases cannot be `auto`")] pub(crate) struct TraitAliasCannotBeAuto { #[primary_span] - #[label(parse_trait_alias_cannot_be_auto)] + #[label("trait aliases cannot be `auto`")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_trait_alias_cannot_be_unsafe)] +#[diag("trait aliases cannot be `unsafe`")] pub(crate) struct TraitAliasCannotBeUnsafe { #[primary_span] - #[label(parse_trait_alias_cannot_be_unsafe)] + #[label("trait aliases cannot be `unsafe`")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_associated_static_item_not_allowed)] +#[diag("associated `static` items are not allowed")] pub(crate) struct AssociatedStaticItemNotAllowed { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_extern_crate_name_with_dashes)] +#[diag("crate name using dashes are not valid in `extern crate` statements")] pub(crate) struct ExternCrateNameWithDashes { #[primary_span] - #[label] + #[label("dash-separated idents are not valid")] pub span: Span, #[subdiagnostic] pub sugg: ExternCrateNameWithDashesSugg, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "if the original crate name uses dashes you need to use underscores in the code", + applicability = "machine-applicable" +)] pub(crate) struct ExternCrateNameWithDashesSugg { #[suggestion_part(code = "_")] pub dashes: Vec, } #[derive(Diagnostic)] -#[diag(parse_extern_item_cannot_be_const)] -#[note] +#[diag("extern items cannot be `const`")] +#[note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html")] pub(crate) struct ExternItemCannotBeConst { #[primary_span] pub ident_span: Span, - #[suggestion(code = "static ", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "try using a static value", + code = "static ", + applicability = "machine-applicable", + style = "verbose" + )] pub const_span: Option, } #[derive(Diagnostic)] -#[diag(parse_const_global_cannot_be_mutable)] +#[diag("const globals cannot be mutable")] pub(crate) struct ConstGlobalCannotBeMutable { #[primary_span] - #[label] + #[label("cannot be mutable")] pub ident_span: Span, - #[suggestion(code = "static", style = "verbose", applicability = "maybe-incorrect")] + #[suggestion( + "you might want to declare a static instead", + code = "static", + style = "verbose", + applicability = "maybe-incorrect" + )] pub const_span: Span, } #[derive(Diagnostic)] -#[diag(parse_missing_const_type)] +#[diag("missing type for `{$kind}` item")] pub(crate) struct MissingConstType { #[primary_span] - #[suggestion(code = "{colon} ", style = "verbose", applicability = "has-placeholders")] + #[suggestion( + "provide a type for the item", + code = "{colon} ", + style = "verbose", + applicability = "has-placeholders" + )] pub span: Span, pub kind: &'static str, @@ -2076,53 +2439,64 @@ pub(crate) struct MissingConstType { } #[derive(Diagnostic)] -#[diag(parse_enum_struct_mutually_exclusive)] +#[diag("`enum` and `struct` are mutually exclusive")] pub(crate) struct EnumStructMutuallyExclusive { #[primary_span] - #[suggestion(code = "enum", style = "verbose", applicability = "machine-applicable")] + #[suggestion( + "replace `enum struct` with", + code = "enum", + style = "verbose", + applicability = "machine-applicable" + )] pub span: Span, } #[derive(Diagnostic)] pub(crate) enum UnexpectedTokenAfterStructName { - #[diag(parse_unexpected_token_after_struct_name_found_reserved_identifier)] + #[diag( + "expected `where`, `{\"{\"}`, `(`, or `;` after struct name, found reserved identifier `{$token}`" + )] ReservedIdentifier { #[primary_span] - #[label(parse_unexpected_token_after_struct_name)] + #[label("expected `where`, `{\"{\"}`, `(`, or `;` after struct name")] span: Span, token: Token, }, - #[diag(parse_unexpected_token_after_struct_name_found_keyword)] + #[diag("expected `where`, `{\"{\"}`, `(`, or `;` after struct name, found keyword `{$token}`")] Keyword { #[primary_span] - #[label(parse_unexpected_token_after_struct_name)] + #[label("expected `where`, `{\"{\"}`, `(`, or `;` after struct name")] span: Span, token: Token, }, - #[diag(parse_unexpected_token_after_struct_name_found_reserved_keyword)] + #[diag( + "expected `where`, `{\"{\"}`, `(`, or `;` after struct name, found reserved keyword `{$token}`" + )] ReservedKeyword { #[primary_span] - #[label(parse_unexpected_token_after_struct_name)] + #[label("expected `where`, `{\"{\"}`, `(`, or `;` after struct name")] span: Span, token: Token, }, - #[diag(parse_unexpected_token_after_struct_name_found_doc_comment)] + #[diag( + "expected `where`, `{\"{\"}`, `(`, or `;` after struct name, found doc comment `{$token}`" + )] DocComment { #[primary_span] - #[label(parse_unexpected_token_after_struct_name)] + #[label("expected `where`, `{\"{\"}`, `(`, or `;` after struct name")] span: Span, token: Token, }, - #[diag(parse_unexpected_token_after_struct_name_found_metavar)] + #[diag("expected `where`, `{\"{\"}`, `(`, or `;` after struct name, found metavar")] MetaVar { #[primary_span] - #[label(parse_unexpected_token_after_struct_name)] + #[label("expected `where`, `{\"{\"}`, `(`, or `;` after struct name")] span: Span, }, - #[diag(parse_unexpected_token_after_struct_name_found_other)] + #[diag("expected `where`, `{\"{\"}`, `(`, or `;` after struct name, found `{$token}`")] Other { #[primary_span] - #[label(parse_unexpected_token_after_struct_name)] + #[label("expected `where`, `{\"{\"}`, `(`, or `;` after struct name")] span: Span, token: Token, }, @@ -2142,45 +2516,50 @@ impl UnexpectedTokenAfterStructName { } #[derive(Diagnostic)] -#[diag(parse_unexpected_self_in_generic_parameters)] -#[note] +#[diag("unexpected keyword `Self` in generic parameters")] +#[note("you cannot use `Self` as a generic parameter because it is reserved for associated items")] pub(crate) struct UnexpectedSelfInGenericParameters { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_unexpected_default_value_for_lifetime_in_generic_parameters)] +#[diag("unexpected default lifetime parameter")] pub(crate) struct UnexpectedDefaultValueForLifetimeInGenericParameters { #[primary_span] - #[label] + #[label("lifetime parameters cannot have default values")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_multiple_where_clauses)] +#[diag("cannot define duplicate `where` clauses on an item")] pub(crate) struct MultipleWhereClauses { #[primary_span] pub span: Span, - #[label] + #[label("previous `where` clause starts here")] pub previous: Span, - #[suggestion(style = "verbose", code = ",", applicability = "maybe-incorrect")] + #[suggestion( + "consider joining the two `where` clauses into one", + style = "verbose", + code = ",", + applicability = "maybe-incorrect" + )] pub between: Span, } #[derive(Diagnostic)] pub(crate) enum UnexpectedNonterminal { - #[diag(parse_nonterminal_expected_item_keyword)] + #[diag("expected an item keyword")] Item(#[primary_span] Span), - #[diag(parse_nonterminal_expected_statement)] + #[diag("expected a statement")] Statement(#[primary_span] Span), - #[diag(parse_nonterminal_expected_ident)] + #[diag("expected ident, found `{$token}`")] Ident { #[primary_span] span: Span, token: Token, }, - #[diag(parse_nonterminal_expected_lifetime)] + #[diag("expected a lifetime, found `{$token}`")] Lifetime { #[primary_span] span: Span, @@ -2190,14 +2569,14 @@ pub(crate) enum UnexpectedNonterminal { #[derive(Diagnostic)] pub(crate) enum TopLevelOrPatternNotAllowed { - #[diag(parse_or_pattern_not_allowed_in_let_binding)] + #[diag("`let` bindings require top-level or-patterns in parentheses")] LetBinding { #[primary_span] span: Span, #[subdiagnostic] sub: Option, }, - #[diag(parse_or_pattern_not_allowed_in_fn_parameters)] + #[diag("function parameters require top-level or-patterns in parentheses")] FunctionParameter { #[primary_span] span: Span, @@ -2207,7 +2586,7 @@ pub(crate) enum TopLevelOrPatternNotAllowed { } #[derive(Diagnostic)] -#[diag(parse_cannot_be_raw_ident)] +#[diag("`{$ident}` cannot be a raw identifier")] pub(crate) struct CannotBeRawIdent { #[primary_span] pub span: Span, @@ -2215,7 +2594,7 @@ pub(crate) struct CannotBeRawIdent { } #[derive(Diagnostic)] -#[diag(parse_cannot_be_raw_lifetime)] +#[diag("`{$ident}` cannot be a raw lifetime")] pub(crate) struct CannotBeRawLifetime { #[primary_span] pub span: Span, @@ -2223,21 +2602,26 @@ pub(crate) struct CannotBeRawLifetime { } #[derive(Diagnostic)] -#[diag(parse_keyword_lifetime)] +#[diag("lifetimes cannot use keyword names")] pub(crate) struct KeywordLifetime { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_keyword_label)] +#[diag("labels cannot use keyword names")] pub(crate) struct KeywordLabel { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_cr_doc_comment)] +#[diag( + "bare CR not allowed in {$block -> + [true] block doc-comment + *[false] doc-comment + }" +)] pub(crate) struct CrDocComment { #[primary_span] pub span: Span, @@ -2245,14 +2629,14 @@ pub(crate) struct CrDocComment { } #[derive(Diagnostic)] -#[diag(parse_no_digits_literal, code = E0768)] +#[diag("no valid digits found for number", code = E0768)] pub(crate) struct NoDigitsLiteral { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_digit_literal)] +#[diag("invalid digit for a base {$base} literal")] pub(crate) struct InvalidDigitLiteral { #[primary_span] pub span: Span, @@ -2260,14 +2644,14 @@ pub(crate) struct InvalidDigitLiteral { } #[derive(Diagnostic)] -#[diag(parse_empty_exponent_float)] +#[diag("expected at least one digit in exponent")] pub(crate) struct EmptyExponentFloat { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_float_literal_unsupported_base)] +#[diag("{$base} float literal is not supported")] pub(crate) struct FloatLiteralUnsupportedBase { #[primary_span] pub span: Span, @@ -2275,11 +2659,11 @@ pub(crate) struct FloatLiteralUnsupportedBase { } #[derive(Diagnostic)] -#[diag(parse_unknown_prefix)] -#[note] +#[diag("prefix `{$prefix}` is unknown")] +#[note("prefixed identifiers and literals are reserved since Rust 2021")] pub(crate) struct UnknownPrefix<'a> { #[primary_span] - #[label] + #[label("unknown prefix")] pub span: Span, pub prefix: &'a str, #[subdiagnostic] @@ -2287,7 +2671,7 @@ pub(crate) struct UnknownPrefix<'a> { } #[derive(Subdiagnostic)] -#[note(parse_macro_expands_to_adt_field)] +#[note("macros cannot expand to {$adt_ty} fields")] pub(crate) struct MacroExpandsToAdtField<'a> { pub adt_ty: &'a str, } @@ -2295,28 +2679,28 @@ pub(crate) struct MacroExpandsToAdtField<'a> { #[derive(Subdiagnostic)] pub(crate) enum UnknownPrefixSugg { #[suggestion( - parse_suggestion_br, + "use `br` for a raw byte string", code = "br", applicability = "maybe-incorrect", style = "verbose" )] UseBr(#[primary_span] Span), #[suggestion( - parse_suggestion_cr, + "use `cr` for a raw C-string", code = "cr", applicability = "maybe-incorrect", style = "verbose" )] UseCr(#[primary_span] Span), #[suggestion( - parse_suggestion_whitespace, + "consider inserting whitespace here", code = " ", applicability = "maybe-incorrect", style = "verbose" )] Whitespace(#[primary_span] Span), #[multipart_suggestion( - parse_suggestion_str, + "if you meant to write a string literal, use double quotes", applicability = "maybe-incorrect", style = "verbose" )] @@ -2329,8 +2713,8 @@ pub(crate) enum UnknownPrefixSugg { } #[derive(Diagnostic)] -#[diag(parse_reserved_multihash)] -#[note] +#[diag("reserved multi-hash token is forbidden")] +#[note("sequences of two or more # are reserved for future use since Rust 2024")] pub(crate) struct ReservedMultihash { #[primary_span] pub span: Span, @@ -2338,8 +2722,8 @@ pub(crate) struct ReservedMultihash { pub sugg: Option, } #[derive(Diagnostic)] -#[diag(parse_reserved_string)] -#[note] +#[diag("invalid string literal")] +#[note("unprefixed guarded string literals are reserved for future use since Rust 2024")] pub(crate) struct ReservedString { #[primary_span] pub span: Span, @@ -2348,7 +2732,7 @@ pub(crate) struct ReservedString { } #[derive(Subdiagnostic)] #[suggestion( - parse_suggestion_whitespace, + "consider inserting whitespace here", code = " ", applicability = "maybe-incorrect", style = "verbose" @@ -2356,7 +2740,9 @@ pub(crate) struct ReservedString { pub(crate) struct GuardedStringSugg(#[primary_span] pub Span); #[derive(Diagnostic)] -#[diag(parse_too_many_hashes)] +#[diag( + "too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found {$num}" +)] pub(crate) struct TooManyHashes { #[primary_span] pub span: Span, @@ -2364,7 +2750,7 @@ pub(crate) struct TooManyHashes { } #[derive(Diagnostic)] -#[diag(parse_unknown_start_of_token)] +#[diag("unknown start of token: {$escaped}")] pub(crate) struct UnknownTokenStart { #[primary_span] pub span: Span, @@ -2382,7 +2768,7 @@ pub(crate) struct UnknownTokenStart { #[derive(Subdiagnostic)] pub(crate) enum TokenSubstitution { #[suggestion( - parse_sugg_quotes, + "Unicode characters '“' (Left Double Quotation Mark) and '”' (Right Double Quotation Mark) look like '{$ascii_str}' ({$ascii_name}), but are not", code = "{suggestion}", applicability = "maybe-incorrect", style = "verbose" @@ -2395,7 +2781,7 @@ pub(crate) enum TokenSubstitution { ascii_name: &'static str, }, #[suggestion( - parse_sugg_other, + "Unicode character '{$ch}' ({$u_name}) looks like '{$ascii_str}' ({$ascii_name}), but it is not", code = "{suggestion}", applicability = "maybe-incorrect", style = "verbose" @@ -2412,35 +2798,52 @@ pub(crate) enum TokenSubstitution { } #[derive(Subdiagnostic)] -#[note(parse_note_repeats)] +#[note( + "character appears {$repeats -> + [one] once more + *[other] {$repeats} more times + }" +)] pub(crate) struct UnknownTokenRepeat { pub repeats: usize, } #[derive(Subdiagnostic)] -#[help(parse_help_invisible_char)] +#[help("invisible characters like '{$escaped}' are not usually visible in text editors")] pub(crate) struct InvisibleCharacter; #[derive(Subdiagnostic)] -#[help(parse_help_null)] +#[help( + "source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used" +)] pub(crate) struct UnknownTokenNull; #[derive(Diagnostic)] pub(crate) enum UnescapeError { - #[diag(parse_invalid_unicode_escape)] - #[help] + #[diag("invalid unicode character escape")] + #[help( + "unicode escape must {$surrogate -> + [true] not be a surrogate + *[false] be at most 10FFFF + }" + )] InvalidUnicodeEscape { #[primary_span] - #[label] + #[label("invalid escape")] span: Span, surrogate: bool, }, - #[diag(parse_escape_only_char)] + #[diag( + "{$byte -> + [true] byte + *[false] character + } constant must be escaped: `{$escaped_msg}`" + )] EscapeOnlyChar { #[primary_span] span: Span, #[suggestion( - parse_escape, + "escape the character", applicability = "machine-applicable", code = "{escaped_sugg}", style = "verbose" @@ -2450,11 +2853,16 @@ pub(crate) enum UnescapeError { escaped_msg: String, byte: bool, }, - #[diag(parse_bare_cr)] + #[diag( + r#"{$double_quotes -> + [true] bare CR not allowed in string, use `\r` instead + *[false] character constant must be escaped: `\r` + }"# + )] BareCr { #[primary_span] #[suggestion( - parse_escape, + "escape the character", applicability = "machine-applicable", code = "\\r", style = "verbose" @@ -2462,93 +2870,103 @@ pub(crate) enum UnescapeError { span: Span, double_quotes: bool, }, - #[diag(parse_bare_cr_in_raw_string)] + #[diag("bare CR not allowed in raw string")] BareCrRawString(#[primary_span] Span), - #[diag(parse_too_short_hex_escape)] + #[diag("numeric character escape is too short")] TooShortHexEscape(#[primary_span] Span), - #[diag(parse_invalid_char_in_escape)] + #[diag( + "invalid character in {$is_hex -> + [true] numeric character + *[false] unicode + } escape: `{$ch}`" + )] InvalidCharInEscape { #[primary_span] - #[label] + #[label( + "invalid character in {$is_hex -> + [true] numeric character + *[false] unicode + } escape" + )] span: Span, is_hex: bool, ch: String, }, - #[diag(parse_leading_underscore_unicode_escape)] + #[diag("invalid start of unicode escape: `_`")] LeadingUnderscoreUnicodeEscape { #[primary_span] - #[label(parse_leading_underscore_unicode_escape_label)] + #[label("invalid start of unicode escape")] span: Span, ch: String, }, - #[diag(parse_overlong_unicode_escape)] + #[diag("overlong unicode escape")] OverlongUnicodeEscape( #[primary_span] - #[label] + #[label("must have at most 6 hex digits")] Span, ), - #[diag(parse_unclosed_unicode_escape)] + #[diag("unterminated unicode escape")] UnclosedUnicodeEscape( #[primary_span] - #[label] + #[label(r#"missing a closing `{"}"}`"#)] Span, #[suggestion( - parse_terminate, + "terminate the unicode escape", code = "}}", applicability = "maybe-incorrect", style = "verbose" )] Span, ), - #[diag(parse_no_brace_unicode_escape)] + #[diag("incorrect unicode escape sequence")] NoBraceInUnicodeEscape { #[primary_span] span: Span, - #[label] + #[label("incorrect unicode escape sequence")] label: Option, #[subdiagnostic] sub: NoBraceUnicodeSub, }, - #[diag(parse_unicode_escape_in_byte)] - #[help] + #[diag("unicode escape in byte string")] + #[help("unicode escape sequences cannot be used as a byte or in a byte string")] UnicodeEscapeInByte( #[primary_span] - #[label] + #[label("unicode escape in byte string")] Span, ), - #[diag(parse_empty_unicode_escape)] + #[diag("empty unicode escape")] EmptyUnicodeEscape( #[primary_span] - #[label] + #[label("this escape must have at least 1 hex digit")] Span, ), - #[diag(parse_zero_chars)] + #[diag("empty character literal")] ZeroChars( #[primary_span] - #[label] + #[label("empty character literal")] Span, ), - #[diag(parse_lone_slash)] + #[diag("invalid trailing slash in literal")] LoneSlash( #[primary_span] - #[label] + #[label("invalid trailing slash in literal")] Span, ), - #[diag(parse_unskipped_whitespace)] + #[diag("whitespace symbol '{$ch}' is not skipped")] UnskippedWhitespace { #[primary_span] span: Span, - #[label] + #[label("whitespace symbol '{$ch}' is not skipped")] char_span: Span, ch: String, }, - #[diag(parse_multiple_skipped_lines)] + #[diag("multiple lines skipped by escaped newline")] MultipleSkippedLinesWarning( #[primary_span] - #[label] + #[label("skipping everything up to and including this point")] Span, ), - #[diag(parse_more_than_one_char)] + #[diag("character literal may only contain one codepoint")] MoreThanOneChar { #[primary_span] span: Span, @@ -2557,7 +2975,7 @@ pub(crate) enum UnescapeError { #[subdiagnostic] suggestion: MoreThanOneCharSugg, }, - #[diag(parse_nul_in_c_str)] + #[diag("null characters in C string literals are not supported")] NulInCStr { #[primary_span] span: Span, @@ -2567,7 +2985,7 @@ pub(crate) enum UnescapeError { #[derive(Subdiagnostic)] pub(crate) enum MoreThanOneCharSugg { #[suggestion( - parse_consider_normalized, + "consider using the normalized form `{$ch}` of this character", code = "{normalized}", applicability = "machine-applicable", style = "verbose" @@ -2579,7 +2997,7 @@ pub(crate) enum MoreThanOneCharSugg { normalized: String, }, #[suggestion( - parse_remove_non, + "consider removing the non-printing characters", code = "{ch}", applicability = "maybe-incorrect", style = "verbose" @@ -2590,7 +3008,10 @@ pub(crate) enum MoreThanOneCharSugg { ch: String, }, #[suggestion( - parse_use_double_quotes, + "if you meant to write a {$is_byte -> + [true] byte string + *[false] string + } literal, use double quotes", code = "{sugg}", applicability = "machine-applicable", style = "verbose" @@ -2601,7 +3022,13 @@ pub(crate) enum MoreThanOneCharSugg { is_byte: bool, sugg: String, }, - #[multipart_suggestion(parse_use_double_quotes, applicability = "machine-applicable")] + #[multipart_suggestion( + "if you meant to write a {$is_byte -> + [true] byte string + *[false] string + } literal, use double quotes", + applicability = "machine-applicable" + )] Quotes { #[suggestion_part(code = "{prefix}\"")] start: Span, @@ -2614,7 +3041,12 @@ pub(crate) enum MoreThanOneCharSugg { #[derive(Subdiagnostic)] pub(crate) enum MoreThanOneCharNote { - #[note(parse_followed_by)] + #[note( + "this `{$chr}` is followed by the combining {$len -> + [one] mark + *[other] marks + } `{$escaped_marks}`" + )] AllCombining { #[primary_span] span: Span, @@ -2622,7 +3054,7 @@ pub(crate) enum MoreThanOneCharNote { len: usize, escaped_marks: String, }, - #[note(parse_non_printing)] + #[note("there are non-printing characters, the full sequence is `{$escaped}`")] NonPrinting { #[primary_span] span: Span, @@ -2633,7 +3065,7 @@ pub(crate) enum MoreThanOneCharNote { #[derive(Subdiagnostic)] pub(crate) enum NoBraceUnicodeSub { #[suggestion( - parse_use_braces, + "format of unicode escape sequences uses braces", code = "{suggestion}", applicability = "maybe-incorrect", style = "verbose" @@ -2643,12 +3075,12 @@ pub(crate) enum NoBraceUnicodeSub { span: Span, suggestion: String, }, - #[help(parse_format_of_unicode)] + #[help(r#"format of unicode escape sequences is `\u{"{...}"}`"#)] Help, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_sugg_wrap_pattern_in_parens, applicability = "machine-applicable")] +#[multipart_suggestion("wrap the pattern in parentheses", applicability = "machine-applicable")] pub(crate) struct WrapInParens { #[suggestion_part(code = "(")] pub(crate) lo: Span, @@ -2659,7 +3091,7 @@ pub(crate) struct WrapInParens { #[derive(Subdiagnostic)] pub(crate) enum TopLevelOrPatternNotAllowedSugg { #[suggestion( - parse_sugg_remove_leading_vert_in_pattern, + "remove the `|`", code = "", applicability = "machine-applicable", style = "tool-only" @@ -2677,27 +3109,37 @@ pub(crate) enum TopLevelOrPatternNotAllowedSugg { } #[derive(Diagnostic)] -#[diag(parse_unexpected_vert_vert_before_function_parameter)] -#[note(parse_note_pattern_alternatives_use_single_vert)] +#[diag("unexpected `||` before function parameter")] +#[note("alternatives in or-patterns are separated with `|`, not `||`")] pub(crate) struct UnexpectedVertVertBeforeFunctionParam { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove the `||`", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_unexpected_vert_vert_in_pattern)] +#[diag("unexpected token `||` in pattern")] pub(crate) struct UnexpectedVertVertInPattern { #[primary_span] - #[suggestion(code = "|", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "use a single `|` to separate multiple alternative patterns", + code = "|", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, - #[label(parse_label_while_parsing_or_pattern_here)] + #[label("while parsing this or-pattern starting here")] pub start: Option, } #[derive(Subdiagnostic)] #[suggestion( - parse_trailing_vert_not_allowed, + "a trailing `{$token}` is not allowed in an or-pattern", code = "", applicability = "machine-applicable", style = "tool-only" @@ -2708,59 +3150,71 @@ pub(crate) struct TrailingVertSuggestion { } #[derive(Diagnostic)] -#[diag(parse_trailing_vert_not_allowed)] +#[diag("a trailing `{$token}` is not allowed in an or-pattern")] pub(crate) struct TrailingVertNotAllowed { #[primary_span] pub span: Span, #[subdiagnostic] pub suggestion: TrailingVertSuggestion, - #[label(parse_label_while_parsing_or_pattern_here)] + #[label("while parsing this or-pattern starting here")] pub start: Option, pub token: Token, - #[note(parse_note_pattern_alternatives_use_single_vert)] + #[note("alternatives in or-patterns are separated with `|`, not `||`")] pub note_double_vert: bool, } #[derive(Diagnostic)] -#[diag(parse_dotdotdot_rest_pattern)] +#[diag("unexpected `...`")] pub(crate) struct DotDotDotRestPattern { #[primary_span] - #[label] + #[label("not a valid pattern")] pub span: Span, - #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] + #[suggestion( + "for a rest pattern, use `..` instead of `...`", + style = "verbose", + code = "", + applicability = "machine-applicable" + )] pub suggestion: Option, - #[note] + #[note( + "only `extern \"C\"` and `extern \"C-unwind\"` functions may have a C variable argument list" + )] pub var_args: Option<()>, } #[derive(Diagnostic)] -#[diag(parse_pattern_on_wrong_side_of_at)] +#[diag("pattern on wrong side of `@`")] pub(crate) struct PatternOnWrongSideOfAt { #[primary_span] - #[suggestion(code = "{whole_pat}", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "switch the order", + code = "{whole_pat}", + applicability = "machine-applicable", + style = "verbose" + )] pub whole_span: Span, pub whole_pat: String, - #[label(parse_label_pattern)] + #[label("pattern on the left, should be on the right")] pub pattern: Span, - #[label(parse_label_binding)] + #[label("binding on the right, should be on the left")] pub binding: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_binding_left_of_at)] -#[note] +#[diag("left-hand side of `@` must be a binding")] +#[note("bindings are `x`, `mut x`, `ref x`, and `ref mut x`")] pub(crate) struct ExpectedBindingLeftOfAt { #[primary_span] pub whole_span: Span, - #[label(parse_label_lhs)] + #[label("interpreted as a pattern, not a binding")] pub lhs: Span, - #[label(parse_label_rhs)] + #[label("also a pattern")] pub rhs: Span, } #[derive(Subdiagnostic)] #[multipart_suggestion( - parse_ambiguous_range_pattern_suggestion, + "add parentheses to clarify the precedence", applicability = "machine-applicable" )] pub(crate) struct ParenRangeSuggestion { @@ -2771,7 +3225,7 @@ pub(crate) struct ParenRangeSuggestion { } #[derive(Diagnostic)] -#[diag(parse_ambiguous_range_pattern)] +#[diag("the range pattern here has ambiguous interpretation")] pub(crate) struct AmbiguousRangePattern { #[primary_span] pub span: Span, @@ -2780,100 +3234,144 @@ pub(crate) struct AmbiguousRangePattern { } #[derive(Diagnostic)] -#[diag(parse_unexpected_lifetime_in_pattern)] +#[diag("unexpected lifetime `{$symbol}` in pattern")] pub(crate) struct UnexpectedLifetimeInPattern { #[primary_span] pub span: Span, pub symbol: Symbol, - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove the lifetime", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] pub(crate) enum InvalidMutInPattern { - #[diag(parse_mut_on_nested_ident_pattern)] - #[note(parse_note_mut_pattern_usage)] + #[diag("`mut` must be attached to each individual binding")] + #[note("`mut` may be followed by `variable` and `variable @ pattern`")] NestedIdent { #[primary_span] - #[suggestion(code = "{pat}", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "add `mut` to each binding", + code = "{pat}", + applicability = "machine-applicable", + style = "verbose" + )] span: Span, pat: String, }, - #[diag(parse_mut_on_non_ident_pattern)] - #[note(parse_note_mut_pattern_usage)] + #[diag("`mut` must be followed by a named binding")] + #[note("`mut` may be followed by `variable` and `variable @ pattern`")] NonIdent { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove the `mut` prefix", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] span: Span, }, } #[derive(Diagnostic)] -#[diag(parse_repeated_mut_in_pattern)] +#[diag("`mut` on a binding may not be repeated")] pub(crate) struct RepeatedMutInPattern { #[primary_span] pub span: Span, - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove the additional `mut`s", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_dot_dot_dot_range_to_pattern_not_allowed)] +#[diag("range-to patterns with `...` are not allowed")] pub(crate) struct DotDotDotRangeToPatternNotAllowed { #[primary_span] - #[suggestion(style = "verbose", code = "..=", applicability = "machine-applicable")] + #[suggestion( + "use `..=` instead", + style = "verbose", + code = "..=", + applicability = "machine-applicable" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_enum_pattern_instead_of_identifier)] +#[diag("expected identifier, found enum pattern")] pub(crate) struct EnumPatternInsteadOfIdentifier { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_at_dot_dot_in_struct_pattern)] +#[diag("`@ ..` is not supported in struct patterns")] pub(crate) struct AtDotDotInStructPattern { #[primary_span] pub span: Span, - #[suggestion(code = "", style = "verbose", applicability = "machine-applicable")] + #[suggestion( + "bind to each field separately or, if you don't need them, just remove `{$ident} @`", + code = "", + style = "verbose", + applicability = "machine-applicable" + )] pub remove: Span, pub ident: Ident, } #[derive(Diagnostic)] -#[diag(parse_at_in_struct_pattern)] -#[note] -#[help] +#[diag("unexpected `@` in struct pattern")] +#[note("struct patterns use `field: pattern` syntax to bind to fields")] +#[help( + "consider replacing `new_name @ field_name` with `field_name: new_name` if that is what you intended" +)] pub(crate) struct AtInStructPattern { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_dot_dot_dot_for_remaining_fields)] +#[diag("expected field pattern, found `{$token_str}`")] pub(crate) struct DotDotDotForRemainingFields { #[primary_span] - #[suggestion(code = "..", style = "verbose", applicability = "machine-applicable")] + #[suggestion( + "to omit remaining fields, use `..`", + code = "..", + style = "verbose", + applicability = "machine-applicable" + )] pub span: Span, pub token_str: Cow<'static, str>, } #[derive(Diagnostic)] -#[diag(parse_expected_comma_after_pattern_field)] +#[diag("expected `,`")] pub(crate) struct ExpectedCommaAfterPatternField { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_unexpected_expr_in_pat)] -#[note] +#[diag( + "expected {$is_bound -> + [true] a pattern range bound + *[false] a pattern + }, found an expression" +)] +#[note( + "arbitrary expressions are not allowed in patterns: " +)] pub(crate) struct UnexpectedExpressionInPattern { /// The unexpected expr's span. #[primary_span] - #[label] + #[label("not a pattern")] pub span: Span, /// Was a `RangePatternBound` expected? pub is_bound: bool, @@ -2884,7 +3382,7 @@ pub(crate) struct UnexpectedExpressionInPattern { #[derive(Subdiagnostic)] pub(crate) enum UnexpectedExpressionInPatternSugg { #[multipart_suggestion( - parse_unexpected_expr_in_pat_create_guard_sugg, + "consider moving the expression to a match arm guard", applicability = "maybe-incorrect" )] CreateGuard { @@ -2901,7 +3399,7 @@ pub(crate) enum UnexpectedExpressionInPatternSugg { }, #[multipart_suggestion( - parse_unexpected_expr_in_pat_update_guard_sugg, + "consider moving the expression to the match arm guard", applicability = "maybe-incorrect" )] UpdateGuard { @@ -2923,7 +3421,7 @@ pub(crate) enum UnexpectedExpressionInPatternSugg { }, #[multipart_suggestion( - parse_unexpected_expr_in_pat_const_sugg, + "consider extracting the expression into a `const`", applicability = "has-placeholders" )] Const { @@ -2943,7 +3441,7 @@ pub(crate) enum UnexpectedExpressionInPatternSugg { } #[derive(Diagnostic)] -#[diag(parse_unexpected_paren_in_range_pat)] +#[diag("range pattern bounds cannot have parentheses")] pub(crate) struct UnexpectedParenInRangePat { #[primary_span] pub span: Vec, @@ -2952,10 +3450,7 @@ pub(crate) struct UnexpectedParenInRangePat { } #[derive(Subdiagnostic)] -#[multipart_suggestion( - parse_unexpected_paren_in_range_pat_sugg, - applicability = "machine-applicable" -)] +#[multipart_suggestion("remove these parentheses", applicability = "machine-applicable")] pub(crate) struct UnexpectedParenInRangePatSugg { #[suggestion_part(code = "")] pub start_span: Span, @@ -2964,104 +3459,145 @@ pub(crate) struct UnexpectedParenInRangePatSugg { } #[derive(Diagnostic)] -#[diag(parse_return_types_use_thin_arrow)] +#[diag("return types are denoted using `->`")] pub(crate) struct ReturnTypesUseThinArrow { #[primary_span] pub span: Span, - #[suggestion(style = "verbose", code = " -> ", applicability = "machine-applicable")] + #[suggestion( + "use `->` instead", + style = "verbose", + code = " -> ", + applicability = "machine-applicable" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_need_plus_after_trait_object_lifetime)] +#[diag("lifetimes must be followed by `+` to form a trait object type")] pub(crate) struct NeedPlusAfterTraitObjectLifetime { #[primary_span] pub span: Span, - #[suggestion(code = " + /* Trait */", applicability = "has-placeholders")] + #[suggestion( + "consider adding a trait bound after the potential lifetime bound", + code = " + /* Trait */", + applicability = "has-placeholders" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_expected_mut_or_const_in_raw_pointer_type)] +#[diag("expected `mut` or `const` keyword in raw pointer type")] pub(crate) struct ExpectedMutOrConstInRawPointerType { #[primary_span] pub span: Span, - #[suggestion(code("mut ", "const "), applicability = "has-placeholders", style = "verbose")] + #[suggestion( + "add `mut` or `const` here", + code("mut ", "const "), + applicability = "has-placeholders", + style = "verbose" + )] pub after_asterisk: Span, } #[derive(Diagnostic)] -#[diag(parse_lifetime_after_mut)] +#[diag("lifetime must precede `mut`")] pub(crate) struct LifetimeAfterMut { #[primary_span] pub span: Span, - #[suggestion(code = "&{snippet} mut", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "place the lifetime before `mut`", + code = "&{snippet} mut", + applicability = "maybe-incorrect", + style = "verbose" + )] pub suggest_lifetime: Option, pub snippet: String, } #[derive(Diagnostic)] -#[diag(parse_dyn_after_mut)] +#[diag("`mut` must precede `dyn`")] pub(crate) struct DynAfterMut { #[primary_span] - #[suggestion(code = "&mut dyn", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "place `mut` before `dyn`", + code = "&mut dyn", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_fn_pointer_cannot_be_const)] -#[note] +#[diag("an `fn` pointer type cannot be `const`")] +#[note("allowed qualifiers are: `unsafe` and `extern`")] pub(crate) struct FnPointerCannotBeConst { #[primary_span] - #[label] + #[label("`const` because of this")] pub span: Span, - #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "remove the `const` qualifier", + code = "", + applicability = "maybe-incorrect", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_fn_pointer_cannot_be_async)] -#[note] +#[diag("an `fn` pointer type cannot be `async`")] +#[note("allowed qualifiers are: `unsafe` and `extern`")] pub(crate) struct FnPointerCannotBeAsync { #[primary_span] - #[label] + #[label("`async` because of this")] pub span: Span, - #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "remove the `async` qualifier", + code = "", + applicability = "maybe-incorrect", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_nested_c_variadic_type, code = E0743)] +#[diag("C-variadic type `...` may not be nested inside another type", code = E0743)] pub(crate) struct NestedCVariadicType { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_dotdotdot_rest_type)] -#[note] +#[diag("unexpected `...`")] +#[note( + "only `extern \"C\"` and `extern \"C-unwind\"` functions may have a C variable argument list" +)] pub(crate) struct InvalidCVariadicType { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_invalid_dyn_keyword)] -#[help] +#[diag("invalid `dyn` keyword")] +#[help("`dyn` is only needed at the start of a trait `+`-separated list")] pub(crate) struct InvalidDynKeyword { #[primary_span] pub span: Span, - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove this keyword", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub suggestion: Span, } #[derive(Subdiagnostic)] pub(crate) enum HelpUseLatestEdition { - #[help(parse_help_set_edition_cargo)] - #[note(parse_note_edition_guide)] + #[help("set `edition = \"{$edition}\"` in `Cargo.toml`")] + #[note("for more on editions, read https://doc.rust-lang.org/edition-guide")] Cargo { edition: Edition }, - #[help(parse_help_set_edition_standalone)] - #[note(parse_note_edition_guide)] + #[help("pass `--edition {$edition}` to `rustc`")] + #[note("for more on editions, read https://doc.rust-lang.org/edition-guide")] Standalone { edition: Edition }, } @@ -3077,7 +3613,7 @@ impl HelpUseLatestEdition { } #[derive(Diagnostic)] -#[diag(parse_box_syntax_removed)] +#[diag("`box_syntax` has been removed")] pub(crate) struct BoxSyntaxRemoved { #[primary_span] pub span: Span, @@ -3087,7 +3623,7 @@ pub(crate) struct BoxSyntaxRemoved { #[derive(Subdiagnostic)] #[multipart_suggestion( - parse_box_syntax_removed_suggestion, + "use `Box::new()` instead", applicability = "machine-applicable", style = "verbose" )] @@ -3099,65 +3635,70 @@ pub(crate) struct AddBoxNew { } #[derive(Diagnostic)] -#[diag(parse_bad_return_type_notation_output)] +#[diag("return type not allowed with return type notation")] pub(crate) struct BadReturnTypeNotationOutput { #[primary_span] pub span: Span, - #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "remove the return type", + code = "", + applicability = "maybe-incorrect", + style = "verbose" + )] pub suggestion: Span, } #[derive(Diagnostic)] -#[diag(parse_bad_assoc_type_bounds)] +#[diag("bounds on associated types do not belong here")] pub(crate) struct BadAssocTypeBounds { #[primary_span] - #[label] + #[label("belongs in `where` clause")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_attr_after_generic)] +#[diag("trailing attribute after generic parameter")] pub(crate) struct AttrAfterGeneric { #[primary_span] - #[label] + #[label("attributes must go before parameters")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_attr_without_generics)] +#[diag("attribute without generic parameters")] pub(crate) struct AttrWithoutGenerics { #[primary_span] - #[label] + #[label("attributes are only permitted when preceding parameters")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_where_generics)] +#[diag("generic parameters on `where` clauses are reserved for future use")] pub(crate) struct WhereOnGenerics { #[primary_span] - #[label] + #[label("currently unsupported")] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_generics_in_path)] +#[diag("unexpected generic arguments in path")] pub(crate) struct GenericsInPath { #[primary_span] pub span: Vec, } #[derive(Diagnostic)] -#[diag(parse_lifetime_in_eq_constraint)] -#[help] +#[diag("lifetimes are not permitted in this context")] +#[help("if you meant to specify a trait object, write `dyn /* Trait */ + {$lifetime}`")] pub(crate) struct LifetimeInEqConstraint { #[primary_span] - #[label] + #[label("lifetime is not allowed here")] pub span: Span, pub lifetime: Ident, - #[label(parse_context_label)] + #[label("this introduces an associated item binding")] pub binding_label: Span, #[suggestion( - parse_colon_sugg, + "you might have meant to write a bound here", style = "verbose", applicability = "maybe-incorrect", code = ": " @@ -3166,119 +3707,159 @@ pub(crate) struct LifetimeInEqConstraint { } #[derive(Diagnostic)] -#[diag(parse_modifier_lifetime)] +#[diag("`{$modifier}` may only modify trait bounds, not lifetime bounds")] pub(crate) struct ModifierLifetime { #[primary_span] - #[suggestion(style = "tool-only", applicability = "maybe-incorrect", code = "")] + #[suggestion( + "remove the `{$modifier}`", + style = "tool-only", + applicability = "maybe-incorrect", + code = "" + )] pub span: Span, pub modifier: &'static str, } #[derive(Diagnostic)] -#[diag(parse_underscore_literal_suffix)] +#[diag("underscore literal suffix is not allowed")] pub(crate) struct UnderscoreLiteralSuffix { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_expect_label_found_ident)] +#[diag("expected a label, found an identifier")] pub(crate) struct ExpectedLabelFoundIdent { #[primary_span] pub span: Span, - #[suggestion(code = "'", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "labels start with a tick", + code = "'", + applicability = "machine-applicable", + style = "verbose" + )] pub start: Span, } #[derive(Diagnostic)] -#[diag(parse_inappropriate_default)] -#[note] +#[diag("{$article} {$descr} cannot be `default`")] +#[note("only associated `fn`, `const`, and `type` items can be `default`")] pub(crate) struct InappropriateDefault { #[primary_span] - #[label] + #[label("`default` because of this")] pub span: Span, pub article: &'static str, pub descr: &'static str, } #[derive(Diagnostic)] -#[diag(parse_recover_import_as_use)] +#[diag("expected item, found {$token_name}")] pub(crate) struct RecoverImportAsUse { #[primary_span] - #[suggestion(code = "use", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "items are imported using the `use` keyword", + code = "use", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, pub token_name: String, } #[derive(Diagnostic)] -#[diag(parse_single_colon_import_path)] -#[note] +#[diag("expected `::`, found `:`")] +#[note("import paths are delimited using `::`")] pub(crate) struct SingleColonImportPath { #[primary_span] - #[suggestion(code = "::", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "use double colon", + code = "::", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_bad_item_kind)] +#[diag("{$descr} is not supported in {$ctx}")] pub(crate) struct BadItemKind { #[primary_span] pub span: Span, pub descr: &'static str, pub ctx: &'static str, - #[help] + #[help("consider moving the {$descr} out to a nearby module scope")] pub help: bool, } #[derive(Diagnostic)] -#[diag(parse_macro_rules_missing_bang)] +#[diag("expected `!` after `macro_rules`")] pub(crate) struct MacroRulesMissingBang { #[primary_span] pub span: Span, - #[suggestion(code = "!", applicability = "machine-applicable", style = "verbose")] + #[suggestion("add a `!`", code = "!", applicability = "machine-applicable", style = "verbose")] pub hi: Span, } #[derive(Diagnostic)] -#[diag(parse_macro_name_remove_bang)] +#[diag("macro names aren't followed by a `!`")] pub(crate) struct MacroNameRemoveBang { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "short")] + #[suggestion( + "remove the `!`", + code = "", + applicability = "machine-applicable", + style = "short" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_macro_rules_visibility)] +#[diag("can't qualify macro_rules invocation with `{$vis}`")] pub(crate) struct MacroRulesVisibility<'a> { #[primary_span] - #[suggestion(code = "#[macro_export]", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "try exporting the macro", + code = "#[macro_export]", + applicability = "maybe-incorrect", + style = "verbose" + )] pub span: Span, pub vis: &'a str, } #[derive(Diagnostic)] -#[diag(parse_macro_invocation_visibility)] -#[help] +#[diag("can't qualify macro invocation with `pub`")] +#[help("try adjusting the macro to put `{$vis}` inside the invocation")] pub(crate) struct MacroInvocationVisibility<'a> { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove the visibility", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, pub vis: &'a str, } #[derive(Diagnostic)] -#[diag(parse_nested_adt)] +#[diag("`{$kw_str}` definition cannot be nested inside `{$keyword}`")] pub(crate) struct NestedAdt<'a> { #[primary_span] pub span: Span, - #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "consider creating a new `{$kw_str}` definition instead of nesting", + code = "", + applicability = "maybe-incorrect", + style = "verbose" + )] pub item: Span, pub keyword: &'a str, pub kw_str: Cow<'a, str>, } #[derive(Diagnostic)] -#[diag(parse_function_body_equals_expr)] +#[diag("function body cannot be `= expression;`")] pub(crate) struct FunctionBodyEqualsExpr { #[primary_span] pub span: Span, @@ -3287,7 +3868,10 @@ pub(crate) struct FunctionBodyEqualsExpr { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + r#"surround the expression with `{"{"}` and `{"}"}` instead of `=` and `;`"#, + applicability = "machine-applicable" +)] pub(crate) struct FunctionBodyEqualsExprSugg { #[suggestion_part(code = "{{")] pub eq: Span, @@ -3296,38 +3880,56 @@ pub(crate) struct FunctionBodyEqualsExprSugg { } #[derive(Diagnostic)] -#[diag(parse_box_not_pat)] +#[diag("expected pattern, found {$descr}")] pub(crate) struct BoxNotPat { #[primary_span] pub span: Span, - #[note] + #[note("`box` is a reserved keyword")] pub kw: Span, - #[suggestion(code = "r#", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion( + "escape `box` to use it as an identifier", + code = "r#", + applicability = "maybe-incorrect", + style = "verbose" + )] pub lo: Span, pub descr: String, } #[derive(Diagnostic)] -#[diag(parse_unmatched_angle)] +#[diag( + "unmatched angle {$plural -> + [true] brackets + *[false] bracket + }" +)] pub(crate) struct UnmatchedAngle { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] + #[suggestion( + "remove extra angle {$plural -> + [true] brackets + *[false] bracket + }", + code = "", + applicability = "machine-applicable", + style = "verbose" + )] pub span: Span, pub plural: bool, } #[derive(Diagnostic)] -#[diag(parse_missing_plus_in_bounds)] +#[diag("expected `+` between lifetime and {$sym}")] pub(crate) struct MissingPlusBounds { #[primary_span] pub span: Span, - #[suggestion(code = " +", applicability = "maybe-incorrect", style = "verbose")] + #[suggestion("add `+`", code = " +", applicability = "maybe-incorrect", style = "verbose")] pub hi: Span, pub sym: Symbol, } #[derive(Diagnostic)] -#[diag(parse_incorrect_parens_trait_bounds)] +#[diag("incorrect parentheses around trait bounds")] pub(crate) struct IncorrectParensTraitBounds { #[primary_span] pub span: Vec, @@ -3336,10 +3938,7 @@ pub(crate) struct IncorrectParensTraitBounds { } #[derive(Subdiagnostic)] -#[multipart_suggestion( - parse_incorrect_parens_trait_bounds_sugg, - applicability = "machine-applicable" -)] +#[multipart_suggestion("fix the parentheses", applicability = "machine-applicable")] pub(crate) struct IncorrectParensTraitBoundsSugg { #[suggestion_part(code = " ")] pub wrong_span: Span, @@ -3348,10 +3947,15 @@ pub(crate) struct IncorrectParensTraitBoundsSugg { } #[derive(Diagnostic)] -#[diag(parse_kw_bad_case)] +#[diag("keyword `{$kw}` is written in the wrong case")] pub(crate) struct KwBadCase<'a> { #[primary_span] - #[suggestion(code = "{kw}", style = "verbose", applicability = "machine-applicable")] + #[suggestion( + "write it in {$case}", + code = "{kw}", + style = "verbose", + applicability = "machine-applicable" + )] pub span: Span, pub kw: &'a str, pub case: Case, @@ -3375,7 +3979,7 @@ impl IntoDiagArg for Case { } #[derive(Diagnostic)] -#[diag(parse_unknown_builtin_construct)] +#[diag("unknown `builtin #` construct `{$name}`")] pub(crate) struct UnknownBuiltinConstruct { #[primary_span] pub span: Span, @@ -3383,35 +3987,38 @@ pub(crate) struct UnknownBuiltinConstruct { } #[derive(Diagnostic)] -#[diag(parse_expected_builtin_ident)] +#[diag("expected identifier after `builtin #`")] pub(crate) struct ExpectedBuiltinIdent { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_static_with_generics)] +#[diag("static items may not have generic parameters")] pub(crate) struct StaticWithGenerics { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_where_clause_before_const_body)] +#[diag("where clauses are not allowed before const item bodies")] pub(crate) struct WhereClauseBeforeConstBody { #[primary_span] - #[label] + #[label("unexpected where clause")] pub span: Span, - #[label(parse_name_label)] + #[label("while parsing this const item")] pub name: Span, - #[label(parse_body_label)] + #[label("the item body")] pub body: Span, #[subdiagnostic] pub sugg: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "move the body before the where clause", + applicability = "machine-applicable" +)] pub(crate) struct WhereClauseBeforeConstBodySugg { #[suggestion_part(code = "= {snippet} ")] pub left: Span, @@ -3421,12 +4028,12 @@ pub(crate) struct WhereClauseBeforeConstBodySugg { } #[derive(Diagnostic)] -#[diag(parse_generic_args_in_pat_require_turbofish_syntax)] +#[diag("generic args in patterns require the turbofish syntax")] pub(crate) struct GenericArgsInPatRequireTurbofishSyntax { #[primary_span] pub span: Span, #[suggestion( - parse_sugg_turbofish_syntax, + "use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments", style = "verbose", code = "::", applicability = "maybe-incorrect" @@ -3435,7 +4042,7 @@ pub(crate) struct GenericArgsInPatRequireTurbofishSyntax { } #[derive(Diagnostic)] -#[diag(parse_transpose_dyn_or_impl)] +#[diag("`for<...>` expected after `{$kw}`, not before")] pub(crate) struct TransposeDynOrImpl<'a> { #[primary_span] pub span: Span, @@ -3445,7 +4052,7 @@ pub(crate) struct TransposeDynOrImpl<'a> { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion("move `{$kw}` before the `for<...>`", applicability = "machine-applicable")] pub(crate) struct TransposeDynOrImplSugg<'a> { #[suggestion_part(code = "")] pub removal_span: Span, @@ -3455,68 +4062,77 @@ pub(crate) struct TransposeDynOrImplSugg<'a> { } #[derive(Diagnostic)] -#[diag(parse_array_index_offset_of)] +#[diag("array indexing not supported in offset_of")] pub(crate) struct ArrayIndexInOffsetOf(#[primary_span] pub Span); #[derive(Diagnostic)] -#[diag(parse_invalid_offset_of)] +#[diag("offset_of expects dot-separated field and variant names")] pub(crate) struct InvalidOffsetOf(#[primary_span] pub Span); #[derive(Diagnostic)] -#[diag(parse_async_impl)] +#[diag("`async` trait implementations are unsupported")] pub(crate) struct AsyncImpl { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_expr_rarrow_call)] -#[help] +#[diag("`->` is not valid syntax for field accesses and method calls")] +#[help( + "the `.` operator will automatically dereference the value, except if the value is a raw pointer" +)] pub(crate) struct ExprRArrowCall { #[primary_span] - #[suggestion(style = "verbose", applicability = "machine-applicable", code = ".")] + #[suggestion( + "try using `.` instead", + style = "verbose", + applicability = "machine-applicable", + code = "." + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_dot_dot_range_attribute)] +#[diag("attributes are not allowed on range expressions starting with `..`")] pub(crate) struct DotDotRangeAttribute { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_binder_before_modifiers)] +#[diag("`for<...>` binder should be placed before trait bound modifiers")] pub(crate) struct BinderBeforeModifiers { #[primary_span] pub binder_span: Span, - #[label] + #[label("place the `for<...>` binder before any modifiers")] pub modifiers_span: Span, } #[derive(Diagnostic)] -#[diag(parse_binder_and_polarity)] +#[diag("`for<...>` binder not allowed with `{$polarity}` trait polarity modifier")] pub(crate) struct BinderAndPolarity { #[primary_span] pub polarity_span: Span, - #[label] + #[label("there is not a well-defined meaning for a higher-ranked `{$polarity}` trait")] pub binder_span: Span, pub polarity: &'static str, } #[derive(Diagnostic)] -#[diag(parse_modifiers_and_polarity)] +#[diag("`{$modifiers_concatenated}` trait not allowed with `{$polarity}` trait polarity modifier")] pub(crate) struct PolarityAndModifiers { #[primary_span] pub polarity_span: Span, - #[label] + #[label( + "there is not a well-defined meaning for a `{$modifiers_concatenated} {$polarity}` trait" + )] pub modifiers_span: Span, pub polarity: &'static str, pub modifiers_concatenated: String, } #[derive(Diagnostic)] -#[diag(parse_incorrect_type_on_self)] +#[diag("type not allowed for shorthand `self` parameter")] pub(crate) struct IncorrectTypeOnSelf { #[primary_span] pub span: Span, @@ -3525,7 +4141,10 @@ pub(crate) struct IncorrectTypeOnSelf { } #[derive(Subdiagnostic)] -#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "move the modifiers on `self` to the type", + applicability = "machine-applicable" +)] pub(crate) struct MoveSelfModifier { #[suggestion_part(code = "")] pub removal_span: Span, @@ -3535,82 +4154,104 @@ pub(crate) struct MoveSelfModifier { } #[derive(Diagnostic)] -#[diag(parse_asm_unsupported_operand)] +#[diag("the `{$symbol}` operand cannot be used with `{$macro_name}!`")] pub(crate) struct AsmUnsupportedOperand<'a> { #[primary_span] - #[label] + #[label( + "the `{$symbol}` operand is not meaningful for global-scoped inline assembly, remove it" + )] pub(crate) span: Span, pub(crate) symbol: &'a str, pub(crate) macro_name: &'static str, } #[derive(Diagnostic)] -#[diag(parse_asm_underscore_input)] +#[diag("_ cannot be used for input operands")] pub(crate) struct AsmUnderscoreInput { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(parse_asm_sym_no_path)] +#[diag("expected a path for argument to `sym`")] pub(crate) struct AsmSymNoPath { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(parse_asm_requires_template)] +#[diag("requires at least a template string argument")] pub(crate) struct AsmRequiresTemplate { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(parse_asm_expected_comma)] +#[diag("expected token: `,`")] pub(crate) struct AsmExpectedComma { #[primary_span] - #[label] + #[label("expected `,`")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(parse_asm_expected_other)] +#[diag( + "expected operand, {$is_inline_asm -> + [false] options + *[true] clobber_abi, options + }, or additional template string" +)] pub(crate) struct AsmExpectedOther { #[primary_span] - #[label(parse_asm_expected_other)] + #[label( + "expected operand, {$is_inline_asm -> + [false] options + *[true] clobber_abi, options + }, or additional template string" + )] pub(crate) span: Span, pub(crate) is_inline_asm: bool, } #[derive(Diagnostic)] -#[diag(parse_asm_non_abi)] +#[diag("at least one abi must be provided as an argument to `clobber_abi`")] pub(crate) struct NonABI { #[primary_span] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(parse_asm_expected_string_literal)] +#[diag("expected string literal")] pub(crate) struct AsmExpectedStringLiteral { #[primary_span] - #[label] + #[label("not a string literal")] pub(crate) span: Span, } #[derive(Diagnostic)] -#[diag(parse_asm_expected_register_class_or_explicit_register)] +#[diag("expected register class or explicit register")] pub(crate) struct ExpectedRegisterClassOrExplicitRegister { #[primary_span] pub(crate) span: Span, } #[derive(LintDiagnostic)] -#[diag(parse_hidden_unicode_codepoints)] -#[note] +#[diag("unicode codepoint changing visible direction of text present in {$label}")] +#[note( + "these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen" +)] pub(crate) struct HiddenUnicodeCodepointsDiag { pub label: String, pub count: usize, - #[label] + #[label( + "this {$label} contains {$count -> + [one] an invisible + *[other] invisible + } unicode text flow control {$count -> + [one] codepoint + *[other] codepoints + }" + )] pub span_label: Span, #[subdiagnostic] pub labels: Option, @@ -3641,13 +4282,13 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub { match self { HiddenUnicodeCodepointsDiagSub::Escape { spans } => { diag.multipart_suggestion_with_style( - fluent::parse_suggestion_remove, + inline_fluent!("if their presence wasn't intentional, you can remove them"), spans.iter().map(|(_, span)| (*span, "".to_string())).collect(), Applicability::MachineApplicable, SuggestionStyle::HideCodeAlways, ); diag.multipart_suggestion( - fluent::parse_suggestion_escape, + inline_fluent!("if you want to keep them but make them visible in your source code, you can escape them"), spans .into_iter() .map(|(c, span)| { @@ -3670,43 +4311,59 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub { .collect::>() .join(", "), ); - diag.note(fluent::parse_suggestion_remove); - diag.note(fluent::parse_no_suggestion_note_escape); + diag.note(inline_fluent!( + "if their presence wasn't intentional, you can remove them" + )); + diag.note(inline_fluent!("if you want to keep them but make them visible in your source code, you can escape them: {$escaped}")); } } } } #[derive(LintDiagnostic)] -#[diag(parse_varargs_without_pattern)] +#[diag("missing pattern for `...` argument")] pub(crate) struct VarargsWithoutPattern { - #[suggestion(code = "_: ...", applicability = "machine-applicable")] + #[suggestion( + "name the argument, or use `_` to continue ignoring it", + code = "_: ...", + applicability = "machine-applicable" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_delegation_non_trait_impl_reuse)] +#[diag("only trait impls can be reused")] pub(crate) struct ImplReuseInherentImpl { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_struct_literal_placeholder_path)] +#[diag("placeholder `_` is not allowed for the path in struct literals")] pub(crate) struct StructLiteralPlaceholderPath { #[primary_span] - #[label] - #[suggestion(applicability = "has-placeholders", code = "/* Type */", style = "verbose")] + #[label("not allowed in struct literals")] + #[suggestion( + "replace it with the correct type", + applicability = "has-placeholders", + code = "/* Type */", + style = "verbose" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(parse_struct_literal_body_without_path_late)] +#[diag("struct literal body without path")] pub(crate) struct StructLiteralWithoutPathLate { #[primary_span] - #[label] + #[label("struct name missing for struct literal")] pub span: Span, - #[suggestion(applicability = "has-placeholders", code = "/* Type */ ", style = "verbose")] + #[suggestion( + "add the correct type", + applicability = "has-placeholders", + code = "/* Type */ ", + style = "verbose" + )] pub suggestion_span: Span, } @@ -3716,19 +4373,22 @@ pub(crate) enum ForbiddenLetReason { /// `let` is not valid and the source environment is not important OtherForbidden, /// A let chain with the `||` operator - #[note(parse_not_supported_or)] + #[note("`||` operators are not supported in let chain expressions")] NotSupportedOr(#[primary_span] Span), /// A let chain with invalid parentheses /// /// For example, `let 1 = 1 && (expr && expr)` is allowed /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not - #[note(parse_not_supported_parentheses)] + #[note("`let`s wrapped in parentheses are not supported in a context with let chains")] NotSupportedParentheses(#[primary_span] Span), } #[derive(Debug, rustc_macros::Subdiagnostic)] #[suggestion( - parse_misspelled_kw, + "{$is_incorrect_case -> + [true] write keyword `{$similar_kw}` in lowercase + *[false] there is a keyword `{$similar_kw}` with a similar name + }", applicability = "machine-applicable", code = "{similar_kw}", style = "verbose" diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index c836d52a71e4..40cdcfc35c2f 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -75,8 +75,6 @@ const _: () = { } }; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - // Unwrap the result if `Ok`, otherwise emit the diagnostics and abort. pub fn unwrap_or_emit_fatal(expr: Result>>) -> T { match expr { diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index fe8c1deedff7..3830d4b4cd41 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -3,7 +3,7 @@ use rustc_ast::token::{self, MetaVarKind}; use rustc_ast::tokenstream::ParserRange; use rustc_ast::{AttrItemKind, Attribute, attr}; use rustc_errors::codes::*; -use rustc_errors::{Diag, PResult}; +use rustc_errors::{Diag, PResult, inline_fluent}; use rustc_span::{BytePos, Span}; use thin_vec::ThinVec; use tracing::debug; @@ -13,7 +13,7 @@ use super::{ Trailing, UsePreAttrPos, }; use crate::parser::FnContext; -use crate::{errors, exp, fluent_generated as fluent}; +use crate::{errors, exp}; // Public for rustfmt usage #[derive(Debug)] @@ -68,7 +68,7 @@ impl<'a> Parser<'a> { let span = self.token.span; let mut err = self .dcx() - .struct_span_err(span, fluent::parse_inner_doc_comment_not_permitted); + .struct_span_err(span, inline_fluent!("expected outer doc comment")); err.code(E0753); if let Some(replacement_span) = self.annotate_following_item_if_applicable( &mut err, @@ -79,10 +79,12 @@ impl<'a> Parser<'a> { }, true, ) { - err.note(fluent::parse_note); + err.note(inline_fluent!( + "inner doc comments like this (starting with `//!` or `/*!`) can only appear before items" + )); err.span_suggestion_verbose( replacement_span, - fluent::parse_suggestion, + inline_fluent!("you might have meant to write a regular comment"), "", rustc_errors::Applicability::MachineApplicable, ); @@ -209,11 +211,11 @@ impl<'a> Parser<'a> { Ok(Some(item)) => { // FIXME(#100717) err.arg("item", item.kind.descr()); - err.span_label(item.span, fluent::parse_label_does_not_annotate_this); + err.span_label(item.span, inline_fluent!("BROKEN")); if suggest_to_outer { err.span_suggestion_verbose( replacement_span, - fluent::parse_sugg_change_inner_to_outer, + inline_fluent!("BROKEN"), match attr_type { OuterAttributeType::Attribute => "", OuterAttributeType::DocBlockComment => "*", @@ -244,28 +246,42 @@ impl<'a> Parser<'a> { self.dcx() .struct_span_err( attr_sp, - fluent::parse_inner_attr_not_permitted_after_outer_doc_comment, + inline_fluent!( + "an inner attribute is not permitted following an outer doc comment" + ), + ) + .with_span_label( + attr_sp, + inline_fluent!("not permitted following an outer doc comment"), ) - .with_span_label(attr_sp, fluent::parse_label_attr) .with_span_label( prev_doc_comment_span, - fluent::parse_label_prev_doc_comment, + inline_fluent!("previous doc comment"), ) } Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) => self .dcx() .struct_span_err( attr_sp, - fluent::parse_inner_attr_not_permitted_after_outer_attr, + inline_fluent!( + "an inner attribute is not permitted following an outer attribute" + ), ) - .with_span_label(attr_sp, fluent::parse_label_attr) - .with_span_label(prev_outer_attr_sp, fluent::parse_label_prev_attr), - Some(InnerAttrForbiddenReason::InCodeBlock) | None => { - self.dcx().struct_span_err(attr_sp, fluent::parse_inner_attr_not_permitted) - } + .with_span_label( + attr_sp, + inline_fluent!("not permitted following an outer attribute"), + ) + .with_span_label( + prev_outer_attr_sp, + inline_fluent!("previous outer attribute"), + ), + Some(InnerAttrForbiddenReason::InCodeBlock) | None => self.dcx().struct_span_err( + attr_sp, + inline_fluent!("an inner attribute is not permitted in this context"), + ), }; - diag.note(fluent::parse_inner_attr_explanation); + diag.note(inline_fluent!("inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files")); if self .annotate_following_item_if_applicable( &mut diag, @@ -275,7 +291,9 @@ impl<'a> Parser<'a> { ) .is_some() { - diag.note(fluent::parse_outer_attr_explanation); + diag.note(inline_fluent!( + "outer attributes, like `#[test]`, annotate the item following them" + )); }; diag.emit(); } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index cb8a291c7fa0..adba2065c457 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -13,7 +13,7 @@ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, PResult, Subdiagnostic, Suggestions, - pluralize, + inline_fluent, pluralize, }; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; @@ -41,10 +41,10 @@ use crate::errors::{ TernaryOperatorSuggestion, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType, }; +use crate::exp; use crate::parser::FnContext; use crate::parser::attr::InnerAttrPolicy; use crate::parser::item::IsDotDotDot; -use crate::{exp, fluent_generated as fluent}; /// Creates a placeholder argument. pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param { @@ -1272,7 +1272,7 @@ impl<'a> Parser<'a> { // We made sense of it. Improve the error message. e.span_suggestion_verbose( binop.span.shrink_to_lo(), - fluent::parse_sugg_turbofish_syntax, + inline_fluent!("use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments"), "::", Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 6b61504f2327..c35ddc4dc943 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -11,7 +11,7 @@ use rustc_ast::{ }; use rustc_ast_pretty::pprust; use rustc_errors::codes::*; -use rustc_errors::{Applicability, PResult, StashKey, struct_span_code_err}; +use rustc_errors::{Applicability, PResult, StashKey, inline_fluent, struct_span_code_err}; use rustc_session::lint::builtin::VARARGS_WITHOUT_PATTERN; use rustc_span::edit_distance::edit_distance; use rustc_span::edition::Edition; @@ -26,7 +26,7 @@ use super::{ Parser, PathStyle, Recovered, Trailing, UsePreAttrPos, }; use crate::errors::{self, FnPointerCannotBeAsync, FnPointerCannotBeConst, MacroExpandsToAdtField}; -use crate::{exp, fluent_generated as fluent}; +use crate::exp; impl<'a> Parser<'a> { /// Parses a source module as a crate. This is the main entry point for the parser. @@ -1721,7 +1721,7 @@ impl<'a> Parser<'a> { if this.token == token::Bang { if let Err(err) = this.unexpected() { - err.with_note(fluent::parse_macro_expands_to_enum_variant).emit(); + err.with_note(inline_fluent!("macros cannot expand to enum variants")).emit(); } this.bump(); diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 61b498431b04..1b17f422345f 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -25,10 +25,6 @@ use crate::lexer::StripTokens; use crate::parser::{AllowConstBlockItems, ForceCollect, Parser}; use crate::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal}; -fn psess() -> ParseSess { - ParseSess::new(vec![crate::DEFAULT_LOCALE_RESOURCE]) -} - fn filename(sm: &SourceMap, path: &str) -> FileName { FileName::Real(sm.path_mapping().to_real_filename(sm.working_dir(), PathBuf::from(path))) } @@ -46,7 +42,7 @@ fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> { fn create_test_handler(theme: OutputTheme) -> (DiagCtxt, Arc, Arc>>) { let output = Arc::new(Mutex::new(Vec::new())); let source_map = Arc::new(SourceMap::new(FilePathMapping::empty())); - let translator = Translator::with_fallback_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false); + let translator = Translator::with_fallback_bundle(vec![], false); let shared: Box = Box::new(Shared { data: output.clone() }); let auto_stream = AutoStream::never(shared); let dcx = DiagCtxt::new(Box::new( @@ -93,7 +89,7 @@ where /// Maps a string to tts, using a made-up filename. pub(crate) fn string_to_stream(source_str: String) -> TokenStream { - let psess = psess(); + let psess = ParseSess::new(vec![]); unwrap_or_emit_fatal(source_str_to_stream( &psess, filename(psess.source_map(), "bogofile"), @@ -2243,12 +2239,12 @@ fn sp(a: u32, b: u32) -> Span { /// Parses a string, return an expression. fn string_to_expr(source_str: String) -> Box { - with_error_checking_parse(source_str, &psess(), |p| p.parse_expr()) + with_error_checking_parse(source_str, &ParseSess::new(vec![]), |p| p.parse_expr()) } /// Parses a string, returns an item. fn string_to_item(source_str: String) -> Option> { - with_error_checking_parse(source_str, &psess(), |p| { + with_error_checking_parse(source_str, &ParseSess::new(vec![]), |p| { p.parse_item(ForceCollect::No, AllowConstBlockItems::Yes) }) } @@ -2484,7 +2480,7 @@ let mut fflags: c_int = wb(); #[test] fn crlf_doc_comments() { create_default_session_globals_then(|| { - let psess = psess(); + let psess = ParseSess::new(vec![]); let name_1 = FileName::Custom("crlf_source_1".to_string()); let source = "/// doc comment\r\nfn foo() {}".to_string(); @@ -2519,7 +2515,7 @@ fn ttdelim_span() { } create_default_session_globals_then(|| { - let psess = psess(); + let psess = ParseSess::new(vec![]); let expr = parse_expr_from_source_str( filename(psess.source_map(), "foo"), "foo!( fn main() { body } )".to_string(), @@ -2555,7 +2551,7 @@ fn look_ahead() { let sym_S = Symbol::intern("S"); let raw_no = IdentIsRaw::No; - let psess = psess(); + let psess = ParseSess::new(vec![]); let mut p = string_to_parser(&psess, "fn f(x: u32) { x } struct S;".to_string()); // Current position is the `fn`. @@ -2630,7 +2626,7 @@ fn look_ahead_non_outermost_stream() { let sym_S = Symbol::intern("S"); let raw_no = IdentIsRaw::No; - let psess = psess(); + let psess = ParseSess::new(vec![]); let mut p = string_to_parser(&psess, "mod m { fn f(x: u32) { x } struct S; }".to_string()); // Move forward to the `fn`, which is not within the outermost token @@ -2662,7 +2658,7 @@ fn look_ahead_non_outermost_stream() { #[test] fn debug_lookahead() { create_default_session_globals_then(|| { - let psess = psess(); + let psess = ParseSess::new(vec![]); let mut p = string_to_parser(&psess, "fn f(x: u32) { x } struct S;".to_string()); // Current position is the `fn`. @@ -2883,7 +2879,7 @@ fn debug_lookahead() { #[test] fn out_of_line_mod() { create_default_session_globals_then(|| { - let psess = psess(); + let psess = ParseSess::new(vec![]); let item = parse_item_from_source_str( filename(psess.source_map(), "foo"), "mod foo { struct S; mod this_does_not_exist; }".to_owned(), diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index d198675c0b22..7bebbc579c43 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -313,8 +313,8 @@ impl ParseSess { } } - pub fn emitter_with_note(locale_resources: Vec<&'static str>, note: String) -> Self { - let translator = Translator::with_fallback_bundle(locale_resources, false); + pub fn emitter_with_note(note: String) -> Self { + let translator = Translator::with_fallback_bundle(vec![], false); let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); let emitter = Box::new(AnnotateSnippetEmitter::new( stderr_destination(ColorConfig::Auto), diff --git a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs index 86f2d5f5954a..894fec248f1f 100644 --- a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs +++ b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs @@ -29,7 +29,7 @@ pub fn main() { } fn parse() { - let psess = ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE]); + let psess = ParseSess::new(vec![]); let path = Path::new(file!()); let path = path.canonicalize().unwrap(); diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs index 08ded2aee53d..7fe71004522a 100644 --- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs @@ -219,7 +219,7 @@ fn main() { } fn run() { - let psess = ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE]); + let psess = ParseSess::new(vec![]); iter_exprs(2, &mut |mut e| { // If the pretty printer is correct, then `parse(print(e))` should be identical to `e`, diff --git a/tests/ui-fulldeps/pprust-parenthesis-insertion.rs b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs index 72b5cfb90630..90cf9b89a293 100644 --- a/tests/ui-fulldeps/pprust-parenthesis-insertion.rs +++ b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs @@ -196,7 +196,7 @@ fn main() -> ExitCode { }; rustc_span::create_default_session_globals_then(|| { - let psess = &ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE]); + let psess = &ParseSess::new(vec![]); for &source_code in EXPRS { let Some(expr) = parse_expr(psess, source_code) else { From cda9b8c15752df635d693cfe73b147e6090faddc Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 16:44:53 +0100 Subject: [PATCH 653/978] Split `ComparisonOrShiftInterpretedAsGenericSugg` --- compiler/rustc_parse/src/errors.rs | 17 +++++++++++++---- compiler/rustc_parse/src/parser/expr.rs | 15 ++++++++------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 4a7031257700..418d56f632bd 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -861,7 +861,16 @@ pub(crate) struct ComparisonInterpretedAsGeneric { #[label("interpreted as generic arguments")] pub args: Span, #[subdiagnostic] - pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg, + pub suggestion: ComparisonInterpretedAsGenericSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("try comparing the cast value", applicability = "machine-applicable")] +pub(crate) struct ComparisonInterpretedAsGenericSugg { + #[suggestion_part(code = "(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, } #[derive(Diagnostic)] @@ -874,12 +883,12 @@ pub(crate) struct ShiftInterpretedAsGeneric { #[label("interpreted as generic arguments")] pub args: Span, #[subdiagnostic] - pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg, + pub suggestion: ShiftInterpretedAsGenericSugg, } #[derive(Subdiagnostic)] -#[multipart_suggestion("BROKEN", applicability = "machine-applicable")] -pub(crate) struct ComparisonOrShiftInterpretedAsGenericSugg { +#[multipart_suggestion("try shifting the cast value", applicability = "machine-applicable")] +pub(crate) struct ShiftInterpretedAsGenericSugg { #[suggestion_part(code = "(")] pub left: Span, #[suggestion_part(code = ")")] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 11cde35fab17..8bb22c2a831b 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -727,25 +727,26 @@ impl<'a> Parser<'a> { ); let args_span = self.look_ahead(1, |t| t.span).to(span_after_type); - let suggestion = errors::ComparisonOrShiftInterpretedAsGenericSugg { - left: expr.span.shrink_to_lo(), - right: expr.span.shrink_to_hi(), - }; - match self.token.kind { token::Lt => { self.dcx().emit_err(errors::ComparisonInterpretedAsGeneric { comparison: self.token.span, r#type: path, args: args_span, - suggestion, + suggestion: errors::ComparisonInterpretedAsGenericSugg { + left: expr.span.shrink_to_lo(), + right: expr.span.shrink_to_hi(), + }, }) } token::Shl => self.dcx().emit_err(errors::ShiftInterpretedAsGeneric { shift: self.token.span, r#type: path, args: args_span, - suggestion, + suggestion: errors::ShiftInterpretedAsGenericSugg { + left: expr.span.shrink_to_lo(), + right: expr.span.shrink_to_hi(), + }, }), _ => { // We can end up here even without `<` being the next token, for From c5587ca91967f91bf2f1467fbfa68e5d5448bce3 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 16:59:55 +0100 Subject: [PATCH 654/978] Split `parse_inner_attr` errors by case --- compiler/rustc_parse/src/parser/attr.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 3830d4b4cd41..3d16f37c000e 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -209,13 +209,25 @@ impl<'a> Parser<'a> { AllowConstBlockItems::Yes, ) { Ok(Some(item)) => { - // FIXME(#100717) err.arg("item", item.kind.descr()); - err.span_label(item.span, inline_fluent!("BROKEN")); + err.span_label( + item.span, + match attr_type { + OuterAttributeType::Attribute => { + inline_fluent!("the inner attribute doesn't annotate this {$item}") + } + OuterAttributeType::DocComment | OuterAttributeType::DocBlockComment => { + inline_fluent!("the inner doc comment doesn't annotate this {$item}") + } + }, + ); if suggest_to_outer { err.span_suggestion_verbose( replacement_span, - inline_fluent!("BROKEN"), + match attr_type { + OuterAttributeType::Attribute => inline_fluent!("to annotate the {$item}, change the attribute from inner to outer style"), + OuterAttributeType::DocComment | OuterAttributeType::DocBlockComment => inline_fluent!("to annotate the {$item}, change the doc comment from inner to outer style"), + }, match attr_type { OuterAttributeType::Attribute => "", OuterAttributeType::DocBlockComment => "*", From 0ef518c94695c7d852ec49ec9903d338efec109d Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 18:00:22 +0100 Subject: [PATCH 655/978] Disable the `run-make/translation` test for now --- tests/run-make/translation/rmake.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/run-make/translation/rmake.rs b/tests/run-make/translation/rmake.rs index 86078888c2e1..4d7fd71a2f4a 100644 --- a/tests/run-make/translation/rmake.rs +++ b/tests/run-make/translation/rmake.rs @@ -10,6 +10,9 @@ //@ needs-symlink //@ needs-subprocess +// FIXME(151366) Currently `-Ztranslate-additional-ftl` is currently broken +//@ ignore-test + #![deny(warnings)] use std::path::{Path, PathBuf}; From 00dd7dbe57923937377ed81369ec3206bf61b161 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 7 Feb 2026 10:31:36 +0100 Subject: [PATCH 656/978] Allow more capitalized words --- compiler/rustc_macros/src/diagnostics/message.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_macros/src/diagnostics/message.rs b/compiler/rustc_macros/src/diagnostics/message.rs index ad3ca4d1f8ea..2db8df2f69ae 100644 --- a/compiler/rustc_macros/src/diagnostics/message.rs +++ b/compiler/rustc_macros/src/diagnostics/message.rs @@ -156,6 +156,8 @@ const ALLOWED_CAPITALIZED_WORDS: &[&str] = &[ "MIR", "NaNs", "OK", + "Rust", + "Unicode", "VS", // tidy-alphabetical-end ]; From c9d59bac1ec002137c1e53bc211f29996a849cea Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 7 Feb 2026 04:39:20 -0600 Subject: [PATCH 657/978] ci: Update all docker images to the latest version --- .../ci/docker/aarch64-unknown-linux-gnu/Dockerfile | 6 +++--- .../ci/docker/arm-unknown-linux-gnueabi/Dockerfile | 6 +++--- .../ci/docker/arm-unknown-linux-gnueabihf/Dockerfile | 6 +++--- .../ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile | 6 +++--- .../ci/docker/i586-unknown-linux-gnu/Dockerfile | 2 +- .../ci/docker/i686-unknown-linux-gnu/Dockerfile | 2 +- .../ci/docker/loongarch64-unknown-linux-gnu/Dockerfile | 6 +++--- .../ci/docker/mips-unknown-linux-gnu/Dockerfile | 6 +++--- .../ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile | 6 +++--- .../ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile | 6 +++--- .../ci/docker/mipsel-unknown-linux-gnu/Dockerfile | 6 +++--- .../ci/docker/powerpc-unknown-linux-gnu/Dockerfile | 6 +++--- .../ci/docker/powerpc64-unknown-linux-gnu/Dockerfile | 6 +++--- .../ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile | 6 +++--- .../ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile | 6 +++--- .../ci/docker/thumbv6m-none-eabi/Dockerfile | 2 +- .../ci/docker/thumbv7em-none-eabi/Dockerfile | 2 +- .../ci/docker/thumbv7em-none-eabihf/Dockerfile | 2 +- .../ci/docker/thumbv7m-none-eabi/Dockerfile | 2 +- .../ci/docker/wasm32-unknown-unknown/Dockerfile | 2 +- .../ci/docker/x86_64-unknown-linux-gnu/Dockerfile | 2 +- library/compiler-builtins/ci/run-docker.sh | 2 +- 22 files changed, 48 insertions(+), 48 deletions(-) diff --git a/library/compiler-builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile index 69b99f5b6b32..683bd07fd47e 100644 --- a/library/compiler-builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/aarch64-unknown-linux-gnu/Dockerfile @@ -1,15 +1,15 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev ca-certificates \ gcc-aarch64-linux-gnu m4 make libc6-dev-arm64-cross \ - qemu-user-static + qemu-user ENV TOOLCHAIN_PREFIX=aarch64-linux-gnu- ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER=qemu-aarch64-static \ + CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER=qemu-aarch64 \ AR_aarch64_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_aarch64_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/aarch64-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile b/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile index 2fa6f8520520..781abd1b6e88 100644 --- a/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile +++ b/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabi/Dockerfile @@ -1,14 +1,14 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev ca-certificates \ - gcc-arm-linux-gnueabi libc6-dev-armel-cross qemu-user-static + gcc-arm-linux-gnueabi libc6-dev-armel-cross qemu-user ENV TOOLCHAIN_PREFIX=arm-linux-gnueabi- ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABI_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABI_RUNNER=qemu-arm-static \ + CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABI_RUNNER=qemu-arm \ AR_arm_unknown_linux_gnueabi="$TOOLCHAIN_PREFIX"ar \ CC_arm_unknown_linux_gnueabi="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/arm-linux-gnueabi \ diff --git a/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile b/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile index 85f7335f5a85..36ea4827dc52 100644 --- a/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile +++ b/library/compiler-builtins/ci/docker/arm-unknown-linux-gnueabihf/Dockerfile @@ -1,14 +1,14 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev ca-certificates \ - gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user-static + gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user ENV TOOLCHAIN_PREFIX=arm-linux-gnueabihf- ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_RUNNER=qemu-arm-static \ + CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_RUNNER=qemu-arm \ AR_arm_unknown_linux_gnueabihf="$TOOLCHAIN_PREFIX"ar \ CC_arm_unknown_linux_gnueabihf="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf \ diff --git a/library/compiler-builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile b/library/compiler-builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile index 42511479f36f..8b76693b2799 100644 --- a/library/compiler-builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile +++ b/library/compiler-builtins/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile @@ -1,14 +1,14 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev ca-certificates \ - gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user-static + gcc-arm-linux-gnueabihf libc6-dev-armhf-cross qemu-user ENV TOOLCHAIN_PREFIX=arm-linux-gnueabihf- ENV CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_RUNNER=qemu-arm-static \ + CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_RUNNER=qemu-arm \ AR_armv7_unknown_linux_gnueabihf="$TOOLCHAIN_PREFIX"ar \ CC_armv7_unknown_linux_gnueabihf="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf \ diff --git a/library/compiler-builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile index 35488c477493..9125038acbde 100644 --- a/library/compiler-builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/i586-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile index 35488c477493..9125038acbde 100644 --- a/library/compiler-builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/i686-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile index e95a1b9163ff..a65223595877 100644 --- a/library/compiler-builtins/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile @@ -1,13 +1,13 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ - gcc libc6-dev qemu-user-static ca-certificates \ + gcc libc6-dev qemu-user ca-certificates \ gcc-14-loongarch64-linux-gnu libc6-dev-loong64-cross ENV CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_LINKER=loongarch64-linux-gnu-gcc-14 \ - CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_RUNNER=qemu-loongarch64-static \ + CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_RUNNER=qemu-loongarch64 \ AR_loongarch64_unknown_linux_gnu=loongarch64-linux-gnu-ar \ CC_loongarch64_unknown_linux_gnu=loongarch64-linux-gnu-gcc-14 \ QEMU_LD_PREFIX=/usr/loongarch64-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile index fd1877603100..0913f33c05ce 100644 --- a/library/compiler-builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/mips-unknown-linux-gnu/Dockerfile @@ -1,15 +1,15 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev ca-certificates \ gcc-mips-linux-gnu libc6-dev-mips-cross \ - binfmt-support qemu-user-static qemu-system-mips + binfmt-support qemu-user qemu-system-mips ENV TOOLCHAIN_PREFIX=mips-linux-gnu- ENV CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_RUNNER=qemu-mips-static \ + CARGO_TARGET_MIPS_UNKNOWN_LINUX_GNU_RUNNER=qemu-mips \ AR_mips_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_mips_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/mips-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile b/library/compiler-builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile index 4e542ce6858c..d2f4e484b1aa 100644 --- a/library/compiler-builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile +++ b/library/compiler-builtins/ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ @@ -8,12 +8,12 @@ RUN apt-get update && \ gcc-mips64-linux-gnuabi64 \ libc6-dev \ libc6-dev-mips64-cross \ - qemu-user-static \ + qemu-user \ qemu-system-mips ENV TOOLCHAIN_PREFIX=mips64-linux-gnuabi64- ENV CARGO_TARGET_MIPS64_UNKNOWN_LINUX_GNUABI64_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_MIPS64_UNKNOWN_LINUX_GNUABI64_RUNNER=qemu-mips64-static \ + CARGO_TARGET_MIPS64_UNKNOWN_LINUX_GNUABI64_RUNNER=qemu-mips64 \ AR_mips64_unknown_linux_gnuabi64="$TOOLCHAIN_PREFIX"ar \ CC_mips64_unknown_linux_gnuabi64="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/mips64-linux-gnuabi64 \ diff --git a/library/compiler-builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile b/library/compiler-builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile index 528dfd8940d5..873754b2793e 100644 --- a/library/compiler-builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile +++ b/library/compiler-builtins/ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ @@ -8,11 +8,11 @@ RUN apt-get update && \ gcc-mips64el-linux-gnuabi64 \ libc6-dev \ libc6-dev-mips64el-cross \ - qemu-user-static + qemu-user ENV TOOLCHAIN_PREFIX=mips64el-linux-gnuabi64- ENV CARGO_TARGET_MIPS64EL_UNKNOWN_LINUX_GNUABI64_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_MIPS64EL_UNKNOWN_LINUX_GNUABI64_RUNNER=qemu-mips64el-static \ + CARGO_TARGET_MIPS64EL_UNKNOWN_LINUX_GNUABI64_RUNNER=qemu-mips64el \ AR_mips64el_unknown_linux_gnuabi64="$TOOLCHAIN_PREFIX"ar \ CC_mips64el_unknown_linux_gnuabi64="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/mips64el-linux-gnuabi64 \ diff --git a/library/compiler-builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile index 2572180238e2..5768b68d6c95 100644 --- a/library/compiler-builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/mipsel-unknown-linux-gnu/Dockerfile @@ -1,15 +1,15 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev ca-certificates \ gcc-mipsel-linux-gnu libc6-dev-mipsel-cross \ - binfmt-support qemu-user-static + binfmt-support qemu-user ENV TOOLCHAIN_PREFIX=mipsel-linux-gnu- ENV CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_GNU_RUNNER=qemu-mipsel-static \ + CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_GNU_RUNNER=qemu-mipsel \ AR_mipsel_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_mipsel_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/mipsel-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile index cac1f23610aa..c625a4bcd5d7 100644 --- a/library/compiler-builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/powerpc-unknown-linux-gnu/Dockerfile @@ -1,15 +1,15 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ - gcc libc6-dev qemu-user-static ca-certificates \ + gcc libc6-dev qemu-user ca-certificates \ gcc-powerpc-linux-gnu libc6-dev-powerpc-cross \ qemu-system-ppc ENV TOOLCHAIN_PREFIX=powerpc-linux-gnu- ENV CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc-static \ + CARGO_TARGET_POWERPC_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc \ AR_powerpc_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_powerpc_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/powerpc-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile index 76127b7dbb8c..86a7a8cd46e4 100644 --- a/library/compiler-builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/powerpc64-unknown-linux-gnu/Dockerfile @@ -1,15 +1,15 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev ca-certificates \ gcc-powerpc64-linux-gnu libc6-dev-ppc64-cross \ - binfmt-support qemu-user-static qemu-system-ppc + binfmt-support qemu-user qemu-system-ppc ENV TOOLCHAIN_PREFIX=powerpc64-linux-gnu- ENV CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc64-static \ + CARGO_TARGET_POWERPC64_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc64 \ AR_powerpc64_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_powerpc64_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/powerpc64-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile index da1d56ca66f2..722b10b0a734 100644 --- a/library/compiler-builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile @@ -1,15 +1,15 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ - gcc libc6-dev qemu-user-static ca-certificates \ + gcc libc6-dev qemu-user ca-certificates \ gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross \ qemu-system-ppc ENV TOOLCHAIN_PREFIX=powerpc64le-linux-gnu- ENV CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc64le-static \ + CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc64le \ AR_powerpc64le_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_powerpc64le_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/powerpc64le-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile index 513efacd6d96..7a721ba05416 100644 --- a/library/compiler-builtins/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile @@ -1,15 +1,15 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ apt-get install -y --no-install-recommends \ - gcc libc6-dev qemu-user-static ca-certificates \ + gcc libc6-dev qemu-user ca-certificates \ gcc-riscv64-linux-gnu libc6-dev-riscv64-cross \ qemu-system-riscv64 ENV TOOLCHAIN_PREFIX=riscv64-linux-gnu- ENV CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \ - CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_RUNNER=qemu-riscv64-static \ + CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_RUNNER=qemu-riscv64 \ AR_riscv64gc_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \ CC_riscv64gc_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \ QEMU_LD_PREFIX=/usr/riscv64-linux-gnu \ diff --git a/library/compiler-builtins/ci/docker/thumbv6m-none-eabi/Dockerfile b/library/compiler-builtins/ci/docker/thumbv6m-none-eabi/Dockerfile index a9a172a21137..a1a6b3cf5cfd 100644 --- a/library/compiler-builtins/ci/docker/thumbv6m-none-eabi/Dockerfile +++ b/library/compiler-builtins/ci/docker/thumbv6m-none-eabi/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/docker/thumbv7em-none-eabi/Dockerfile b/library/compiler-builtins/ci/docker/thumbv7em-none-eabi/Dockerfile index a9a172a21137..a1a6b3cf5cfd 100644 --- a/library/compiler-builtins/ci/docker/thumbv7em-none-eabi/Dockerfile +++ b/library/compiler-builtins/ci/docker/thumbv7em-none-eabi/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/docker/thumbv7em-none-eabihf/Dockerfile b/library/compiler-builtins/ci/docker/thumbv7em-none-eabihf/Dockerfile index a9a172a21137..a1a6b3cf5cfd 100644 --- a/library/compiler-builtins/ci/docker/thumbv7em-none-eabihf/Dockerfile +++ b/library/compiler-builtins/ci/docker/thumbv7em-none-eabihf/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/docker/thumbv7m-none-eabi/Dockerfile b/library/compiler-builtins/ci/docker/thumbv7m-none-eabi/Dockerfile index a9a172a21137..a1a6b3cf5cfd 100644 --- a/library/compiler-builtins/ci/docker/thumbv7m-none-eabi/Dockerfile +++ b/library/compiler-builtins/ci/docker/thumbv7m-none-eabi/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/docker/wasm32-unknown-unknown/Dockerfile b/library/compiler-builtins/ci/docker/wasm32-unknown-unknown/Dockerfile index 2813d318670e..b646a72bb37c 100644 --- a/library/compiler-builtins/ci/docker/wasm32-unknown-unknown/Dockerfile +++ b/library/compiler-builtins/ci/docker/wasm32-unknown-unknown/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:20.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile b/library/compiler-builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile index 2ef800129d67..927515f90f32 100644 --- a/library/compiler-builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile +++ b/library/compiler-builtins/ci/docker/x86_64-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -ARG IMAGE=ubuntu:25.04 +ARG IMAGE=ubuntu:25.10 FROM $IMAGE RUN apt-get update && \ diff --git a/library/compiler-builtins/ci/run-docker.sh b/library/compiler-builtins/ci/run-docker.sh index 4c1fe0fe2644..e65ada271904 100755 --- a/library/compiler-builtins/ci/run-docker.sh +++ b/library/compiler-builtins/ci/run-docker.sh @@ -97,7 +97,7 @@ if [ "${1:-}" = "--help" ] || [ "$#" -gt 1 ]; then usage: ./ci/run-docker.sh [target] you can also set DOCKER_BASE_IMAGE to use something other than the default - ubuntu:25.04 (or rustlang/rust:nightly). + ubuntu:25.10 (or rustlang/rust:nightly). " exit fi From 4d24b508bb1004116eb71b93afaabfd83a3aa9e3 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 7 Feb 2026 04:10:45 -0600 Subject: [PATCH 658/978] meta: Upgrade all dependencies to the latest compatible versions This allows us to drop wasm-specific configuration for `getrandom`. Link: https://github.com/rust-random/getrandom/blob/314fd5ab3e6d9ef2ec90243894731865a725417d/CHANGELOG.md#major-change-to-wasm_js-backend --- library/compiler-builtins/ci/run.sh | 5 ----- .../crates/libm-macros/Cargo.toml | 6 +++--- .../crates/musl-math-sys/Cargo.toml | 2 +- .../crates/symbol-check/Cargo.toml | 4 ++-- library/compiler-builtins/crates/util/Cargo.toml | 2 +- library/compiler-builtins/libm-test/Cargo.toml | 16 ++++++++-------- .../compiler-builtins/libm-test/src/precision.rs | 2 +- 7 files changed, 16 insertions(+), 21 deletions(-) diff --git a/library/compiler-builtins/ci/run.sh b/library/compiler-builtins/ci/run.sh index 0c07b32c74b9..52fb4b151ca5 100755 --- a/library/compiler-builtins/ci/run.sh +++ b/library/compiler-builtins/ci/run.sh @@ -13,11 +13,6 @@ if [ -z "$target" ]; then target="$host_target" fi -if [[ "$target" = *"wasm"* ]]; then - # Enable the random backend - export RUSTFLAGS="${RUSTFLAGS:-} --cfg getrandom_backend=\"wasm_js\"" -fi - if [ "${USING_CONTAINER_RUSTC:-}" = 1 ]; then # Install nonstandard components if we have control of the environment rustup target list --installed | diff --git a/library/compiler-builtins/crates/libm-macros/Cargo.toml b/library/compiler-builtins/crates/libm-macros/Cargo.toml index 100a8d0ec30e..f6697b783457 100644 --- a/library/compiler-builtins/crates/libm-macros/Cargo.toml +++ b/library/compiler-builtins/crates/libm-macros/Cargo.toml @@ -10,9 +10,9 @@ proc-macro = true [dependencies] heck = "0.5.0" -proc-macro2 = "1.0.95" -quote = "1.0.40" -syn = { version = "2.0.104", features = ["full", "extra-traits", "visit-mut"] } +proc-macro2 = "1.0.106" +quote = "1.0.44" +syn = { version = "2.0.114", features = ["full", "extra-traits", "visit-mut"] } [lints.rust] # Values used during testing diff --git a/library/compiler-builtins/crates/musl-math-sys/Cargo.toml b/library/compiler-builtins/crates/musl-math-sys/Cargo.toml index 39f6fa9065bd..60b0647b6dc6 100644 --- a/library/compiler-builtins/crates/musl-math-sys/Cargo.toml +++ b/library/compiler-builtins/crates/musl-math-sys/Cargo.toml @@ -11,4 +11,4 @@ license = "MIT OR Apache-2.0" libm = { path = "../../libm" } [build-dependencies] -cc = "1.2.29" +cc = "1.2.55" diff --git a/library/compiler-builtins/crates/symbol-check/Cargo.toml b/library/compiler-builtins/crates/symbol-check/Cargo.toml index e2218b491720..9f027df1e4f5 100644 --- a/library/compiler-builtins/crates/symbol-check/Cargo.toml +++ b/library/compiler-builtins/crates/symbol-check/Cargo.toml @@ -5,8 +5,8 @@ edition = "2024" publish = false [dependencies] -object = "0.37.1" -serde_json = "1.0.140" +object = "0.37.3" +serde_json = "1.0.149" [features] wasm = ["object/wasm"] diff --git a/library/compiler-builtins/crates/util/Cargo.toml b/library/compiler-builtins/crates/util/Cargo.toml index 614c54bd8355..b1ccd8a9e63c 100644 --- a/library/compiler-builtins/crates/util/Cargo.toml +++ b/library/compiler-builtins/crates/util/Cargo.toml @@ -16,4 +16,4 @@ libm = { path = "../../libm", default-features = false } libm-macros = { path = "../libm-macros" } libm-test = { path = "../../libm-test", default-features = false } musl-math-sys = { path = "../musl-math-sys", optional = true } -rug = { version = "1.27.0", optional = true, default-features = false, features = ["float", "std"] } +rug = { version = "1.28.1", optional = true, default-features = false, features = ["float", "std"] } diff --git a/library/compiler-builtins/libm-test/Cargo.toml b/library/compiler-builtins/libm-test/Cargo.toml index adecfc1af6b8..b813331a8552 100644 --- a/library/compiler-builtins/libm-test/Cargo.toml +++ b/library/compiler-builtins/libm-test/Cargo.toml @@ -28,25 +28,25 @@ icount = ["dep:gungraun"] short-benchmarks = [] [dependencies] -anyhow = "1.0.98" +anyhow = "1.0.101" # This is not directly used but is required so we can enable `gmp-mpfr-sys/force-cross`. -gmp-mpfr-sys = { version = "1.6.5", optional = true, default-features = false } +gmp-mpfr-sys = { version = "1.6.8", optional = true, default-features = false } gungraun = { version = "0.17.0", optional = true } -indicatif = { version = "0.18.0", default-features = false } +indicatif = { version = "0.18.3", default-features = false } libm = { path = "../libm", features = ["unstable-public-internals"] } libm-macros = { path = "../crates/libm-macros" } musl-math-sys = { path = "../crates/musl-math-sys", optional = true } paste = "1.0.15" -rand = "0.9.1" +rand = "0.9.2" rand_chacha = "0.9.0" -rayon = "1.10.0" -rug = { version = "1.27.0", optional = true, default-features = false, features = ["float", "integer", "std"] } +rayon = "1.11.0" +rug = { version = "1.28.1", optional = true, default-features = false, features = ["float", "integer", "std"] } [target.'cfg(target_family = "wasm")'.dependencies] -getrandom = { version = "0.3.3", features = ["wasm_js"] } +getrandom = { version = "0.3.4", features = ["wasm_js"] } [build-dependencies] -rand = { version = "0.9.1", optional = true } +rand = { version = "0.9.2", optional = true } [dev-dependencies] criterion = { version = "0.6.0", default-features = false, features = ["cargo_bench_support"] } diff --git a/library/compiler-builtins/libm-test/src/precision.rs b/library/compiler-builtins/libm-test/src/precision.rs index 897f21da78e7..a94fe429f5f3 100644 --- a/library/compiler-builtins/libm-test/src/precision.rs +++ b/library/compiler-builtins/libm-test/src/precision.rs @@ -498,7 +498,7 @@ fn int_float_common( if input.0 > 4000 { return XFAIL_NOCHECK; } else if input.0 > 100 { - return CheckAction::AssertWithUlp(1_000_000); + return CheckAction::AssertWithUlp(2_000_000); } } DEFAULT From 6733cf42a6f5e26cd98b2ae7ad87b4e3c57ffe9b Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 7 Feb 2026 05:04:20 -0600 Subject: [PATCH 659/978] symcheck: Enable wasm by default The build time isn't very different so we can keep things simpler. --- library/compiler-builtins/ci/run.sh | 1 - library/compiler-builtins/crates/symbol-check/Cargo.toml | 5 +---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/library/compiler-builtins/ci/run.sh b/library/compiler-builtins/ci/run.sh index 52fb4b151ca5..ca1304f3dc87 100755 --- a/library/compiler-builtins/ci/run.sh +++ b/library/compiler-builtins/ci/run.sh @@ -47,7 +47,6 @@ fi # `compiler-builtins` is built with various features. Symcheck invokes Cargo to # build with the arguments we provide it, then validates the built artifacts. symcheck=(cargo run -p symbol-check --release) -[[ "$target" = "wasm"* ]] && symcheck+=(--features wasm) symcheck+=(-- build-and-check) "${symcheck[@]}" "$target" -- -p compiler_builtins diff --git a/library/compiler-builtins/crates/symbol-check/Cargo.toml b/library/compiler-builtins/crates/symbol-check/Cargo.toml index 9f027df1e4f5..9e4bc739da15 100644 --- a/library/compiler-builtins/crates/symbol-check/Cargo.toml +++ b/library/compiler-builtins/crates/symbol-check/Cargo.toml @@ -5,8 +5,5 @@ edition = "2024" publish = false [dependencies] -object = "0.37.3" +object = { version = "0.37.3", features = ["wasm"] } serde_json = "1.0.149" - -[features] -wasm = ["object/wasm"] From 9184a5f661e074690b59ab28d7ef16c1c6ae0d06 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 6 Feb 2026 17:54:06 -0600 Subject: [PATCH 660/978] symcheck: Add tests for the symbol checker Ensure that these are actually doing what is expected. --- library/compiler-builtins/ci/run.sh | 4 +- .../crates/symbol-check/Cargo.toml | 5 + .../crates/symbol-check/build.rs | 6 + .../crates/symbol-check/src/main.rs | 30 ++--- .../crates/symbol-check/tests/all.rs | 124 ++++++++++++++++++ .../symbol-check/tests/input/core_symbols.rs | 11 ++ .../symbol-check/tests/input/duplicates.rs | 12 ++ .../crates/symbol-check/tests/input/good.rs | 4 + 8 files changed, 176 insertions(+), 20 deletions(-) create mode 100644 library/compiler-builtins/crates/symbol-check/build.rs create mode 100644 library/compiler-builtins/crates/symbol-check/tests/all.rs create mode 100644 library/compiler-builtins/crates/symbol-check/tests/input/core_symbols.rs create mode 100644 library/compiler-builtins/crates/symbol-check/tests/input/duplicates.rs create mode 100644 library/compiler-builtins/crates/symbol-check/tests/input/good.rs diff --git a/library/compiler-builtins/ci/run.sh b/library/compiler-builtins/ci/run.sh index ca1304f3dc87..12b3f37889c9 100755 --- a/library/compiler-builtins/ci/run.sh +++ b/library/compiler-builtins/ci/run.sh @@ -46,6 +46,7 @@ fi # Ensure there are no duplicate symbols or references to `core` when # `compiler-builtins` is built with various features. Symcheck invokes Cargo to # build with the arguments we provide it, then validates the built artifacts. +SYMCHECK_TEST_TARGET="$target" cargo test -p symbol-check --release symcheck=(cargo run -p symbol-check --release) symcheck+=(-- build-and-check) @@ -151,7 +152,8 @@ if [ "${BUILD_ONLY:-}" = "1" ]; then echo "can't run tests on $target; skipping" else - mflags+=(--workspace --target "$target") + # symcheck tests need specific env setup, and is already tested above + mflags+=(--workspace --exclude symbol-check --target "$target") cmd=(cargo test "${mflags[@]}") profile_flag="--profile" diff --git a/library/compiler-builtins/crates/symbol-check/Cargo.toml b/library/compiler-builtins/crates/symbol-check/Cargo.toml index 9e4bc739da15..774d1c31a4b0 100644 --- a/library/compiler-builtins/crates/symbol-check/Cargo.toml +++ b/library/compiler-builtins/crates/symbol-check/Cargo.toml @@ -7,3 +7,8 @@ publish = false [dependencies] object = { version = "0.37.3", features = ["wasm"] } serde_json = "1.0.149" + +[dev-dependencies] +assert_cmd = "2.1.2" +cc = "1.2.55" +tempfile = "3.24.0" diff --git a/library/compiler-builtins/crates/symbol-check/build.rs b/library/compiler-builtins/crates/symbol-check/build.rs new file mode 100644 index 000000000000..b3e53c38b0bd --- /dev/null +++ b/library/compiler-builtins/crates/symbol-check/build.rs @@ -0,0 +1,6 @@ +use std::env; + +fn main() { + println!("cargo::rustc-env=HOST={}", env::var("HOST").unwrap()); + println!("cargo::rustc-env=TARGET={}", env::var("TARGET").unwrap()); +} diff --git a/library/compiler-builtins/crates/symbol-check/src/main.rs b/library/compiler-builtins/crates/symbol-check/src/main.rs index 7d0b7e90addb..1413042e6c70 100644 --- a/library/compiler-builtins/crates/symbol-check/src/main.rs +++ b/library/compiler-builtins/crates/symbol-check/src/main.rs @@ -1,7 +1,10 @@ //! Tool used by CI to inspect compiler-builtins archives and help ensure we won't run into any //! linking errors. +//! +//! Note that symcheck is a "hostprog", i.e. is built and run on the host target even when the +//! actual target is cross compiled. -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::{BTreeMap, BTreeSet, HashSet}; use std::fs; use std::io::{BufRead, BufReader}; use std::path::{Path, PathBuf}; @@ -42,8 +45,7 @@ fn main() { run_build_and_check(target, args); } ["build-and-check", "--", args @ ..] if !args.is_empty() => { - let target = &host_target(); - run_build_and_check(target, args); + run_build_and_check(env!("HOST"), args); } ["check", paths @ ..] if !paths.is_empty() => { check_paths(paths); @@ -80,20 +82,6 @@ fn check_paths>(paths: &[P]) { } } -fn host_target() -> String { - let out = Command::new("rustc") - .arg("--version") - .arg("--verbose") - .output() - .unwrap(); - assert!(out.status.success()); - let out = String::from_utf8(out.stdout).unwrap(); - out.lines() - .find_map(|s| s.strip_prefix("host: ")) - .unwrap() - .to_owned() -} - /// Run `cargo build` with the provided additional arguments, collecting the list of created /// libraries. fn exec_cargo_with_args(target: &str, args: &[&str]) -> Vec { @@ -257,8 +245,9 @@ fn verify_no_duplicates(archive: &BinFile) { assert!(found_any, "no symbols found"); if !dups.is_empty() { + let count = dups.iter().map(|x| &x.name).collect::>().len(); dups.sort_unstable_by(|a, b| a.name.cmp(&b.name)); - panic!("found duplicate symbols: {dups:#?}"); + panic!("found {count} duplicate symbols: {dups:#?}"); } println!(" success: no duplicate symbols found"); @@ -293,7 +282,10 @@ fn verify_core_symbols(archive: &BinFile) { if !undefined.is_empty() { undefined.sort_unstable_by(|a, b| a.name.cmp(&b.name)); - panic!("found undefined symbols from core: {undefined:#?}"); + panic!( + "found {} undefined symbols from core: {undefined:#?}", + undefined.len() + ); } println!(" success: no undefined references to core found"); diff --git a/library/compiler-builtins/crates/symbol-check/tests/all.rs b/library/compiler-builtins/crates/symbol-check/tests/all.rs new file mode 100644 index 000000000000..4ad9509726fb --- /dev/null +++ b/library/compiler-builtins/crates/symbol-check/tests/all.rs @@ -0,0 +1,124 @@ +use std::env; +use std::ffi::OsString; +use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; +use std::sync::LazyLock; + +use assert_cmd::assert::Assert; +use assert_cmd::cargo::cargo_bin_cmd; +use tempfile::tempdir; + +trait AssertExt { + fn stderr_contains(self, s: &str) -> Self; +} + +impl AssertExt for Assert { + fn stderr_contains(self, s: &str) -> Self { + let out = String::from_utf8_lossy(&self.get_output().stderr); + assert!(out.contains(s), "looking for: `{s}`\nout:\n```\n{out}\n```"); + self + } +} + +#[test] +fn test_duplicates() { + let dir = tempdir().unwrap(); + let dup_out = dir.path().join("dup.o"); + let lib_out = dir.path().join("libfoo.rlib"); + + // For the "bad" file, we need duplicate symbols from different object files in the archive. Do + // this reliably by building an archive and a separate object file then merging them. + rustc_build(&input_dir().join("duplicates.rs"), &lib_out, |cmd| cmd); + rustc_build(&input_dir().join("duplicates.rs"), &dup_out, |cmd| { + cmd.arg("--emit=obj") + }); + + let mut ar = cc_build().get_archiver(); + + if ar.get_program().to_string_lossy().contains("lib.exe") { + let mut out_arg = OsString::from("-out:"); + out_arg.push(&lib_out); + ar.arg(&out_arg); + // Repeating the same file as the first arg makes lib.exe append (taken from the + // `cc` implementation). + ar.arg(&lib_out); + } else { + ar.arg("rs") + // Eat an `libfoo.rlib(lib.rmeta) has no symbols` info message on MacOS + .stderr(Stdio::null()) + .arg(&lib_out); + } + let status = ar.arg(&dup_out).status().unwrap(); + assert!(status.success()); + + let assert = cargo_bin_cmd!().arg("check").arg(&lib_out).assert(); + assert + .failure() + .stderr_contains("duplicate symbols") + .stderr_contains("FDUP") + .stderr_contains("IDUP") + .stderr_contains("fndup"); +} + +#[test] +fn test_core_symbols() { + let dir = tempdir().unwrap(); + let lib_out = dir.path().join("libfoo.rlib"); + rustc_build(&input_dir().join("core_symbols.rs"), &lib_out, |cmd| cmd); + let assert = cargo_bin_cmd!().arg("check").arg(&lib_out).assert(); + // FIXME(symcheck): this should fail but we don't detect the new mangling. + assert.success(); +} + +#[test] +fn test_good() { + let dir = tempdir().unwrap(); + let lib_out = dir.path().join("libfoo.rlib"); + rustc_build(&input_dir().join("good.rs"), &lib_out, |cmd| cmd); + let assert = cargo_bin_cmd!().arg("check").arg(&lib_out).assert(); + assert.success(); +} + +/// Build i -> o with optional additional configuration. +fn rustc_build(i: &Path, o: &Path, mut f: impl FnMut(&mut Command) -> &mut Command) { + let mut cmd = Command::new("rustc"); + cmd.arg(i) + .arg("--target") + .arg(target()) + .arg("--crate-type=lib") + .arg("-o") + .arg(o); + f(&mut cmd); + let status = cmd.status().unwrap(); + assert!(status.success()); +} + +/// Configure `cc` with the host and target. +fn cc_build() -> cc::Build { + let mut b = cc::Build::new(); + b.host(env!("HOST")).target(&target()); + b +} + +/// Symcheck runs on the host but we want to verify that we find issues on all targets, so +/// the cross target may be specified. +fn target() -> String { + static TARGET: LazyLock = LazyLock::new(|| { + let target = match env::var("SYMCHECK_TEST_TARGET") { + Ok(t) => t, + // Require on CI so we don't accidentally always test the native target + _ if env::var("CI").is_ok() => panic!("SYMCHECK_TEST_TARGET must be set in CI"), + // Fall back to native for local convenience. + Err(_) => env!("HOST").to_string(), + }; + + println!("using target {target}"); + target + }); + + TARGET.clone() +} + +fn input_dir() -> PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/input") +} diff --git a/library/compiler-builtins/crates/symbol-check/tests/input/core_symbols.rs b/library/compiler-builtins/crates/symbol-check/tests/input/core_symbols.rs new file mode 100644 index 000000000000..cf74f9779661 --- /dev/null +++ b/library/compiler-builtins/crates/symbol-check/tests/input/core_symbols.rs @@ -0,0 +1,11 @@ +//! Ensure we catch calls to `core`. + +#![no_std] + +#[unsafe(no_mangle)] +pub fn call_from_core(s: &[u8]) -> &str { + match core::str::from_utf8(&s) { + Ok(s) => s, + Err(_) => "", + } +} diff --git a/library/compiler-builtins/crates/symbol-check/tests/input/duplicates.rs b/library/compiler-builtins/crates/symbol-check/tests/input/duplicates.rs new file mode 100644 index 000000000000..92623a0b2e1a --- /dev/null +++ b/library/compiler-builtins/crates/symbol-check/tests/input/duplicates.rs @@ -0,0 +1,12 @@ +//! Ensure we catch duplicate symbols (the duplicates are in the aux file). Gets built twice +//! as separate object files. + +#![no_std] + +#[unsafe(no_mangle)] +static IDUP: i32 = 0; +#[unsafe(no_mangle)] +static FDUP: f32 = 0.0; + +#[unsafe(no_mangle)] +pub fn fndup() {} diff --git a/library/compiler-builtins/crates/symbol-check/tests/input/good.rs b/library/compiler-builtins/crates/symbol-check/tests/input/good.rs new file mode 100644 index 000000000000..6679ee1dd30c --- /dev/null +++ b/library/compiler-builtins/crates/symbol-check/tests/input/good.rs @@ -0,0 +1,4 @@ +#![no_std] + +#[unsafe(no_mangle)] +pub fn good() {} From 0de74158757dcb2db583c27b412f14391ae9ce0c Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 7 Feb 2026 19:44:34 +0900 Subject: [PATCH 661/978] borrowck: suggest `&mut *x` for pattern reborrows --- .../src/diagnostics/mutability_errors.rs | 73 +++++++++++++++++-- tests/ui/borrowck/mut-borrow-of-mut-ref.fixed | 37 ++++++++++ tests/ui/borrowck/mut-borrow-of-mut-ref.rs | 3 +- .../ui/borrowck/mut-borrow-of-mut-ref.stderr | 16 +--- .../reborrow-in-match-suggest-deref.fixed | 23 ++++++ .../reborrow-in-match-suggest-deref.rs | 23 ++++++ .../reborrow-in-match-suggest-deref.stderr | 23 ++++++ 7 files changed, 175 insertions(+), 23 deletions(-) create mode 100644 tests/ui/borrowck/mut-borrow-of-mut-ref.fixed create mode 100644 tests/ui/borrowck/reborrow-in-match-suggest-deref.fixed create mode 100644 tests/ui/borrowck/reborrow-in-match-suggest-deref.rs create mode 100644 tests/ui/borrowck/reborrow-in-match-suggest-deref.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 4fb739403ced..07d2313cc7fd 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -354,14 +354,71 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.infcx.tcx.sess.source_map().span_to_snippet(source_info.span) { if snippet.starts_with("&mut ") { - // We don't have access to the HIR to get accurate spans, but we can - // give a best effort structured suggestion. - err.span_suggestion_verbose( - source_info.span.with_hi(source_info.span.lo() + BytePos(5)), - "if there is only one mutable reborrow, remove the `&mut`", - "", - Applicability::MaybeIncorrect, - ); + // In calls, `&mut &mut T` may be deref-coerced to `&mut T`, and + // removing the extra `&mut` is the most direct suggestion. But for + // pattern-matching expressions (`match`, `if let`, `while let`), that + // can easily turn into a move, so prefer suggesting an explicit + // reborrow via `&mut *x` instead. + let mut in_pat_scrutinee = false; + let mut is_deref_coerced = false; + if let Some(expr) = self.find_expr(source_info.span) { + let tcx = self.infcx.tcx; + let span = expr.span.source_callsite(); + for (_, node) in tcx.hir_parent_iter(expr.hir_id) { + if let Node::Expr(parent_expr) = node { + match parent_expr.kind { + ExprKind::Match(scrutinee, ..) + if scrutinee + .span + .source_callsite() + .contains(span) => + { + in_pat_scrutinee = true; + break; + } + ExprKind::Let(let_expr) + if let_expr + .init + .span + .source_callsite() + .contains(span) => + { + in_pat_scrutinee = true; + break; + } + _ => {} + } + } + } + + let typeck = tcx.typeck(expr.hir_id.owner.def_id); + is_deref_coerced = + typeck.expr_adjustments(expr).iter().any(|adj| { + matches!(adj.kind, ty::adjustment::Adjust::Deref(_)) + }); + } + + if in_pat_scrutinee { + // Best-effort structured suggestion: insert `*` after `&mut `. + err.span_suggestion_verbose( + source_info + .span + .with_lo(source_info.span.lo() + BytePos(5)) + .shrink_to_lo(), + "to reborrow the mutable reference, add `*`", + "*", + Applicability::MaybeIncorrect, + ); + } else if is_deref_coerced { + // We don't have access to the HIR to get accurate spans, but we + // can give a best effort structured suggestion. + err.span_suggestion_verbose( + source_info.span.with_hi(source_info.span.lo() + BytePos(5)), + "if there is only one mutable reborrow, remove the `&mut`", + "", + Applicability::MaybeIncorrect, + ); + } } else { // This can occur with things like `(&mut self).foo()`. err.span_help(source_info.span, "try removing `&mut` here"); diff --git a/tests/ui/borrowck/mut-borrow-of-mut-ref.fixed b/tests/ui/borrowck/mut-borrow-of-mut-ref.fixed new file mode 100644 index 000000000000..f70983c65223 --- /dev/null +++ b/tests/ui/borrowck/mut-borrow-of-mut-ref.fixed @@ -0,0 +1,37 @@ +// Suggest not mutably borrowing a mutable reference +//@ run-rustfix +#![crate_type = "rlib"] + +pub fn f(mut b: &mut i32) { + //~^ ERROR: cannot borrow + //~| NOTE: not mutable + //~| NOTE: the binding is already a mutable borrow + //~| HELP: consider making the binding mutable if you need to reborrow multiple times + h(b); + //~^ NOTE: cannot borrow as mutable + //~| HELP: if there is only one mutable reborrow, remove the `&mut` + g(&mut &mut b); + //~^ NOTE: cannot borrow as mutable +} + +pub fn g(mut b: &mut i32) { //~ NOTE: the binding is already a mutable borrow + //~^ HELP: consider making the binding mutable if you need to reborrow multiple times + h(&mut &mut b); + //~^ ERROR: cannot borrow + //~| NOTE: cannot borrow as mutable +} + +pub fn h(_: &mut i32) {} + +trait Foo { + fn bar(&mut self); +} + +impl Foo for &mut String { + fn bar(&mut self) {} +} + +pub fn baz(mut f: &mut String) { //~ HELP consider making the binding mutable + f.bar(); //~ ERROR cannot borrow `f` as mutable, as it is not declared as mutable + //~^ NOTE cannot borrow as mutable +} diff --git a/tests/ui/borrowck/mut-borrow-of-mut-ref.rs b/tests/ui/borrowck/mut-borrow-of-mut-ref.rs index 33954592bf65..d150b249bf2d 100644 --- a/tests/ui/borrowck/mut-borrow-of-mut-ref.rs +++ b/tests/ui/borrowck/mut-borrow-of-mut-ref.rs @@ -1,4 +1,5 @@ // Suggest not mutably borrowing a mutable reference +//@ run-rustfix #![crate_type = "rlib"] pub fn f(b: &mut i32) { @@ -11,7 +12,6 @@ pub fn f(b: &mut i32) { //~| HELP: if there is only one mutable reborrow, remove the `&mut` g(&mut &mut b); //~^ NOTE: cannot borrow as mutable - //~| HELP: if there is only one mutable reborrow, remove the `&mut` } pub fn g(b: &mut i32) { //~ NOTE: the binding is already a mutable borrow @@ -19,7 +19,6 @@ pub fn g(b: &mut i32) { //~ NOTE: the binding is already a mutable borrow h(&mut &mut b); //~^ ERROR: cannot borrow //~| NOTE: cannot borrow as mutable - //~| HELP: if there is only one mutable reborrow, remove the `&mut` } pub fn h(_: &mut i32) {} diff --git a/tests/ui/borrowck/mut-borrow-of-mut-ref.stderr b/tests/ui/borrowck/mut-borrow-of-mut-ref.stderr index 4c4a5e718393..01ceba90c943 100644 --- a/tests/ui/borrowck/mut-borrow-of-mut-ref.stderr +++ b/tests/ui/borrowck/mut-borrow-of-mut-ref.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable - --> $DIR/mut-borrow-of-mut-ref.rs:4:10 + --> $DIR/mut-borrow-of-mut-ref.rs:5:10 | LL | pub fn f(b: &mut i32) { | ^ not mutable @@ -11,7 +11,7 @@ LL | g(&mut &mut b); | ------ cannot borrow as mutable | note: the binding is already a mutable borrow - --> $DIR/mut-borrow-of-mut-ref.rs:4:13 + --> $DIR/mut-borrow-of-mut-ref.rs:5:13 | LL | pub fn f(b: &mut i32) { | ^^^^^^^^ @@ -24,11 +24,6 @@ help: if there is only one mutable reborrow, remove the `&mut` LL - h(&mut b); LL + h(b); | -help: if there is only one mutable reborrow, remove the `&mut` - | -LL - g(&mut &mut b); -LL + g(&mut b); - | error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable --> $DIR/mut-borrow-of-mut-ref.rs:19:12 @@ -45,14 +40,9 @@ help: consider making the binding mutable if you need to reborrow multiple times | LL | pub fn g(mut b: &mut i32) { | +++ -help: if there is only one mutable reborrow, remove the `&mut` - | -LL - h(&mut &mut b); -LL + h(&mut b); - | error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable - --> $DIR/mut-borrow-of-mut-ref.rs:36:5 + --> $DIR/mut-borrow-of-mut-ref.rs:35:5 | LL | f.bar(); | ^ cannot borrow as mutable diff --git a/tests/ui/borrowck/reborrow-in-match-suggest-deref.fixed b/tests/ui/borrowck/reborrow-in-match-suggest-deref.fixed new file mode 100644 index 000000000000..3f52e57a804c --- /dev/null +++ b/tests/ui/borrowck/reborrow-in-match-suggest-deref.fixed @@ -0,0 +1,23 @@ +// Regression test for #81059. +// edition:2024 +//@ run-rustfix + +#![allow(unused)] + +fn test(mut outer: &mut Option) { + //~^ NOTE: the binding is already a mutable borrow + //~| HELP: consider making the binding mutable if you need to reborrow multiple times + match (&mut *outer, 23) { + //~^ ERROR: cannot borrow `outer` as mutable, as it is not declared as mutable + //~| NOTE: cannot borrow as mutable + //~| HELP: to reborrow the mutable reference, add `*` + (Some(inner), _) => { + *inner = 17; + } + _ => { + *outer = Some(2); + } + } +} + +fn main() {} diff --git a/tests/ui/borrowck/reborrow-in-match-suggest-deref.rs b/tests/ui/borrowck/reborrow-in-match-suggest-deref.rs new file mode 100644 index 000000000000..34c299f4f7b1 --- /dev/null +++ b/tests/ui/borrowck/reborrow-in-match-suggest-deref.rs @@ -0,0 +1,23 @@ +// Regression test for #81059. +// edition:2024 +//@ run-rustfix + +#![allow(unused)] + +fn test(outer: &mut Option) { + //~^ NOTE: the binding is already a mutable borrow + //~| HELP: consider making the binding mutable if you need to reborrow multiple times + match (&mut outer, 23) { + //~^ ERROR: cannot borrow `outer` as mutable, as it is not declared as mutable + //~| NOTE: cannot borrow as mutable + //~| HELP: to reborrow the mutable reference, add `*` + (Some(inner), _) => { + *inner = 17; + } + _ => { + *outer = Some(2); + } + } +} + +fn main() {} diff --git a/tests/ui/borrowck/reborrow-in-match-suggest-deref.stderr b/tests/ui/borrowck/reborrow-in-match-suggest-deref.stderr new file mode 100644 index 000000000000..db3129461518 --- /dev/null +++ b/tests/ui/borrowck/reborrow-in-match-suggest-deref.stderr @@ -0,0 +1,23 @@ +error[E0596]: cannot borrow `outer` as mutable, as it is not declared as mutable + --> $DIR/reborrow-in-match-suggest-deref.rs:10:12 + | +LL | match (&mut outer, 23) { + | ^^^^^^^^^^ cannot borrow as mutable + | +note: the binding is already a mutable borrow + --> $DIR/reborrow-in-match-suggest-deref.rs:7:16 + | +LL | fn test(outer: &mut Option) { + | ^^^^^^^^^^^^^^^^ +help: consider making the binding mutable if you need to reborrow multiple times + | +LL | fn test(mut outer: &mut Option) { + | +++ +help: to reborrow the mutable reference, add `*` + | +LL | match (&mut *outer, 23) { + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0596`. From 5768fb7d93414e830c6ca0fbf0f4f8502d2de4f4 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 7 Feb 2026 05:49:02 -0600 Subject: [PATCH 662/978] symcheck: Check for core symbols with the new mangling The recent switch in default mangling meant that the check was no longer working correctly. Resolve this by checking for both legacy- and v0-mangled core symbols to the extent that this is possible. --- .../compiler-builtins/crates/symbol-check/Cargo.toml | 1 + .../crates/symbol-check/src/main.rs | 12 +++++++++++- .../crates/symbol-check/tests/all.rs | 6 ++++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/library/compiler-builtins/crates/symbol-check/Cargo.toml b/library/compiler-builtins/crates/symbol-check/Cargo.toml index 774d1c31a4b0..6291a0ca7f45 100644 --- a/library/compiler-builtins/crates/symbol-check/Cargo.toml +++ b/library/compiler-builtins/crates/symbol-check/Cargo.toml @@ -6,6 +6,7 @@ publish = false [dependencies] object = { version = "0.37.3", features = ["wasm"] } +regex = "1.12.3" serde_json = "1.0.149" [dev-dependencies] diff --git a/library/compiler-builtins/crates/symbol-check/src/main.rs b/library/compiler-builtins/crates/symbol-check/src/main.rs index 1413042e6c70..733d9f4e8bef 100644 --- a/library/compiler-builtins/crates/symbol-check/src/main.rs +++ b/library/compiler-builtins/crates/symbol-check/src/main.rs @@ -9,12 +9,14 @@ use std::fs; use std::io::{BufRead, BufReader}; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; +use std::sync::LazyLock; use object::read::archive::ArchiveFile; use object::{ File as ObjFile, Object, ObjectSection, ObjectSymbol, Result as ObjResult, Symbol, SymbolKind, SymbolScope, }; +use regex::Regex; use serde_json::Value; const CHECK_LIBRARIES: &[&str] = &["compiler_builtins", "builtins_test_intrinsics"]; @@ -255,6 +257,14 @@ fn verify_no_duplicates(archive: &BinFile) { /// Ensure that there are no references to symbols from `core` that aren't also (somehow) defined. fn verify_core_symbols(archive: &BinFile) { + // Match both mangling styles: + // + // * `_ZN4core3str8converts9from_utf817hd4454ac14cbbb790E` (old) + // * `_RNvNtNtCscK9O3IwVk7N_4core3str8converts9from_utf8` (v0) + // + // Also account for the Apple leading `_`. + static RE: LazyLock = LazyLock::new(|| Regex::new(r"^_?_[RZ].*4core").unwrap()); + let mut defined = BTreeSet::new(); let mut undefined = Vec::new(); let mut has_symbols = false; @@ -263,7 +273,7 @@ fn verify_core_symbols(archive: &BinFile) { has_symbols = true; // Find only symbols from `core` - if !symbol.name().unwrap().contains("_ZN4core") { + if !RE.is_match(symbol.name().unwrap()) { return; } diff --git a/library/compiler-builtins/crates/symbol-check/tests/all.rs b/library/compiler-builtins/crates/symbol-check/tests/all.rs index 4ad9509726fb..400469a49e2a 100644 --- a/library/compiler-builtins/crates/symbol-check/tests/all.rs +++ b/library/compiler-builtins/crates/symbol-check/tests/all.rs @@ -66,8 +66,10 @@ fn test_core_symbols() { let lib_out = dir.path().join("libfoo.rlib"); rustc_build(&input_dir().join("core_symbols.rs"), &lib_out, |cmd| cmd); let assert = cargo_bin_cmd!().arg("check").arg(&lib_out).assert(); - // FIXME(symcheck): this should fail but we don't detect the new mangling. - assert.success(); + assert + .failure() + .stderr_contains("found 1 undefined symbols from core") + .stderr_contains("from_utf8"); } #[test] From bad1a450c01c285b727e82b116c5baf226ed4f86 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 7 Feb 2026 13:33:25 +0100 Subject: [PATCH 663/978] use `test` instead of `unix` to be platform-independent --- tests/ui/macros/cfg_select.rs | 6 ++++-- tests/ui/macros/cfg_select.stderr | 32 ++++++++++++++++++------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs index 09d2c116a86d..0f009756e211 100644 --- a/tests/ui/macros/cfg_select.rs +++ b/tests/ui/macros/cfg_select.rs @@ -151,8 +151,10 @@ cfg_select! { } cfg_select! { - unix => {} - unix => {} + test => {} + test => {} + //~^ WARN unreachable configuration predicate + _ => {} //~^ WARN unreachable configuration predicate } diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index be238e0a65e5..5878708668d3 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -1,5 +1,5 @@ error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:159:1 + --> $DIR/cfg_select.rs:161:1 | LL | / cfg_select! { LL | | @@ -8,49 +8,49 @@ LL | | } | |_^ error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:164:1 + --> $DIR/cfg_select.rs:166:1 | LL | cfg_select! {} | ^^^^^^^^^^^^^^ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `=>` - --> $DIR/cfg_select.rs:168:5 + --> $DIR/cfg_select.rs:170:5 | LL | => {} | ^^ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression - --> $DIR/cfg_select.rs:173:5 + --> $DIR/cfg_select.rs:175:5 | LL | () => {} | ^^ expressions are not allowed here error[E0539]: malformed `cfg_select` macro input - --> $DIR/cfg_select.rs:178:5 + --> $DIR/cfg_select.rs:180:5 | LL | "str" => {} | ^^^^^ expected a valid identifier here error[E0539]: malformed `cfg_select` macro input - --> $DIR/cfg_select.rs:183:5 + --> $DIR/cfg_select.rs:185:5 | LL | a::b => {} | ^^^^ expected a valid identifier here error[E0537]: invalid predicate `a` - --> $DIR/cfg_select.rs:188:5 + --> $DIR/cfg_select.rs:190:5 | LL | a() => {} | ^^^ error: expected one of `(`, `::`, `=>`, or `=`, found `+` - --> $DIR/cfg_select.rs:193:7 + --> $DIR/cfg_select.rs:195:7 | LL | a + 1 => {} | ^ expected one of `(`, `::`, `=>`, or `=` error: expected one of `(`, `::`, `=>`, or `=`, found `!` - --> $DIR/cfg_select.rs:199:8 + --> $DIR/cfg_select.rs:201:8 | LL | cfg!() => {} | ^ expected one of `(`, `::`, `=>`, or `=` @@ -86,11 +86,17 @@ LL | _ => {} warning: unreachable configuration predicate --> $DIR/cfg_select.rs:155:5 | -LL | unix => {} +LL | test => {} | ^^^^ this configuration predicate is never reached +warning: unreachable configuration predicate + --> $DIR/cfg_select.rs:157:5 + | +LL | _ => {} + | ^ this configuration predicate is never reached + warning: unexpected `cfg` condition name: `a` - --> $DIR/cfg_select.rs:193:5 + --> $DIR/cfg_select.rs:195:5 | LL | a + 1 => {} | ^ help: found config with similar value: `target_feature = "a"` @@ -101,7 +107,7 @@ LL | a + 1 => {} = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `cfg` - --> $DIR/cfg_select.rs:199:5 + --> $DIR/cfg_select.rs:201:5 | LL | cfg!() => {} | ^^^ @@ -109,7 +115,7 @@ LL | cfg!() => {} = help: to expect this configuration use `--check-cfg=cfg(cfg)` = note: see for more information about checking conditional configuration -error: aborting due to 9 previous errors; 6 warnings emitted +error: aborting due to 9 previous errors; 7 warnings emitted Some errors have detailed explanations: E0537, E0539. For more information about an error, try `rustc --explain E0537`. From fb5a4dca328798ec30fa001aed16f19ceb32e000 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 7 Feb 2026 23:16:12 +1100 Subject: [PATCH 664/978] Regression test for `let x = offset_of!(..) else { .. }` span --- tests/ui/span/let-offset-of.rs | 19 +++++++++++++++++++ tests/ui/span/let-offset-of.stderr | 17 +++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/ui/span/let-offset-of.rs create mode 100644 tests/ui/span/let-offset-of.stderr diff --git a/tests/ui/span/let-offset-of.rs b/tests/ui/span/let-offset-of.rs new file mode 100644 index 000000000000..99b34a192847 --- /dev/null +++ b/tests/ui/span/let-offset-of.rs @@ -0,0 +1,19 @@ +#![crate_type = "rlib"] +//@ edition: 2024 +//@ check-pass + +// Using `offset_of` in the RHS of a let-else statement should not produce +// malformed spans or a blank diagnostic snippet. +// +// Regression test for . + +fn init_to_offset_of() { + use std::mem::offset_of; + struct Foo { field: u32 } + + if let x = offset_of!(Foo, field) {} + //~^ WARN irrefutable `if let` pattern + + let x = offset_of!(Foo, field) else { return; }; + //~^ WARN irrefutable `let...else` pattern +} diff --git a/tests/ui/span/let-offset-of.stderr b/tests/ui/span/let-offset-of.stderr new file mode 100644 index 000000000000..a0ef3fcc5ef5 --- /dev/null +++ b/tests/ui/span/let-offset-of.stderr @@ -0,0 +1,17 @@ +warning: irrefutable `if let` pattern + --> $DIR/let-offset-of.rs:14:8 + | +LL | if let x = offset_of!(Foo, field) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + = note: `#[warn(irrefutable_let_patterns)]` on by default + +warning: irrefutable `let...else` pattern + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: 2 warnings emitted + From cc3fdc637a6314f69bcc5be0a4c281f285a04bbc Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 7 Feb 2026 22:27:23 +1100 Subject: [PATCH 665/978] Avoid a bogus THIR span for `let x = offset_of!(..)` --- compiler/rustc_mir_build/src/thir/cx/block.rs | 9 +++++++-- tests/ui/span/let-offset-of.stderr | 4 ++++ tests/ui/thir-print/offset_of.stdout | 18 +++++++++--------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index fad73a7115b0..b108dff5555f 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -75,8 +75,13 @@ impl<'tcx> ThirBuildCx<'tcx> { debug!(?pattern); let span = match local.init { - Some(init) => local.span.with_hi(init.span.hi()), - None => local.span, + Some(init) + if let Some(init_span) = + init.span.find_ancestor_inside_same_ctxt(local.span) => + { + local.span.with_hi(init_span.hi()) + } + Some(_) | None => local.span, }; let stmt = Stmt { kind: StmtKind::Let { diff --git a/tests/ui/span/let-offset-of.stderr b/tests/ui/span/let-offset-of.stderr index a0ef3fcc5ef5..6ea9b2194a36 100644 --- a/tests/ui/span/let-offset-of.stderr +++ b/tests/ui/span/let-offset-of.stderr @@ -9,6 +9,10 @@ LL | if let x = offset_of!(Foo, field) {} = note: `#[warn(irrefutable_let_patterns)]` on by default warning: irrefutable `let...else` pattern + --> $DIR/let-offset-of.rs:17:5 + | +LL | let x = offset_of!(Foo, field) else { return; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this pattern will always match, so the `else` clause is useless = help: consider removing the `else` clause diff --git a/tests/ui/thir-print/offset_of.stdout b/tests/ui/thir-print/offset_of.stdout index 5666a5972f37..25c099438754 100644 --- a/tests/ui/thir-print/offset_of.stdout +++ b/tests/ui/thir-print/offset_of.stdout @@ -68,7 +68,7 @@ body: ) else_block: None hir_id: HirId(DefId(offset_of::concrete).10) - span: $DIR/offset_of.rs:37:5: 1445:57 (#0) + span: $DIR/offset_of.rs:37:5: 37:33 (#0) } } Stmt { @@ -117,7 +117,7 @@ body: ) else_block: None hir_id: HirId(DefId(offset_of::concrete).20) - span: $DIR/offset_of.rs:38:5: 1445:57 (#0) + span: $DIR/offset_of.rs:38:5: 38:33 (#0) } } Stmt { @@ -166,7 +166,7 @@ body: ) else_block: None hir_id: HirId(DefId(offset_of::concrete).30) - span: $DIR/offset_of.rs:39:5: 1445:57 (#0) + span: $DIR/offset_of.rs:39:5: 39:34 (#0) } } Stmt { @@ -215,7 +215,7 @@ body: ) else_block: None hir_id: HirId(DefId(offset_of::concrete).40) - span: $DIR/offset_of.rs:40:5: 1445:57 (#0) + span: $DIR/offset_of.rs:40:5: 40:36 (#0) } } Stmt { @@ -264,7 +264,7 @@ body: ) else_block: None hir_id: HirId(DefId(offset_of::concrete).50) - span: $DIR/offset_of.rs:41:5: 1445:57 (#0) + span: $DIR/offset_of.rs:41:5: 41:36 (#0) } } ] @@ -864,7 +864,7 @@ body: ) else_block: None hir_id: HirId(DefId(offset_of::generic).12) - span: $DIR/offset_of.rs:45:5: 1445:57 (#0) + span: $DIR/offset_of.rs:45:5: 45:37 (#0) } } Stmt { @@ -913,7 +913,7 @@ body: ) else_block: None hir_id: HirId(DefId(offset_of::generic).24) - span: $DIR/offset_of.rs:46:5: 1445:57 (#0) + span: $DIR/offset_of.rs:46:5: 46:37 (#0) } } Stmt { @@ -962,7 +962,7 @@ body: ) else_block: None hir_id: HirId(DefId(offset_of::generic).36) - span: $DIR/offset_of.rs:47:5: 1445:57 (#0) + span: $DIR/offset_of.rs:47:5: 47:37 (#0) } } Stmt { @@ -1011,7 +1011,7 @@ body: ) else_block: None hir_id: HirId(DefId(offset_of::generic).48) - span: $DIR/offset_of.rs:48:5: 1445:57 (#0) + span: $DIR/offset_of.rs:48:5: 48:37 (#0) } } ] From cee9cc6113b1c5ae3f47a87b73f546099d4b4296 Mon Sep 17 00:00:00 2001 From: Jacob Adam Date: Sat, 7 Feb 2026 12:37:00 +0100 Subject: [PATCH 666/978] Fix an ICE in the vtable iteration for a trait reference in const eval when a supertrait not implemented compiler/rustc_trait_selection/src/traits/vtable.rs@`vtable_entries`: The impossible predicates check in `vtable_entries` used `instantiate_own` which only includes the method's own where-clauses, not the parent trait's bounds. Replace it with `instantiate_and_check_impossible_predicates` which also checks the trait ref itself, so unsatisfied supertrait bounds are caught and the method is marked `Vacant` instead of ICEing. --- compiler/rustc_trait_selection/src/traits/vtable.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 584c8e2a27c8..bd48068eb579 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -12,7 +12,7 @@ use rustc_span::DUMMY_SP; use smallvec::{SmallVec, smallvec}; use tracing::debug; -use crate::traits::{impossible_predicates, is_vtable_safe_method}; +use crate::traits::is_vtable_safe_method; #[derive(Clone, Debug)] pub enum VtblSegment<'tcx> { @@ -271,11 +271,7 @@ fn vtable_entries<'tcx>( // do not hold for this particular set of type parameters. // Note that this method could then never be called, so we // do not want to try and codegen it, in that case (see #23435). - let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, args); - if impossible_predicates( - tcx, - predicates.map(|(predicate, _)| predicate).collect(), - ) { + if tcx.instantiate_and_check_impossible_predicates((def_id, args)) { debug!("vtable_entries: predicates do not hold"); return VtblEntry::Vacant; } From 6af91c56d199851abfebbbab4745f34f229649f1 Mon Sep 17 00:00:00 2001 From: Jacob Adam Date: Sat, 7 Feb 2026 12:42:59 +0100 Subject: [PATCH 667/978] Move tests from tests/crashes to tests/ui now that they don't ICE --- tests/crashes/137190-2.rs | 18 ------------- tests/crashes/137190-3.rs | 10 -------- .../vtable-impossible-predicates-async.rs} | 6 ++++- .../vtable-unsatisfied-supertrait-generics.rs | 25 +++++++++++++++++++ ...ble-unsatisfied-supertrait-generics.stderr | 20 +++++++++++++++ .../coercion/vtable-unsatisfied-supertrait.rs | 16 ++++++++++++ .../vtable-unsatisfied-supertrait.stderr | 20 +++++++++++++++ 7 files changed, 86 insertions(+), 29 deletions(-) delete mode 100644 tests/crashes/137190-2.rs delete mode 100644 tests/crashes/137190-3.rs rename tests/{crashes/135470.rs => ui/coercion/vtable-impossible-predicates-async.rs} (79%) create mode 100644 tests/ui/coercion/vtable-unsatisfied-supertrait-generics.rs create mode 100644 tests/ui/coercion/vtable-unsatisfied-supertrait-generics.stderr create mode 100644 tests/ui/coercion/vtable-unsatisfied-supertrait.rs create mode 100644 tests/ui/coercion/vtable-unsatisfied-supertrait.stderr diff --git a/tests/crashes/137190-2.rs b/tests/crashes/137190-2.rs deleted file mode 100644 index 0c68b5aa4a51..000000000000 --- a/tests/crashes/137190-2.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ known-bug: #137190 -trait Supertrait { - fn method(&self) {} -} - -trait Trait

: Supertrait<()> {} - -impl

Trait

for () {} - -const fn upcast

(x: &dyn Trait

) -> &dyn Supertrait<()> { - x -} - -const fn foo() -> &'static dyn Supertrait<()> { - upcast::<()>(&()) -} - -const _: &'static dyn Supertrait<()> = foo(); diff --git a/tests/crashes/137190-3.rs b/tests/crashes/137190-3.rs deleted file mode 100644 index 88ae88e11bcd..000000000000 --- a/tests/crashes/137190-3.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #137190 -trait Supertrait { - fn method(&self) {} -} - -trait Trait: Supertrait {} - -impl Trait for () {} - -const _: &dyn Supertrait = &() as &dyn Trait as &dyn Supertrait; diff --git a/tests/crashes/135470.rs b/tests/ui/coercion/vtable-impossible-predicates-async.rs similarity index 79% rename from tests/crashes/135470.rs rename to tests/ui/coercion/vtable-impossible-predicates-async.rs index efa017b5457c..fe6aa9843fc6 100644 --- a/tests/crashes/135470.rs +++ b/tests/ui/coercion/vtable-impossible-predicates-async.rs @@ -1,4 +1,8 @@ -//@ known-bug: #135470 +// Regression test for #135470. +// Verify that we don't ICE when building vtable entries +// for a blanket impl involving async and impossible predicates. + +//@ check-pass //@ compile-flags: -Copt-level=0 //@ edition: 2021 diff --git a/tests/ui/coercion/vtable-unsatisfied-supertrait-generics.rs b/tests/ui/coercion/vtable-unsatisfied-supertrait-generics.rs new file mode 100644 index 000000000000..41e603fc0a0a --- /dev/null +++ b/tests/ui/coercion/vtable-unsatisfied-supertrait-generics.rs @@ -0,0 +1,25 @@ +// Regression test for #137190. +// Variant of vtable-unsatisfied-supertrait.rs with generic traits. +// Verify that we don't ICE when building vtable entries +// for a generic trait whose supertrait is not implemented. + +//@ compile-flags: --crate-type lib + +trait Supertrait { + fn method(&self) {} +} + +trait Trait

: Supertrait<()> {} + +impl

Trait

for () {} +//~^ ERROR the trait bound `(): Supertrait<()>` is not satisfied + +const fn upcast

(x: &dyn Trait

) -> &dyn Supertrait<()> { + x +} + +const fn foo() -> &'static dyn Supertrait<()> { + upcast::<()>(&()) +} + +const _: &'static dyn Supertrait<()> = foo(); diff --git a/tests/ui/coercion/vtable-unsatisfied-supertrait-generics.stderr b/tests/ui/coercion/vtable-unsatisfied-supertrait-generics.stderr new file mode 100644 index 000000000000..a485d2d53953 --- /dev/null +++ b/tests/ui/coercion/vtable-unsatisfied-supertrait-generics.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `(): Supertrait<()>` is not satisfied + --> $DIR/vtable-unsatisfied-supertrait-generics.rs:14:22 + | +LL | impl

Trait

for () {} + | ^^ the trait `Supertrait<()>` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/vtable-unsatisfied-supertrait-generics.rs:8:1 + | +LL | trait Supertrait { + | ^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `Trait` + --> $DIR/vtable-unsatisfied-supertrait-generics.rs:12:17 + | +LL | trait Trait

: Supertrait<()> {} + | ^^^^^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coercion/vtable-unsatisfied-supertrait.rs b/tests/ui/coercion/vtable-unsatisfied-supertrait.rs new file mode 100644 index 000000000000..26a83d2fb066 --- /dev/null +++ b/tests/ui/coercion/vtable-unsatisfied-supertrait.rs @@ -0,0 +1,16 @@ +// Regression test for #137190. +// Verify that we don't ICE when building vtable entries +// for a trait whose supertrait is not implemented. + +//@ compile-flags: --crate-type lib + +trait Supertrait { + fn method(&self) {} +} + +trait Trait: Supertrait {} + +impl Trait for () {} +//~^ ERROR the trait bound `(): Supertrait` is not satisfied + +const _: &dyn Supertrait = &() as &dyn Trait as &dyn Supertrait; diff --git a/tests/ui/coercion/vtable-unsatisfied-supertrait.stderr b/tests/ui/coercion/vtable-unsatisfied-supertrait.stderr new file mode 100644 index 000000000000..7df2c95c7fac --- /dev/null +++ b/tests/ui/coercion/vtable-unsatisfied-supertrait.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `(): Supertrait` is not satisfied + --> $DIR/vtable-unsatisfied-supertrait.rs:13:16 + | +LL | impl Trait for () {} + | ^^ the trait `Supertrait` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/vtable-unsatisfied-supertrait.rs:7:1 + | +LL | trait Supertrait { + | ^^^^^^^^^^^^^^^^ +note: required by a bound in `Trait` + --> $DIR/vtable-unsatisfied-supertrait.rs:11:14 + | +LL | trait Trait: Supertrait {} + | ^^^^^^^^^^ required by this bound in `Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 9249e9f78a7c12f1e797e6519375df698fd96970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Thu, 5 Feb 2026 14:02:06 +0100 Subject: [PATCH 668/978] Port rustc_intrinsic to the new attribute parser --- compiler/rustc_ast_lowering/src/item.rs | 2 +- .../rustc_attr_parsing/src/attributes/rustc_internal.rs | 9 +++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ compiler/rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_middle/src/ty/util.rs | 6 ++++-- compiler/rustc_mir_transform/src/check_inline.rs | 5 +++-- compiler/rustc_mir_transform/src/cross_crate_inline.rs | 7 ++++--- compiler/rustc_passes/src/check_attr.rs | 2 +- src/tools/clippy/clippy_lints/src/loops/empty_loop.rs | 7 ++++--- 10 files changed, 31 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index cde8b8f9fe2e..12eaa99143e9 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1397,7 +1397,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // create a fake body so that the entire rest of the compiler doesn't have to deal with // this as a special case. return self.lower_fn_body(decl, contract, |this| { - if attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic)) + if find_attr!(attrs, AttributeKind::RustcIntrinsic) || this.tcx.is_sdylib_interface_build() { let span = this.lower_span(span); diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 3b7d25b43ba2..637912210638 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -810,3 +810,12 @@ impl SingleAttributeParser for RustcDefPath { Some(AttributeKind::RustcDefPath(cx.attr_span)) } } + +pub(crate) struct RustcIntrinsicParser; + +impl NoArgsAttributeParser for RustcIntrinsicParser { + const PATH: &[Symbol] = &[sym::rustc_intrinsic]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsic; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 5b489d306499..68c9f232e1b1 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -264,6 +264,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index fa781a74c9e2..1bcf0bf1541e 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1120,6 +1120,9 @@ pub enum AttributeKind { /// Represents `#[rustc_if_this_changed]` RustcIfThisChanged(Span, Option), + /// Represents `#[rustc_intrinsic]` + RustcIntrinsic, + /// Represents `#[rustc_layout]` RustcLayout(ThinVec), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 14b54c129d3e..92066c9cfad4 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -118,6 +118,7 @@ impl AttributeKind { RustcHasIncoherentInherentImpls => Yes, RustcHiddenTypeOfOpaques => No, RustcIfThisChanged(..) => No, + RustcIntrinsic => Yes, RustcLayout(..) => No, RustcLayoutScalarValidRangeEnd(..) => Yes, RustcLayoutScalarValidRangeStart(..) => Yes, diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index d6e6ffae7300..47b9bb95f830 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -10,11 +10,11 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorGuaranteed; use rustc_hashes::Hash128; -use rustc_hir as hir; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_hir::limit::Limit; +use rustc_hir::{self as hir, find_attr}; use rustc_index::bit_set::GrowableBitSet; use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension}; use rustc_span::sym; @@ -1679,7 +1679,9 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool { /// the compiler to make some assumptions about its shape; if the user doesn't use a feature gate, they may /// cause an ICE that we otherwise may want to prevent. pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - if tcx.features().intrinsics() && tcx.has_attr(def_id, sym::rustc_intrinsic) { + if tcx.features().intrinsics() + && find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcIntrinsic) + { let must_be_overridden = match tcx.hir_node_by_def_id(def_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { has_body, .. }, .. }) => { !has_body diff --git a/compiler/rustc_mir_transform/src/check_inline.rs b/compiler/rustc_mir_transform/src/check_inline.rs index 8d28cb3ca003..2d1876426727 100644 --- a/compiler/rustc_mir_transform/src/check_inline.rs +++ b/compiler/rustc_mir_transform/src/check_inline.rs @@ -1,8 +1,9 @@ //! Check that a body annotated with `#[rustc_force_inline]` will not fail to inline based on its //! definition alone (irrespective of any specific caller). -use rustc_hir::attrs::InlineAttr; +use rustc_hir::attrs::{AttributeKind, InlineAttr}; use rustc_hir::def_id::DefId; +use rustc_hir::find_attr; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::{Body, TerminatorKind}; use rustc_middle::ty; @@ -62,7 +63,7 @@ pub(super) fn is_inline_valid_on_fn<'tcx>( // but at this stage we don't know whether codegen knows the intrinsic, // so just conservatively don't inline it. This also ensures that we do not // accidentally inline the body of an intrinsic that *must* be overridden. - if tcx.has_attr(def_id, sym::rustc_intrinsic) { + if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcIntrinsic) { return Err("callee is an intrinsic"); } diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 71bdafa958ca..da133861617f 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -1,6 +1,7 @@ -use rustc_hir::attrs::InlineAttr; +use rustc_hir::attrs::{AttributeKind, InlineAttr}; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; +use rustc_hir::find_attr; use rustc_middle::bug; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -43,7 +44,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { return true; } - if tcx.has_attr(def_id, sym::rustc_intrinsic) { + if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcIntrinsic) { // Intrinsic fallback bodies are always cross-crate inlineable. // To ensure that the MIR inliner doesn't cluelessly try to inline fallback // bodies even when the backend would implement something better, we stop @@ -157,7 +158,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { // But intrinsics don't have a body that gets assigned to a CGU, so they are // ignored. if let Some((fn_def_id, _)) = func.const_fn_def() - && self.tcx.has_attr(fn_def_id, sym::rustc_intrinsic) + && find_attr!(tcx.get_all_attrs(fn_def_id), AttributeKind::RustcIntrinsic) { return; } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 680a93908354..8dcc0eb63c2f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -313,6 +313,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcHasIncoherentInherentImpls | AttributeKind::RustcHiddenTypeOfOpaques | AttributeKind::RustcIfThisChanged(..) + | AttributeKind::RustcIntrinsic | AttributeKind::RustcLayout(..) | AttributeKind::RustcLayoutScalarValidRangeEnd(..) | AttributeKind::RustcLayoutScalarValidRangeStart(..) @@ -385,7 +386,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_no_mir_inline | sym::rustc_insignificant_dtor | sym::rustc_nonnull_optimization_guaranteed - | sym::rustc_intrinsic | sym::rustc_inherit_overflow_checks | sym::rustc_intrinsic_const_stable_indirect | sym::rustc_trivial_field_reads diff --git a/src/tools/clippy/clippy_lints/src/loops/empty_loop.rs b/src/tools/clippy/clippy_lints/src/loops/empty_loop.rs index e809987d75a0..0a5b26bfa689 100644 --- a/src/tools/clippy/clippy_lints/src/loops/empty_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/empty_loop.rs @@ -1,8 +1,9 @@ use super::EMPTY_LOOP; use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::{is_in_panic_handler, is_no_std_crate, sym}; +use clippy_utils::{is_in_panic_handler, is_no_std_crate}; -use rustc_hir::{Block, Expr, ItemKind, Node}; +use rustc_hir::attrs::AttributeKind; +use rustc_hir::{Block, Expr, ItemKind, Node, find_attr}; use rustc_lint::LateContext; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, loop_block: &Block<'_>) { @@ -10,7 +11,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, loop_block: &Block<'_ if let Node::Item(parent_node) = cx.tcx.hir_node(parent_hir_id) && matches!(parent_node.kind, ItemKind::Fn { .. }) && let attrs = cx.tcx.hir_attrs(parent_hir_id) - && attrs.iter().any(|attr| attr.has_name(sym::rustc_intrinsic)) + && find_attr!(attrs, AttributeKind::RustcIntrinsic) { // Intrinsic functions are expanded into an empty loop when lowering the AST // to simplify the job of later passes which might expect any function to have a body. From c42a581d2f02da46b77f0c2ff00f6a7e6ff4b524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Thu, 5 Feb 2026 14:09:40 +0100 Subject: [PATCH 669/978] Port rustc_intrinsic_const_stable_indirect to the new attribute parser --- .../src/attributes/rustc_internal.rs | 10 ++++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ compiler/rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_middle/src/ty/util.rs | 5 ++++- compiler/rustc_passes/src/check_attr.rs | 2 +- 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 637912210638..7e4feedd2548 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -490,6 +490,7 @@ impl CombineAttributeParser for RustcMirParser { .collect() } } + pub(crate) struct RustcNonConstTraitMethodParser; impl NoArgsAttributeParser for RustcNonConstTraitMethodParser { @@ -819,3 +820,12 @@ impl NoArgsAttributeParser for RustcIntrinsicParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsic; } + +pub(crate) struct RustcIntrinsicConstStableIndirectParser; + +impl NoArgsAttributeParser for RustcIntrinsicConstStableIndirectParser { + const PATH: &'static [Symbol] = &[sym::rustc_intrinsic_const_stable_indirect]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 68c9f232e1b1..0d594270ba68 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -264,6 +264,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 1bcf0bf1541e..0e6208831190 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1123,6 +1123,9 @@ pub enum AttributeKind { /// Represents `#[rustc_intrinsic]` RustcIntrinsic, + /// Represents `#[rustc_intrinsic_const_stable_indirect]` + RustcIntrinsicConstStableIndirect, + /// Represents `#[rustc_layout]` RustcLayout(ThinVec), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 92066c9cfad4..1f322d84fad4 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -119,6 +119,7 @@ impl AttributeKind { RustcHiddenTypeOfOpaques => No, RustcIfThisChanged(..) => No, RustcIntrinsic => Yes, + RustcIntrinsicConstStableIndirect => No, RustcLayout(..) => No, RustcLayoutScalarValidRangeEnd(..) => Yes, RustcLayoutScalarValidRangeStart(..) => Yes, diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 47b9bb95f830..e01a5721a5e0 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1691,7 +1691,10 @@ pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option CheckAttrVisitor<'tcx> { | AttributeKind::RustcHiddenTypeOfOpaques | AttributeKind::RustcIfThisChanged(..) | AttributeKind::RustcIntrinsic + | AttributeKind::RustcIntrinsicConstStableIndirect | AttributeKind::RustcLayout(..) | AttributeKind::RustcLayoutScalarValidRangeEnd(..) | AttributeKind::RustcLayoutScalarValidRangeStart(..) @@ -387,7 +388,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_insignificant_dtor | sym::rustc_nonnull_optimization_guaranteed | sym::rustc_inherit_overflow_checks - | sym::rustc_intrinsic_const_stable_indirect | sym::rustc_trivial_field_reads | sym::rustc_on_unimplemented | sym::rustc_do_not_const_check From f090e9ce83e0873591e5faca204cfb68da93ff67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Thu, 5 Feb 2026 14:02:06 +0100 Subject: [PATCH 670/978] Port rustc_intrinsic to the new attribute parser --- clippy_lints/src/loops/empty_loop.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/loops/empty_loop.rs b/clippy_lints/src/loops/empty_loop.rs index e809987d75a0..0a5b26bfa689 100644 --- a/clippy_lints/src/loops/empty_loop.rs +++ b/clippy_lints/src/loops/empty_loop.rs @@ -1,8 +1,9 @@ use super::EMPTY_LOOP; use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::{is_in_panic_handler, is_no_std_crate, sym}; +use clippy_utils::{is_in_panic_handler, is_no_std_crate}; -use rustc_hir::{Block, Expr, ItemKind, Node}; +use rustc_hir::attrs::AttributeKind; +use rustc_hir::{Block, Expr, ItemKind, Node, find_attr}; use rustc_lint::LateContext; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, loop_block: &Block<'_>) { @@ -10,7 +11,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, loop_block: &Block<'_ if let Node::Item(parent_node) = cx.tcx.hir_node(parent_hir_id) && matches!(parent_node.kind, ItemKind::Fn { .. }) && let attrs = cx.tcx.hir_attrs(parent_hir_id) - && attrs.iter().any(|attr| attr.has_name(sym::rustc_intrinsic)) + && find_attr!(attrs, AttributeKind::RustcIntrinsic) { // Intrinsic functions are expanded into an empty loop when lowering the AST // to simplify the job of later passes which might expect any function to have a body. From fd7ff90f7029a79f2b19f696471c0e675932c283 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 7 Feb 2026 14:28:12 +0100 Subject: [PATCH 671/978] Allow only a single accepter per attribute --- compiler/rustc_attr_parsing/src/context.rs | 36 ++++++++++-------- compiler/rustc_attr_parsing/src/interface.rs | 40 ++++++++++---------- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 5b489d306499..8db561575562 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; use std::collections::BTreeMap; +use std::collections::btree_map::Entry; use std::ops::{Deref, DerefMut}; use std::sync::LazyLock; @@ -61,7 +62,7 @@ use crate::target_checking::AllowedTargets; type GroupType = LazyLock>; pub(super) struct GroupTypeInner { - pub(super) accepters: BTreeMap<&'static [Symbol], Vec>>, + pub(super) accepters: BTreeMap<&'static [Symbol], GroupTypeInnerAccept>, } pub(super) struct GroupTypeInnerAccept { @@ -101,7 +102,7 @@ macro_rules! attribute_parsers { @[$stage: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?]; ) => { pub(crate) static $name: GroupType<$stage> = LazyLock::new(|| { - let mut accepters = BTreeMap::<_, Vec>>::new(); + let mut accepters = BTreeMap::<_, GroupTypeInnerAccept<$stage>>::new(); $( { thread_local! { @@ -109,19 +110,24 @@ macro_rules! attribute_parsers { }; for (path, template, accept_fn) in <$names>::ATTRIBUTES { - accepters.entry(*path).or_default().push(GroupTypeInnerAccept { - template: *template, - accept_fn: Box::new(|cx, args| { - STATE_OBJECT.with_borrow_mut(|s| { - accept_fn(s, cx, args) - }) - }), - allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS, - finalizer: Box::new(|cx| { - let state = STATE_OBJECT.take(); - state.finalize(cx) - }), - }); + match accepters.entry(*path) { + Entry::Vacant(e) => { + e.insert(GroupTypeInnerAccept { + template: *template, + accept_fn: Box::new(|cx, args| { + STATE_OBJECT.with_borrow_mut(|s| { + accept_fn(s, cx, args) + }) + }), + allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS, + finalizer: Box::new(|cx| { + let state = STATE_OBJECT.take(); + state.finalize(cx) + }) + }); + } + Entry::Occupied(_) => panic!("Attribute {path:?} has multiple accepters"), + } } } )* diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index bac4936c20d2..f75f63a0e811 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -327,7 +327,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { let parts = n.item.path.segments.iter().map(|seg| seg.ident.name).collect::>(); - if let Some(accepts) = S::parsers().accepters.get(parts.as_slice()) { + if let Some(accept) = S::parsers().accepters.get(parts.as_slice()) { let Some(args) = ArgParser::from_attr_args( args, &parts, @@ -368,28 +368,26 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { continue; } - for accept in accepts { - let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext { - shared: SharedContext { - cx: self, - target_span, - target, - emit_lint: &mut emit_lint, - }, - attr_span, - inner_span: lower_span(n.item.span()), - attr_style: attr.style, - parsed_description: ParsedDescription::Attribute, - template: &accept.template, - attr_path: attr_path.clone(), - }; + let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext { + shared: SharedContext { + cx: self, + target_span, + target, + emit_lint: &mut emit_lint, + }, + attr_span, + inner_span: lower_span(n.item.span()), + attr_style: attr.style, + parsed_description: ParsedDescription::Attribute, + template: &accept.template, + attr_path: attr_path.clone(), + }; - (accept.accept_fn)(&mut cx, &args); - finalizers.push(&accept.finalizer); + (accept.accept_fn)(&mut cx, &args); + finalizers.push(&accept.finalizer); - if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) { - Self::check_target(&accept.allowed_targets, target, &mut cx); - } + if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) { + Self::check_target(&accept.allowed_targets, target, &mut cx); } } else { // If we're here, we must be compiling a tool attribute... Or someone From 2407f47903869fab5ff713126037c932caf77e3a Mon Sep 17 00:00:00 2001 From: Urgau Date: Sat, 7 Feb 2026 14:29:40 +0100 Subject: [PATCH 672/978] Also duplicate `#[expect]` attribute in `#[derive]`-ed code --- .../src/deriving/generic/mod.rs | 1 + .../derive-expect-issue-150553-2.rs | 14 ++++++++++++ .../derive-expect-issue-150553-3.rs | 14 ++++++++++++ .../derive-expect-issue-150553-3.stderr | 18 +++++++++++++++ .../derive-expect-issue-150553.rs | 22 +++++++++++++++++++ 5 files changed, 69 insertions(+) create mode 100644 tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-2.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-3.rs create mode 100644 tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-3.stderr create mode 100644 tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553.rs diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index bc86cdbc9f7e..3fe5e89ef06d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -540,6 +540,7 @@ impl<'a> TraitDef<'a> { .filter(|a| { a.has_any_name(&[ sym::allow, + sym::expect, sym::warn, sym::deny, sym::forbid, diff --git a/tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-2.rs b/tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-2.rs new file mode 100644 index 000000000000..43ee6bf26a69 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-2.rs @@ -0,0 +1,14 @@ +// Make sure that the copied `#[expect]` attr in the derived code does not trigger an unfulfilled +// expectation as it's linked to the original one which is fulfilled. +// +// See for rational. + +//@ check-pass + +#[expect(non_camel_case_types)] +#[derive(Debug)] +pub struct SCREAMING_CASE { + pub t_ref: i64, +} + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-3.rs b/tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-3.rs new file mode 100644 index 000000000000..904366e6532e --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-3.rs @@ -0,0 +1,14 @@ +// Make sure we produce the unfulfilled expectation lint if neither the struct or the +// derived code fulfilled it. + +//@ check-pass + +#[expect(unexpected_cfgs)] +//~^ WARN this lint expectation is unfulfilled +//~^^ WARN this lint expectation is unfulfilled +#[derive(Debug)] +pub struct MyStruct { + pub t_ref: i64, +} + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-3.stderr b/tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-3.stderr new file mode 100644 index 000000000000..6478ec435db0 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553-3.stderr @@ -0,0 +1,18 @@ +warning: this lint expectation is unfulfilled + --> $DIR/derive-expect-issue-150553-3.rs:6:10 + | +LL | #[expect(unexpected_cfgs)] + | ^^^^^^^^^^^^^^^ + | + = note: `#[warn(unfulfilled_lint_expectations)]` on by default + +warning: this lint expectation is unfulfilled + --> $DIR/derive-expect-issue-150553-3.rs:6:10 + | +LL | #[expect(unexpected_cfgs)] + | ^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553.rs b/tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553.rs new file mode 100644 index 000000000000..1752835c8bb8 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/derive-expect-issue-150553.rs @@ -0,0 +1,22 @@ +// Make sure we properly copy the `#[expect]` attr to the derived code and that no +// unfulfilled expectations are trigerred. +// +// See for rational. + +//@ check-pass + +#![deny(redundant_lifetimes)] + +use std::fmt::Debug; + +#[derive(Debug)] +#[expect(redundant_lifetimes)] +pub struct RefWrapper<'a, T> +where + 'a: 'static, + T: Debug, +{ + pub t_ref: &'a T, +} + +fn main() {} From 0538f7b2ab82f5ea828dec77eeded64f0df24c8f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 7 Feb 2026 06:33:33 -0600 Subject: [PATCH 673/978] meta: Switch to workspace dependencies We have a handful of repeated dependencies that can be cleaned up, so change here. --- library/compiler-builtins/Cargo.toml | 33 +++++++++++++++++++ .../builtins-shim/Cargo.toml | 5 ++- .../builtins-test/Cargo.toml | 21 ++++++------ .../compiler-builtins/Cargo.toml | 2 +- .../crates/libm-macros/Cargo.toml | 8 ++--- .../crates/musl-math-sys/Cargo.toml | 6 ++-- .../crates/symbol-check/Cargo.toml | 12 +++---- .../compiler-builtins/crates/util/Cargo.toml | 10 +++--- .../compiler-builtins/libm-test/Cargo.toml | 32 +++++++++--------- library/compiler-builtins/libm/Cargo.toml | 1 + 10 files changed, 82 insertions(+), 48 deletions(-) diff --git a/library/compiler-builtins/Cargo.toml b/library/compiler-builtins/Cargo.toml index d0eaa16393cd..26f67e02fc52 100644 --- a/library/compiler-builtins/Cargo.toml +++ b/library/compiler-builtins/Cargo.toml @@ -31,6 +31,39 @@ exclude = [ "compiler-builtins", ] +[workspace.dependencies] +anyhow = "1.0.101" +assert_cmd = "2.1.2" +cc = "1.2.55" +compiler_builtins = { path = "builtins-shim", default-features = false } +criterion = { version = "0.6.0", default-features = false, features = ["cargo_bench_support"] } +getrandom = "0.3.4" +gmp-mpfr-sys = { version = "1.6.8", default-features = false } +gungraun = "0.17.0" +heck = "0.5.0" +indicatif = { version = "0.18.3", default-features = false } +libm = { path = "libm", default-features = false } +libm-macros = { path = "crates/libm-macros" } +libm-test = { path = "libm-test", default-features = false } +libtest-mimic = "0.8.1" +musl-math-sys = { path = "crates/musl-math-sys" } +no-panic = "0.1.35" +object = { version = "0.37.3", features = ["wasm"] } +panic-handler = { path = "crates/panic-handler" } +paste = "1.0.15" +proc-macro2 = "1.0.106" +quote = "1.0.44" +rand = "0.9.2" +rand_chacha = "0.9.0" +rand_xoshiro = "0.7" +rayon = "1.11.0" +regex = "1.12.3" +rug = { version = "1.28.1", default-features = false, features = ["float", "integer", "std"] } +rustc_apfloat = "0.2.3" +serde_json = "1.0.149" +syn = "2.0.114" +tempfile = "3.24.0" + [profile.release] panic = "abort" diff --git a/library/compiler-builtins/builtins-shim/Cargo.toml b/library/compiler-builtins/builtins-shim/Cargo.toml index 746d5b21dc3f..37d3407e9f66 100644 --- a/library/compiler-builtins/builtins-shim/Cargo.toml +++ b/library/compiler-builtins/builtins-shim/Cargo.toml @@ -7,6 +7,9 @@ # manifest that is identical except for the `core` dependency and forwards # to the same sources, which acts as the `compiler-builtins` Cargo entrypoint # for out of tree testing +# +# Ideally we can eventually replace this with a patch in the workspace +# manifest . [package] name = "compiler_builtins" @@ -33,7 +36,7 @@ doctest = false test = false [build-dependencies] -cc = { optional = true, version = "1.2" } +cc = { version = "1.2", optional = true } [features] default = ["compiler-builtins"] diff --git a/library/compiler-builtins/builtins-test/Cargo.toml b/library/compiler-builtins/builtins-test/Cargo.toml index 550f736a76db..9395ab1a985e 100644 --- a/library/compiler-builtins/builtins-test/Cargo.toml +++ b/library/compiler-builtins/builtins-test/Cargo.toml @@ -6,23 +6,22 @@ publish = false license = "MIT AND Apache-2.0 WITH LLVM-exception AND (MIT OR Apache-2.0)" [dependencies] +compiler_builtins = { workspace = true, features = ["unstable-public-internals"] } + # For fuzzing tests we want a deterministic seedable RNG. We also eliminate potential # problems with system RNGs on the variety of platforms this crate is tested on. # `xoshiro128**` is used for its quality, size, and speed at generating `u32` shift amounts. -rand_xoshiro = "0.7" -# To compare float builtins against -rustc_apfloat = "0.2.3" -# Really a dev dependency, but dev dependencies can't be optional -gungraun = { version = "0.17.0", optional = true } +rand_xoshiro.workspace = true -[dependencies.compiler_builtins] -path = "../builtins-shim" -default-features = false -features = ["unstable-public-internals"] +# To compare float builtins against +rustc_apfloat.workspace = true + +# Really a dev dependency, but dev dependencies can't be optional +gungraun = { workspace = true, optional = true } [dev-dependencies] -criterion = { version = "0.6.0", default-features = false, features = ["cargo_bench_support"] } -paste = "1.0.15" +criterion.workspace = true +paste.workspace = true [target.'cfg(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")), target_os = "linux"))'.dev-dependencies] test = { git = "https://github.com/japaric/utest" } diff --git a/library/compiler-builtins/compiler-builtins/Cargo.toml b/library/compiler-builtins/compiler-builtins/Cargo.toml index 496dde2d4cf2..a8b8920421b3 100644 --- a/library/compiler-builtins/compiler-builtins/Cargo.toml +++ b/library/compiler-builtins/compiler-builtins/Cargo.toml @@ -31,7 +31,7 @@ doc = false core = { path = "../../core", optional = true } [build-dependencies] -cc = { optional = true, version = "1.2" } +cc = { version = "1.2", optional = true } [features] default = ["compiler-builtins"] diff --git a/library/compiler-builtins/crates/libm-macros/Cargo.toml b/library/compiler-builtins/crates/libm-macros/Cargo.toml index f6697b783457..f99a92e21c70 100644 --- a/library/compiler-builtins/crates/libm-macros/Cargo.toml +++ b/library/compiler-builtins/crates/libm-macros/Cargo.toml @@ -9,10 +9,10 @@ license = "MIT OR Apache-2.0" proc-macro = true [dependencies] -heck = "0.5.0" -proc-macro2 = "1.0.106" -quote = "1.0.44" -syn = { version = "2.0.114", features = ["full", "extra-traits", "visit-mut"] } +heck.workspace = true +proc-macro2.workspace = true +quote.workspace = true +syn = { workspace = true, features = ["full", "extra-traits", "visit-mut"] } [lints.rust] # Values used during testing diff --git a/library/compiler-builtins/crates/musl-math-sys/Cargo.toml b/library/compiler-builtins/crates/musl-math-sys/Cargo.toml index 60b0647b6dc6..eb97ffbc8669 100644 --- a/library/compiler-builtins/crates/musl-math-sys/Cargo.toml +++ b/library/compiler-builtins/crates/musl-math-sys/Cargo.toml @@ -5,10 +5,8 @@ edition = "2024" publish = false license = "MIT OR Apache-2.0" -[dependencies] - [dev-dependencies] -libm = { path = "../../libm" } +libm.workspace = true [build-dependencies] -cc = "1.2.55" +cc.workspace = true diff --git a/library/compiler-builtins/crates/symbol-check/Cargo.toml b/library/compiler-builtins/crates/symbol-check/Cargo.toml index 6291a0ca7f45..5bc13d337c27 100644 --- a/library/compiler-builtins/crates/symbol-check/Cargo.toml +++ b/library/compiler-builtins/crates/symbol-check/Cargo.toml @@ -5,11 +5,11 @@ edition = "2024" publish = false [dependencies] -object = { version = "0.37.3", features = ["wasm"] } -regex = "1.12.3" -serde_json = "1.0.149" +object.workspace = true +regex.workspace = true +serde_json.workspace = true [dev-dependencies] -assert_cmd = "2.1.2" -cc = "1.2.55" -tempfile = "3.24.0" +assert_cmd.workspace = true +cc.workspace = true +tempfile.workspace = true diff --git a/library/compiler-builtins/crates/util/Cargo.toml b/library/compiler-builtins/crates/util/Cargo.toml index b1ccd8a9e63c..88e0b332065d 100644 --- a/library/compiler-builtins/crates/util/Cargo.toml +++ b/library/compiler-builtins/crates/util/Cargo.toml @@ -12,8 +12,8 @@ build-mpfr = ["libm-test/build-mpfr", "dep:rug"] unstable-float = ["libm/unstable-float", "libm-test/unstable-float", "rug?/nightly-float"] [dependencies] -libm = { path = "../../libm", default-features = false } -libm-macros = { path = "../libm-macros" } -libm-test = { path = "../../libm-test", default-features = false } -musl-math-sys = { path = "../musl-math-sys", optional = true } -rug = { version = "1.28.1", optional = true, default-features = false, features = ["float", "std"] } +libm.workspace = true +libm-macros.workspace = true +libm-test.workspace = true +musl-math-sys = { workspace = true, optional = true } +rug = { workspace = true, optional = true } diff --git a/library/compiler-builtins/libm-test/Cargo.toml b/library/compiler-builtins/libm-test/Cargo.toml index b813331a8552..c395d6a21bd5 100644 --- a/library/compiler-builtins/libm-test/Cargo.toml +++ b/library/compiler-builtins/libm-test/Cargo.toml @@ -28,29 +28,29 @@ icount = ["dep:gungraun"] short-benchmarks = [] [dependencies] -anyhow = "1.0.101" +anyhow.workspace = true # This is not directly used but is required so we can enable `gmp-mpfr-sys/force-cross`. -gmp-mpfr-sys = { version = "1.6.8", optional = true, default-features = false } -gungraun = { version = "0.17.0", optional = true } -indicatif = { version = "0.18.3", default-features = false } -libm = { path = "../libm", features = ["unstable-public-internals"] } -libm-macros = { path = "../crates/libm-macros" } -musl-math-sys = { path = "../crates/musl-math-sys", optional = true } -paste = "1.0.15" -rand = "0.9.2" -rand_chacha = "0.9.0" -rayon = "1.11.0" -rug = { version = "1.28.1", optional = true, default-features = false, features = ["float", "integer", "std"] } +gmp-mpfr-sys = { workspace = true, optional = true } +gungraun = { workspace = true, optional = true } +indicatif.workspace = true +libm = { workspace = true, default-features = true, features = ["unstable-public-internals"] } +libm-macros.workspace = true +musl-math-sys = { workspace = true, optional = true } +paste.workspace = true +rand.workspace = true +rand_chacha.workspace = true +rayon.workspace = true +rug = { workspace = true, optional = true } [target.'cfg(target_family = "wasm")'.dependencies] -getrandom = { version = "0.3.4", features = ["wasm_js"] } +getrandom = { workspace = true, features = ["wasm_js"] } [build-dependencies] -rand = { version = "0.9.2", optional = true } +rand = { workspace = true, optional = true } [dev-dependencies] -criterion = { version = "0.6.0", default-features = false, features = ["cargo_bench_support"] } -libtest-mimic = "0.8.1" +criterion.workspace = true +libtest-mimic.workspace = true [[bench]] name = "icount" diff --git a/library/compiler-builtins/libm/Cargo.toml b/library/compiler-builtins/libm/Cargo.toml index 4d8b9bf827ad..617914a4dfae 100644 --- a/library/compiler-builtins/libm/Cargo.toml +++ b/library/compiler-builtins/libm/Cargo.toml @@ -43,6 +43,7 @@ unstable-float = [] force-soft-floats = [] [dev-dependencies] +# FIXME(msrv): switch to `no-panic.workspace` when possible no-panic = "0.1.35" [lints.rust] From 7c9ae5b0213393660abe57add8d4b34c90c3430f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 7 Feb 2026 06:48:37 -0600 Subject: [PATCH 674/978] meta: Sort Cargo.toml `[features]` table after `[dependencies]` --- .../compiler-builtins/crates/util/Cargo.toml | 12 ++--- .../compiler-builtins/libm-test/Cargo.toml | 44 +++++++++---------- library/compiler-builtins/libm/Cargo.toml | 8 ++-- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/library/compiler-builtins/crates/util/Cargo.toml b/library/compiler-builtins/crates/util/Cargo.toml index 88e0b332065d..c56e2cc12ea5 100644 --- a/library/compiler-builtins/crates/util/Cargo.toml +++ b/library/compiler-builtins/crates/util/Cargo.toml @@ -5,15 +5,15 @@ edition = "2024" publish = false license = "MIT OR Apache-2.0" -[features] -default = ["build-musl", "build-mpfr", "unstable-float"] -build-musl = ["libm-test/build-musl", "dep:musl-math-sys"] -build-mpfr = ["libm-test/build-mpfr", "dep:rug"] -unstable-float = ["libm/unstable-float", "libm-test/unstable-float", "rug?/nightly-float"] - [dependencies] libm.workspace = true libm-macros.workspace = true libm-test.workspace = true musl-math-sys = { workspace = true, optional = true } rug = { workspace = true, optional = true } + +[features] +default = ["build-musl", "build-mpfr", "unstable-float"] +build-musl = ["libm-test/build-musl", "dep:musl-math-sys"] +build-mpfr = ["libm-test/build-mpfr", "dep:rug"] +unstable-float = ["libm/unstable-float", "libm-test/unstable-float", "rug?/nightly-float"] diff --git a/library/compiler-builtins/libm-test/Cargo.toml b/library/compiler-builtins/libm-test/Cargo.toml index c395d6a21bd5..4f65504bd584 100644 --- a/library/compiler-builtins/libm-test/Cargo.toml +++ b/library/compiler-builtins/libm-test/Cargo.toml @@ -5,28 +5,6 @@ edition = "2024" publish = false license = "MIT OR Apache-2.0" -[features] -default = ["build-mpfr", "unstable-float"] - -# Propagated from libm because this affects which functions we test. -unstable-float = ["libm/unstable-float", "rug?/nightly-float"] - -# Generate tests which are random inputs and the outputs are calculated with -# musl libc. -build-mpfr = ["dep:rug", "dep:gmp-mpfr-sys"] - -# Build our own musl for testing and benchmarks -build-musl = ["dep:musl-math-sys"] - -# Enable report generation without bringing in more dependencies by default -benchmarking-reports = ["criterion/plotters", "criterion/html_reports"] - -# Enable icount benchmarks (requires gungraun-runner and valgrind locally) -icount = ["dep:gungraun"] - -# Run with a reduced set of benchmarks, such as for CI -short-benchmarks = [] - [dependencies] anyhow.workspace = true # This is not directly used but is required so we can enable `gmp-mpfr-sys/force-cross`. @@ -52,6 +30,28 @@ rand = { workspace = true, optional = true } criterion.workspace = true libtest-mimic.workspace = true +[features] +default = ["build-mpfr", "unstable-float"] + +# Propagated from libm because this affects which functions we test. +unstable-float = ["libm/unstable-float", "rug?/nightly-float"] + +# Generate tests which are random inputs and the outputs are calculated with +# musl libc. +build-mpfr = ["dep:rug", "dep:gmp-mpfr-sys"] + +# Build our own musl for testing and benchmarks +build-musl = ["dep:musl-math-sys"] + +# Enable report generation without bringing in more dependencies by default +benchmarking-reports = ["criterion/plotters", "criterion/html_reports"] + +# Enable icount benchmarks (requires gungraun-runner and valgrind locally) +icount = ["dep:gungraun"] + +# Run with a reduced set of benchmarks, such as for CI +short-benchmarks = [] + [[bench]] name = "icount" harness = false diff --git a/library/compiler-builtins/libm/Cargo.toml b/library/compiler-builtins/libm/Cargo.toml index 617914a4dfae..d80ddab0ab7a 100644 --- a/library/compiler-builtins/libm/Cargo.toml +++ b/library/compiler-builtins/libm/Cargo.toml @@ -15,6 +15,10 @@ license = "MIT" edition = "2021" rust-version = "1.63" +[dev-dependencies] +# FIXME(msrv): switch to `no-panic.workspace` when possible +no-panic = "0.1.35" + [features] default = ["arch"] @@ -42,10 +46,6 @@ unstable-float = [] # hard float operations. force-soft-floats = [] -[dev-dependencies] -# FIXME(msrv): switch to `no-panic.workspace` when possible -no-panic = "0.1.35" - [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = [ # compiler-builtins sets this feature, but we use it in `libm` From da421f55850b5f7ef7e560ec8e52b41c39ff03be Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Tue, 27 Jan 2026 23:54:24 +0300 Subject: [PATCH 675/978] =?UTF-8?q?`const=20{=20'=CE=A3'.len=5Futf8()=20}`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- library/alloc/src/str.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index e772ac25a95c..8a3326c7d76a 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -411,9 +411,8 @@ impl str { fn map_uppercase_sigma(from: &str, i: usize) -> char { // See https://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 // for the definition of `Final_Sigma`. - debug_assert!('Σ'.len_utf8() == 2); let is_word_final = case_ignorable_then_cased(from[..i].chars().rev()) - && !case_ignorable_then_cased(from[i + 2..].chars()); + && !case_ignorable_then_cased(from[i + const { 'Σ'.len_utf8() }..].chars()); if is_word_final { 'ς' } else { 'σ' } } From 03dcd99aa322a0d5c9b5f203b1222798bbabf941 Mon Sep 17 00:00:00 2001 From: ia0 Date: Sat, 7 Feb 2026 15:39:42 +0100 Subject: [PATCH 676/978] Format heterogeneous try blocks --- src/tools/rustfmt/src/expr.rs | 29 +++++++++++++-- .../tests/source/try_blocks_heterogeneous.rs | 34 ++++++++++++++++++ .../tests/target/try_blocks_heterogeneous.rs | 36 +++++++++++++++++++ 3 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 src/tools/rustfmt/tests/source/try_blocks_heterogeneous.rs create mode 100644 src/tools/rustfmt/tests/target/try_blocks_heterogeneous.rs diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index de96f004dc87..70bce1920047 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -385,8 +385,33 @@ pub(crate) fn format_expr( )) } } - // FIXME: heterogeneous try blocks, which include a type so are harder to format - ast::ExprKind::TryBlock(_, Some(_)) => Err(RewriteError::Unknown), + ast::ExprKind::TryBlock(ref block, Some(ref ty)) => { + let keyword = "try bikeshed "; + // 2 = " {".len() + let ty_shape = shape + .shrink_left(keyword.len()) + .and_then(|shape| shape.sub_width(2)) + .max_width_error(shape.width, expr.span)?; + let ty_str = ty.rewrite_result(context, ty_shape)?; + let prefix = format!("{keyword}{ty_str} "); + if let rw @ Ok(_) = + rewrite_single_line_block(context, &prefix, block, Some(&expr.attrs), None, shape) + { + rw + } else { + let budget = shape.width.saturating_sub(prefix.len()); + Ok(format!( + "{prefix}{}", + rewrite_block( + block, + Some(&expr.attrs), + None, + context, + Shape::legacy(budget, shape.indent) + )? + )) + } + } ast::ExprKind::Gen(capture_by, ref block, ref kind, _) => { let mover = if matches!(capture_by, ast::CaptureBy::Value { .. }) { "move " diff --git a/src/tools/rustfmt/tests/source/try_blocks_heterogeneous.rs b/src/tools/rustfmt/tests/source/try_blocks_heterogeneous.rs new file mode 100644 index 000000000000..bae0060374d8 --- /dev/null +++ b/src/tools/rustfmt/tests/source/try_blocks_heterogeneous.rs @@ -0,0 +1,34 @@ +// rustfmt-edition: 2018 + +fn main() -> Result<(), !> { + let _x = try bikeshed Option<_> { + 4 + }; + + try bikeshed Result<_, _> {} +} + +fn baz() -> Option { + if (1 == 1) { + return try bikeshed Option { + 5 + }; + } + + // test + let x = try bikeshed Option<()> { + // try blocks are great + }; + + let y = try bikeshed Option { + 6 + }; // comment + + let x = try bikeshed Option { baz()?; baz()?; baz()?; 7 }; + + let x = try bikeshed Foo { 1 + 1 + 1 }; + + let x = try bikeshed Foo {}; + + return None; +} diff --git a/src/tools/rustfmt/tests/target/try_blocks_heterogeneous.rs b/src/tools/rustfmt/tests/target/try_blocks_heterogeneous.rs new file mode 100644 index 000000000000..6f910ed5d051 --- /dev/null +++ b/src/tools/rustfmt/tests/target/try_blocks_heterogeneous.rs @@ -0,0 +1,36 @@ +// rustfmt-edition: 2018 + +fn main() -> Result<(), !> { + let _x = try bikeshed Option<_> { 4 }; + + try bikeshed Result<_, _> {} +} + +fn baz() -> Option { + if (1 == 1) { + return try bikeshed Option { 5 }; + } + + // test + let x = try bikeshed Option<()> { + // try blocks are great + }; + + let y = try bikeshed Option { 6 }; // comment + + let x = try bikeshed Option { + baz()?; + baz()?; + baz()?; + 7 + }; + + let x = try bikeshed Foo { + 1 + 1 + 1 + }; + + let x = + try bikeshed Foo {}; + + return None; +} From 1ec5101f20cfffb67557692a5ec647133e2bcd19 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 7 Feb 2026 07:06:05 -0600 Subject: [PATCH 677/978] Bump the libm MSRV to 1.67 This gets us: * `saturating_sub_unsigned` * `::ilog2` * Correct lexing of float literals with the `f16` or `f128` suffix Link: https://github.com/rust-lang/compiler-builtins/issues/1017 --- library/compiler-builtins/libm/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/compiler-builtins/libm/Cargo.toml b/library/compiler-builtins/libm/Cargo.toml index d80ddab0ab7a..98202d1977dc 100644 --- a/library/compiler-builtins/libm/Cargo.toml +++ b/library/compiler-builtins/libm/Cargo.toml @@ -13,7 +13,7 @@ keywords = ["libm", "math"] repository = "https://github.com/rust-lang/compiler-builtins" license = "MIT" edition = "2021" -rust-version = "1.63" +rust-version = "1.67" [dev-dependencies] # FIXME(msrv): switch to `no-panic.workspace` when possible From 3d0989266de7d312a17ffac4e8251eb7a710358f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 7 Feb 2026 07:06:05 -0600 Subject: [PATCH 678/978] cleanup: Perform some simplifications possible with the MSRV bump --- .../libm/src/math/generic/sqrt.rs | 4 +-- .../libm/src/math/support/float_traits.rs | 7 +---- .../libm/src/math/support/hex_float.rs | 28 +------------------ 3 files changed, 3 insertions(+), 36 deletions(-) diff --git a/library/compiler-builtins/libm/src/math/generic/sqrt.rs b/library/compiler-builtins/libm/src/math/generic/sqrt.rs index 9481c4cdb7bb..e97a43d34956 100644 --- a/library/compiler-builtins/libm/src/math/generic/sqrt.rs +++ b/library/compiler-builtins/libm/src/math/generic/sqrt.rs @@ -419,9 +419,7 @@ mod tests { fn conformance_tests_f16() { let cases = [ (f16::PI, 0x3f17_u16), - // 10_000.0, using a hex literal for MSRV hack (Rust < 1.67 checks literal widths as - // part of the AST, so the `cfg` is irrelevant here). - (f16::from_bits(0x70e2), 0x5640_u16), + (10000.0_f16, 0x5640_u16), (f16::from_bits(0x0000000f), 0x13bf_u16), (f16::INFINITY, f16::INFINITY.to_bits()), ]; diff --git a/library/compiler-builtins/libm/src/math/support/float_traits.rs b/library/compiler-builtins/libm/src/math/support/float_traits.rs index 4e5011f62e0f..60c8bfca5165 100644 --- a/library/compiler-builtins/libm/src/math/support/float_traits.rs +++ b/library/compiler-builtins/libm/src/math/support/float_traits.rs @@ -1,5 +1,3 @@ -#![allow(unknown_lints)] // FIXME(msrv) we shouldn't need this - use core::{fmt, mem, ops}; use super::int_traits::{CastFrom, Int, MinInt}; @@ -289,10 +287,7 @@ macro_rules! float_impl { cfg_if! { // fma is not yet available in `core` if #[cfg(intrinsics_enabled)] { - // FIXME(msrv,bench): once our benchmark rustc version is above the - // 2022-09-23 nightly, this can be removed. - #[allow(unused_unsafe)] - unsafe { core::intrinsics::$fma_intrinsic(self, y, z) } + core::intrinsics::$fma_intrinsic(self, y, z) } else { super::super::$fma_fn(self, y, z) } diff --git a/library/compiler-builtins/libm/src/math/support/hex_float.rs b/library/compiler-builtins/libm/src/math/support/hex_float.rs index c8558b90053d..2f9369e50441 100644 --- a/library/compiler-builtins/libm/src/math/support/hex_float.rs +++ b/library/compiler-builtins/libm/src/math/support/hex_float.rs @@ -121,7 +121,7 @@ const fn parse_finite( Ok(Parsed { sig, exp }) => (sig, exp), }; - let mut round_bits = u128_ilog2(sig) as i32 - sig_bits as i32; + let mut round_bits = sig.ilog2() as i32 - sig_bits as i32; // Round at least up to min_lsb if exp < min_lsb - round_bits { @@ -299,29 +299,11 @@ const fn parse_hex(mut b: &[u8]) -> Result { )); }; - { - let e; - if negate_exp { - e = (exp as i64) - (pexp as i64); - } else { - e = (exp as i64) + (pexp as i64); - }; - - exp = if e < i32::MIN as i64 { - i32::MIN - } else if e > i32::MAX as i64 { - i32::MAX - } else { - e as i32 - }; - } - /* FIXME(msrv): once MSRV >= 1.66, replace the above workaround block with: if negate_exp { exp = exp.saturating_sub_unsigned(pexp); } else { exp = exp.saturating_add_unsigned(pexp); }; - */ Ok(Parsed { sig, exp }) } @@ -342,14 +324,6 @@ const fn hex_digit(c: u8) -> Option { } } -/* FIXME(msrv): vendor some things that are not const stable at our MSRV */ - -/// `u128::ilog2` -const fn u128_ilog2(v: u128) -> u32 { - assert!(v != 0); - u128::BITS - 1 - v.leading_zeros() -} - #[cfg(any(test, feature = "unstable-public-internals"))] mod hex_fmt { use core::fmt; From cf1a784f3f2643bb5afb0fa7e1944c8748a0fefa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sat, 7 Feb 2026 17:21:25 +0100 Subject: [PATCH 679/978] Port rustc_regions to the new attribute parser --- .../src/attributes/rustc_internal.rs | 16 ++++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + compiler/rustc_borrowck/src/nll.rs | 5 +++-- compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 2 +- 6 files changed, 25 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 3b7d25b43ba2..526d5ec1e1dc 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -219,6 +219,22 @@ impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintQueryInstability; } +pub(crate) struct RustcRegionsParser; + +impl NoArgsAttributeParser for RustcRegionsParser { + const PATH: &[Symbol] = &[sym::rustc_regions]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); + + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcRegions; +} + pub(crate) struct RustcLintUntrackedQueryInformationParser; impl NoArgsAttributeParser for RustcLintUntrackedQueryInformationParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 5b489d306499..3c49c272c121 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -276,6 +276,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 64e3b59acfff..ee32d64e9958 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -7,6 +7,8 @@ use std::str::FromStr; use polonius_engine::{Algorithm, AllFacts, Output}; use rustc_data_structures::frozen::Frozen; +use rustc_hir::attrs::AttributeKind; +use rustc_hir::find_attr; use rustc_index::IndexSlice; use rustc_middle::mir::pretty::PrettyPrintMirOptions; use rustc_middle::mir::{Body, MirDumper, PassWhere, Promoted}; @@ -15,7 +17,6 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_session::config::MirIncludeSpans; -use rustc_span::sym; use tracing::{debug, instrument}; use crate::borrow_set::BorrowSet; @@ -295,7 +296,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>( ) { let tcx = infcx.tcx; let base_def_id = tcx.typeck_root_def_id(body.source.def_id()); - if !tcx.has_attr(base_def_id, sym::rustc_regions) { + if !find_attr!(tcx.get_all_attrs(base_def_id), AttributeKind::RustcRegions) { return; } diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index fa781a74c9e2..2bbb19e0d10f 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1198,6 +1198,9 @@ pub enum AttributeKind { /// Represents `#[rustc_reallocator]` RustcReallocator, + /// Represents `#[rustc_regions]` + RustcRegions, + /// Represents `#[rustc_scalable_vector(N)]` RustcScalableVector { /// The base multiple of lanes that are in a scalable vector, if provided. `element_count` diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 14b54c129d3e..ee4915eec649 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -144,6 +144,7 @@ impl AttributeKind { RustcPreserveUbChecks => No, RustcPubTransparent(..) => Yes, RustcReallocator => No, + RustcRegions => No, RustcScalableVector { .. } => Yes, RustcShouldNotBeCalledOnConstItems(..) => Yes, RustcSimdMonomorphizeLaneLimit(..) => Yes, // Affects layout computation, which needs to work cross-crate diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 680a93908354..292db8e1b684 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -335,6 +335,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcPassIndirectlyInNonRusticAbis(..) | AttributeKind::RustcPreserveUbChecks | AttributeKind::RustcReallocator + | AttributeKind::RustcRegions | AttributeKind::RustcScalableVector { .. } | AttributeKind::RustcShouldNotBeCalledOnConstItems(..) | AttributeKind::RustcSimdMonomorphizeLaneLimit(..) @@ -401,7 +402,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_never_type_options | sym::rustc_autodiff | sym::rustc_capture_analysis - | sym::rustc_regions | sym::rustc_strict_coherence | sym::rustc_mir | sym::rustc_outlives From 85ca098f55cade17d59dd625d2e9af724a73a33b Mon Sep 17 00:00:00 2001 From: Usman Akinyemi Date: Sun, 1 Feb 2026 22:34:22 +0530 Subject: [PATCH 680/978] rustc_parse: improve the error diagnostic for "missing let" Signed-off-by: Usman Akinyemi --- compiler/rustc_parse/src/errors.rs | 18 ++++++++++ compiler/rustc_parse/src/parser/expr.rs | 47 ++++++++++++++++++++++++- tests/ui/missing/missing-let.rs | 12 +++++++ tests/ui/missing/missing-let.stderr | 28 +++++++++++++-- 4 files changed, 102 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 418d56f632bd..aafe585a4649 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -573,6 +573,24 @@ pub(crate) struct ExpectedExpressionFoundLet { pub comparison: Option, } +#[derive(Diagnostic)] +#[diag("let-chain with missing `let`")] +pub(crate) struct LetChainMissingLet { + #[primary_span] + pub span: Span, + #[label("expected `let` expression, found assignment")] + pub label_span: Span, + #[label("let expression later in the condition")] + pub rhs_span: Span, + #[suggestion( + "add `let` before the expression", + applicability = "maybe-incorrect", + code = "let ", + style = "verbose" + )] + pub sug_span: Span, +} + #[derive(Diagnostic)] #[diag("`||` operators are not supported in let chain conditions")] pub(crate) struct OrInLetChain { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 8bb22c2a831b..05216be06ff5 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -4282,7 +4282,52 @@ impl MutVisitor for CondChecker<'_> { mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } - ExprKind::Assign(ref lhs, _, span) => { + ExprKind::Assign(ref lhs, ref rhs, span) => { + if let ExprKind::Call(_, _) = &lhs.kind { + fn get_path_from_rhs(e: &Expr) -> Option<(u32, &Path)> { + fn inner(e: &Expr, depth: u32) -> Option<(u32, &Path)> { + match &e.kind { + ExprKind::Binary(_, lhs, _) => inner(lhs, depth + 1), + ExprKind::Path(_, path) => Some((depth, path)), + _ => None, + } + } + + inner(e, 0) + } + + if let Some((depth, path)) = get_path_from_rhs(rhs) { + // For cases like if Some(_) = x && let Some(_) = y && let Some(_) = z + // This return let Some(_) = y expression + fn find_let_some(expr: &Expr) -> Option<&Expr> { + match &expr.kind { + ExprKind::Let(..) => Some(expr), + + ExprKind::Binary(op, lhs, rhs) if op.node == BinOpKind::And => { + find_let_some(lhs).or_else(|| find_let_some(rhs)) + } + + _ => None, + } + } + + let expr_span = lhs.span.to(path.span); + + if let Some(later_rhs) = find_let_some(rhs) + && depth > 0 + { + let guar = self.parser.dcx().emit_err(errors::LetChainMissingLet { + span: lhs.span, + label_span: expr_span, + rhs_span: later_rhs.span, + sug_span: lhs.span.shrink_to_lo(), + }); + + self.found_incorrect_let_chain = Some(guar); + } + } + } + let forbid_let_reason = self.forbid_let_reason; self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden); let missing_let = self.missing_let; diff --git a/tests/ui/missing/missing-let.rs b/tests/ui/missing/missing-let.rs index 36db7bc95826..595de640470b 100644 --- a/tests/ui/missing/missing-let.rs +++ b/tests/ui/missing/missing-let.rs @@ -1,6 +1,18 @@ fn main() { let x = Some(42); + let y = Some(42); + let z = Some(42); if let Some(_) = x && Some(x) = x //~^ ERROR expected expression, found `let` statement + //~| NOTE: only supported directly in conditions of `if` and `while` expressions + {} + + if Some(_) = y && + //~^ NOTE expected `let` expression, found assignment + //~| ERROR let-chain with missing `let` + let Some(_) = z + //~^ ERROR: expected expression, found `let` statement + //~| NOTE: let expression later in the condition + //~| NOTE: only supported directly in conditions of `if` and `while` expressions {} } diff --git a/tests/ui/missing/missing-let.stderr b/tests/ui/missing/missing-let.stderr index 897ff6329d59..0a6e76b154f7 100644 --- a/tests/ui/missing/missing-let.stderr +++ b/tests/ui/missing/missing-let.stderr @@ -1,5 +1,5 @@ error: expected expression, found `let` statement - --> $DIR/missing-let.rs:3:8 + --> $DIR/missing-let.rs:5:8 | LL | if let Some(_) = x | ^^^^^^^^^^^^^^^ @@ -14,5 +14,29 @@ help: you might have meant to compare for equality LL | && Some(x) == x | + -error: aborting due to 1 previous error +error: expected expression, found `let` statement + --> $DIR/missing-let.rs:13:9 + | +LL | let Some(_) = z + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: let-chain with missing `let` + --> $DIR/missing-let.rs:10:8 + | +LL | if Some(_) = y && + | ^^^^^^^---- + | | + | expected `let` expression, found assignment +... +LL | let Some(_) = z + | --------------- let expression later in the condition + | +help: add `let` before the expression + | +LL | if let Some(_) = y && + | +++ + +error: aborting due to 3 previous errors From c814f76c0680cb073941c19e8750d859be7e6393 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 14:58:56 +0100 Subject: [PATCH 681/978] Convert to inline diagnostics in `rustc_lint` --- Cargo.lock | 1 - compiler/rustc_driver_impl/src/lib.rs | 6 +- compiler/rustc_lint/Cargo.toml | 1 - compiler/rustc_lint/messages.ftl | 1088 ----------- compiler/rustc_lint/src/async_closures.rs | 8 +- compiler/rustc_lint/src/builtin.rs | 15 +- compiler/rustc_lint/src/errors.rs | 41 +- compiler/rustc_lint/src/if_let_rescope.rs | 23 +- .../rustc_lint/src/impl_trait_overcaptures.rs | 26 +- compiler/rustc_lint/src/levels.rs | 7 +- compiler/rustc_lint/src/lib.rs | 2 - compiler/rustc_lint/src/lints.rs | 1740 +++++++++++------ compiler/rustc_lint/src/non_fmt_panic.rs | 23 +- compiler/rustc_lint/src/non_local_def.rs | 11 +- .../src/opaque_hidden_inferred_bound.rs | 6 +- compiler/rustc_lint/src/transmute.rs | 10 +- .../rustc_lint/src/types/improper_ctypes.rs | 112 +- 17 files changed, 1307 insertions(+), 1813 deletions(-) delete mode 100644 compiler/rustc_lint/messages.ftl diff --git a/Cargo.lock b/Cargo.lock index 7a8e06e5ba93..03cf3bcba894 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4143,7 +4143,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", - "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_infer", diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 315b11056085..d72913764e9d 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -111,11 +111,7 @@ pub fn default_translator() -> Translator { Translator::with_fallback_bundle(DEFAULT_LOCALE_RESOURCES.to_vec(), false) } -pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ - // tidy-alphabetical-start - rustc_lint::DEFAULT_LOCALE_RESOURCE, - // tidy-alphabetical-end -]; +pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[]; /// Exit status code used for successful compilation and help output. pub const EXIT_SUCCESS: i32 = 0; diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index 035d8b4903fa..758d2762a6af 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -14,7 +14,6 @@ rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl deleted file mode 100644 index ff771532ae49..000000000000 --- a/compiler/rustc_lint/messages.ftl +++ /dev/null @@ -1,1088 +0,0 @@ -lint_abs_path_with_module = absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition - .suggestion = use `crate` - -lint_ambiguous_glob_reexport = ambiguous glob re-exports - .label_first_reexport = the name `{$name}` in the {$namespace} namespace is first re-exported here - .label_duplicate_reexport = but the name `{$name}` in the {$namespace} namespace is also re-exported here - -lint_ambiguous_negative_literals = `-` has lower precedence than method calls, which might be unexpected - .example = e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` - .negative_literal = add parentheses around the `-` and the literal to call the method on a negative literal - .current_behavior = add parentheses around the literal and the method call to keep the current behavior - -lint_ambiguous_wide_pointer_comparisons = ambiguous wide pointer comparison, the comparison includes metadata which may not be expected - .addr_metadata_suggestion = use explicit `std::ptr::eq` method to compare metadata and addresses - .addr_suggestion = use `std::ptr::addr_eq` or untyped pointers to only compare their addresses - .cast_suggestion = use untyped pointers to only compare their addresses - .expect_suggestion = or expect the lint to compare the pointers metadata and addresses - -lint_associated_const_elided_lifetime = {$elided -> - [true] `&` without an explicit lifetime name cannot be used here - *[false] `'_` cannot be used here - } - .suggestion = use the `'static` lifetime - .note = cannot automatically infer `'static` because of other lifetimes in scope - -lint_async_fn_in_trait = use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified - .note = you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future` - .suggestion = you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send`, but these cannot be relaxed without a breaking API change - -lint_atomic_ordering_fence = memory fences cannot have `Relaxed` ordering - .help = consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst` - -lint_atomic_ordering_invalid = `{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write - .label = invalid failure ordering - .help = consider using `Acquire` or `Relaxed` failure ordering instead - -lint_atomic_ordering_load = atomic loads cannot have `Release` or `AcqRel` ordering - .help = consider using ordering modes `Acquire`, `SeqCst` or `Relaxed` - -lint_atomic_ordering_store = atomic stores cannot have `Acquire` or `AcqRel` ordering - .help = consider using ordering modes `Release`, `SeqCst` or `Relaxed` - -lint_attr_crate_level = - this attribute can only be applied at the crate level - .suggestion = to apply to the crate, use an inner attribute - .note = read for more information - -lint_bad_attribute_argument = bad attribute argument - -lint_bad_opt_access = {$msg} - -lint_break_with_label_and_loop = this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression - .suggestion = wrap this expression in parentheses - -lint_builtin_allow_internal_unsafe = - `allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site - -lint_builtin_anonymous_params = anonymous parameters are deprecated and will be removed in the next edition - .suggestion = try naming the parameter or explicitly ignoring it - -lint_builtin_clashing_extern_diff_name = `{$this}` redeclares `{$orig}` with a different signature - .previous_decl_label = `{$orig}` previously declared here - .mismatch_label = this signature doesn't match the previous declaration - -lint_builtin_clashing_extern_same_name = `{$this}` redeclared with a different signature - .previous_decl_label = `{$orig}` previously declared here - .mismatch_label = this signature doesn't match the previous declaration -lint_builtin_const_no_mangle = const items should never be `#[no_mangle]` - .suggestion = try a static value - -lint_builtin_decl_unsafe_fn = declaration of an `unsafe` function -lint_builtin_decl_unsafe_method = declaration of an `unsafe` method - -lint_builtin_deref_nullptr = dereferencing a null pointer - .label = this code causes undefined behavior when executed - -lint_builtin_double_negations = use of a double negation - .note = the prefix `--` could be misinterpreted as a decrement operator which exists in other languages - .note_decrement = use `-= 1` if you meant to decrement the value - .add_parens_suggestion = add parentheses for clarity - -lint_builtin_ellipsis_inclusive_range_patterns = `...` range patterns are deprecated - .suggestion = use `..=` for an inclusive range - -lint_builtin_explicit_outlives = outlives requirements can be inferred - .suggestion = remove {$count -> - [one] this bound - *[other] these bounds - } - -lint_builtin_export_name_fn = declaration of a function with `export_name` -lint_builtin_export_name_method = declaration of a method with `export_name` -lint_builtin_export_name_static = declaration of a static with `export_name` - -lint_builtin_global_asm = usage of `core::arch::global_asm` -lint_builtin_global_macro_unsafety = using this macro is unsafe even though it does not need an `unsafe` block - -lint_builtin_impl_unsafe_method = implementation of an `unsafe` method - -lint_builtin_incomplete_features = the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes - .note = see issue #{$n} for more information - .help = consider using `min_{$name}` instead, which is more stable and complete - -lint_builtin_internal_features = the feature `{$name}` is internal to the compiler or standard library - .note = using it is strongly discouraged - -lint_builtin_keyword_idents = `{$kw}` is a keyword in the {$next} edition - .suggestion = you can use a raw identifier to stay compatible - -lint_builtin_link_section_fn = declaration of a function with `link_section` - -lint_builtin_link_section_static = declaration of a static with `link_section` - -lint_builtin_missing_copy_impl = type could implement `Copy`; consider adding `impl Copy` - -lint_builtin_missing_debug_impl = - type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation - -lint_builtin_missing_doc = missing documentation for {$article} {$desc} - -lint_builtin_mutable_transmutes = - transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell - -lint_builtin_no_mangle_fn = declaration of a `no_mangle` function -lint_builtin_no_mangle_generic = functions generic over types or consts must be mangled - .suggestion = remove this attribute - -lint_builtin_no_mangle_method = declaration of a `no_mangle` method -lint_builtin_no_mangle_static = declaration of a `no_mangle` static -lint_builtin_non_shorthand_field_patterns = the `{$ident}:` in this pattern is redundant - .suggestion = use shorthand field pattern - -lint_builtin_overridden_symbol_name = - the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them - -lint_builtin_overridden_symbol_section = - the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them - -lint_builtin_special_module_name_used_lib = found module declaration for lib.rs - .note = lib.rs is the root of this crate's library target - .help = to refer to it from other targets, use the library's name as the path - -lint_builtin_special_module_name_used_main = found module declaration for main.rs - .note = a binary crate cannot be used as library - -lint_builtin_trivial_bounds = {$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters - -lint_builtin_type_alias_bounds_enable_feat_help = add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics -lint_builtin_type_alias_bounds_label = will not be checked at usage sites of the type alias -lint_builtin_type_alias_bounds_limitation_note = this is a known limitation of the type checker that may be lifted in a future edition. - see issue #112792 for more information -lint_builtin_type_alias_bounds_param_bounds = bounds on generic parameters in type aliases are not enforced - .suggestion = remove {$count -> - [one] this bound - *[other] these bounds - } -lint_builtin_type_alias_bounds_qualify_assoc_tys_sugg = fully qualify this associated type -lint_builtin_type_alias_bounds_where_clause = where clauses on type aliases are not enforced - .suggestion = remove this where clause - -lint_builtin_unpermitted_type_init_label = this code causes undefined behavior when executed -lint_builtin_unpermitted_type_init_label_suggestion = help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done - -lint_builtin_unpermitted_type_init_uninit = the type `{$ty}` does not permit being left uninitialized - -lint_builtin_unpermitted_type_init_zeroed = the type `{$ty}` does not permit zero-initialization -lint_builtin_unreachable_pub = unreachable `pub` {$what} - .suggestion = consider restricting its visibility - .help = or consider exporting it for use by other crates - -lint_builtin_unsafe_block = usage of an `unsafe` block - -lint_builtin_unsafe_extern_block = usage of an `unsafe extern` block - -lint_builtin_unsafe_impl = implementation of an `unsafe` trait - -lint_builtin_unsafe_trait = declaration of an `unsafe` trait - -lint_builtin_unstable_features = use of an unstable feature - -lint_builtin_unused_doc_comment = unused doc comment - .label = rustdoc does not generate documentation for {$kind} - .plain_help = use `//` for a plain comment - .block_help = use `/* */` for a plain comment - -lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}` - .suggestion = use `loop` - -lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}` - -lint_closure_returning_async_block = closure returning async block can be made into an async closure - .label = this async block can be removed, and the closure can be turned into an async closure - .suggestion = turn this into an async closure - -lint_command_line_source = `forbid` lint level was set on command line - -lint_confusable_identifier_pair = found both `{$existing_sym}` and `{$sym}` as identifiers, which look alike - .current_use = this identifier can be confused with `{$existing_sym}` - .other_use = other identifier used here - -lint_const_item_interior_mutations = - mutation of an interior mutable `const` item with call to `{$method_name}` - .label = `{$const_name}` is a interior mutable `const` item of type `{$const_ty}` - .temporary = each usage of a `const` item creates a new temporary - .never_original = only the temporaries and never the original `const {$const_name}` will be modified - .suggestion_static = for a shared instance of `{$const_name}`, consider making it a `static` item instead - .help = for more details on interior mutability see - -lint_dangling_pointers_from_locals = {$fn_kind} returns a dangling pointer to dropped local variable `{$local_var_name}` - .ret_ty = return type is `{$ret_ty}` - .local_var = local variable `{$local_var_name}` is dropped at the end of the {$fn_kind} - .created_at = dangling pointer created here - .note_safe = a dangling pointer is safe, but dereferencing one is undefined behavior - .note_more_info = for more information, see - -lint_dangling_pointers_from_temporaries = this creates a dangling pointer because temporary `{$ty}` is dropped at end of statement - .label_ptr = pointer created here - .label_temporary = this `{$ty}` is dropped at end of statement - .help_bind = bind the `{$ty}` to a variable such that it outlives the pointer returned by `{$callee}` - .note_safe = a dangling pointer is safe, but dereferencing one is undefined behavior - .note_return = returning a pointer to a local variable will always result in a dangling pointer - .note_more_info = for more information, see - - -lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better performance - .note = a `use rustc_data_structures::fx::{$preferred}` may be necessary - -lint_default_source = `forbid` lint level is the default for {$id} - -lint_deprecated_lint_name = - lint name `{$name}` is deprecated and may not have an effect in the future - .suggestion = change it to - .help = change it to {$replace} - -lint_deprecated_where_clause_location = where clause not allowed here - .note = see issue #89122 for more information - .suggestion_move_to_end = move it to the end of the type declaration - .suggestion_remove_where = remove this `where` - -lint_doc_alias_duplicated = doc alias is duplicated - .label = first defined here - -lint_doc_auto_cfg_expects_hide_or_show = - only `hide` or `show` are allowed in `#[doc(auto_cfg(...))]` - -lint_doc_auto_cfg_hide_show_expects_list = - `#![doc(auto_cfg({$attr_name}(...)))]` expects a list of items - -lint_doc_auto_cfg_hide_show_unexpected_item = - `#![doc(auto_cfg({$attr_name}(...)))]` only accepts identifiers or key/value items - -lint_doc_auto_cfg_wrong_literal = - expected boolean for `#[doc(auto_cfg = ...)]` - -lint_doc_invalid = - invalid `doc` attribute - -lint_doc_test_literal = `#![doc(test(...)]` does not take a literal - -lint_doc_test_takes_list = - `#[doc(test(...)]` takes a list of attributes - -lint_doc_test_unknown = - unknown `doc(test)` attribute `{$name}` - -lint_doc_unknown_any = - unknown `doc` attribute `{$name}` - -lint_doc_unknown_include = - unknown `doc` attribute `include` - .suggestion = use `doc = include_str!` instead - -lint_doc_unknown_passes = - unknown `doc` attribute `{$name}` - .note = `doc` attribute `{$name}` no longer functions; see issue #44136 - .label = no longer functions - .no_op_note = `doc({$name})` is now a no-op - -lint_doc_unknown_plugins = - unknown `doc` attribute `plugins` - .note = `doc` attribute `plugins` no longer functions; see issue #44136 and CVE-2018-1000622 - .label = no longer functions - .no_op_note = `doc(plugins)` is now a no-op - -lint_doc_unknown_spotlight = - unknown `doc` attribute `spotlight` - .note = `doc(spotlight)` was renamed to `doc(notable_trait)` - .suggestion = use `notable_trait` instead - .no_op_note = `doc(spotlight)` is now a no-op - - -lint_drop_glue = - types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped - -lint_drop_trait_constraints = - bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped - -lint_dropping_copy_types = calls to `std::mem::drop` with a value that implements `Copy` does nothing - .label = argument has type `{$arg_ty}` - -lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing - .label = argument has type `{$arg_ty}` - -lint_empty_attribute = - unused attribute - .suggestion = {$valid_without_list -> - [true] remove these parentheses - *[other] remove this attribute - } - .note = {$valid_without_list -> - [true] using `{$attr_path}` with an empty list is equivalent to not using a list at all - *[other] using `{$attr_path}` with an empty list has no effect - } - --lint_previously_accepted = - this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -lint_enum_intrinsics_mem_discriminant = - the return value of `mem::discriminant` is unspecified when called with a non-enum type - .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum - -lint_enum_intrinsics_mem_variant = - the return value of `mem::variant_count` is unspecified when called with a non-enum type - .note = the type parameter of `variant_count` should be an enum, but it was instantiated with the type `{$ty_param}`, which is not an enum - -lint_expectation = this lint expectation is unfulfilled - .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message - .rationale = {$rationale} - -lint_expected_name_value = - expected this to be of the form `... = "..."` - .warn = {-lint_previously_accepted} - -lint_expected_no_args = - didn't expect any arguments here - .warn = {-lint_previously_accepted} - -lint_for_loops_over_fallibles = - for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement - .suggestion = consider using `if let` to clear intent - .remove_next = to iterate over `{$recv_snip}` remove the call to `next` - .use_while_let = to check pattern in a loop use `while let` - .use_question_mark = consider unwrapping the `Result` with `?` to iterate over its contents - -lint_forgetting_copy_types = calls to `std::mem::forget` with a value that implements `Copy` does nothing - .label = argument has type `{$arg_ty}` - -lint_forgetting_references = calls to `std::mem::forget` with a reference instead of an owned value does nothing - .label = argument has type `{$arg_ty}` - -lint_function_casts_as_integer = direct cast of function item into an integer - .cast_as_fn = first cast to a pointer `as *const ()` - -lint_hidden_glob_reexport = private item shadows public glob re-export - .note_glob_reexport = the name `{$name}` in the {$namespace} namespace is supposed to be publicly re-exported here - .note_private_item = but the private item here shadows it - -lint_hidden_lifetime_parameters = hidden lifetime parameters in types are deprecated - -lint_identifier_non_ascii_char = identifier contains non-ASCII characters - -lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len -> - [one] { $identifier_type -> - [Exclusion] a character from an archaic script - [Technical] a character that is for non-linguistic, specialized usage - [Limited_Use] a character from a script in limited use - [Not_NFKC] a non normalized (NFKC) character - *[other] an uncommon character - } - *[other] { $identifier_type -> - [Exclusion] {$codepoints_len} characters from archaic scripts - [Technical] {$codepoints_len} characters that are for non-linguistic, specialized usage - [Limited_Use] {$codepoints_len} characters from scripts in limited use - [Not_NFKC] {$codepoints_len} non normalized (NFKC) characters - *[other] uncommon characters - } -}: {$codepoints} - .note = {$codepoints_len -> - [one] this character is - *[other] these characters are - } included in the{$identifier_type -> - [Restricted] {""} - *[other] {" "}{$identifier_type} - } Unicode general security profile - -lint_if_let_dtor = {$dtor_kind -> - [dyn] value may invoke a custom destructor because it contains a trait object - *[concrete] value invokes this custom destructor - } - -lint_if_let_rescope = `if let` assigns a shorter lifetime since Edition 2024 - .label = this value has a significant drop implementation which may observe a major change in drop order and requires your discretion - .help = the value is now dropped here in Edition 2024 - .suggestion = a `match` with a single arm can preserve the drop order up to Edition 2021 - -lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level - -lint_ill_formed_attribute_input = {$num_suggestions -> - [1] attribute must be of the form {$suggestions} - *[other] valid forms for the attribute are {$suggestions} - } - .note = for more information, visit <{$docs}> - -lint_impl_trait_overcaptures = `{$self_ty}` will capture more lifetimes than possibly intended in edition 2024 - .note = specifically, {$num_captured -> - [one] this lifetime is - *[other] these lifetimes are - } in scope but not mentioned in the type's bounds - .note2 = all lifetimes in scope will be captured by `impl Trait`s in edition 2024 - -lint_impl_trait_redundant_captures = all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - .suggestion = remove the `use<...>` syntax - -lint_implicit_sysroot_crate_import = dangerous use of `extern crate {$name}` which is not guaranteed to exist exactly once in the sysroot - .help = try using a cargo dependency or using a re-export of the dependency provided by a rustc_* crate - -lint_implicit_unsafe_autorefs = implicit autoref creates a reference to the dereference of a raw pointer - .note = creating a reference requires the pointer target to be valid and imposes aliasing requirements - .raw_ptr = this raw pointer has type `{$raw_ptr_ty}` - .autoref = autoref is being applied to this expression, resulting in: `{$autoref_ty}` - .overloaded_deref = references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations - .method_def = method calls to `{$method_name}` require a reference - .suggestion = try using a raw pointer method instead; or if this reference is intentional, make it explicit - -lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe - .label = not FFI-safe - .note = the type is defined here - -lint_improper_ctypes_array_help = consider passing a pointer to the array - -lint_improper_ctypes_array_reason = passing raw arrays by value is not FFI-safe -lint_improper_ctypes_box = box cannot be represented as a single pointer - -lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead - -lint_improper_ctypes_char_reason = the `char` type has no C equivalent - -lint_improper_ctypes_cstr_help = - consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()` -lint_improper_ctypes_cstr_reason = `CStr`/`CString` do not have a guaranteed layout - -lint_improper_ctypes_dyn = trait objects have no C equivalent - -lint_improper_ctypes_enum_repr_help = - consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum - -lint_improper_ctypes_enum_repr_reason = enum has no representation hint -lint_improper_ctypes_fnptr_help = consider using an `extern fn(...) -> ...` function pointer instead - -lint_improper_ctypes_fnptr_reason = this function pointer has Rust-specific calling convention -lint_improper_ctypes_non_exhaustive = this enum is non-exhaustive -lint_improper_ctypes_non_exhaustive_variant = this enum has non-exhaustive variants - -lint_improper_ctypes_only_phantomdata = composed only of `PhantomData` - -lint_improper_ctypes_opaque = opaque types have no C equivalent - -lint_improper_ctypes_slice_help = consider using a raw pointer instead - -lint_improper_ctypes_slice_reason = slices have no C equivalent -lint_improper_ctypes_str_help = consider using `*const u8` and a length instead - -lint_improper_ctypes_str_reason = string slices have no C equivalent -lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct - -lint_improper_ctypes_struct_fieldless_reason = this struct has no fields -lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct - -lint_improper_ctypes_struct_layout_reason = this struct has unspecified layout -lint_improper_ctypes_struct_non_exhaustive = this struct is non-exhaustive -lint_improper_ctypes_struct_zst = this struct contains only zero-sized fields - -lint_improper_ctypes_tuple_help = consider using a struct instead - -lint_improper_ctypes_tuple_reason = tuples have unspecified layout -lint_improper_ctypes_union_fieldless_help = consider adding a member to this union - -lint_improper_ctypes_union_fieldless_reason = this union has no fields -lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union - -lint_improper_ctypes_union_layout_reason = this union has unspecified layout -lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive - -lint_improper_ctypes_unsafe_binder = unsafe binders are incompatible with foreign function interfaces - -lint_improper_gpu_kernel_arg = passing type `{$ty}` to a function with "gpu-kernel" ABI may have unexpected behavior - .help = use primitive types and raw pointers to get reliable behavior - -lint_incorrect_do_not_recommend_args = - `#[diagnostic::do_not_recommend]` does not expect any arguments - -lint_int_to_ptr_transmutes = transmuting an integer to a pointer creates a pointer without provenance - .note = this is dangerous because dereferencing the resulting pointer is undefined behavior - .note_exposed_provenance = exposed provenance semantics can be used to create a pointer based on some previously exposed provenance - .help_transmute = for more information about transmute, see - .help_exposed_provenance = for more information about exposed provenance, see - .suggestion_with_exposed_provenance = use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance - .suggestion_without_provenance_mut = if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` - -lint_invalid_asm_label_binary = avoid using labels containing only the digits `0` and `1` in inline assembly - .label = use a different label that doesn't start with `0` or `1` - .help = start numbering with `2` instead - .note1 = an LLVM bug makes these labels ambiguous with a binary literal number on x86 - .note2 = see for more information - -lint_invalid_asm_label_format_arg = avoid using named labels in inline assembly - .help = only local labels of the form `:` should be used in inline asm - .note1 = format arguments may expand to a non-numeric value - .note2 = see the asm section of Rust By Example for more information -lint_invalid_asm_label_named = avoid using named labels in inline assembly - .help = only local labels of the form `:` should be used in inline asm - .note = see the asm section of Rust By Example for more information -lint_invalid_asm_label_no_span = the label may be declared in the expansion of a macro - -lint_invalid_crate_type_value = invalid `crate_type` value - .suggestion = did you mean - -# FIXME: we should ordinalize $valid_up_to when we add support for doing so -lint_invalid_from_utf8_checked = calls to `{$method}` with an invalid literal always return an error - .label = the literal was valid UTF-8 up to the {$valid_up_to} bytes - -# FIXME: we should ordinalize $valid_up_to when we add support for doing so -lint_invalid_from_utf8_unchecked = calls to `{$method}` with an invalid literal are undefined behavior - .label = the literal was valid UTF-8 up to the {$valid_up_to} bytes - -lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be directly compared to itself - .suggestion = use `f32::is_nan()` or `f64::is_nan()` instead - -lint_invalid_nan_comparisons_lt_le_gt_ge = incorrect NaN comparison, NaN is not orderable - -lint_invalid_null_arguments = calling this function with a null pointer is undefined behavior, even if the result of the function is unused - .origin = null pointer originates from here - .doc = for more information, visit and - -lint_invalid_reference_casting_assign_to_ref = assigning to `&T` is undefined behavior, consider using an `UnsafeCell` - .label = casting happened here - -lint_invalid_reference_casting_bigger_layout = casting references to a bigger memory layout than the backing allocation is undefined behavior, even if the reference is unused - .label = casting happened here - .alloc = backing allocation comes from here - .layout = casting from `{$from_ty}` ({$from_size} bytes) to `{$to_ty}` ({$to_size} bytes) - -lint_invalid_reference_casting_borrow_as_mut = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` - .label = casting happened here - -lint_invalid_reference_casting_note_book = for more information, visit - -lint_invalid_reference_casting_note_ty_has_interior_mutability = even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get` - -lint_invalid_style = {$is_used_as_inner -> - [false] crate-level attribute should be an inner attribute: add an exclamation mark: `#![{$name}]` - *[other] the `#![{$name}]` attribute can only be used at the crate root - } - .note = this attribute does not have an `!`, which means it is applied to this {$target} - -lint_invalid_target = `#[{$name}]` attribute cannot be used on {$target} - .warn = {-lint_previously_accepted} - .help = `#[{$name}]` can {$only}be applied to {$applied} - .suggestion = remove the attribute - -lint_lintpass_by_hand = implementing `LintPass` by hand - .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead - -lint_macro_expr_fragment_specifier_2024_migration = - the `expr` fragment specifier will accept more expressions in the 2024 edition - .suggestion = to keep the existing behavior, use the `expr_2021` fragment specifier - -lint_malformed_attribute = malformed lint attribute input - -lint_malformed_doc = - malformed `doc` attribute input - .warn = {-lint_previously_accepted} - -lint_map_unit_fn = `Iterator::map` call that discard the iterator's values - .note = `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated - .function_label = this function returns `()`, which is likely not what you wanted - .argument_label = called `Iterator::map` with callable that returns `()` - .map_label = after this call to map, the resulting iterator is `impl Iterator`, which means the only information carried by the iterator is the number of items - .suggestion = you might have meant to use `Iterator::for_each` - -lint_mismatched_lifetime_syntaxes_eliding_while_named = - eliding a lifetime that's named elsewhere is confusing - -lint_mismatched_lifetime_syntaxes_help = - the same lifetime is referred to in inconsistent ways, making the signature confusing - -lint_mismatched_lifetime_syntaxes_hiding_and_eliding_while_named = - hiding or eliding a lifetime that's named elsewhere is confusing - -lint_mismatched_lifetime_syntaxes_hiding_while_elided = - hiding a lifetime that's elided elsewhere is confusing - -lint_mismatched_lifetime_syntaxes_hiding_while_named = - hiding a lifetime that's named elsewhere is confusing - -lint_mismatched_lifetime_syntaxes_input_elided = - the lifetime is elided here - -lint_mismatched_lifetime_syntaxes_input_hidden = - the lifetime is hidden here - -lint_mismatched_lifetime_syntaxes_input_named = - the lifetime is named here - -lint_mismatched_lifetime_syntaxes_output_elided = - the same lifetime is elided here - -lint_mismatched_lifetime_syntaxes_output_hidden = - the same lifetime is hidden here - -lint_mismatched_lifetime_syntaxes_output_named = - the same lifetime is named here - -lint_mismatched_lifetime_syntaxes_suggestion_explicit = - consistently use `{$lifetime_name}` - -lint_mismatched_lifetime_syntaxes_suggestion_implicit = - remove the lifetime name from references - -lint_mismatched_lifetime_syntaxes_suggestion_mixed = - remove the lifetime name from references and use `'_` for type paths - -lint_mismatched_lifetime_syntaxes_suggestion_mixed_only_paths = - use `'_` for type paths - -lint_missing_gpu_kernel_export_name = function with the "gpu-kernel" ABI has a mangled name - .note = mangled names make it hard to find the kernel, this is usually not intended - .help = use `unsafe(no_mangle)` or `unsafe(export_name = "")` - -lint_mixed_script_confusables = - the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables - .includes_note = the usage includes {$includes} - .note = please recheck to make sure their usages are indeed what you want - -lint_multiple_supertrait_upcastable = `{$ident}` is dyn-compatible and has multiple supertraits - -lint_named_argument_used_positionally = named argument `{$named_arg_name}` is not used by name - .label_named_arg = this named argument is referred to by position in formatting string - .label_position_arg = this formatting argument uses named argument `{$named_arg_name}` by position - .suggestion = use the named argument by name to avoid ambiguity - -lint_node_source = `forbid` level set here - .note = {$reason} - -lint_non_binding_let_multi_drop_fn = - consider immediately dropping the value using `drop(..)` after the `let` statement - -lint_non_binding_let_multi_suggestion = - consider immediately dropping the value - -lint_non_binding_let_on_drop_type = - non-binding let on a type that has a destructor - -lint_non_binding_let_on_sync_lock = non-binding let on a synchronization lock - .label = this lock is not assigned to a binding and is immediately dropped - -lint_non_binding_let_suggestion = - consider binding to an unused variable to avoid immediately dropping the value - -lint_non_camel_case_type = {$sort} `{$name}` should have an upper camel case name - .suggestion = convert the identifier to upper camel case - .label = should have an UpperCamelCase name - -lint_non_fmt_panic = panic message is not a string literal - .note = this usage of `{$name}!()` is deprecated; it will be a hard error in Rust 2021 - .more_info_note = for more information, see - .supports_fmt_note = the `{$name}!()` macro supports formatting, so there's no need for the `format!()` macro here - .supports_fmt_suggestion = remove the `format!(..)` macro call - .display_suggestion = add a "{"{"}{"}"}" format string to `Display` the message - .debug_suggestion = - add a "{"{"}:?{"}"}" format string to use the `Debug` implementation of `{$ty}` - .panic_suggestion = {$already_suggested -> - [true] or use - *[false] use - } std::panic::panic_any instead - -lint_non_fmt_panic_braces = - panic message contains {$count -> - [one] a brace - *[other] braces - } - .note = this message is not used as a format string, but will be in Rust 2021 - .suggestion = add a "{"{"}{"}"}" format string to use the message literally - -lint_non_fmt_panic_unused = - panic message contains {$count -> - [one] an unused - *[other] unused - } formatting {$count -> - [one] placeholder - *[other] placeholders - } - .note = this message is not used as a format string when given without arguments, but will be in Rust 2021 - .add_args_suggestion = add the missing {$count -> - [one] argument - *[other] arguments - } - .add_fmt_suggestion = or add a "{"{"}{"}"}" format string to use the message literally - -lint_non_glob_import_type_ir_inherent = non-glob import of `rustc_type_ir::inherent` - .suggestion = try using a glob import instead - -lint_non_local_definitions_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}` - -lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks should be written at the same level as their item - .non_local = an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - .doctest = make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}` - .exception = items in an anonymous const item (`const _: () = {"{"} ... {"}"}`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint - .const_anon = use a const-anon item to suppress this lint - .macro_to_change = the {$macro_kind} `{$macro_to_change}` defines the non-local `impl`, and may need to be changed - -lint_non_local_definitions_impl_move_help = - move the `impl` block outside of this {$body_kind_descr} {$depth -> - [one] `{$body_name}` - *[other] `{$body_name}` and up {$depth} bodies - } - -lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module - .help = - remove the `#[macro_export]` or move this `macro_rules!` outside the of the current {$body_kind_descr} {$depth -> - [one] `{$body_name}` - *[other] `{$body_name}` and up {$depth} bodies - } - .help_doctest = - remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}` - .non_local = a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - -lint_non_snake_case = {$sort} `{$name}` should have a snake case name - .rename_or_convert_suggestion = rename the identifier or convert it to a snake case raw identifier - .cannot_convert_note = `{$sc}` cannot be used as a raw identifier - .rename_suggestion = rename the identifier - .convert_suggestion = convert the identifier to snake case - .help = convert the identifier to snake case: `{$sc}` - .label = should have a snake_case name - -lint_non_upper_case_global = {$sort} `{$name}` should have an upper case name - .suggestion = convert the identifier to upper case - .label = should have an UPPER_CASE name - -lint_noop_method_call = call to `.{$method}()` on a reference in this situation does nothing - .suggestion = remove this redundant call - .note = the type `{$orig_ty}` does not implement `{$trait_}`, so calling `{$method}` on `&{$orig_ty}` copies the reference, which does not do anything and can be removed - .derive_suggestion = if you meant to clone `{$orig_ty}`, implement `Clone` for it - -lint_only_cast_u8_to_char = only `u8` can be cast into `char` - .suggestion = use a `char` literal instead - -lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its associated type bounds - .specifically = this associated type bound is unsatisfied for `{$proj_ty}` - -lint_opaque_hidden_inferred_bound_sugg = add this bound - -lint_overflowing_bin_hex = literal out of range for `{$ty}` - .negative_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` - .negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}` - .positive_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` and will become `{$actually}{$ty}` - .suggestion = consider using the type `{$suggestion_ty}` instead - .sign_bit_suggestion = to use as a negative number (decimal `{$negative_val}`), consider using the type `{$uint_ty}` for the literal and cast it to `{$int_ty}` - .help = consider using the type `{$suggestion_ty}` instead - -lint_overflowing_int = literal out of range for `{$ty}` - .note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}` - .help = consider using the type `{$suggestion_ty}` instead - -lint_overflowing_literal = literal out of range for `{$ty}` - .note = the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY` - -lint_overflowing_uint = literal out of range for `{$ty}` - .note = the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}` - -lint_overruled_attribute = {$lint_level}({$lint_source}) incompatible with previous forbid - .label = overruled by previous forbid - -lint_pass_by_value = passing `{$ty}` by reference - .suggestion = try passing by value - -lint_path_statement_drop = path statement drops value - .suggestion = use `drop` to clarify the intent - -lint_path_statement_no_effect = path statement with no effect - -lint_pattern_in_bodiless = patterns aren't allowed in functions without bodies - .label = pattern not allowed in function without body - -lint_pattern_in_foreign = patterns aren't allowed in foreign function declarations - .label = pattern not allowed in foreign function - -lint_query_instability = using `{$query}` can result in unstable query results - .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale - -lint_query_untracked = `{$method}` accesses information that is not tracked by the query system - .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale - -lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}` - -lint_range_use_inclusive_range = use an inclusive range instead - - -lint_raw_prefix = prefix `'r` is reserved - .label = reserved prefix - .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 - -lint_reason_must_be_string_literal = reason must be a string literal - -lint_reason_must_come_last = reason in lint attribute must come last - -lint_redundant_import = the item `{$ident}` is imported redundantly - .label_imported_here = the item `{$ident}` is already imported here - .label_defined_here = the item `{$ident}` is already defined here - .label_imported_prelude = the item `{$ident}` is already imported by the extern prelude - .label_defined_prelude = the item `{$ident}` is already defined by the extern prelude - -lint_redundant_semicolons = - unnecessary trailing {$multiple -> - [true] semicolons - *[false] semicolon - } - -lint_redundant_semicolons_suggestion = remove {$multiple_semicolons -> - [true] these semicolons - *[false] this semicolon - } - -lint_remove_mut_from_pattern = remove `mut` from the parameter - -lint_removed_lint = lint `{$name}` has been removed: {$reason} - -lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}` - .suggestion = use the new name - .help = use the new name `{$replace}` - -lint_requested_level = requested on the command line with `{$level} {$lint_name}` - -lint_reserved_multihash = reserved token in Rust 2024 - .suggestion = insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024 - -lint_reserved_prefix = prefix `{$prefix}` is unknown - .label = unknown prefix - .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 - -lint_reserved_string = will be parsed as a guarded string in Rust 2024 - .suggestion = insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 - -lint_shadowed_into_iter = - this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition} - .use_iter_suggestion = use `.iter()` instead of `.into_iter()` to avoid ambiguity - .remove_into_iter_suggestion = or remove `.into_iter()` to iterate by value - .use_explicit_into_iter_suggestion = - or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value - -lint_single_use_lifetime = lifetime parameter `{$ident}` only used once - .label_param = this lifetime... - .label_use = ...is used only here - .suggestion = elide the single-use lifetime - -lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()` - -lint_static_mut_refs_lint = creating a {$shared_label}reference to mutable static - .label = {$shared_label}reference to mutable static - .suggestion = use `&raw const` instead to create a raw pointer - .suggestion_mut = use `&raw mut` instead to create a raw pointer - .shared_note = shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives - .mut_note = mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives - -lint_supertrait_as_deref_target = this `Deref` implementation is covered by an implicit supertrait coercion - .label = `{$self_ty}` implements `Deref` which conflicts with supertrait `{$supertrait_principal}` - .label2 = target type is a supertrait of `{$self_ty}` - .help = consider removing this implementation or replacing it with a method instead - -lint_surrogate_char_cast = surrogate values are not valid for `char` - .note = `0xD800..=0xDFFF` are reserved for Unicode surrogates and are not valid `char` values - -lint_suspicious_double_ref_clone = - using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type - -lint_suspicious_double_ref_deref = - using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type - -lint_symbol_intern_string_literal = using `Symbol::intern` on a string literal - .help = consider adding the symbol to `compiler/rustc_span/src/symbol.rs` - -lint_too_large_char_cast = value exceeds maximum `char` value - .note = maximum valid `char` value is `0x10FFFF` - -lint_ty_qualified = usage of qualified `ty::{$ty}` - .suggestion = try importing it and using it unqualified - -lint_tykind = usage of `ty::TyKind` - .help = try using `Ty` instead - -lint_tykind_kind = usage of `ty::TyKind::` - .suggestion = try using `ty::` directly - -lint_type_ir_direct_use = do not use `rustc_type_ir` unless you are implementing type system internals - .note = use `rustc_middle::ty` instead - -lint_type_ir_inherent_usage = do not use `rustc_type_ir::inherent` unless you're inside of the trait solver - .note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler - -lint_type_ir_trait_usage = do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver - .note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler - -lint_undefined_transmute = pointers cannot be transmuted to integers during const eval - .note = at compile-time, pointers do not have an integer value - .note2 = avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior - .help = for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html - -lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing - .label = argument has type `{$arg_ty}` - .suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value - -lint_unexpected_cfg_add_build_rs_println = or consider adding `{$build_rs_println}` to the top of the `build.rs` -lint_unexpected_cfg_add_cargo_feature = consider using a Cargo feature instead -lint_unexpected_cfg_add_cargo_toml_lint_cfg = or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:{$cargo_toml_lint_cfg} -lint_unexpected_cfg_add_cmdline_arg = to expect this configuration use `{$cmdline_arg}` -lint_unexpected_cfg_boolean = you may have meant to use `{$literal}` (notice the capitalization). Doing so makes this predicate evaluate to `{$literal}` unconditionally -lint_unexpected_cfg_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}` - -lint_unexpected_cfg_define_features = consider defining some features in `Cargo.toml` -lint_unexpected_cfg_doc_cargo = see for more information about checking conditional configuration -lint_unexpected_cfg_doc_rustc = see for more information about checking conditional configuration - -lint_unexpected_cfg_from_external_macro_origin = using a cfg inside a {$macro_kind} will use the cfgs from the destination crate and not the ones from the defining crate -lint_unexpected_cfg_from_external_macro_refer = try referring to `{$macro_name}` crate for guidance on how handle this unexpected cfg -lint_unexpected_cfg_name = unexpected `cfg` condition name: `{$name}` -lint_unexpected_cfg_name_expected_names = expected names are: {$possibilities}{$and_more -> - [0] {""} - *[other] {" "}and {$and_more} more - } -lint_unexpected_cfg_name_expected_values = expected values for `{$best_match}` are: {$possibilities} -lint_unexpected_cfg_name_similar_name = there is a config with a similar name -lint_unexpected_cfg_name_similar_name_different_values = there is a config with a similar name and different values -lint_unexpected_cfg_name_similar_name_no_value = there is a config with a similar name and no value -lint_unexpected_cfg_name_similar_name_value = there is a config with a similar name and value -lint_unexpected_cfg_name_version_syntax = there is a similar config predicate: `version("..")` -lint_unexpected_cfg_name_with_similar_value = found config with similar value - -lint_unexpected_cfg_value = unexpected `cfg` condition value: {$has_value -> - [true] `{$value}` - *[false] (none) - } -lint_unexpected_cfg_value_add_feature = consider adding `{$value}` as a feature in `Cargo.toml` -lint_unexpected_cfg_value_expected_values = expected values for `{$name}` are: {$have_none_possibility -> - [true] {"(none), "} - *[false] {""} - }{$possibilities}{$and_more -> - [0] {""} - *[other] {" "}and {$and_more} more - } -lint_unexpected_cfg_value_no_expected_value = no expected value for `{$name}` -lint_unexpected_cfg_value_no_expected_values = no expected values for `{$name}` -lint_unexpected_cfg_value_remove_condition = remove the condition -lint_unexpected_cfg_value_remove_value = remove the value -lint_unexpected_cfg_value_similar_name = there is a expected value with a similar name -lint_unexpected_cfg_value_specify_value = specify a config value - -lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op - .label = this function will not propagate the caller location - -lint_unicode_text_flow = unicode codepoint changing visible direction of text present in comment - .label = {$num_codepoints -> - [1] this comment contains an invisible unicode text flow control codepoint - *[other] this comment contains invisible unicode text flow control codepoints - } - .note = these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen - .suggestion = if their presence wasn't intentional, you can remove them - .label_comment_char = {$c_debug} - - -lint_unit_bindings = binding has unit type `()` - .label = this pattern is inferred to be the unit type `()` - -lint_unknown_gated_lint = - unknown lint: `{$name}` - .note = the `{$name}` lint is unstable - -lint_unknown_lint = - unknown lint: `{$name}` - .suggestion = {$from_rustc -> - [true] a lint with a similar name exists in `rustc` lints - *[false] did you mean - } - .help = {$from_rustc -> - [true] a lint with a similar name exists in `rustc` lints: `{$replace}` - *[false] did you mean: `{$replace}` - } - -lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}` - .help = add `#![register_tool({$tool_name})]` to the crate root - -lint_unnecessary_qualification = unnecessary qualification - .suggestion = remove the unnecessary path segments - -lint_unpredictable_fn_pointer_comparisons = function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique - .note_duplicated_fn = the address of the same function can vary between different codegen units - .note_deduplicated_fn = furthermore, different functions could have the same address after being merged together - .note_visit_fn_addr_eq = for more information visit - .fn_addr_eq_suggestion = refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint - -lint_unqualified_local_imports = `use` of a local item without leading `self::`, `super::`, or `crate::` - -lint_unreachable_cfg_select_predicate = unreachable configuration predicate - .label = this configuration predicate is never reached - -lint_unreachable_cfg_select_predicate_wildcard = unreachable configuration predicate - .label = always matches - .label2 = this configuration predicate is never reached - -lint_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe - .label = usage of unsafe attribute -lint_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)` - -lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´ - -lint_unused_allocation = unnecessary allocation, use `&` instead -lint_unused_allocation_mut = unnecessary allocation, use `&mut` instead - -lint_unused_closure = - unused {$pre}{$count -> - [one] closure - *[other] closures - }{$post} that must be used - .note = closures are lazy and do nothing unless called - -lint_unused_comparisons = comparison is useless due to type limits - -lint_unused_coroutine = - unused {$pre}{$count -> - [one] coroutine - *[other] coroutine - }{$post} that must be used - .note = coroutines are lazy and do nothing unless resumed - -lint_unused_crate_dependency = extern crate `{$extern_crate}` is unused in crate `{$local_crate}` - .help = remove the dependency or add `use {$extern_crate} as _;` to the crate root - -lint_unused_def = unused {$pre}`{$def}`{$post} that must be used - .suggestion = use `let _ = ...` to ignore the resulting value - -lint_unused_delim = unnecessary {$delim} around {$item} - .suggestion = remove these {$delim} - -lint_unused_duplicate = - unused attribute - .suggestion = remove this attribute - .note = attribute also specified here - .warn = {-lint_previously_accepted} - -lint_unused_import_braces = braces around {$node} is unnecessary - -lint_unused_imports = {$num_snippets -> - [one] unused import: {$span_snippets} - *[other] unused imports: {$span_snippets} - } - .suggestion_remove_whole_use = remove the whole `use` item - .suggestion_remove_imports = {$num_to_remove -> - [one] remove the unused import - *[other] remove the unused imports - } - .help = if this is a test module, consider adding a `#[cfg(test)]` to the containing module - -lint_unused_lifetime = lifetime parameter `{$ident}` never used - .suggestion = elide the unused lifetime - -lint_unused_op = unused {$op} that must be used - .label = the {$op} produces a value - .suggestion = use `let _ = ...` to ignore the resulting value - -lint_unused_result = unused result of type `{$ty}` - -lint_unused_visibilities = visibility qualifiers have no effect on `const _` declarations - .note = `const _` does not declare a name, so there is nothing for the qualifier to apply to - .suggestion = remove the qualifier - -lint_use_let_underscore_ignore_suggestion = use `let _ = ...` to ignore the expression or result - -lint_useless_ptr_null_checks_fn_ptr = function pointers are not nullable, so checking them for null will always return false - .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value - .label = expression has type `{$orig_ty}` - -lint_useless_ptr_null_checks_fn_ret = returned pointer of `{$fn_name}` call is never null, so checking it for null will always return false - -lint_useless_ptr_null_checks_ref = references are not nullable, so checking them for null will always return false - .label = expression has type `{$orig_ty}` - -lint_uses_power_alignment = repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type - -lint_variant_size_differences = - enum variant is more than three times larger ({$largest} bytes) than the next largest diff --git a/compiler/rustc_lint/src/async_closures.rs b/compiler/rustc_lint/src/async_closures.rs index 02fb22bf782e..0d3a954667f7 100644 --- a/compiler/rustc_lint/src/async_closures.rs +++ b/compiler/rustc_lint/src/async_closures.rs @@ -108,16 +108,18 @@ impl<'tcx> LateLintPass<'tcx> for AsyncClosureUsage { } #[derive(LintDiagnostic)] -#[diag(lint_closure_returning_async_block)] +#[diag("closure returning async block can be made into an async closure")] struct ClosureReturningAsyncBlock { - #[label] + #[label( + "this async block can be removed, and the closure can be turned into an async closure" + )] async_decl_span: Span, #[subdiagnostic] sugg: AsyncClosureSugg, } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion("turn this into an async closure", applicability = "maybe-incorrect")] struct AsyncClosureSugg { #[suggestion_part(code = "")] deletion_span: Span, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index e2a061cab680..ef21b3f573be 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -22,7 +22,7 @@ use rustc_ast::visit::{FnCtxt, FnKind}; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust::expr_to_string; use rustc_attr_parsing::AttributeParser; -use rustc_errors::{Applicability, LintDiagnostic}; +use rustc_errors::{Applicability, LintDiagnostic, inline_fluent}; use rustc_feature::GateIssue; use rustc_hir as hir; use rustc_hir::attrs::{AttributeKind, DocAttribute}; @@ -61,10 +61,7 @@ use crate::lints::{ BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel, }; -use crate::{ - EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext, - fluent_generated as fluent, -}; +use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext}; declare_lint! { /// The `while_true` lint detects `while true { }`. /// @@ -2655,8 +2652,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { let conjured_ty = cx.typeck_results().expr_ty(expr); if let Some(err) = with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init)) { let msg = match init { - InitKind::Zeroed => fluent::lint_builtin_unpermitted_type_init_zeroed, - InitKind::Uninit => fluent::lint_builtin_unpermitted_type_init_uninit, + InitKind::Zeroed => { + inline_fluent!("the type `{$ty}` does not permit zero-initialization") + } + InitKind::Uninit => { + inline_fluent!("the type `{$ty}` does not permit being left uninitialized") + } }; let sub = BuiltinUnpermittedTypeInitSub { err }; cx.emit_span_lint( diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 8f2f3594161a..b0154bed1a51 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -1,17 +1,15 @@ use rustc_errors::codes::*; -use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic}; +use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic, inline_fluent}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::lint::Level; use rustc_span::{Span, Symbol}; -use crate::fluent_generated as fluent; - #[derive(Diagnostic)] -#[diag(lint_overruled_attribute, code = E0453)] +#[diag("{$lint_level}({$lint_source}) incompatible with previous forbid", code = E0453)] pub(crate) struct OverruledAttribute<'a> { #[primary_span] pub span: Span, - #[label] + #[label("overruled by previous forbid")] pub overruled: Span, pub lint_level: &'a str, pub lint_source: Symbol, @@ -29,24 +27,24 @@ impl Subdiagnostic for OverruledAttributeSub { fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { OverruledAttributeSub::DefaultSource { id } => { - diag.note(fluent::lint_default_source); + diag.note(inline_fluent!("`forbid` lint level is the default for {$id}")); diag.arg("id", id); } OverruledAttributeSub::NodeSource { span, reason } => { - diag.span_label(span, fluent::lint_node_source); + diag.span_label(span, inline_fluent!("`forbid` level set here")); if let Some(rationale) = reason { diag.note(rationale.to_string()); } } OverruledAttributeSub::CommandLineSource => { - diag.note(fluent::lint_command_line_source); + diag.note(inline_fluent!("`forbid` lint level was set on command line")); } } } } #[derive(Diagnostic)] -#[diag(lint_malformed_attribute, code = E0452)] +#[diag("malformed lint attribute input", code = E0452)] pub(crate) struct MalformedAttribute { #[primary_span] pub span: Span, @@ -56,50 +54,55 @@ pub(crate) struct MalformedAttribute { #[derive(Subdiagnostic)] pub(crate) enum MalformedAttributeSub { - #[label(lint_bad_attribute_argument)] + #[label("bad attribute argument")] BadAttributeArgument(#[primary_span] Span), - #[label(lint_reason_must_be_string_literal)] + #[label("reason must be a string literal")] ReasonMustBeStringLiteral(#[primary_span] Span), - #[label(lint_reason_must_come_last)] + #[label("reason in lint attribute must come last")] ReasonMustComeLast(#[primary_span] Span), } #[derive(Diagnostic)] -#[diag(lint_unknown_tool_in_scoped_lint, code = E0710)] +#[diag("unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`", code = E0710)] pub(crate) struct UnknownToolInScopedLint { #[primary_span] pub span: Option, pub tool_name: Symbol, pub lint_name: String, - #[help] + #[help("add `#![register_tool({$tool_name})]` to the crate root")] pub is_nightly_build: bool, } #[derive(Diagnostic)] -#[diag(lint_builtin_ellipsis_inclusive_range_patterns, code = E0783)] +#[diag("`...` range patterns are deprecated", code = E0783)] pub(crate) struct BuiltinEllipsisInclusiveRangePatterns { #[primary_span] pub span: Span, - #[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")] + #[suggestion( + "use `..=` for an inclusive range", + style = "short", + code = "{replace}", + applicability = "machine-applicable" + )] pub suggestion: Span, pub replace: String, } #[derive(Subdiagnostic)] -#[note(lint_requested_level)] +#[note("requested on the command line with `{$level} {$lint_name}`")] pub(crate) struct RequestedLevel<'a> { pub level: Level, pub lint_name: &'a str, } #[derive(Diagnostic)] -#[diag(lint_unsupported_group, code = E0602)] +#[diag("`{$lint_group}` lint group is not supported with ´--force-warn´", code = E0602)] pub(crate) struct UnsupportedGroup { pub lint_group: String, } #[derive(Diagnostic)] -#[diag(lint_check_name_unknown_tool, code = E0602)] +#[diag("unknown lint tool: `{$tool_name}`", code = E0602)] pub(crate) struct CheckNameUnknownTool<'a> { pub tool_name: Symbol, #[subdiagnostic] diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 612d542a27de..8569070a43ca 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -3,7 +3,9 @@ use std::ops::ControlFlow; use hir::intravisit::{self, Visitor}; use rustc_ast::Recovered; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic, SuggestionStyle}; +use rustc_errors::{ + Applicability, Diag, EmissionGuarantee, Subdiagnostic, SuggestionStyle, inline_fluent, +}; use rustc_hir::{self as hir, HirIdSet}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::adjustment::Adjust; @@ -303,13 +305,15 @@ impl<'tcx> LateLintPass<'tcx> for IfLetRescope { } #[derive(LintDiagnostic)] -#[diag(lint_if_let_rescope)] +#[diag("`if let` assigns a shorter lifetime since Edition 2024")] struct IfLetRescopeLint { #[subdiagnostic] destructors: Vec, - #[label] + #[label( + "this value has a significant drop implementation which may observe a major change in drop order and requires your discretion" + )] significant_droppers: Vec, - #[help] + #[help("the value is now dropped here in Edition 2024")] lifetime_ends: Vec, #[subdiagnostic] rewrite: Option, @@ -352,7 +356,9 @@ impl Subdiagnostic for IfLetRescopeRewrite { .chain(repeat_n('}', closing_brackets.count)) .collect(), )); - let msg = diag.eagerly_translate(crate::fluent_generated::lint_suggestion); + let msg = diag.eagerly_translate(inline_fluent!( + "a `match` with a single arm can preserve the drop order up to Edition 2021" + )); diag.multipart_suggestion_with_style( msg, suggestions, @@ -363,7 +369,12 @@ impl Subdiagnostic for IfLetRescopeRewrite { } #[derive(Subdiagnostic)] -#[note(lint_if_let_dtor)] +#[note( + "{$dtor_kind -> + [dyn] value may invoke a custom destructor because it contains a trait object + *[concrete] value invokes this custom destructor + }" +)] struct DestructorLabel { #[primary_span] span: Span, diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 1cdc5e4a1b36..087403719968 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -3,7 +3,7 @@ use std::cell::LazyCell; use rustc_data_structures::debug_assert_matches; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordSet; -use rustc_errors::{LintDiagnostic, Subdiagnostic}; +use rustc_errors::{LintDiagnostic, Subdiagnostic, inline_fluent}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -28,7 +28,7 @@ use rustc_trait_selection::errors::{ use rustc_trait_selection::regions::OutlivesEnvironmentBuildExt; use rustc_trait_selection::traits::ObligationCtxt; -use crate::{LateContext, LateLintPass, fluent_generated as fluent}; +use crate::{LateContext, LateLintPass}; declare_lint! { /// The `impl_trait_overcaptures` lint warns against cases where lifetime @@ -435,11 +435,23 @@ struct ImplTraitOvercapturesLint<'tcx> { impl<'a> LintDiagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) { - diag.primary_message(fluent::lint_impl_trait_overcaptures); + diag.primary_message(inline_fluent!( + "`{$self_ty}` will capture more lifetimes than possibly intended in edition 2024" + )); diag.arg("self_ty", self.self_ty.to_string()) .arg("num_captured", self.num_captured) - .span_note(self.uncaptured_spans, fluent::lint_note) - .note(fluent::lint_note2); + .span_note( + self.uncaptured_spans, + inline_fluent!( + "specifically, {$num_captured -> + [one] this lifetime is + *[other] these lifetimes are + } in scope but not mentioned in the type's bounds" + ), + ) + .note(inline_fluent!( + "all lifetimes in scope will be captured by `impl Trait`s in edition 2024" + )); if let Some(suggestion) = self.suggestion { suggestion.add_to_diag(diag); } @@ -447,9 +459,9 @@ impl<'a> LintDiagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> { } #[derive(LintDiagnostic)] -#[diag(lint_impl_trait_redundant_captures)] +#[diag("all possible in-scope parameters are already captured, so `use<...>` syntax is redundant")] struct ImplTraitRedundantCapturesLint { - #[suggestion(lint_suggestion, code = "", applicability = "machine-applicable")] + #[suggestion("remove the `use<...>` syntax", code = "", applicability = "machine-applicable")] capturing_span: Span, } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 57dacbc11e05..cebe1a5dc373 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -2,7 +2,7 @@ use rustc_ast::attr::AttributeExt; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::unord::UnordSet; -use rustc_errors::{Diag, LintDiagnostic, MultiSpan}; +use rustc_errors::{Diag, LintDiagnostic, MultiSpan, inline_fluent}; use rustc_feature::{Features, GateIssue}; use rustc_hir::HirId; use rustc_hir::intravisit::{self, Visitor}; @@ -31,7 +31,6 @@ use crate::errors::{ CheckNameUnknownTool, MalformedAttribute, MalformedAttributeSub, OverruledAttribute, OverruledAttributeSub, RequestedLevel, UnknownToolInScopedLint, UnsupportedGroup, }; -use crate::fluent_generated as fluent; use crate::late::unerased_lint_store; use crate::lints::{ DeprecatedLintName, DeprecatedLintNameFromCommandLine, IgnoredUnlessCrateSpecified, @@ -942,9 +941,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let lint = builtin::UNKNOWN_LINTS; let level = self.lint_level(builtin::UNKNOWN_LINTS); lint_level(self.sess, lint, level, Some(span.into()), |lint| { - lint.primary_message(fluent::lint_unknown_gated_lint); + lint.primary_message(inline_fluent!("unknown lint: `{$name}`")); lint.arg("name", lint_id.lint.name_lower()); - lint.note(fluent::lint_note); + lint.note(inline_fluent!("the `{$name}` lint is unstable")); rustc_session::parse::add_feature_diagnostics_for_issue( lint, &self.sess, diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index ea31a6373cbc..93b6f1491041 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -139,8 +139,6 @@ pub use rustc_errors::BufferedEarlyLint; pub use rustc_session::lint::Level::{self, *}; pub use rustc_session::lint::{FutureIncompatibleInfo, Lint, LintId, LintPass, LintVec}; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - pub fn provide(providers: &mut Providers) { levels::provide(providers); expect::provide(providers); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index bdc171f11e3b..0aa5199cffc6 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -5,7 +5,7 @@ use std::num::NonZero; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, ElidedLifetimeInPathSubdiag, - EmissionGuarantee, LintDiagnostic, MultiSpan, Subdiagnostic, SuggestionStyle, + EmissionGuarantee, LintDiagnostic, MultiSpan, Subdiagnostic, SuggestionStyle, inline_fluent, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -17,18 +17,24 @@ use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::{Ident, Span, Symbol, sym}; +use crate::LateContext; use crate::builtin::{InitError, ShorthandAssocTyCollector, TypeAliasBounds}; use crate::errors::{OverruledAttributeSub, RequestedLevel}; use crate::lifetime_syntax::LifetimeSyntaxCategories; -use crate::{LateContext, fluent_generated as fluent}; // array_into_iter.rs #[derive(LintDiagnostic)] -#[diag(lint_shadowed_into_iter)] +#[diag( + "this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition}" +)] pub(crate) struct ShadowedIntoIterDiag { pub target: &'static str, pub edition: &'static str, - #[suggestion(lint_use_iter_suggestion, code = "iter", applicability = "machine-applicable")] + #[suggestion( + "use `.iter()` instead of `.into_iter()` to avoid ambiguity", + code = "iter", + applicability = "machine-applicable" + )] pub suggestion: Span, #[subdiagnostic] pub sub: Option, @@ -36,13 +42,17 @@ pub(crate) struct ShadowedIntoIterDiag { #[derive(Subdiagnostic)] pub(crate) enum ShadowedIntoIterDiagSub { - #[suggestion(lint_remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")] + #[suggestion( + "or remove `.into_iter()` to iterate by value", + code = "", + applicability = "maybe-incorrect" + )] RemoveIntoIter { #[primary_span] span: Span, }, #[multipart_suggestion( - lint_use_explicit_into_iter_suggestion, + "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value", applicability = "maybe-incorrect" )] UseExplicitIntoIter { @@ -55,10 +65,12 @@ pub(crate) enum ShadowedIntoIterDiagSub { // autorefs.rs #[derive(LintDiagnostic)] -#[diag(lint_implicit_unsafe_autorefs)] -#[note] +#[diag("implicit autoref creates a reference to the dereference of a raw pointer")] +#[note( + "creating a reference requires the pointer target to be valid and imposes aliasing requirements" +)] pub(crate) struct ImplicitUnsafeAutorefsDiag<'a> { - #[label(lint_raw_ptr)] + #[label("this raw pointer has type `{$raw_ptr_ty}`")] pub raw_ptr_span: Span, pub raw_ptr_ty: Ty<'a>, #[subdiagnostic] @@ -71,18 +83,20 @@ pub(crate) struct ImplicitUnsafeAutorefsDiag<'a> { #[derive(Subdiagnostic)] pub(crate) enum ImplicitUnsafeAutorefsOrigin<'a> { - #[note(lint_autoref)] + #[note("autoref is being applied to this expression, resulting in: `{$autoref_ty}`")] Autoref { #[primary_span] autoref_span: Span, autoref_ty: Ty<'a>, }, - #[note(lint_overloaded_deref)] + #[note( + "references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations" + )] OverloadedDeref, } #[derive(Subdiagnostic)] -#[note(lint_method_def)] +#[note("method calls to `{$method_name}` require a reference")] pub(crate) struct ImplicitUnsafeAutorefsMethodNote { #[primary_span] pub def_span: Span, @@ -90,7 +104,10 @@ pub(crate) struct ImplicitUnsafeAutorefsMethodNote { } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "try using a raw pointer method instead; or if this reference is intentional, make it explicit", + applicability = "maybe-incorrect" +)] pub(crate) struct ImplicitUnsafeAutorefsSuggestion { pub mutbl: &'static str, pub deref: &'static str, @@ -102,78 +119,105 @@ pub(crate) struct ImplicitUnsafeAutorefsSuggestion { // builtin.rs #[derive(LintDiagnostic)] -#[diag(lint_builtin_while_true)] +#[diag("denote infinite loops with `loop {\"{\"} ... {\"}\"}`")] pub(crate) struct BuiltinWhileTrue { - #[suggestion(style = "short", code = "{replace}", applicability = "machine-applicable")] + #[suggestion( + "use `loop`", + style = "short", + code = "{replace}", + applicability = "machine-applicable" + )] pub suggestion: Span, pub replace: String, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_non_shorthand_field_patterns)] +#[diag("the `{$ident}:` in this pattern is redundant")] pub(crate) struct BuiltinNonShorthandFieldPatterns { pub ident: Ident, - #[suggestion(code = "{prefix}{ident}", applicability = "machine-applicable")] + #[suggestion( + "use shorthand field pattern", + code = "{prefix}{ident}", + applicability = "machine-applicable" + )] pub suggestion: Span, pub prefix: &'static str, } #[derive(LintDiagnostic)] pub(crate) enum BuiltinUnsafe { - #[diag(lint_builtin_allow_internal_unsafe)] + #[diag( + "`allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site" + )] AllowInternalUnsafe, - #[diag(lint_builtin_unsafe_block)] + #[diag("usage of an `unsafe` block")] UnsafeBlock, - #[diag(lint_builtin_unsafe_extern_block)] + #[diag("usage of an `unsafe extern` block")] UnsafeExternBlock, - #[diag(lint_builtin_unsafe_trait)] + #[diag("declaration of an `unsafe` trait")] UnsafeTrait, - #[diag(lint_builtin_unsafe_impl)] + #[diag("implementation of an `unsafe` trait")] UnsafeImpl, - #[diag(lint_builtin_no_mangle_fn)] - #[note(lint_builtin_overridden_symbol_name)] + #[diag("declaration of a `no_mangle` function")] + #[note( + "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" + )] NoMangleFn, - #[diag(lint_builtin_export_name_fn)] - #[note(lint_builtin_overridden_symbol_name)] + #[diag("declaration of a function with `export_name`")] + #[note( + "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" + )] ExportNameFn, - #[diag(lint_builtin_link_section_fn)] - #[note(lint_builtin_overridden_symbol_section)] + #[diag("declaration of a function with `link_section`")] + #[note( + "the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them" + )] LinkSectionFn, - #[diag(lint_builtin_no_mangle_static)] - #[note(lint_builtin_overridden_symbol_name)] + #[diag("declaration of a `no_mangle` static")] + #[note( + "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" + )] NoMangleStatic, - #[diag(lint_builtin_export_name_static)] - #[note(lint_builtin_overridden_symbol_name)] + #[diag("declaration of a static with `export_name`")] + #[note( + "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" + )] ExportNameStatic, - #[diag(lint_builtin_link_section_static)] - #[note(lint_builtin_overridden_symbol_section)] + #[diag("declaration of a static with `link_section`")] + #[note( + "the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them" + )] LinkSectionStatic, - #[diag(lint_builtin_no_mangle_method)] - #[note(lint_builtin_overridden_symbol_name)] + #[diag("declaration of a `no_mangle` method")] + #[note( + "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" + )] NoMangleMethod, - #[diag(lint_builtin_export_name_method)] - #[note(lint_builtin_overridden_symbol_name)] + #[diag("declaration of a method with `export_name`")] + #[note( + "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them" + )] ExportNameMethod, - #[diag(lint_builtin_decl_unsafe_fn)] + #[diag("declaration of an `unsafe` function")] DeclUnsafeFn, - #[diag(lint_builtin_decl_unsafe_method)] + #[diag("declaration of an `unsafe` method")] DeclUnsafeMethod, - #[diag(lint_builtin_impl_unsafe_method)] + #[diag("implementation of an `unsafe` method")] ImplUnsafeMethod, - #[diag(lint_builtin_global_asm)] - #[note(lint_builtin_global_macro_unsafety)] + #[diag("usage of `core::arch::global_asm`")] + #[note("using this macro is unsafe even though it does not need an `unsafe` block")] GlobalAsm, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_missing_doc)] +#[diag("missing documentation for {$article} {$desc}")] pub(crate) struct BuiltinMissingDoc<'a> { pub article: &'a str, pub desc: &'a str, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_missing_copy_impl)] +#[diag("type could implement `Copy`; consider adding `impl Copy`")] pub(crate) struct BuiltinMissingCopyImpl; pub(crate) struct BuiltinMissingDebugImpl<'a> { @@ -184,24 +228,24 @@ pub(crate) struct BuiltinMissingDebugImpl<'a> { // Needed for def_path_str impl<'a> LintDiagnostic<'a, ()> for BuiltinMissingDebugImpl<'_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) { - diag.primary_message(fluent::lint_builtin_missing_debug_impl); + diag.primary_message(inline_fluent!("type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation")); diag.arg("debug", self.tcx.def_path_str(self.def_id)); } } #[derive(LintDiagnostic)] -#[diag(lint_builtin_anonymous_params)] +#[diag("anonymous parameters are deprecated and will be removed in the next edition")] pub(crate) struct BuiltinAnonymousParams<'a> { - #[suggestion(code = "_: {ty_snip}")] + #[suggestion("try naming the parameter or explicitly ignoring it", code = "_: {ty_snip}")] pub suggestion: (Span, Applicability), pub ty_snip: &'a str, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_unused_doc_comment)] +#[diag("unused doc comment")] pub(crate) struct BuiltinUnusedDocComment<'a> { pub kind: &'a str, - #[label] + #[label("rustdoc does not generate documentation for {$kind}")] pub label: Span, #[subdiagnostic] pub sub: BuiltinUnusedDocCommentSub, @@ -209,34 +253,41 @@ pub(crate) struct BuiltinUnusedDocComment<'a> { #[derive(Subdiagnostic)] pub(crate) enum BuiltinUnusedDocCommentSub { - #[help(lint_plain_help)] + #[help("use `//` for a plain comment")] PlainHelp, - #[help(lint_block_help)] + #[help("use `/* */` for a plain comment")] BlockHelp, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_no_mangle_generic)] +#[diag("functions generic over types or consts must be mangled")] pub(crate) struct BuiltinNoMangleGeneric { // Use of `#[no_mangle]` suggests FFI intent; correct // fix may be to monomorphize source by hand - #[suggestion(style = "short", code = "", applicability = "maybe-incorrect")] + #[suggestion( + "remove this attribute", + style = "short", + code = "", + applicability = "maybe-incorrect" + )] pub suggestion: Span, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_const_no_mangle)] +#[diag("const items should never be `#[no_mangle]`")] pub(crate) struct BuiltinConstNoMangle { - #[suggestion(code = "pub static ", applicability = "machine-applicable")] + #[suggestion("try a static value", code = "pub static ", applicability = "machine-applicable")] pub suggestion: Option, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_mutable_transmutes)] +#[diag( + "transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell" +)] pub(crate) struct BuiltinMutablesTransmutes; #[derive(LintDiagnostic)] -#[diag(lint_builtin_unstable_features)] +#[diag("use of an unstable feature")] pub(crate) struct BuiltinUnstableFeatures; // lint_ungated_async_fn_track_caller @@ -247,8 +298,11 @@ pub(crate) struct BuiltinUngatedAsyncFnTrackCaller<'a> { impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(fluent::lint_ungated_async_fn_track_caller); - diag.span_label(self.label, fluent::lint_label); + diag.primary_message(inline_fluent!("`#[track_caller]` on async functions is a no-op")); + diag.span_label( + self.label, + inline_fluent!("this function will not propagate the caller location"), + ); rustc_session::parse::add_feature_diagnostics( diag, self.session, @@ -258,20 +312,24 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { } #[derive(LintDiagnostic)] -#[diag(lint_builtin_unreachable_pub)] +#[diag("unreachable `pub` {$what}")] pub(crate) struct BuiltinUnreachablePub<'a> { pub what: &'a str, pub new_vis: &'a str, - #[suggestion(code = "{new_vis}")] + #[suggestion("consider restricting its visibility", code = "{new_vis}")] pub suggestion: (Span, Applicability), - #[help] + #[help("or consider exporting it for use by other crates")] pub help: bool, } #[derive(LintDiagnostic)] -#[diag(lint_macro_expr_fragment_specifier_2024_migration)] +#[diag("the `expr` fragment specifier will accept more expressions in the 2024 edition")] pub(crate) struct MacroExprFragment2024 { - #[suggestion(code = "expr_2021", applicability = "machine-applicable")] + #[suggestion( + "to keep the existing behavior, use the `expr_2021` fragment specifier", + code = "expr_2021", + applicability = "machine-applicable" + )] pub suggestion: Span, } @@ -287,14 +345,18 @@ pub(crate) struct BuiltinTypeAliasBounds<'hir> { impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { diag.primary_message(if self.in_where_clause { - fluent::lint_builtin_type_alias_bounds_where_clause + inline_fluent!("where clauses on type aliases are not enforced") } else { - fluent::lint_builtin_type_alias_bounds_param_bounds + inline_fluent!("bounds on generic parameters in type aliases are not enforced") }); - diag.span_label(self.label, fluent::lint_builtin_type_alias_bounds_label); - diag.note(fluent::lint_builtin_type_alias_bounds_limitation_note); + diag.span_label( + self.label, + inline_fluent!("will not be checked at usage sites of the type alias"), + ); + diag.note(inline_fluent!("this is a known limitation of the type checker that may be lifted in a future edition. + see issue #112792 for more information")); if self.enable_feat_help { - diag.help(fluent::lint_builtin_type_alias_bounds_enable_feat_help); + diag.help(inline_fluent!("add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics")); } // We perform the walk in here instead of in `` to @@ -319,7 +381,20 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { }; diag.arg("count", self.suggestions.len()); - diag.multipart_suggestion(fluent::lint_suggestion, self.suggestions, applicability); + diag.multipart_suggestion( + if self.in_where_clause { + inline_fluent!("remove this where clause") + } else { + inline_fluent!( + "remove {$count -> + [one] this bound + *[other] these bounds + }" + ) + }, + self.suggestions, + applicability, + ); // Suggest fully qualifying paths of the form `T::Assoc` with `T` type param via // `::Assoc` to remove their reliance on any type param bounds. @@ -333,7 +408,7 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { // (We could employ some simple heuristics but that's likely not worth it). for qself in collector.qselves { diag.multipart_suggestion( - fluent::lint_builtin_type_alias_bounds_qualify_assoc_tys_sugg, + inline_fluent!("fully qualify this associated type"), vec![ (qself.shrink_to_lo(), "<".into()), (qself.shrink_to_hi(), " as /* Trait */>".into()), @@ -345,23 +420,27 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { } #[derive(LintDiagnostic)] -#[diag(lint_builtin_trivial_bounds)] +#[diag( + "{$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters" +)] pub(crate) struct BuiltinTrivialBounds<'a> { pub predicate_kind_name: &'a str, pub predicate: Clause<'a>, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_double_negations)] -#[note(lint_note)] -#[note(lint_note_decrement)] +#[diag("use of a double negation")] +#[note( + "the prefix `--` could be misinterpreted as a decrement operator which exists in other languages" +)] +#[note("use `-= 1` if you meant to decrement the value")] pub(crate) struct BuiltinDoubleNegations { #[subdiagnostic] pub add_parens: BuiltinDoubleNegationsAddParens, } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_add_parens_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion("add parentheses for clarity", applicability = "maybe-incorrect")] pub(crate) struct BuiltinDoubleNegationsAddParens { #[suggestion_part(code = "(")] pub start_span: Span, @@ -371,31 +450,44 @@ pub(crate) struct BuiltinDoubleNegationsAddParens { #[derive(LintDiagnostic)] pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint { - #[diag(lint_builtin_ellipsis_inclusive_range_patterns)] + #[diag("`...` range patterns are deprecated")] Parenthesise { - #[suggestion(code = "{replace}", applicability = "machine-applicable")] + #[suggestion( + "use `..=` for an inclusive range", + code = "{replace}", + applicability = "machine-applicable" + )] suggestion: Span, replace: String, }, - #[diag(lint_builtin_ellipsis_inclusive_range_patterns)] + #[diag("`...` range patterns are deprecated")] NonParenthesise { - #[suggestion(style = "short", code = "..=", applicability = "machine-applicable")] + #[suggestion( + "use `..=` for an inclusive range", + style = "short", + code = "..=", + applicability = "machine-applicable" + )] suggestion: Span, }, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_keyword_idents)] +#[diag("`{$kw}` is a keyword in the {$next} edition")] pub(crate) struct BuiltinKeywordIdents { pub kw: Ident, pub next: Edition, - #[suggestion(code = "{prefix}r#{kw}", applicability = "machine-applicable")] + #[suggestion( + "you can use a raw identifier to stay compatible", + code = "{prefix}r#{kw}", + applicability = "machine-applicable" + )] pub suggestion: Span, pub prefix: &'static str, } #[derive(LintDiagnostic)] -#[diag(lint_builtin_explicit_outlives)] +#[diag("outlives requirements can be inferred")] pub(crate) struct BuiltinExplicitOutlives { pub count: usize, #[subdiagnostic] @@ -403,7 +495,12 @@ pub(crate) struct BuiltinExplicitOutlives { } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion)] +#[multipart_suggestion( + "remove {$count -> + [one] this bound + *[other] these bounds + }" +)] pub(crate) struct BuiltinExplicitOutlivesSuggestion { #[suggestion_part(code = "")] pub spans: Vec, @@ -412,7 +509,9 @@ pub(crate) struct BuiltinExplicitOutlivesSuggestion { } #[derive(LintDiagnostic)] -#[diag(lint_builtin_incomplete_features)] +#[diag( + "the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes" +)] pub(crate) struct BuiltinIncompleteFeatures { pub name: Symbol, #[subdiagnostic] @@ -422,18 +521,18 @@ pub(crate) struct BuiltinIncompleteFeatures { } #[derive(LintDiagnostic)] -#[diag(lint_builtin_internal_features)] -#[note] +#[diag("the feature `{$name}` is internal to the compiler or standard library")] +#[note("using it is strongly discouraged")] pub(crate) struct BuiltinInternalFeatures { pub name: Symbol, } #[derive(Subdiagnostic)] -#[help(lint_help)] +#[help("consider using `min_{$name}` instead, which is more stable and complete")] pub(crate) struct BuiltinIncompleteFeaturesHelp; #[derive(Subdiagnostic)] -#[note(lint_note)] +#[note("see issue #{$n} for more information")] pub(crate) struct BuiltinFeatureIssueNote { pub n: NonZero, } @@ -450,12 +549,15 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { diag.primary_message(self.msg); diag.arg("ty", self.ty); - diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label); + diag.span_label( + self.label, + inline_fluent!("this code causes undefined behavior when executed"), + ); if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) { // Only suggest late `MaybeUninit::assume_init` initialization if the type is inhabited. diag.span_label( self.label, - fluent::lint_builtin_unpermitted_type_init_label_suggestion, + inline_fluent!("help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done"), ); } self.sub.add_to_diag(diag); @@ -487,24 +589,24 @@ impl Subdiagnostic for BuiltinUnpermittedTypeInitSub { #[derive(LintDiagnostic)] pub(crate) enum BuiltinClashingExtern<'a> { - #[diag(lint_builtin_clashing_extern_same_name)] + #[diag("`{$this}` redeclared with a different signature")] SameName { this: Symbol, orig: Symbol, - #[label(lint_previous_decl_label)] + #[label("`{$orig}` previously declared here")] previous_decl_label: Span, - #[label(lint_mismatch_label)] + #[label("this signature doesn't match the previous declaration")] mismatch_label: Span, #[subdiagnostic] sub: BuiltinClashingExternSub<'a>, }, - #[diag(lint_builtin_clashing_extern_diff_name)] + #[diag("`{$this}` redeclares `{$orig}` with a different signature")] DiffName { this: Symbol, orig: Symbol, - #[label(lint_previous_decl_label)] + #[label("`{$orig}` previously declared here")] previous_decl_label: Span, - #[label(lint_mismatch_label)] + #[label("this signature doesn't match the previous declaration")] mismatch_label: Span, #[subdiagnostic] sub: BuiltinClashingExternSub<'a>, @@ -529,9 +631,9 @@ impl Subdiagnostic for BuiltinClashingExternSub<'_> { } #[derive(LintDiagnostic)] -#[diag(lint_builtin_deref_nullptr)] +#[diag("dereferencing a null pointer")] pub(crate) struct BuiltinDerefNullptr { - #[label] + #[label("this code causes undefined behavior when executed")] pub label: Span, } @@ -539,30 +641,32 @@ pub(crate) struct BuiltinDerefNullptr { #[derive(LintDiagnostic)] pub(crate) enum BuiltinSpecialModuleNameUsed { - #[diag(lint_builtin_special_module_name_used_lib)] - #[note] - #[help] + #[diag("found module declaration for lib.rs")] + #[note("lib.rs is the root of this crate's library target")] + #[help("to refer to it from other targets, use the library's name as the path")] Lib, - #[diag(lint_builtin_special_module_name_used_main)] - #[note] + #[diag("found module declaration for main.rs")] + #[note("a binary crate cannot be used as library")] Main, } // deref_into_dyn_supertrait.rs #[derive(LintDiagnostic)] -#[diag(lint_supertrait_as_deref_target)] +#[diag("this `Deref` implementation is covered by an implicit supertrait coercion")] pub(crate) struct SupertraitAsDerefTarget<'a> { pub self_ty: Ty<'a>, pub supertrait_principal: PolyExistentialTraitRef<'a>, pub target_principal: PolyExistentialTraitRef<'a>, - #[label] + #[label( + "`{$self_ty}` implements `Deref` which conflicts with supertrait `{$supertrait_principal}`" + )] pub label: Span, #[subdiagnostic] pub label2: Option, } #[derive(Subdiagnostic)] -#[label(lint_label2)] +#[label("target type is a supertrait of `{$self_ty}`")] pub(crate) struct SupertraitAsDerefTargetLabel { #[primary_span] pub label: Span, @@ -570,32 +674,38 @@ pub(crate) struct SupertraitAsDerefTargetLabel { // enum_intrinsics_non_enums.rs #[derive(LintDiagnostic)] -#[diag(lint_enum_intrinsics_mem_discriminant)] +#[diag("the return value of `mem::discriminant` is unspecified when called with a non-enum type")] pub(crate) struct EnumIntrinsicsMemDiscriminate<'a> { pub ty_param: Ty<'a>, - #[note] + #[note( + "the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum" + )] pub note: Span, } #[derive(LintDiagnostic)] -#[diag(lint_enum_intrinsics_mem_variant)] -#[note] +#[diag("the return value of `mem::variant_count` is unspecified when called with a non-enum type")] +#[note( + "the type parameter of `variant_count` should be an enum, but it was instantiated with the type `{$ty_param}`, which is not an enum" +)] pub(crate) struct EnumIntrinsicsMemVariant<'a> { pub ty_param: Ty<'a>, } // expect.rs #[derive(LintDiagnostic)] -#[diag(lint_expectation)] +#[diag("this lint expectation is unfulfilled")] pub(crate) struct Expectation { #[subdiagnostic] pub rationale: Option, - #[note] + #[note( + "the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message" + )] pub note: bool, } #[derive(Subdiagnostic)] -#[note(lint_rationale)] +#[note("{$rationale}")] pub(crate) struct ExpectationNote { pub rationale: Symbol, } @@ -603,42 +713,58 @@ pub(crate) struct ExpectationNote { // ptr_nulls.rs #[derive(LintDiagnostic)] pub(crate) enum UselessPtrNullChecksDiag<'a> { - #[diag(lint_useless_ptr_null_checks_fn_ptr)] - #[help] + #[diag( + "function pointers are not nullable, so checking them for null will always return false" + )] + #[help( + "wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value" + )] FnPtr { orig_ty: Ty<'a>, - #[label] + #[label("expression has type `{$orig_ty}`")] label: Span, }, - #[diag(lint_useless_ptr_null_checks_ref)] + #[diag("references are not nullable, so checking them for null will always return false")] Ref { orig_ty: Ty<'a>, - #[label] + #[label("expression has type `{$orig_ty}`")] label: Span, }, - #[diag(lint_useless_ptr_null_checks_fn_ret)] + #[diag( + "returned pointer of `{$fn_name}` call is never null, so checking it for null will always return false" + )] FnRet { fn_name: Ident }, } #[derive(LintDiagnostic)] pub(crate) enum InvalidNullArgumentsDiag { - #[diag(lint_invalid_null_arguments)] - #[help(lint_doc)] + #[diag( + "calling this function with a null pointer is undefined behavior, even if the result of the function is unused" + )] + #[help( + "for more information, visit and " + )] NullPtrInline { - #[label(lint_origin)] + #[label("null pointer originates from here")] null_span: Span, }, - #[diag(lint_invalid_null_arguments)] - #[help(lint_doc)] + #[diag( + "calling this function with a null pointer is undefined behavior, even if the result of the function is unused" + )] + #[help( + "for more information, visit and " + )] NullPtrThroughBinding { - #[note(lint_origin)] + #[note("null pointer originates from here")] null_span: Span, }, } // for_loops_over_fallibles.rs #[derive(LintDiagnostic)] -#[diag(lint_for_loops_over_fallibles)] +#[diag( + "for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement" +)] pub(crate) struct ForLoopsOverFalliblesDiag<'a> { pub article: &'static str, pub ref_prefix: &'static str, @@ -653,13 +779,20 @@ pub(crate) struct ForLoopsOverFalliblesDiag<'a> { #[derive(Subdiagnostic)] pub(crate) enum ForLoopsOverFalliblesLoopSub<'a> { - #[suggestion(lint_remove_next, code = ".by_ref()", applicability = "maybe-incorrect")] + #[suggestion( + "to iterate over `{$recv_snip}` remove the call to `next`", + code = ".by_ref()", + applicability = "maybe-incorrect" + )] RemoveNext { #[primary_span] suggestion: Span, recv_snip: String, }, - #[multipart_suggestion(lint_use_while_let, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "to check pattern in a loop use `while let`", + applicability = "maybe-incorrect" + )] UseWhileLet { #[suggestion_part(code = "while let {var}(")] start_span: Span, @@ -670,14 +803,21 @@ pub(crate) enum ForLoopsOverFalliblesLoopSub<'a> { } #[derive(Subdiagnostic)] -#[suggestion(lint_use_question_mark, code = "?", applicability = "maybe-incorrect")] +#[suggestion( + "consider unwrapping the `Result` with `?` to iterate over its contents", + code = "?", + applicability = "maybe-incorrect" +)] pub(crate) struct ForLoopsOverFalliblesQuestionMark { #[primary_span] pub suggestion: Span, } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "consider using `if let` to clear intent", + applicability = "maybe-incorrect" +)] pub(crate) struct ForLoopsOverFalliblesSuggestion<'a> { pub var: &'a str, #[suggestion_part(code = "if let {var}(")] @@ -688,10 +828,10 @@ pub(crate) struct ForLoopsOverFalliblesSuggestion<'a> { #[derive(Subdiagnostic)] pub(crate) enum UseLetUnderscoreIgnoreSuggestion { - #[note(lint_use_let_underscore_ignore_suggestion)] + #[note("use `let _ = ...` to ignore the expression or result")] Note, #[multipart_suggestion( - lint_use_let_underscore_ignore_suggestion, + "use `let _ = ...` to ignore the expression or result", style = "verbose", applicability = "maybe-incorrect" )] @@ -705,57 +845,62 @@ pub(crate) enum UseLetUnderscoreIgnoreSuggestion { // drop_forget_useless.rs #[derive(LintDiagnostic)] -#[diag(lint_dropping_references)] +#[diag("calls to `std::mem::drop` with a reference instead of an owned value does nothing")] pub(crate) struct DropRefDiag<'a> { pub arg_ty: Ty<'a>, - #[label] + #[label("argument has type `{$arg_ty}`")] pub label: Span, #[subdiagnostic] pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] -#[diag(lint_dropping_copy_types)] +#[diag("calls to `std::mem::drop` with a value that implements `Copy` does nothing")] pub(crate) struct DropCopyDiag<'a> { pub arg_ty: Ty<'a>, - #[label] + #[label("argument has type `{$arg_ty}`")] pub label: Span, #[subdiagnostic] pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] -#[diag(lint_forgetting_references)] +#[diag("calls to `std::mem::forget` with a reference instead of an owned value does nothing")] pub(crate) struct ForgetRefDiag<'a> { pub arg_ty: Ty<'a>, - #[label] + #[label("argument has type `{$arg_ty}`")] pub label: Span, #[subdiagnostic] pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] -#[diag(lint_forgetting_copy_types)] +#[diag("calls to `std::mem::forget` with a value that implements `Copy` does nothing")] pub(crate) struct ForgetCopyDiag<'a> { pub arg_ty: Ty<'a>, - #[label] + #[label("argument has type `{$arg_ty}`")] pub label: Span, #[subdiagnostic] pub sugg: UseLetUnderscoreIgnoreSuggestion, } #[derive(LintDiagnostic)] -#[diag(lint_undropped_manually_drops)] +#[diag( + "calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing" +)] pub(crate) struct UndroppedManuallyDropsDiag<'a> { pub arg_ty: Ty<'a>, - #[label] + #[label("argument has type `{$arg_ty}`")] pub label: Span, #[subdiagnostic] pub suggestion: UndroppedManuallyDropsSuggestion, } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion( + "use `std::mem::ManuallyDrop::into_inner` to get the inner value", + applicability = "machine-applicable" +)] pub(crate) struct UndroppedManuallyDropsSuggestion { #[suggestion_part(code = "std::mem::ManuallyDrop::into_inner(")] pub start_span: Span, @@ -766,33 +911,35 @@ pub(crate) struct UndroppedManuallyDropsSuggestion { // invalid_from_utf8.rs #[derive(LintDiagnostic)] pub(crate) enum InvalidFromUtf8Diag { - #[diag(lint_invalid_from_utf8_unchecked)] + #[diag("calls to `{$method}` with an invalid literal are undefined behavior")] Unchecked { method: String, valid_up_to: usize, - #[label] + #[label("the literal was valid UTF-8 up to the {$valid_up_to} bytes")] label: Span, }, - #[diag(lint_invalid_from_utf8_checked)] + #[diag("calls to `{$method}` with an invalid literal always return an error")] Checked { method: String, valid_up_to: usize, - #[label] + #[label("the literal was valid UTF-8 up to the {$valid_up_to} bytes")] label: Span, }, } // interior_mutable_consts.rs #[derive(LintDiagnostic)] -#[diag(lint_const_item_interior_mutations)] -#[note(lint_temporary)] -#[note(lint_never_original)] -#[help] +#[diag("mutation of an interior mutable `const` item with call to `{$method_name}`")] +#[note("each usage of a `const` item creates a new temporary")] +#[note("only the temporaries and never the original `const {$const_name}` will be modified")] +#[help( + "for more details on interior mutability see " +)] pub(crate) struct ConstItemInteriorMutationsDiag<'tcx> { pub method_name: Ident, pub const_name: Ident, pub const_ty: Ty<'tcx>, - #[label] + #[label("`{$const_name}` is a interior mutable `const` item of type `{$const_ty}`")] pub receiver_span: Span, #[subdiagnostic] pub sugg_static: Option, @@ -801,7 +948,7 @@ pub(crate) struct ConstItemInteriorMutationsDiag<'tcx> { #[derive(Subdiagnostic)] pub(crate) enum ConstItemInteriorMutationsSuggestionStatic { #[suggestion( - lint_suggestion_static, + "for a shared instance of `{$const_name}`, consider making it a `static` item instead", code = "{before}static ", style = "verbose", applicability = "maybe-incorrect" @@ -811,35 +958,47 @@ pub(crate) enum ConstItemInteriorMutationsSuggestionStatic { const_: Span, before: &'static str, }, - #[help(lint_suggestion_static)] + #[help("for a shared instance of `{$const_name}`, consider making it a `static` item instead")] Spanless, } // reference_casting.rs #[derive(LintDiagnostic)] pub(crate) enum InvalidReferenceCastingDiag<'tcx> { - #[diag(lint_invalid_reference_casting_borrow_as_mut)] - #[note(lint_invalid_reference_casting_note_book)] + #[diag( + "casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`" + )] + #[note( + "for more information, visit " + )] BorrowAsMut { - #[label] + #[label("casting happened here")] orig_cast: Option, - #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)] + #[note( + "even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get`" + )] ty_has_interior_mutability: bool, }, - #[diag(lint_invalid_reference_casting_assign_to_ref)] - #[note(lint_invalid_reference_casting_note_book)] + #[diag("assigning to `&T` is undefined behavior, consider using an `UnsafeCell`")] + #[note( + "for more information, visit " + )] AssignToRef { - #[label] + #[label("casting happened here")] orig_cast: Option, - #[note(lint_invalid_reference_casting_note_ty_has_interior_mutability)] + #[note( + "even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get`" + )] ty_has_interior_mutability: bool, }, - #[diag(lint_invalid_reference_casting_bigger_layout)] - #[note(lint_layout)] + #[diag( + "casting references to a bigger memory layout than the backing allocation is undefined behavior, even if the reference is unused" + )] + #[note("casting from `{$from_ty}` ({$from_size} bytes) to `{$to_ty}` ({$to_size} bytes)")] BiggerLayout { - #[label] + #[label("casting happened here")] orig_cast: Option, - #[label(lint_alloc)] + #[label("backing allocation comes from here")] alloc: Span, from_ty: Ty<'tcx>, from_size: u64, @@ -850,108 +1009,143 @@ pub(crate) enum InvalidReferenceCastingDiag<'tcx> { // map_unit_fn.rs #[derive(LintDiagnostic)] -#[diag(lint_map_unit_fn)] -#[note] +#[diag("`Iterator::map` call that discard the iterator's values")] +#[note( + "`Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated" +)] pub(crate) struct MappingToUnit { - #[label(lint_function_label)] + #[label("this function returns `()`, which is likely not what you wanted")] pub function_label: Span, - #[label(lint_argument_label)] + #[label("called `Iterator::map` with callable that returns `()`")] pub argument_label: Span, - #[label(lint_map_label)] + #[label( + "after this call to map, the resulting iterator is `impl Iterator`, which means the only information carried by the iterator is the number of items" + )] pub map_label: Span, - #[suggestion(style = "verbose", code = "for_each", applicability = "maybe-incorrect")] + #[suggestion( + "you might have meant to use `Iterator::for_each`", + style = "verbose", + code = "for_each", + applicability = "maybe-incorrect" + )] pub suggestion: Span, } // internal.rs #[derive(LintDiagnostic)] -#[diag(lint_default_hash_types)] -#[note] +#[diag("prefer `{$preferred}` over `{$used}`, it has better performance")] +#[note("a `use rustc_data_structures::fx::{$preferred}` may be necessary")] pub(crate) struct DefaultHashTypesDiag<'a> { pub preferred: &'a str, pub used: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_query_instability)] -#[note] +#[diag("using `{$query}` can result in unstable query results")] +#[note( + "if you believe this case to be fine, allow this lint and add a comment explaining your rationale" +)] pub(crate) struct QueryInstability { pub query: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_query_untracked)] -#[note] +#[diag("`{$method}` accesses information that is not tracked by the query system")] +#[note( + "if you believe this case to be fine, allow this lint and add a comment explaining your rationale" +)] pub(crate) struct QueryUntracked { pub method: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_span_use_eq_ctxt)] +#[diag("use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`")] pub(crate) struct SpanUseEqCtxtDiag; #[derive(LintDiagnostic)] -#[diag(lint_symbol_intern_string_literal)] -#[help] +#[diag("using `Symbol::intern` on a string literal")] +#[help("consider adding the symbol to `compiler/rustc_span/src/symbol.rs`")] pub(crate) struct SymbolInternStringLiteralDiag; #[derive(LintDiagnostic)] -#[diag(lint_tykind_kind)] +#[diag("usage of `ty::TyKind::`")] pub(crate) struct TykindKind { - #[suggestion(code = "ty", applicability = "maybe-incorrect")] + #[suggestion( + "try using `ty::` directly", + code = "ty", + applicability = "maybe-incorrect" + )] pub suggestion: Span, } #[derive(LintDiagnostic)] -#[diag(lint_tykind)] -#[help] +#[diag("usage of `ty::TyKind`")] +#[help("try using `Ty` instead")] pub(crate) struct TykindDiag; #[derive(LintDiagnostic)] -#[diag(lint_ty_qualified)] +#[diag("usage of qualified `ty::{$ty}`")] pub(crate) struct TyQualified { pub ty: String, - #[suggestion(code = "{ty}", applicability = "maybe-incorrect")] + #[suggestion( + "try importing it and using it unqualified", + code = "{ty}", + applicability = "maybe-incorrect" + )] pub suggestion: Span, } #[derive(LintDiagnostic)] -#[diag(lint_type_ir_inherent_usage)] -#[note] +#[diag("do not use `rustc_type_ir::inherent` unless you're inside of the trait solver")] +#[note( + "the method or struct you're looking for is likely defined somewhere else downstream in the compiler" +)] pub(crate) struct TypeIrInherentUsage; #[derive(LintDiagnostic)] -#[diag(lint_type_ir_trait_usage)] -#[note] +#[diag( + "do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver" +)] +#[note( + "the method or struct you're looking for is likely defined somewhere else downstream in the compiler" +)] pub(crate) struct TypeIrTraitUsage; #[derive(LintDiagnostic)] -#[diag(lint_type_ir_direct_use)] -#[note] +#[diag("do not use `rustc_type_ir` unless you are implementing type system internals")] +#[note("use `rustc_middle::ty` instead")] pub(crate) struct TypeIrDirectUse; #[derive(LintDiagnostic)] -#[diag(lint_non_glob_import_type_ir_inherent)] +#[diag("non-glob import of `rustc_type_ir::inherent`")] pub(crate) struct NonGlobImportTypeIrInherent { - #[suggestion(code = "{snippet}", applicability = "maybe-incorrect")] + #[suggestion( + "try using a glob import instead", + code = "{snippet}", + applicability = "maybe-incorrect" + )] pub suggestion: Option, pub snippet: &'static str, } #[derive(LintDiagnostic)] -#[diag(lint_lintpass_by_hand)] -#[help] +#[diag("implementing `LintPass` by hand")] +#[help("try using `declare_lint_pass!` or `impl_lint_pass!` instead")] pub(crate) struct LintPassByHand; #[derive(LintDiagnostic)] -#[diag(lint_bad_opt_access)] +#[diag("{$msg}")] pub(crate) struct BadOptAccessDiag<'a> { pub msg: &'a str, } #[derive(LintDiagnostic)] -#[diag(lint_implicit_sysroot_crate_import)] -#[help] +#[diag( + "dangerous use of `extern crate {$name}` which is not guaranteed to exist exactly once in the sysroot" +)] +#[help( + "try using a cargo dependency or using a re-export of the dependency provided by a rustc_* crate" +)] pub(crate) struct ImplicitSysrootCrateImportDiag<'a> { pub name: &'a str, } @@ -959,14 +1153,14 @@ pub(crate) struct ImplicitSysrootCrateImportDiag<'a> { // let_underscore.rs #[derive(LintDiagnostic)] pub(crate) enum NonBindingLet { - #[diag(lint_non_binding_let_on_sync_lock)] + #[diag("non-binding let on a synchronization lock")] SyncLock { - #[label] + #[label("this lock is not assigned to a binding and is immediately dropped")] pat: Span, #[subdiagnostic] sub: NonBindingLetSub, }, - #[diag(lint_non_binding_let_on_drop_type)] + #[diag("non-binding let on a type that has a destructor")] DropType { #[subdiagnostic] sub: NonBindingLetSub, @@ -987,16 +1181,23 @@ impl Subdiagnostic for NonBindingLetSub { let prefix = if self.is_assign_desugar { "let " } else { "" }; diag.span_suggestion_verbose( self.suggestion, - fluent::lint_non_binding_let_suggestion, + inline_fluent!( + "consider binding to an unused variable to avoid immediately dropping the value" + ), format!("{prefix}_unused"), Applicability::MachineApplicable, ); } else { - diag.span_help(self.suggestion, fluent::lint_non_binding_let_suggestion); + diag.span_help( + self.suggestion, + inline_fluent!( + "consider binding to an unused variable to avoid immediately dropping the value" + ), + ); } if let Some(drop_fn_start_end) = self.drop_fn_start_end { diag.multipart_suggestion( - fluent::lint_non_binding_let_multi_suggestion, + inline_fluent!("consider immediately dropping the value"), vec![ (drop_fn_start_end.0, "drop(".to_string()), (drop_fn_start_end.1, ")".to_string()), @@ -1004,16 +1205,18 @@ impl Subdiagnostic for NonBindingLetSub { Applicability::MachineApplicable, ); } else { - diag.help(fluent::lint_non_binding_let_multi_drop_fn); + diag.help(inline_fluent!( + "consider immediately dropping the value using `drop(..)` after the `let` statement" + )); } } } // levels.rs #[derive(LintDiagnostic)] -#[diag(lint_overruled_attribute)] +#[diag("{$lint_level}({$lint_source}) incompatible with previous forbid")] pub(crate) struct OverruledAttributeLint<'a> { - #[label] + #[label("overruled by previous forbid")] pub overruled: Span, pub lint_level: &'a str, pub lint_source: Symbol, @@ -1022,17 +1225,17 @@ pub(crate) struct OverruledAttributeLint<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_deprecated_lint_name)] +#[diag("lint name `{$name}` is deprecated and may not have an effect in the future")] pub(crate) struct DeprecatedLintName<'a> { pub name: String, - #[suggestion(code = "{replace}", applicability = "machine-applicable")] + #[suggestion("change it to", code = "{replace}", applicability = "machine-applicable")] pub suggestion: Span, pub replace: &'a str, } #[derive(LintDiagnostic)] -#[diag(lint_deprecated_lint_name)] -#[help] +#[diag("lint name `{$name}` is deprecated and may not have an effect in the future")] +#[help("change it to {$replace}")] pub(crate) struct DeprecatedLintNameFromCommandLine<'a> { pub name: String, pub replace: &'a str, @@ -1041,7 +1244,7 @@ pub(crate) struct DeprecatedLintNameFromCommandLine<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_renamed_lint)] +#[diag("lint `{$name}` has been renamed to `{$replace}`")] pub(crate) struct RenamedLint<'a> { pub name: &'a str, pub replace: &'a str, @@ -1051,18 +1254,18 @@ pub(crate) struct RenamedLint<'a> { #[derive(Subdiagnostic)] pub(crate) enum RenamedLintSuggestion<'a> { - #[suggestion(lint_suggestion, code = "{replace}", applicability = "machine-applicable")] + #[suggestion("use the new name", code = "{replace}", applicability = "machine-applicable")] WithSpan { #[primary_span] suggestion: Span, replace: &'a str, }, - #[help(lint_help)] + #[help("use the new name `{$replace}`")] WithoutSpan { replace: &'a str }, } #[derive(LintDiagnostic)] -#[diag(lint_renamed_lint)] +#[diag("lint `{$name}` has been renamed to `{$replace}`")] pub(crate) struct RenamedLintFromCommandLine<'a> { pub name: &'a str, pub replace: &'a str, @@ -1073,14 +1276,14 @@ pub(crate) struct RenamedLintFromCommandLine<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_removed_lint)] +#[diag("lint `{$name}` has been removed: {$reason}")] pub(crate) struct RemovedLint<'a> { pub name: &'a str, pub reason: &'a str, } #[derive(LintDiagnostic)] -#[diag(lint_removed_lint)] +#[diag("lint `{$name}` has been removed: {$reason}")] pub(crate) struct RemovedLintFromCommandLine<'a> { pub name: &'a str, pub reason: &'a str, @@ -1089,7 +1292,7 @@ pub(crate) struct RemovedLintFromCommandLine<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_unknown_lint)] +#[diag("unknown lint: `{$name}`")] pub(crate) struct UnknownLint { pub name: String, #[subdiagnostic] @@ -1098,19 +1301,31 @@ pub(crate) struct UnknownLint { #[derive(Subdiagnostic)] pub(crate) enum UnknownLintSuggestion { - #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")] + #[suggestion( + "{$from_rustc -> + [true] a lint with a similar name exists in `rustc` lints + *[false] did you mean + }", + code = "{replace}", + applicability = "maybe-incorrect" + )] WithSpan { #[primary_span] suggestion: Span, replace: Symbol, from_rustc: bool, }, - #[help(lint_help)] + #[help( + "{$from_rustc -> + [true] a lint with a similar name exists in `rustc` lints: `{$replace}` + *[false] did you mean: `{$replace}` + }" + )] WithoutSpan { replace: Symbol, from_rustc: bool }, } #[derive(LintDiagnostic)] -#[diag(lint_unknown_lint, code = E0602)] +#[diag("unknown lint: `{$name}`", code = E0602)] pub(crate) struct UnknownLintFromCommandLine<'a> { pub name: String, #[subdiagnostic] @@ -1120,7 +1335,7 @@ pub(crate) struct UnknownLintFromCommandLine<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_ignored_unless_crate_specified)] +#[diag("{$level}({$name}) is ignored unless specified at crate level")] pub(crate) struct IgnoredUnlessCrateSpecified<'a> { pub level: &'a str, pub name: Symbol, @@ -1128,53 +1343,78 @@ pub(crate) struct IgnoredUnlessCrateSpecified<'a> { // dangling.rs #[derive(LintDiagnostic)] -#[diag(lint_dangling_pointers_from_temporaries)] -#[help(lint_help_bind)] -#[note(lint_note_safe)] -#[note(lint_note_return)] -#[note(lint_note_more_info)] +#[diag("this creates a dangling pointer because temporary `{$ty}` is dropped at end of statement")] +#[help("bind the `{$ty}` to a variable such that it outlives the pointer returned by `{$callee}`")] +#[note("a dangling pointer is safe, but dereferencing one is undefined behavior")] +#[note("returning a pointer to a local variable will always result in a dangling pointer")] +#[note("for more information, see ")] // FIXME: put #[primary_span] on `ptr_span` once it does not cause conflicts pub(crate) struct DanglingPointersFromTemporaries<'tcx> { pub callee: Ident, pub ty: Ty<'tcx>, - #[label(lint_label_ptr)] + #[label("pointer created here")] pub ptr_span: Span, - #[label(lint_label_temporary)] + #[label("this `{$ty}` is dropped at end of statement")] pub temporary_span: Span, } #[derive(LintDiagnostic)] -#[diag(lint_dangling_pointers_from_locals)] -#[note(lint_note_safe)] -#[note(lint_note_more_info)] +#[diag("{$fn_kind} returns a dangling pointer to dropped local variable `{$local_var_name}`")] +#[note("a dangling pointer is safe, but dereferencing one is undefined behavior")] +#[note("for more information, see ")] pub(crate) struct DanglingPointersFromLocals<'tcx> { pub ret_ty: Ty<'tcx>, - #[label(lint_ret_ty)] + #[label("return type is `{$ret_ty}`")] pub ret_ty_span: Span, pub fn_kind: &'static str, - #[label(lint_local_var)] + #[label("local variable `{$local_var_name}` is dropped at the end of the {$fn_kind}")] pub local_var: Span, pub local_var_name: Ident, pub local_var_ty: Ty<'tcx>, - #[label(lint_created_at)] + #[label("dangling pointer created here")] pub created_at: Option, } // multiple_supertrait_upcastable.rs #[derive(LintDiagnostic)] -#[diag(lint_multiple_supertrait_upcastable)] +#[diag("`{$ident}` is dyn-compatible and has multiple supertraits")] pub(crate) struct MultipleSupertraitUpcastable { pub ident: Ident, } // non_ascii_idents.rs #[derive(LintDiagnostic)] -#[diag(lint_identifier_non_ascii_char)] +#[diag("identifier contains non-ASCII characters")] pub(crate) struct IdentifierNonAsciiChar; #[derive(LintDiagnostic)] -#[diag(lint_identifier_uncommon_codepoints)] -#[note] +#[diag( + "identifier contains {$codepoints_len -> + [one] { $identifier_type -> + [Exclusion] a character from an archaic script + [Technical] a character that is for non-linguistic, specialized usage + [Limited_Use] a character from a script in limited use + [Not_NFKC] a non normalized (NFKC) character + *[other] an uncommon character + } + *[other] { $identifier_type -> + [Exclusion] {$codepoints_len} characters from archaic scripts + [Technical] {$codepoints_len} characters that are for non-linguistic, specialized usage + [Limited_Use] {$codepoints_len} characters from scripts in limited use + [Not_NFKC] {$codepoints_len} non normalized (NFKC) characters + *[other] uncommon characters + } + }: {$codepoints}" +)] +#[note( + r#"{$codepoints_len -> + [one] this character is + *[other] these characters are + } included in the{$identifier_type -> + [Restricted] {""} + *[other] {" "}{$identifier_type} + } Unicode general security profile"# +)] pub(crate) struct IdentifierUncommonCodepoints { pub codepoints: Vec, pub codepoints_len: usize, @@ -1182,20 +1422,22 @@ pub(crate) struct IdentifierUncommonCodepoints { } #[derive(LintDiagnostic)] -#[diag(lint_confusable_identifier_pair)] +#[diag("found both `{$existing_sym}` and `{$sym}` as identifiers, which look alike")] pub(crate) struct ConfusableIdentifierPair { pub existing_sym: Symbol, pub sym: Symbol, - #[label(lint_other_use)] + #[label("other identifier used here")] pub label: Span, - #[label(lint_current_use)] + #[label("this identifier can be confused with `{$existing_sym}`")] pub main_label: Span, } #[derive(LintDiagnostic)] -#[diag(lint_mixed_script_confusables)] -#[note(lint_includes_note)] -#[note] +#[diag( + "the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables" +)] +#[note("the usage includes {$includes}")] +#[note("please recheck to make sure their usages are indeed what you want")] pub(crate) struct MixedScriptConfusables { pub set: String, pub includes: String, @@ -1210,19 +1452,34 @@ pub(crate) struct NonFmtPanicUnused { // Used because of two suggestions based on one Option impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(fluent::lint_non_fmt_panic_unused); + diag.primary_message(inline_fluent!( + "panic message contains {$count -> + [one] an unused + *[other] unused + } formatting {$count -> + [one] placeholder + *[other] placeholders + }" + )); diag.arg("count", self.count); - diag.note(fluent::lint_note); + diag.note(inline_fluent!("this message is not used as a format string when given without arguments, but will be in Rust 2021")); if let Some(span) = self.suggestion { diag.span_suggestion( span.shrink_to_hi(), - fluent::lint_add_args_suggestion, + inline_fluent!( + "add the missing {$count -> + [one] argument + *[other] arguments + }" + ), ", ...", Applicability::HasPlaceholders, ); diag.span_suggestion( span.shrink_to_lo(), - fluent::lint_add_fmt_suggestion, + inline_fluent!( + r#"or add a "{"{"}{"}"}" format string to use the message literally"# + ), "\"{}\", ", Applicability::MachineApplicable, ); @@ -1231,17 +1488,26 @@ impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused { } #[derive(LintDiagnostic)] -#[diag(lint_non_fmt_panic_braces)] -#[note] +#[diag( + "panic message contains {$count -> + [one] a brace + *[other] braces + }" +)] +#[note("this message is not used as a format string, but will be in Rust 2021")] pub(crate) struct NonFmtPanicBraces { pub count: usize, - #[suggestion(code = "\"{{}}\", ", applicability = "machine-applicable")] + #[suggestion( + "add a \"{\"{\"}{\"}\"}\" format string to use the message literally", + code = "\"{{}}\", ", + applicability = "machine-applicable" + )] pub suggestion: Option, } // nonstandard_style.rs #[derive(LintDiagnostic)] -#[diag(lint_non_camel_case_type)] +#[diag("{$sort} `{$name}` should have an upper camel case name")] pub(crate) struct NonCamelCaseType<'a> { pub sort: &'a str, pub name: &'a str, @@ -1251,12 +1517,16 @@ pub(crate) struct NonCamelCaseType<'a> { #[derive(Subdiagnostic)] pub(crate) enum NonCamelCaseTypeSub { - #[label(lint_label)] + #[label("should have an UpperCamelCase name")] Label { #[primary_span] span: Span, }, - #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")] + #[suggestion( + "convert the identifier to upper camel case", + code = "{replace}", + applicability = "maybe-incorrect" + )] Suggestion { #[primary_span] span: Span, @@ -1265,7 +1535,7 @@ pub(crate) enum NonCamelCaseTypeSub { } #[derive(LintDiagnostic)] -#[diag(lint_non_snake_case)] +#[diag("{$sort} `{$name}` should have a snake case name")] pub(crate) struct NonSnakeCaseDiag<'a> { pub sort: &'a str, pub name: &'a str, @@ -1286,15 +1556,15 @@ impl Subdiagnostic for NonSnakeCaseDiagSub { fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { NonSnakeCaseDiagSub::Label { span } => { - diag.span_label(span, fluent::lint_label); + diag.span_label(span, inline_fluent!("should have a snake_case name")); } NonSnakeCaseDiagSub::Help => { - diag.help(fluent::lint_help); + diag.help(inline_fluent!("convert the identifier to snake case: `{$sc}`")); } NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => { diag.span_suggestion( span, - fluent::lint_convert_suggestion, + inline_fluent!("convert the identifier to snake case"), suggestion, Applicability::MaybeIncorrect, ); @@ -1302,16 +1572,18 @@ impl Subdiagnostic for NonSnakeCaseDiagSub { NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => { diag.span_suggestion( span, - fluent::lint_rename_or_convert_suggestion, + inline_fluent!( + "rename the identifier or convert it to a snake case raw identifier" + ), suggestion, Applicability::MaybeIncorrect, ); } NonSnakeCaseDiagSub::SuggestionAndNote { span } => { - diag.note(fluent::lint_cannot_convert_note); + diag.note(inline_fluent!("`{$sc}` cannot be used as a raw identifier")); diag.span_suggestion( span, - fluent::lint_rename_suggestion, + inline_fluent!("rename the identifier"), "", Applicability::MaybeIncorrect, ); @@ -1321,7 +1593,7 @@ impl Subdiagnostic for NonSnakeCaseDiagSub { } #[derive(LintDiagnostic)] -#[diag(lint_non_upper_case_global)] +#[diag("{$sort} `{$name}` should have an upper case name")] pub(crate) struct NonUpperCaseGlobal<'a> { pub sort: &'a str, pub name: &'a str, @@ -1333,12 +1605,12 @@ pub(crate) struct NonUpperCaseGlobal<'a> { #[derive(Subdiagnostic)] pub(crate) enum NonUpperCaseGlobalSub { - #[label(lint_label)] + #[label("should have an UPPER_CASE name")] Label { #[primary_span] span: Span, }, - #[suggestion(lint_suggestion, code = "{replace}")] + #[suggestion("convert the identifier to upper case", code = "{replace}")] Suggestion { #[primary_span] span: Span, @@ -1350,7 +1622,7 @@ pub(crate) enum NonUpperCaseGlobalSub { #[derive(Subdiagnostic)] #[suggestion( - lint_suggestion, + "convert the identifier to upper case", code = "{replace}", applicability = "machine-applicable", style = "tool-only" @@ -1363,16 +1635,18 @@ pub(crate) struct NonUpperCaseGlobalSubTool { // noop_method_call.rs #[derive(LintDiagnostic)] -#[diag(lint_noop_method_call)] -#[note] +#[diag("call to `.{$method}()` on a reference in this situation does nothing")] +#[note( + "the type `{$orig_ty}` does not implement `{$trait_}`, so calling `{$method}` on `&{$orig_ty}` copies the reference, which does not do anything and can be removed" +)] pub(crate) struct NoopMethodCallDiag<'a> { pub method: Ident, pub orig_ty: Ty<'a>, pub trait_: Symbol, - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove this redundant call", code = "", applicability = "machine-applicable")] pub label: Span, #[suggestion( - lint_derive_suggestion, + "if you meant to clone `{$orig_ty}`, implement `Clone` for it", code = "#[derive(Clone)]\n", applicability = "maybe-incorrect" )] @@ -1380,13 +1654,17 @@ pub(crate) struct NoopMethodCallDiag<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_suspicious_double_ref_deref)] +#[diag( + "using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type" +)] pub(crate) struct SuspiciousDoubleRefDerefDiag<'a> { pub ty: Ty<'a>, } #[derive(LintDiagnostic)] -#[diag(lint_suspicious_double_ref_clone)] +#[diag( + "using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type" +)] pub(crate) struct SuspiciousDoubleRefCloneDiag<'a> { pub ty: Ty<'a>, } @@ -1423,7 +1701,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { doctest, macro_to_change, } => { - diag.primary_message(fluent::lint_non_local_definitions_impl); + diag.primary_message(inline_fluent!("non-local `impl` definition, `impl` blocks should be written at the same level as their item")); diag.arg("depth", depth); diag.arg("body_kind_descr", body_kind_descr); diag.arg("body_name", body_name); @@ -1431,24 +1709,24 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { if let Some((macro_to_change, macro_kind)) = macro_to_change { diag.arg("macro_to_change", macro_to_change); diag.arg("macro_kind", macro_kind); - diag.note(fluent::lint_macro_to_change); + diag.note(inline_fluent!("the {$macro_kind} `{$macro_to_change}` defines the non-local `impl`, and may need to be changed")); } if let Some(cargo_update) = cargo_update { diag.subdiagnostic(cargo_update); } - diag.note(fluent::lint_non_local); + diag.note(inline_fluent!("an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`")); if doctest { - diag.help(fluent::lint_doctest); + diag.help(inline_fluent!("make this doc-test a standalone test with its own `fn main() {\"{\"} ... {\"}\"}`")); } if let Some(const_anon) = const_anon { - diag.note(fluent::lint_exception); + diag.note(inline_fluent!("items in an anonymous const item (`const _: () = {\"{\"} ... {\"}\"}`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint")); if let Some(const_anon) = const_anon { diag.span_suggestion( const_anon, - fluent::lint_const_anon, + inline_fluent!("use a const-anon item to suppress this lint"), "_", Applicability::MachineApplicable, ); @@ -1462,18 +1740,21 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { doctest, cargo_update, } => { - diag.primary_message(fluent::lint_non_local_definitions_macro_rules); + diag.primary_message(inline_fluent!("non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module")); diag.arg("depth", depth); diag.arg("body_kind_descr", body_kind_descr); diag.arg("body_name", body_name); if doctest { - diag.help(fluent::lint_help_doctest); + diag.help(inline_fluent!(r#"remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}`"#)); } else { - diag.help(fluent::lint_help); + diag.help(inline_fluent!("remove the `#[macro_export]` or move this `macro_rules!` outside the of the current {$body_kind_descr} {$depth -> + [one] `{$body_name}` + *[other] `{$body_name}` and up {$depth} bodies + }")); } - diag.note(fluent::lint_non_local); + diag.note(inline_fluent!("a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute")); if let Some(cargo_update) = cargo_update { diag.subdiagnostic(cargo_update); @@ -1484,7 +1765,9 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { } #[derive(Subdiagnostic)] -#[note(lint_non_local_definitions_cargo_update)] +#[note( + "the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}`" +)] pub(crate) struct NonLocalDefinitionsCargoUpdateNote { pub macro_kind: &'static str, pub macro_name: Symbol, @@ -1493,8 +1776,8 @@ pub(crate) struct NonLocalDefinitionsCargoUpdateNote { // precedence.rs #[derive(LintDiagnostic)] -#[diag(lint_ambiguous_negative_literals)] -#[note(lint_example)] +#[diag("`-` has lower precedence than method calls, which might be unexpected")] +#[note("e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`")] pub(crate) struct AmbiguousNegativeLiteralsDiag { #[subdiagnostic] pub negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion, @@ -1503,7 +1786,10 @@ pub(crate) struct AmbiguousNegativeLiteralsDiag { } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_negative_literal, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "add parentheses around the `-` and the literal to call the method on a negative literal", + applicability = "maybe-incorrect" +)] pub(crate) struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion { #[suggestion_part(code = "(")] pub start_span: Span, @@ -1512,7 +1798,10 @@ pub(crate) struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion { } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_current_behavior, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "add parentheses around the literal and the method call to keep the current behavior", + applicability = "maybe-incorrect" +)] pub(crate) struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { #[suggestion_part(code = "(")] pub start_span: Span, @@ -1522,16 +1811,21 @@ pub(crate) struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { // pass_by_value.rs #[derive(LintDiagnostic)] -#[diag(lint_pass_by_value)] +#[diag("passing `{$ty}` by reference")] pub(crate) struct PassByValueDiag { pub ty: String, - #[suggestion(code = "{ty}", applicability = "maybe-incorrect")] + #[suggestion("try passing by value", code = "{ty}", applicability = "maybe-incorrect")] pub suggestion: Span, } // redundant_semicolon.rs #[derive(LintDiagnostic)] -#[diag(lint_redundant_semicolons)] +#[diag( + "unnecessary trailing {$multiple -> + [true] semicolons + *[false] semicolon + }" +)] pub(crate) struct RedundantSemicolonsDiag { pub multiple: bool, #[subdiagnostic] @@ -1539,7 +1833,14 @@ pub(crate) struct RedundantSemicolonsDiag { } #[derive(Subdiagnostic)] -#[suggestion(lint_redundant_semicolons_suggestion, code = "", applicability = "maybe-incorrect")] +#[suggestion( + "remove {$multiple_semicolons -> + [true] these semicolons + *[false] this semicolon + }", + code = "", + applicability = "maybe-incorrect" +)] pub(crate) struct RedundantSemicolonsSuggestion { pub multiple_semicolons: bool, #[primary_span] @@ -1556,7 +1857,7 @@ pub(crate) struct DropTraitConstraintsDiag<'a> { // Needed for def_path_str impl<'a> LintDiagnostic<'a, ()> for DropTraitConstraintsDiag<'_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(fluent::lint_drop_trait_constraints); + diag.primary_message(inline_fluent!("bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped")); diag.arg("predicate", self.predicate); diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); } @@ -1570,19 +1871,27 @@ pub(crate) struct DropGlue<'a> { // Needed for def_path_str impl<'a> LintDiagnostic<'a, ()> for DropGlue<'_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(fluent::lint_drop_glue); + diag.primary_message(inline_fluent!("types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped")); diag.arg("needs_drop", self.tcx.def_path_str(self.def_id)); } } // transmute.rs #[derive(LintDiagnostic)] -#[diag(lint_int_to_ptr_transmutes)] -#[note] -#[note(lint_note_exposed_provenance)] -#[help(lint_suggestion_without_provenance_mut)] -#[help(lint_help_transmute)] -#[help(lint_help_exposed_provenance)] +#[diag("transmuting an integer to a pointer creates a pointer without provenance")] +#[note("this is dangerous because dereferencing the resulting pointer is undefined behavior")] +#[note( + "exposed provenance semantics can be used to create a pointer based on some previously exposed provenance" +)] +#[help( + "if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`" +)] +#[help( + "for more information about transmute, see " +)] +#[help( + "for more information about exposed provenance, see " +)] pub(crate) struct IntegerToPtrTransmutes<'tcx> { #[subdiagnostic] pub suggestion: Option>, @@ -1591,7 +1900,7 @@ pub(crate) struct IntegerToPtrTransmutes<'tcx> { #[derive(Subdiagnostic)] pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> { #[multipart_suggestion( - lint_suggestion_with_exposed_provenance, + "use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance", applicability = "machine-applicable", style = "verbose" )] @@ -1602,7 +1911,7 @@ pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> { start_call: Span, }, #[multipart_suggestion( - lint_suggestion_with_exposed_provenance, + "use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance", applicability = "machine-applicable", style = "verbose" )] @@ -1619,7 +1928,7 @@ pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> { // types.rs #[derive(LintDiagnostic)] -#[diag(lint_range_endpoint_out_of_range)] +#[diag("range endpoint is out of range for `{$ty}`")] pub(crate) struct RangeEndpointOutOfRange<'a> { pub ty: &'a str, #[subdiagnostic] @@ -1629,7 +1938,7 @@ pub(crate) struct RangeEndpointOutOfRange<'a> { #[derive(Subdiagnostic)] pub(crate) enum UseInclusiveRange<'a> { #[suggestion( - lint_range_use_inclusive_range, + "use an inclusive range instead", code = "{start}..={literal}{suffix}", applicability = "machine-applicable" )] @@ -1640,7 +1949,7 @@ pub(crate) enum UseInclusiveRange<'a> { literal: u128, suffix: &'a str, }, - #[multipart_suggestion(lint_range_use_inclusive_range, applicability = "machine-applicable")] + #[multipart_suggestion("use an inclusive range instead", applicability = "machine-applicable")] WithParen { #[suggestion_part(code = "=")] eq_sugg: Span, @@ -1652,7 +1961,7 @@ pub(crate) enum UseInclusiveRange<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_overflowing_bin_hex)] +#[diag("literal out of range for `{$ty}`")] pub(crate) struct OverflowingBinHex<'a> { pub ty: &'a str, pub lit: String, @@ -1675,11 +1984,13 @@ impl Subdiagnostic for OverflowingBinHexSign { fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { OverflowingBinHexSign::Positive => { - diag.note(fluent::lint_positive_note); + diag.note(inline_fluent!("the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` and will become `{$actually}{$ty}`")); } OverflowingBinHexSign::Negative => { - diag.note(fluent::lint_negative_note); - diag.note(fluent::lint_negative_becomes_note); + diag.note(inline_fluent!( + "the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`" + )); + diag.note(inline_fluent!("and the value `-{$lit}` will become `{$actually}{$ty}`")); } } } @@ -1688,7 +1999,7 @@ impl Subdiagnostic for OverflowingBinHexSign { #[derive(Subdiagnostic)] pub(crate) enum OverflowingBinHexSub<'a> { #[suggestion( - lint_suggestion, + "consider using the type `{$suggestion_ty}` instead", code = "{sans_suffix}{suggestion_ty}", applicability = "machine-applicable" )] @@ -1698,13 +2009,13 @@ pub(crate) enum OverflowingBinHexSub<'a> { suggestion_ty: &'a str, sans_suffix: &'a str, }, - #[help(lint_help)] + #[help("consider using the type `{$suggestion_ty}` instead")] Help { suggestion_ty: &'a str }, } #[derive(Subdiagnostic)] #[suggestion( - lint_sign_bit_suggestion, + "to use as a negative number (decimal `{$negative_val}`), consider using the type `{$uint_ty}` for the literal and cast it to `{$int_ty}`", code = "{lit_no_suffix}{uint_ty} as {int_ty}", applicability = "maybe-incorrect" )] @@ -1718,8 +2029,8 @@ pub(crate) struct OverflowingBinHexSignBitSub<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_overflowing_int)] -#[note] +#[diag("literal out of range for `{$ty}`")] +#[note("the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`")] pub(crate) struct OverflowingInt<'a> { pub ty: &'a str, pub lit: String, @@ -1730,22 +2041,26 @@ pub(crate) struct OverflowingInt<'a> { } #[derive(Subdiagnostic)] -#[help(lint_help)] +#[help("consider using the type `{$suggestion_ty}` instead")] pub(crate) struct OverflowingIntHelp<'a> { pub suggestion_ty: &'a str, } #[derive(LintDiagnostic)] -#[diag(lint_only_cast_u8_to_char)] +#[diag("only `u8` can be cast into `char`")] pub(crate) struct OnlyCastu8ToChar { - #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")] + #[suggestion( + "use a `char` literal instead", + code = "'\\u{{{literal:X}}}'", + applicability = "machine-applicable" + )] pub span: Span, pub literal: u128, } #[derive(LintDiagnostic)] -#[diag(lint_overflowing_uint)] -#[note] +#[diag("literal out of range for `{$ty}`")] +#[note("the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`")] pub(crate) struct OverflowingUInt<'a> { pub ty: &'a str, pub lit: String, @@ -1754,50 +2069,54 @@ pub(crate) struct OverflowingUInt<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_overflowing_literal)] -#[note] +#[diag("literal out of range for `{$ty}`")] +#[note( + "the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY`" +)] pub(crate) struct OverflowingLiteral<'a> { pub ty: &'a str, pub lit: String, } #[derive(LintDiagnostic)] -#[diag(lint_surrogate_char_cast)] -#[note] +#[diag("surrogate values are not valid for `char`")] +#[note("`0xD800..=0xDFFF` are reserved for Unicode surrogates and are not valid `char` values")] pub(crate) struct SurrogateCharCast { pub literal: u128, } #[derive(LintDiagnostic)] -#[diag(lint_too_large_char_cast)] -#[note] +#[diag("value exceeds maximum `char` value")] +#[note("maximum valid `char` value is `0x10FFFF`")] pub(crate) struct TooLargeCharCast { pub literal: u128, } #[derive(LintDiagnostic)] -#[diag(lint_uses_power_alignment)] +#[diag( + "repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type" +)] pub(crate) struct UsesPowerAlignment; #[derive(LintDiagnostic)] -#[diag(lint_unused_comparisons)] +#[diag("comparison is useless due to type limits")] pub(crate) struct UnusedComparisons; #[derive(LintDiagnostic)] pub(crate) enum InvalidNanComparisons { - #[diag(lint_invalid_nan_comparisons_eq_ne)] + #[diag("incorrect NaN comparison, NaN cannot be directly compared to itself")] EqNe { #[subdiagnostic] suggestion: InvalidNanComparisonsSuggestion, }, - #[diag(lint_invalid_nan_comparisons_lt_le_gt_ge)] + #[diag("incorrect NaN comparison, NaN is not orderable")] LtLeGtGe, } #[derive(Subdiagnostic)] pub(crate) enum InvalidNanComparisonsSuggestion { #[multipart_suggestion( - lint_suggestion, + "use `f32::is_nan()` or `f64::is_nan()` instead", style = "verbose", applicability = "machine-applicable" )] @@ -1809,35 +2128,41 @@ pub(crate) enum InvalidNanComparisonsSuggestion { #[suggestion_part(code = "")] nan_plus_binop: Span, }, - #[help(lint_suggestion)] + #[help("use `f32::is_nan()` or `f64::is_nan()` instead")] Spanless, } #[derive(LintDiagnostic)] pub(crate) enum AmbiguousWidePointerComparisons<'a> { - #[diag(lint_ambiguous_wide_pointer_comparisons)] + #[diag( + "ambiguous wide pointer comparison, the comparison includes metadata which may not be expected" + )] SpanfulEq { #[subdiagnostic] addr_suggestion: AmbiguousWidePointerComparisonsAddrSuggestion<'a>, #[subdiagnostic] addr_metadata_suggestion: Option>, }, - #[diag(lint_ambiguous_wide_pointer_comparisons)] + #[diag( + "ambiguous wide pointer comparison, the comparison includes metadata which may not be expected" + )] SpanfulCmp { #[subdiagnostic] cast_suggestion: AmbiguousWidePointerComparisonsCastSuggestion<'a>, #[subdiagnostic] expect_suggestion: AmbiguousWidePointerComparisonsExpectSuggestion<'a>, }, - #[diag(lint_ambiguous_wide_pointer_comparisons)] - #[help(lint_addr_metadata_suggestion)] - #[help(lint_addr_suggestion)] + #[diag( + "ambiguous wide pointer comparison, the comparison includes metadata which may not be expected" + )] + #[help("use explicit `std::ptr::eq` method to compare metadata and addresses")] + #[help("use `std::ptr::addr_eq` or untyped pointers to only compare their addresses")] Spanless, } #[derive(Subdiagnostic)] #[multipart_suggestion( - lint_addr_metadata_suggestion, + "use explicit `std::ptr::eq` method to compare metadata and addresses", style = "verbose", // FIXME(#53934): make machine-applicable again applicability = "maybe-incorrect" @@ -1858,7 +2183,7 @@ pub(crate) struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> { #[derive(Subdiagnostic)] #[multipart_suggestion( - lint_addr_suggestion, + "use `std::ptr::addr_eq` or untyped pointers to only compare their addresses", style = "verbose", // FIXME(#53934): make machine-applicable again applicability = "maybe-incorrect" @@ -1879,7 +2204,7 @@ pub(crate) struct AmbiguousWidePointerComparisonsAddrSuggestion<'a> { #[derive(Subdiagnostic)] #[multipart_suggestion( - lint_cast_suggestion, + "use untyped pointers to only compare their addresses", style = "verbose", // FIXME(#53934): make machine-applicable again applicability = "maybe-incorrect" @@ -1903,7 +2228,7 @@ pub(crate) struct AmbiguousWidePointerComparisonsCastSuggestion<'a> { #[derive(Subdiagnostic)] #[multipart_suggestion( - lint_expect_suggestion, + "or expect the lint to compare the pointers metadata and addresses", style = "verbose", // FIXME(#53934): make machine-applicable again applicability = "maybe-incorrect" @@ -1922,25 +2247,37 @@ pub(crate) struct AmbiguousWidePointerComparisonsExpectSuggestion<'a> { #[derive(LintDiagnostic)] pub(crate) enum UnpredictableFunctionPointerComparisons<'a, 'tcx> { - #[diag(lint_unpredictable_fn_pointer_comparisons)] - #[note(lint_note_duplicated_fn)] - #[note(lint_note_deduplicated_fn)] - #[note(lint_note_visit_fn_addr_eq)] + #[diag( + "function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique" + )] + #[note("the address of the same function can vary between different codegen units")] + #[note( + "furthermore, different functions could have the same address after being merged together" + )] + #[note( + "for more information visit " + )] Suggestion { #[subdiagnostic] sugg: UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx>, }, - #[diag(lint_unpredictable_fn_pointer_comparisons)] - #[note(lint_note_duplicated_fn)] - #[note(lint_note_deduplicated_fn)] - #[note(lint_note_visit_fn_addr_eq)] + #[diag( + "function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique" + )] + #[note("the address of the same function can vary between different codegen units")] + #[note( + "furthermore, different functions could have the same address after being merged together" + )] + #[note( + "for more information visit " + )] Warn, } #[derive(Subdiagnostic)] pub(crate) enum UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx> { #[multipart_suggestion( - lint_fn_addr_eq_suggestion, + "refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint", style = "verbose", applicability = "maybe-incorrect" )] @@ -1956,7 +2293,7 @@ pub(crate) enum UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx> { right: Span, }, #[multipart_suggestion( - lint_fn_addr_eq_suggestion, + "refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint", style = "verbose", applicability = "maybe-incorrect" )] @@ -1986,69 +2323,73 @@ pub(crate) struct ImproperCTypes<'a> { // Used because of the complexity of Option, DiagMessage, and Option impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(fluent::lint_improper_ctypes); + diag.primary_message(inline_fluent!( + "`extern` {$desc} uses type `{$ty}`, which is not FFI-safe" + )); diag.arg("ty", self.ty); diag.arg("desc", self.desc); - diag.span_label(self.label, fluent::lint_label); + diag.span_label(self.label, inline_fluent!("not FFI-safe")); if let Some(help) = self.help { diag.help(help); } diag.note(self.note); if let Some(note) = self.span_note { - diag.span_note(note, fluent::lint_note); + diag.span_note(note, inline_fluent!("the type is defined here")); } } } #[derive(LintDiagnostic)] -#[diag(lint_improper_gpu_kernel_arg)] -#[help] +#[diag("passing type `{$ty}` to a function with \"gpu-kernel\" ABI may have unexpected behavior")] +#[help("use primitive types and raw pointers to get reliable behavior")] pub(crate) struct ImproperGpuKernelArg<'a> { pub ty: Ty<'a>, } #[derive(LintDiagnostic)] -#[diag(lint_missing_gpu_kernel_export_name)] -#[help] -#[note] +#[diag("function with the \"gpu-kernel\" ABI has a mangled name")] +#[help("use `unsafe(no_mangle)` or `unsafe(export_name = \"\")`")] +#[note("mangled names make it hard to find the kernel, this is usually not intended")] pub(crate) struct MissingGpuKernelExportName; #[derive(LintDiagnostic)] -#[diag(lint_variant_size_differences)] +#[diag("enum variant is more than three times larger ({$largest} bytes) than the next largest")] pub(crate) struct VariantSizeDifferencesDiag { pub largest: u64, } #[derive(LintDiagnostic)] -#[diag(lint_atomic_ordering_load)] -#[help] +#[diag("atomic loads cannot have `Release` or `AcqRel` ordering")] +#[help("consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`")] pub(crate) struct AtomicOrderingLoad; #[derive(LintDiagnostic)] -#[diag(lint_atomic_ordering_store)] -#[help] +#[diag("atomic stores cannot have `Acquire` or `AcqRel` ordering")] +#[help("consider using ordering modes `Release`, `SeqCst` or `Relaxed`")] pub(crate) struct AtomicOrderingStore; #[derive(LintDiagnostic)] -#[diag(lint_atomic_ordering_fence)] -#[help] +#[diag("memory fences cannot have `Relaxed` ordering")] +#[help("consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`")] pub(crate) struct AtomicOrderingFence; #[derive(LintDiagnostic)] -#[diag(lint_atomic_ordering_invalid)] -#[help] +#[diag( + "`{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write" +)] +#[help("consider using `Acquire` or `Relaxed` failure ordering instead")] pub(crate) struct InvalidAtomicOrderingDiag { pub method: Symbol, - #[label] + #[label("invalid failure ordering")] pub fail_order_arg_span: Span, } // unused.rs #[derive(LintDiagnostic)] -#[diag(lint_unused_op)] +#[diag("unused {$op} that must be used")] pub(crate) struct UnusedOp<'a> { pub op: &'a str, - #[label] + #[label("the {$op} produces a value")] pub label: Span, #[subdiagnostic] pub suggestion: UnusedOpSuggestion, @@ -2057,7 +2398,7 @@ pub(crate) struct UnusedOp<'a> { #[derive(Subdiagnostic)] pub(crate) enum UnusedOpSuggestion { #[suggestion( - lint_suggestion, + "use `let _ = ...` to ignore the resulting value", style = "verbose", code = "let _ = ", applicability = "maybe-incorrect" @@ -2066,7 +2407,11 @@ pub(crate) enum UnusedOpSuggestion { #[primary_span] span: Span, }, - #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")] + #[multipart_suggestion( + "use `let _ = ...` to ignore the resulting value", + style = "verbose", + applicability = "maybe-incorrect" + )] BlockTailExpr { #[suggestion_part(code = "let _ = ")] before_span: Span, @@ -2076,7 +2421,7 @@ pub(crate) enum UnusedOpSuggestion { } #[derive(LintDiagnostic)] -#[diag(lint_unused_result)] +#[diag("unused result of type `{$ty}`")] pub(crate) struct UnusedResult<'a> { pub ty: Ty<'a>, } @@ -2084,8 +2429,13 @@ pub(crate) struct UnusedResult<'a> { // FIXME(davidtwco): this isn't properly translatable because of the // pre/post strings #[derive(LintDiagnostic)] -#[diag(lint_unused_closure)] -#[note] +#[diag( + "unused {$pre}{$count -> + [one] closure + *[other] closures + }{$post} that must be used" +)] +#[note("closures are lazy and do nothing unless called")] pub(crate) struct UnusedClosure<'a> { pub count: usize, pub pre: &'a str, @@ -2095,8 +2445,13 @@ pub(crate) struct UnusedClosure<'a> { // FIXME(davidtwco): this isn't properly translatable because of the // pre/post strings #[derive(LintDiagnostic)] -#[diag(lint_unused_coroutine)] -#[note] +#[diag( + "unused {$pre}{$count -> + [one] coroutine + *[other] coroutine + }{$post} that must be used" +)] +#[note("coroutines are lazy and do nothing unless resumed")] pub(crate) struct UnusedCoroutine<'a> { pub count: usize, pub pre: &'a str, @@ -2115,10 +2470,9 @@ pub(crate) struct UnusedDef<'a, 'b> { } #[derive(Subdiagnostic)] - pub(crate) enum UnusedDefSuggestion { #[suggestion( - lint_suggestion, + "use `let _ = ...` to ignore the resulting value", style = "verbose", code = "let _ = ", applicability = "maybe-incorrect" @@ -2127,7 +2481,11 @@ pub(crate) enum UnusedDefSuggestion { #[primary_span] span: Span, }, - #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")] + #[multipart_suggestion( + "use `let _ = ...` to ignore the resulting value", + style = "verbose", + applicability = "maybe-incorrect" + )] BlockTailExpr { #[suggestion_part(code = "let _ = ")] before_span: Span, @@ -2139,7 +2497,7 @@ pub(crate) enum UnusedDefSuggestion { // Needed because of def_path_str impl<'a> LintDiagnostic<'a, ()> for UnusedDef<'_, '_> { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(fluent::lint_unused_def); + diag.primary_message(inline_fluent!("unused {$pre}`{$def}`{$post} that must be used")); diag.arg("pre", self.pre); diag.arg("post", self.post); diag.arg("def", self.cx.tcx.def_path_str(self.def_id)); @@ -2154,7 +2512,7 @@ impl<'a> LintDiagnostic<'a, ()> for UnusedDef<'_, '_> { } #[derive(LintDiagnostic)] -#[diag(lint_path_statement_drop)] +#[diag("path statement drops value")] pub(crate) struct PathStatementDrop { #[subdiagnostic] pub sub: PathStatementDropSub, @@ -2162,13 +2520,17 @@ pub(crate) struct PathStatementDrop { #[derive(Subdiagnostic)] pub(crate) enum PathStatementDropSub { - #[suggestion(lint_suggestion, code = "drop({snippet});", applicability = "machine-applicable")] + #[suggestion( + "use `drop` to clarify the intent", + code = "drop({snippet});", + applicability = "machine-applicable" + )] Suggestion { #[primary_span] span: Span, snippet: String, }, - #[help(lint_help)] + #[help("use `drop` to clarify the intent")] Help { #[primary_span] span: Span, @@ -2176,11 +2538,11 @@ pub(crate) enum PathStatementDropSub { } #[derive(LintDiagnostic)] -#[diag(lint_path_statement_no_effect)] +#[diag("path statement with no effect")] pub(crate) struct PathStatementNoEffect; #[derive(LintDiagnostic)] -#[diag(lint_unused_delim)] +#[diag("unnecessary {$delim} around {$item}")] pub(crate) struct UnusedDelim<'a> { pub delim: &'static str, pub item: &'a str, @@ -2189,7 +2551,7 @@ pub(crate) struct UnusedDelim<'a> { } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion("remove these {$delim}", applicability = "machine-applicable")] pub(crate) struct UnusedDelimSuggestion { #[suggestion_part(code = "{start_replace}")] pub start_span: Span, @@ -2200,17 +2562,17 @@ pub(crate) struct UnusedDelimSuggestion { } #[derive(LintDiagnostic)] -#[diag(lint_unused_import_braces)] +#[diag("braces around {$node} is unnecessary")] pub(crate) struct UnusedImportBracesDiag { pub node: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_unused_allocation)] +#[diag("unnecessary allocation, use `&` instead")] pub(crate) struct UnusedAllocationDiag; #[derive(LintDiagnostic)] -#[diag(lint_unused_allocation_mut)] +#[diag("unnecessary allocation, use `&mut` instead")] pub(crate) struct UnusedAllocationMutDiag; pub(crate) struct AsyncFnInTraitDiag { @@ -2219,59 +2581,67 @@ pub(crate) struct AsyncFnInTraitDiag { impl<'a> LintDiagnostic<'a, ()> for AsyncFnInTraitDiag { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) { - diag.primary_message(fluent::lint_async_fn_in_trait); - diag.note(fluent::lint_note); + diag.primary_message(inline_fluent!("use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified")); + diag.note(inline_fluent!("you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future`")); if let Some(sugg) = self.sugg { - diag.multipart_suggestion(fluent::lint_suggestion, sugg, Applicability::MaybeIncorrect); + diag.multipart_suggestion(inline_fluent!("you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send`, but these cannot be relaxed without a breaking API change"), sugg, Applicability::MaybeIncorrect); } } } #[derive(LintDiagnostic)] -#[diag(lint_unit_bindings)] +#[diag("binding has unit type `()`")] pub(crate) struct UnitBindingsDiag { - #[label] + #[label("this pattern is inferred to be the unit type `()`")] pub label: Span, } #[derive(LintDiagnostic)] pub(crate) enum InvalidAsmLabel { - #[diag(lint_invalid_asm_label_named)] - #[help] - #[note] + #[diag("avoid using named labels in inline assembly")] + #[help("only local labels of the form `:` should be used in inline asm")] + #[note( + "see the asm section of Rust By Example for more information" + )] Named { - #[note(lint_invalid_asm_label_no_span)] + #[note("the label may be declared in the expansion of a macro")] missing_precise_span: bool, }, - #[diag(lint_invalid_asm_label_format_arg)] - #[help] - #[note(lint_note1)] - #[note(lint_note2)] + #[diag("avoid using named labels in inline assembly")] + #[help("only local labels of the form `:` should be used in inline asm")] + #[note("format arguments may expand to a non-numeric value")] + #[note( + "see the asm section of Rust By Example for more information" + )] FormatArg { - #[note(lint_invalid_asm_label_no_span)] + #[note("the label may be declared in the expansion of a macro")] missing_precise_span: bool, }, - #[diag(lint_invalid_asm_label_binary)] - #[help] - #[note(lint_note1)] - #[note(lint_note2)] + #[diag("avoid using labels containing only the digits `0` and `1` in inline assembly")] + #[help("start numbering with `2` instead")] + #[note("an LLVM bug makes these labels ambiguous with a binary literal number on x86")] + #[note("see for more information")] Binary { - #[note(lint_invalid_asm_label_no_span)] + #[note("the label may be declared in the expansion of a macro")] missing_precise_span: bool, // hack to get a label on the whole span, must match the emitted span - #[label] + #[label("use a different label that doesn't start with `0` or `1`")] span: Span, }, } #[derive(Subdiagnostic)] pub(crate) enum UnexpectedCfgCargoHelp { - #[help(lint_unexpected_cfg_add_cargo_feature)] - #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)] + #[help("consider using a Cargo feature instead")] + #[help( + "or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:{$cargo_toml_lint_cfg}" + )] LintCfg { cargo_toml_lint_cfg: String }, - #[help(lint_unexpected_cfg_add_cargo_feature)] - #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)] - #[help(lint_unexpected_cfg_add_build_rs_println)] + #[help("consider using a Cargo feature instead")] + #[help( + "or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:{$cargo_toml_lint_cfg}" + )] + #[help("or consider adding `{$build_rs_println}` to the top of the `build.rs`")] LintCfgAndBuildRs { cargo_toml_lint_cfg: String, build_rs_println: String }, } @@ -2297,7 +2667,7 @@ impl UnexpectedCfgCargoHelp { } #[derive(Subdiagnostic)] -#[help(lint_unexpected_cfg_add_cmdline_arg)] +#[help("to expect this configuration use `{$cmdline_arg}`")] pub(crate) struct UnexpectedCfgRustcHelp { pub cmdline_arg: String, } @@ -2309,17 +2679,23 @@ impl UnexpectedCfgRustcHelp { } #[derive(Subdiagnostic)] -#[note(lint_unexpected_cfg_from_external_macro_origin)] -#[help(lint_unexpected_cfg_from_external_macro_refer)] +#[note( + "using a cfg inside a {$macro_kind} will use the cfgs from the destination crate and not the ones from the defining crate" +)] +#[help("try referring to `{$macro_name}` crate for guidance on how handle this unexpected cfg")] pub(crate) struct UnexpectedCfgRustcMacroHelp { pub macro_kind: &'static str, pub macro_name: Symbol, } #[derive(Subdiagnostic)] -#[note(lint_unexpected_cfg_from_external_macro_origin)] -#[help(lint_unexpected_cfg_from_external_macro_refer)] -#[help(lint_unexpected_cfg_cargo_update)] +#[note( + "using a cfg inside a {$macro_kind} will use the cfgs from the destination crate and not the ones from the defining crate" +)] +#[help("try referring to `{$macro_name}` crate for guidance on how handle this unexpected cfg")] +#[help( + "the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}`" +)] pub(crate) struct UnexpectedCfgCargoMacroHelp { pub macro_kind: &'static str, pub macro_name: Symbol, @@ -2327,7 +2703,7 @@ pub(crate) struct UnexpectedCfgCargoMacroHelp { } #[derive(LintDiagnostic)] -#[diag(lint_unexpected_cfg_name)] +#[diag("unexpected `cfg` condition name: `{$name}`")] pub(crate) struct UnexpectedCfgName { #[subdiagnostic] pub code_sugg: unexpected_cfg_name::CodeSuggestion, @@ -2344,10 +2720,10 @@ pub(crate) mod unexpected_cfg_name { #[derive(Subdiagnostic)] pub(crate) enum CodeSuggestion { - #[help(lint_unexpected_cfg_define_features)] + #[help("consider defining some features in `Cargo.toml`")] DefineFeatures, #[multipart_suggestion( - lint_unexpected_cfg_name_version_syntax, + "there is a similar config predicate: `version(\"..\")`", applicability = "machine-applicable" )] VersionSyntax { @@ -2357,7 +2733,7 @@ pub(crate) mod unexpected_cfg_name { after_value: Span, }, #[suggestion( - lint_unexpected_cfg_name_similar_name_value, + "there is a config with a similar name and value", applicability = "maybe-incorrect", code = "{code}" )] @@ -2367,7 +2743,7 @@ pub(crate) mod unexpected_cfg_name { code: String, }, #[suggestion( - lint_unexpected_cfg_name_similar_name_no_value, + "there is a config with a similar name and no value", applicability = "maybe-incorrect", code = "{code}" )] @@ -2377,7 +2753,7 @@ pub(crate) mod unexpected_cfg_name { code: String, }, #[suggestion( - lint_unexpected_cfg_name_similar_name_different_values, + "there is a config with a similar name and different values", applicability = "maybe-incorrect", code = "{code}" )] @@ -2389,7 +2765,7 @@ pub(crate) mod unexpected_cfg_name { expected: Option, }, #[suggestion( - lint_unexpected_cfg_name_similar_name, + "there is a config with a similar name", applicability = "maybe-incorrect", code = "{code}" )] @@ -2407,7 +2783,7 @@ pub(crate) mod unexpected_cfg_name { expected_names: Option, }, #[suggestion( - lint_unexpected_cfg_boolean, + "you may have meant to use `{$literal}` (notice the capitalization). Doing so makes this predicate evaluate to `{$literal}` unconditionally", applicability = "machine-applicable", style = "verbose", code = "{literal}" @@ -2420,7 +2796,7 @@ pub(crate) mod unexpected_cfg_name { } #[derive(Subdiagnostic)] - #[help(lint_unexpected_cfg_name_expected_values)] + #[help("expected values for `{$best_match}` are: {$possibilities}")] pub(crate) struct ExpectedValues { pub best_match: Symbol, pub possibilities: DiagSymbolList, @@ -2428,7 +2804,7 @@ pub(crate) mod unexpected_cfg_name { #[derive(Subdiagnostic)] #[suggestion( - lint_unexpected_cfg_name_with_similar_value, + "found config with similar value", applicability = "maybe-incorrect", code = "{code}" )] @@ -2439,7 +2815,12 @@ pub(crate) mod unexpected_cfg_name { } #[derive(Subdiagnostic)] - #[help_once(lint_unexpected_cfg_name_expected_names)] + #[help_once( + "expected names are: {$possibilities}{$and_more -> + [0] {\"\"} + *[other] {\" \"}and {$and_more} more + }" + )] pub(crate) struct ExpectedNames { pub possibilities: DiagSymbolList, pub and_more: usize, @@ -2447,14 +2828,18 @@ pub(crate) mod unexpected_cfg_name { #[derive(Subdiagnostic)] pub(crate) enum InvocationHelp { - #[note(lint_unexpected_cfg_doc_cargo)] + #[note( + "see for more information about checking conditional configuration" + )] Cargo { #[subdiagnostic] macro_help: Option, #[subdiagnostic] help: Option, }, - #[note(lint_unexpected_cfg_doc_rustc)] + #[note( + "see for more information about checking conditional configuration" + )] Rustc { #[subdiagnostic] macro_help: Option, @@ -2465,7 +2850,12 @@ pub(crate) mod unexpected_cfg_name { } #[derive(LintDiagnostic)] -#[diag(lint_unexpected_cfg_value)] +#[diag( + "unexpected `cfg` condition value: {$has_value -> + [true] `{$value}` + *[false] (none) + }" +)] pub(crate) struct UnexpectedCfgValue { #[subdiagnostic] pub code_sugg: unexpected_cfg_value::CodeSuggestion, @@ -2489,14 +2879,14 @@ pub(crate) mod unexpected_cfg_value { #[subdiagnostic] suggestion: Option, }, - #[note(lint_unexpected_cfg_value_no_expected_value)] + #[note("no expected value for `{$name}`")] RemoveValue { #[subdiagnostic] suggestion: Option, name: Symbol, }, - #[note(lint_unexpected_cfg_value_no_expected_values)] + #[note("no expected values for `{$name}`")] RemoveCondition { #[subdiagnostic] suggestion: RemoveConditionSuggestion, @@ -2508,7 +2898,7 @@ pub(crate) mod unexpected_cfg_value { #[derive(Subdiagnostic)] pub(crate) enum ChangeValueSuggestion { #[suggestion( - lint_unexpected_cfg_value_similar_name, + "there is a expected value with a similar name", code = r#""{best_match}""#, applicability = "maybe-incorrect" )] @@ -2518,7 +2908,7 @@ pub(crate) mod unexpected_cfg_value { best_match: Symbol, }, #[suggestion( - lint_unexpected_cfg_value_specify_value, + "specify a config value", code = r#" = "{first_possibility}""#, applicability = "maybe-incorrect" )] @@ -2530,29 +2920,29 @@ pub(crate) mod unexpected_cfg_value { } #[derive(Subdiagnostic)] - #[suggestion( - lint_unexpected_cfg_value_remove_value, - code = "", - applicability = "maybe-incorrect" - )] + #[suggestion("remove the value", code = "", applicability = "maybe-incorrect")] pub(crate) struct RemoveValueSuggestion { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] - #[suggestion( - lint_unexpected_cfg_value_remove_condition, - code = "", - applicability = "maybe-incorrect" - )] + #[suggestion("remove the condition", code = "", applicability = "maybe-incorrect")] pub(crate) struct RemoveConditionSuggestion { #[primary_span] pub span: Span, } #[derive(Subdiagnostic)] - #[note(lint_unexpected_cfg_value_expected_values)] + #[note( + "expected values for `{$name}` are: {$have_none_possibility -> + [true] {\"(none), \"} + *[false] {\"\"} + }{$possibilities}{$and_more -> + [0] {\"\"} + *[other] {\" \"}and {$and_more} more + }" + )] pub(crate) struct ExpectedValues { pub name: Symbol, pub have_none_possibility: bool, @@ -2562,14 +2952,18 @@ pub(crate) mod unexpected_cfg_value { #[derive(Subdiagnostic)] pub(crate) enum InvocationHelp { - #[note(lint_unexpected_cfg_doc_cargo)] + #[note( + "see for more information about checking conditional configuration" + )] Cargo { #[subdiagnostic] help: Option, #[subdiagnostic] macro_help: Option, }, - #[note(lint_unexpected_cfg_doc_rustc)] + #[note( + "see for more information about checking conditional configuration" + )] Rustc { #[subdiagnostic] help: Option, @@ -2580,19 +2974,19 @@ pub(crate) mod unexpected_cfg_value { #[derive(Subdiagnostic)] pub(crate) enum CargoHelp { - #[help(lint_unexpected_cfg_value_add_feature)] + #[help("consider adding `{$value}` as a feature in `Cargo.toml`")] AddFeature { value: Symbol, }, - #[help(lint_unexpected_cfg_define_features)] + #[help("consider defining some features in `Cargo.toml`")] DefineFeatures, Other(#[subdiagnostic] super::UnexpectedCfgCargoHelp), } } #[derive(LintDiagnostic)] -#[diag(lint_unused_crate_dependency)] -#[help] +#[diag("extern crate `{$extern_crate}` is unused in crate `{$local_crate}`")] +#[help("remove the dependency or add `use {$extern_crate} as _;` to the crate root")] pub(crate) struct UnusedCrateDependency { pub extern_crate: Symbol, pub local_crate: Symbol, @@ -2600,20 +2994,32 @@ pub(crate) struct UnusedCrateDependency { // FIXME(jdonszelmann): duplicated in rustc_attr_parsing, should be moved there completely. #[derive(LintDiagnostic)] -#[diag(lint_ill_formed_attribute_input)] +#[diag( + "{$num_suggestions -> + [1] attribute must be of the form {$suggestions} + *[other] valid forms for the attribute are {$suggestions} + }" +)] pub(crate) struct IllFormedAttributeInput { pub num_suggestions: usize, pub suggestions: DiagArgValue, - #[note] + #[note("for more information, visit <{$docs}>")] pub has_docs: bool, pub docs: &'static str, } #[derive(LintDiagnostic)] -#[diag(lint_unicode_text_flow)] -#[note] +#[diag("unicode codepoint changing visible direction of text present in comment")] +#[note( + "these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen" +)] pub(crate) struct UnicodeTextFlow { - #[label] + #[label( + "{$num_codepoints -> + [1] this comment contains an invisible unicode text flow control codepoint + *[other] this comment contains invisible unicode text flow control codepoints + }" + )] pub comment_span: Span, #[subdiagnostic] pub characters: Vec, @@ -2624,7 +3030,7 @@ pub(crate) struct UnicodeTextFlow { } #[derive(Subdiagnostic)] -#[label(lint_label_comment_char)] +#[label("{$c_debug}")] pub(crate) struct UnicodeCharNoteSub { #[primary_span] pub span: Span, @@ -2632,21 +3038,27 @@ pub(crate) struct UnicodeCharNoteSub { } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable", style = "hidden")] +#[multipart_suggestion( + "if their presence wasn't intentional, you can remove them", + applicability = "machine-applicable", + style = "hidden" +)] pub(crate) struct UnicodeTextFlowSuggestion { #[suggestion_part(code = "")] pub spans: Vec, } #[derive(LintDiagnostic)] -#[diag(lint_abs_path_with_module)] +#[diag( + "absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition" +)] pub(crate) struct AbsPathWithModule { #[subdiagnostic] pub sugg: AbsPathWithModuleSugg, } #[derive(Subdiagnostic)] -#[suggestion(lint_suggestion, code = "{replacement}")] +#[suggestion("use `crate`", code = "{replacement}")] pub(crate) struct AbsPathWithModuleSugg { #[primary_span] pub span: Span, @@ -2656,18 +3068,23 @@ pub(crate) struct AbsPathWithModuleSugg { } #[derive(LintDiagnostic)] -#[diag(lint_hidden_lifetime_parameters)] +#[diag("hidden lifetime parameters in types are deprecated")] pub(crate) struct ElidedLifetimesInPaths { #[subdiagnostic] pub subdiag: ElidedLifetimeInPathSubdiag, } #[derive(LintDiagnostic)] -#[diag(lint_unused_imports)] +#[diag( + "{$num_snippets -> + [one] unused import: {$span_snippets} + *[other] unused imports: {$span_snippets} + }" +)] pub(crate) struct UnusedImports { #[subdiagnostic] pub sugg: UnusedImportsSugg, - #[help] + #[help("if this is a test module, consider adding a `#[cfg(test)]` to the containing module")] pub test_module_span: Option, pub span_snippets: DiagArgValue, @@ -2677,7 +3094,7 @@ pub(crate) struct UnusedImports { #[derive(Subdiagnostic)] pub(crate) enum UnusedImportsSugg { #[suggestion( - lint_suggestion_remove_whole_use, + "remove the whole `use` item", applicability = "machine-applicable", code = "", style = "tool-only" @@ -2687,7 +3104,10 @@ pub(crate) enum UnusedImportsSugg { span: Span, }, #[multipart_suggestion( - lint_suggestion_remove_imports, + "{$num_to_remove -> + [one] remove the unused import + *[other] remove the unused imports + }", applicability = "machine-applicable", style = "tool-only" )] @@ -2699,7 +3119,7 @@ pub(crate) enum UnusedImportsSugg { } #[derive(LintDiagnostic)] -#[diag(lint_redundant_import)] +#[diag("the item `{$ident}` is imported redundantly")] pub(crate) struct RedundantImport { #[subdiagnostic] pub subs: Vec, @@ -2709,24 +3129,24 @@ pub(crate) struct RedundantImport { #[derive(Subdiagnostic)] pub(crate) enum RedundantImportSub { - #[label(lint_label_imported_here)] + #[label("the item `{$ident}` is already imported here")] ImportedHere(#[primary_span] Span), - #[label(lint_label_defined_here)] + #[label("the item `{$ident}` is already defined here")] DefinedHere(#[primary_span] Span), - #[label(lint_label_imported_prelude)] + #[label("the item `{$ident}` is already imported by the extern prelude")] ImportedPrelude(#[primary_span] Span), - #[label(lint_label_defined_prelude)] + #[label("the item `{$ident}` is already defined by the extern prelude")] DefinedPrelude(#[primary_span] Span), } #[derive(LintDiagnostic)] pub(crate) enum PatternsInFnsWithoutBody { - #[diag(lint_pattern_in_foreign)] + #[diag("patterns aren't allowed in foreign function declarations")] Foreign { #[subdiagnostic] sub: PatternsInFnsWithoutBodySub, }, - #[diag(lint_pattern_in_bodiless)] + #[diag("patterns aren't allowed in functions without bodies")] Bodiless { #[subdiagnostic] sub: PatternsInFnsWithoutBodySub, @@ -2734,7 +3154,11 @@ pub(crate) enum PatternsInFnsWithoutBody { } #[derive(Subdiagnostic)] -#[suggestion(lint_remove_mut_from_pattern, code = "{ident}", applicability = "machine-applicable")] +#[suggestion( + "remove `mut` from the parameter", + code = "{ident}", + applicability = "machine-applicable" +)] pub(crate) struct PatternsInFnsWithoutBodySub { #[primary_span] pub span: Span, @@ -2743,34 +3167,44 @@ pub(crate) struct PatternsInFnsWithoutBodySub { } #[derive(LintDiagnostic)] -#[diag(lint_reserved_prefix)] +#[diag("prefix `{$prefix}` is unknown")] pub(crate) struct ReservedPrefix { - #[label] + #[label("unknown prefix")] pub label: Span, - #[suggestion(code = " ", applicability = "machine-applicable")] + #[suggestion( + "insert whitespace here to avoid this being parsed as a prefix in Rust 2021", + code = " ", + applicability = "machine-applicable" + )] pub suggestion: Span, pub prefix: String, } #[derive(LintDiagnostic)] -#[diag(lint_raw_prefix)] +#[diag("prefix `'r` is reserved")] pub(crate) struct RawPrefix { - #[label] + #[label("reserved prefix")] pub label: Span, - #[suggestion(code = " ", applicability = "machine-applicable")] + #[suggestion( + "insert whitespace here to avoid this being parsed as a prefix in Rust 2021", + code = " ", + applicability = "machine-applicable" + )] pub suggestion: Span, } #[derive(LintDiagnostic)] -#[diag(lint_break_with_label_and_loop)] +#[diag( + "this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression" +)] pub(crate) struct BreakWithLabelAndLoop { #[subdiagnostic] pub sub: BreakWithLabelAndLoopSub, } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion("wrap this expression in parentheses", applicability = "machine-applicable")] pub(crate) struct BreakWithLabelAndLoopSub { #[suggestion_part(code = "(")] pub left: Span, @@ -2779,8 +3213,8 @@ pub(crate) struct BreakWithLabelAndLoopSub { } #[derive(LintDiagnostic)] -#[diag(lint_deprecated_where_clause_location)] -#[note] +#[diag("where clause not allowed here")] +#[note("see issue #89122 for more information")] pub(crate) struct DeprecatedWhereClauseLocation { #[subdiagnostic] pub suggestion: DeprecatedWhereClauseLocationSugg, @@ -2788,7 +3222,10 @@ pub(crate) struct DeprecatedWhereClauseLocation { #[derive(Subdiagnostic)] pub(crate) enum DeprecatedWhereClauseLocationSugg { - #[multipart_suggestion(lint_suggestion_move_to_end, applicability = "machine-applicable")] + #[multipart_suggestion( + "move it to the end of the type declaration", + applicability = "machine-applicable" + )] MoveToEnd { #[suggestion_part(code = "")] left: Span, @@ -2797,7 +3234,7 @@ pub(crate) enum DeprecatedWhereClauseLocationSugg { sugg: String, }, - #[suggestion(lint_suggestion_remove_where, code = "", applicability = "machine-applicable")] + #[suggestion("remove this `where`", code = "", applicability = "machine-applicable")] RemoveWhere { #[primary_span] span: Span, @@ -2805,11 +3242,11 @@ pub(crate) enum DeprecatedWhereClauseLocationSugg { } #[derive(LintDiagnostic)] -#[diag(lint_single_use_lifetime)] +#[diag("lifetime parameter `{$ident}` only used once")] pub(crate) struct SingleUseLifetime { - #[label(lint_label_param)] + #[label("this lifetime...")] pub param_span: Span, - #[label(lint_label_use)] + #[label("...is used only here")] pub use_span: Span, #[subdiagnostic] pub suggestion: Option, @@ -2818,7 +3255,7 @@ pub(crate) struct SingleUseLifetime { } #[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion("elide the single-use lifetime", applicability = "machine-applicable")] pub(crate) struct SingleUseLifetimeSugg { #[suggestion_part(code = "")] pub deletion_span: Option, @@ -2829,22 +3266,27 @@ pub(crate) struct SingleUseLifetimeSugg { } #[derive(LintDiagnostic)] -#[diag(lint_unused_lifetime)] +#[diag("lifetime parameter `{$ident}` never used")] pub(crate) struct UnusedLifetime { - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("elide the unused lifetime", code = "", applicability = "machine-applicable")] pub deletion_span: Option, pub ident: Ident, } #[derive(LintDiagnostic)] -#[diag(lint_named_argument_used_positionally)] +#[diag("named argument `{$named_arg_name}` is not used by name")] pub(crate) struct NamedArgumentUsedPositionally { - #[label(lint_label_named_arg)] + #[label("this named argument is referred to by position in formatting string")] pub named_arg_sp: Span, - #[label(lint_label_position_arg)] + #[label("this formatting argument uses named argument `{$named_arg_name}` by position")] pub position_label_sp: Option, - #[suggestion(style = "verbose", code = "{name}", applicability = "maybe-incorrect")] + #[suggestion( + "use the named argument by name to avoid ambiguity", + style = "verbose", + code = "{name}", + applicability = "maybe-incorrect" + )] pub suggestion: Option, pub name: String, @@ -2852,11 +3294,11 @@ pub(crate) struct NamedArgumentUsedPositionally { } #[derive(LintDiagnostic)] -#[diag(lint_ambiguous_glob_reexport)] +#[diag("ambiguous glob re-exports")] pub(crate) struct AmbiguousGlobReexports { - #[label(lint_label_first_reexport)] + #[label("the name `{$name}` in the {$namespace} namespace is first re-exported here")] pub first_reexport: Span, - #[label(lint_label_duplicate_reexport)] + #[label("but the name `{$name}` in the {$namespace} namespace is also re-exported here")] pub duplicate_reexport: Span, pub name: String, @@ -2864,11 +3306,13 @@ pub(crate) struct AmbiguousGlobReexports { } #[derive(LintDiagnostic)] -#[diag(lint_hidden_glob_reexport)] +#[diag("private item shadows public glob re-export")] pub(crate) struct HiddenGlobReexports { - #[note(lint_note_glob_reexport)] + #[note( + "the name `{$name}` in the {$namespace} namespace is supposed to be publicly re-exported here" + )] pub glob_reexport: Span, - #[note(lint_note_private_item)] + #[note("but the private item here shadows it")] pub private_item: Span, pub name: String, @@ -2876,47 +3320,70 @@ pub(crate) struct HiddenGlobReexports { } #[derive(LintDiagnostic)] -#[diag(lint_unnecessary_qualification)] +#[diag("unnecessary qualification")] pub(crate) struct UnusedQualifications { - #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] + #[suggestion( + "remove the unnecessary path segments", + style = "verbose", + code = "", + applicability = "machine-applicable" + )] pub removal_span: Span, } #[derive(LintDiagnostic)] -#[diag(lint_associated_const_elided_lifetime)] +#[diag( + "{$elided -> + [true] `&` without an explicit lifetime name cannot be used here + *[false] `'_` cannot be used here + }" +)] pub(crate) struct AssociatedConstElidedLifetime { - #[suggestion(style = "verbose", code = "{code}", applicability = "machine-applicable")] + #[suggestion( + "use the `'static` lifetime", + style = "verbose", + code = "{code}", + applicability = "machine-applicable" + )] pub span: Span, pub code: &'static str, pub elided: bool, - #[note] + #[note("cannot automatically infer `'static` because of other lifetimes in scope")] pub lifetimes_in_scope: MultiSpan, } #[derive(LintDiagnostic)] -#[diag(lint_static_mut_refs_lint)] +#[diag("creating a {$shared_label}reference to mutable static")] pub(crate) struct RefOfMutStatic<'a> { - #[label] + #[label("{$shared_label}reference to mutable static")] pub span: Span, #[subdiagnostic] pub sugg: Option, pub shared_label: &'a str, - #[note(lint_shared_note)] + #[note( + "shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives" + )] pub shared_note: bool, - #[note(lint_mut_note)] + #[note( + "mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives" + )] pub mut_note: bool, } #[derive(Subdiagnostic)] pub(crate) enum MutRefSugg { - #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")] + #[multipart_suggestion( + "use `&raw const` instead to create a raw pointer", + style = "verbose", + applicability = "maybe-incorrect" + )] Shared { #[suggestion_part(code = "&raw const ")] span: Span, }, #[multipart_suggestion( - lint_suggestion_mut, + "use `&raw mut` instead to create a raw pointer", style = "verbose", applicability = "maybe-incorrect" )] @@ -2927,25 +3394,33 @@ pub(crate) enum MutRefSugg { } #[derive(LintDiagnostic)] -#[diag(lint_unqualified_local_imports)] +#[diag("`use` of a local item without leading `self::`, `super::`, or `crate::`")] pub(crate) struct UnqualifiedLocalImportsDiag {} #[derive(LintDiagnostic)] -#[diag(lint_reserved_string)] +#[diag("will be parsed as a guarded string in Rust 2024")] pub(crate) struct ReservedString { - #[suggestion(code = " ", applicability = "machine-applicable")] + #[suggestion( + "insert whitespace here to avoid this being parsed as a guarded string in Rust 2024", + code = " ", + applicability = "machine-applicable" + )] pub suggestion: Span, } #[derive(LintDiagnostic)] -#[diag(lint_reserved_multihash)] +#[diag("reserved token in Rust 2024")] pub(crate) struct ReservedMultihash { - #[suggestion(code = " ", applicability = "machine-applicable")] + #[suggestion( + "insert whitespace here to avoid this being parsed as a forbidden token in Rust 2024", + code = " ", + applicability = "machine-applicable" + )] pub suggestion: Span, } #[derive(LintDiagnostic)] -#[diag(lint_function_casts_as_integer)] +#[diag("direct cast of function item into an integer")] pub(crate) struct FunctionCastsAsIntegerDiag<'tcx> { #[subdiagnostic] pub(crate) sugg: FunctionCastsAsIntegerSugg<'tcx>, @@ -2953,7 +3428,7 @@ pub(crate) struct FunctionCastsAsIntegerDiag<'tcx> { #[derive(Subdiagnostic)] #[suggestion( - lint_cast_as_fn, + "first cast to a pointer `as *const ()`", code = " as *const ()", applicability = "machine-applicable", style = "verbose" @@ -2981,44 +3456,46 @@ impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for MismatchedLifetimeSynta } LifetimeSyntaxCategories { hidden: _, elided: _, named: 0 } => { - fluent::lint_mismatched_lifetime_syntaxes_hiding_while_elided + inline_fluent!("hiding a lifetime that's elided elsewhere is confusing") } LifetimeSyntaxCategories { hidden: _, elided: 0, named: _ } => { - fluent::lint_mismatched_lifetime_syntaxes_hiding_while_named + inline_fluent!("hiding a lifetime that's named elsewhere is confusing") } LifetimeSyntaxCategories { hidden: 0, elided: _, named: _ } => { - fluent::lint_mismatched_lifetime_syntaxes_eliding_while_named + inline_fluent!("eliding a lifetime that's named elsewhere is confusing") } LifetimeSyntaxCategories { hidden: _, elided: _, named: _ } => { - fluent::lint_mismatched_lifetime_syntaxes_hiding_and_eliding_while_named + inline_fluent!("hiding or eliding a lifetime that's named elsewhere is confusing") } }; diag.primary_message(message); for s in self.inputs.hidden { - diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_input_hidden); + diag.span_label(s, inline_fluent!("the lifetime is hidden here")); } for s in self.inputs.elided { - diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_input_elided); + diag.span_label(s, inline_fluent!("the lifetime is elided here")); } for s in self.inputs.named { - diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_input_named); + diag.span_label(s, inline_fluent!("the lifetime is named here")); } for s in self.outputs.hidden { - diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_output_hidden); + diag.span_label(s, inline_fluent!("the same lifetime is hidden here")); } for s in self.outputs.elided { - diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_output_elided); + diag.span_label(s, inline_fluent!("the same lifetime is elided here")); } for s in self.outputs.named { - diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_output_named); + diag.span_label(s, inline_fluent!("the same lifetime is named here")); } - diag.help(fluent::lint_mismatched_lifetime_syntaxes_help); + diag.help(inline_fluent!( + "the same lifetime is referred to in inconsistent ways, making the signature confusing" + )); let mut suggestions = self.suggestions.into_iter(); if let Some(s) = suggestions.next() { @@ -3092,7 +3569,7 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { Implicit { suggestions, optional_alternative } => { let suggestions = suggestions.into_iter().map(|s| (s, String::new())).collect(); diag.multipart_suggestion_with_style( - fluent::lint_mismatched_lifetime_syntaxes_suggestion_implicit, + inline_fluent!("remove the lifetime name from references"), suggestions, applicability(optional_alternative), style(optional_alternative), @@ -3105,9 +3582,11 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { optional_alternative, } => { let message = if implicit_suggestions.is_empty() { - fluent::lint_mismatched_lifetime_syntaxes_suggestion_mixed_only_paths + inline_fluent!("use `'_` for type paths") } else { - fluent::lint_mismatched_lifetime_syntaxes_suggestion_mixed + inline_fluent!( + "remove the lifetime name from references and use `'_` for type paths" + ) }; let implicit_suggestions = @@ -3126,9 +3605,8 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { Explicit { lifetime_name, suggestions, optional_alternative } => { diag.arg("lifetime_name", lifetime_name); - let msg = diag.eagerly_translate( - fluent::lint_mismatched_lifetime_syntaxes_suggestion_explicit, - ); + let msg = + diag.eagerly_translate(inline_fluent!("consistently use `{$lifetime_name}`")); diag.remove_arg("lifetime_name"); diag.multipart_suggestion_with_style( msg, @@ -3142,78 +3620,107 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { } #[derive(LintDiagnostic)] -#[diag(lint_empty_attribute)] -#[note] +#[diag("unused attribute")] +#[note( + "{$valid_without_list -> + [true] using `{$attr_path}` with an empty list is equivalent to not using a list at all + *[other] using `{$attr_path}` with an empty list has no effect + }" +)] pub(crate) struct EmptyAttributeList { - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion( + "{$valid_without_list -> + [true] remove these parentheses + *[other] remove this attribute + }", + code = "", + applicability = "machine-applicable" + )] pub attr_span: Span, pub attr_path: String, pub valid_without_list: bool, } #[derive(LintDiagnostic)] -#[diag(lint_invalid_target)] -#[warning] -#[help] +#[diag("`#[{$name}]` attribute cannot be used on {$target}")] +#[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" +)] +#[help("`#[{$name}]` can {$only}be applied to {$applied}")] pub(crate) struct InvalidTargetLint { pub name: String, pub target: &'static str, pub applied: DiagArgValue, pub only: &'static str, - #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + #[suggestion( + "remove the attribute", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] pub attr_span: Span, } #[derive(LintDiagnostic)] -#[diag(lint_invalid_style)] +#[diag( + "{$is_used_as_inner -> + [false] crate-level attribute should be an inner attribute: add an exclamation mark: `#![{$name}]` + *[other] the `#![{$name}]` attribute can only be used at the crate root + }" +)] pub(crate) struct InvalidAttrStyle { pub name: String, pub is_used_as_inner: bool, - #[note] + #[note("this attribute does not have an `!`, which means it is applied to this {$target}")] pub target_span: Option, pub target: &'static str, } #[derive(LintDiagnostic)] -#[diag(lint_unused_duplicate)] +#[diag("unused attribute")] pub(crate) struct UnusedDuplicate { - #[suggestion(code = "", applicability = "machine-applicable")] + #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] pub this: Span, - #[note] + #[note("attribute also specified here")] pub other: Span, - #[warning] + #[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" + )] pub warning: bool, } #[derive(LintDiagnostic)] -#[diag(lint_malformed_doc)] -#[warning] +#[diag("malformed `doc` attribute input")] +#[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" +)] pub(crate) struct MalformedDoc; #[derive(LintDiagnostic)] -#[diag(lint_expected_no_args)] -#[warning] +#[diag("didn't expect any arguments here")] +#[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" +)] pub(crate) struct ExpectedNoArgs; #[derive(LintDiagnostic)] -#[diag(lint_expected_name_value)] -#[warning] +#[diag("expected this to be of the form `... = \"...\"`")] +#[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" +)] pub(crate) struct ExpectedNameValue; #[derive(LintDiagnostic)] -#[diag(lint_unsafe_attr_outside_unsafe)] +#[diag("unsafe attribute used without unsafe")] pub(crate) struct UnsafeAttrOutsideUnsafeLint { - #[label] + #[label("usage of unsafe attribute")] pub span: Span, #[subdiagnostic] pub suggestion: Option, } #[derive(Subdiagnostic)] -#[multipart_suggestion( - lint_unsafe_attr_outside_unsafe_suggestion, - applicability = "machine-applicable" -)] +#[multipart_suggestion("wrap the attribute in `unsafe(...)`", applicability = "machine-applicable")] pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { #[suggestion_part(code = "unsafe(")] pub left: Span, @@ -3222,119 +3729,138 @@ pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { } #[derive(LintDiagnostic)] -#[diag(lint_unused_visibilities)] -#[note] +#[diag("visibility qualifiers have no effect on `const _` declarations")] +#[note("`const _` does not declare a name, so there is nothing for the qualifier to apply to")] pub(crate) struct UnusedVisibility { - #[suggestion(style = "short", code = "", applicability = "machine-applicable")] + #[suggestion( + "remove the qualifier", + style = "short", + code = "", + applicability = "machine-applicable" + )] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(lint_doc_alias_duplicated)] +#[diag("doc alias is duplicated")] pub(crate) struct DocAliasDuplicated { - #[label] + #[label("first defined here")] pub first_defn: Span, } #[derive(LintDiagnostic)] -#[diag(lint_doc_auto_cfg_expects_hide_or_show)] +#[diag("only `hide` or `show` are allowed in `#[doc(auto_cfg(...))]`")] pub(crate) struct DocAutoCfgExpectsHideOrShow; #[derive(LintDiagnostic)] -#[diag(lint_doc_auto_cfg_hide_show_unexpected_item)] +#[diag("`#![doc(auto_cfg({$attr_name}(...)))]` only accepts identifiers or key/value items")] pub(crate) struct DocAutoCfgHideShowUnexpectedItem { pub attr_name: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_doc_auto_cfg_hide_show_expects_list)] +#[diag("`#![doc(auto_cfg({$attr_name}(...)))]` expects a list of items")] pub(crate) struct DocAutoCfgHideShowExpectsList { pub attr_name: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_doc_invalid)] +#[diag("invalid `doc` attribute")] pub(crate) struct DocInvalid; #[derive(LintDiagnostic)] -#[diag(lint_doc_unknown_include)] +#[diag("unknown `doc` attribute `include`")] pub(crate) struct DocUnknownInclude { pub inner: &'static str, pub value: Symbol, - #[suggestion(code = "#{inner}[doc = include_str!(\"{value}\")]")] + #[suggestion( + "use `doc = include_str!` instead", + code = "#{inner}[doc = include_str!(\"{value}\")]" + )] pub sugg: (Span, Applicability), } #[derive(LintDiagnostic)] -#[diag(lint_doc_unknown_spotlight)] -#[note] -#[note(lint_no_op_note)] +#[diag("unknown `doc` attribute `spotlight`")] +#[note("`doc(spotlight)` was renamed to `doc(notable_trait)`")] +#[note("`doc(spotlight)` is now a no-op")] pub(crate) struct DocUnknownSpotlight { - #[suggestion(style = "short", applicability = "machine-applicable", code = "notable_trait")] + #[suggestion( + "use `notable_trait` instead", + style = "short", + applicability = "machine-applicable", + code = "notable_trait" + )] pub sugg_span: Span, } #[derive(LintDiagnostic)] -#[diag(lint_doc_unknown_passes)] -#[note] -#[note(lint_no_op_note)] +#[diag("unknown `doc` attribute `{$name}`")] +#[note( + "`doc` attribute `{$name}` no longer functions; see issue #44136 " +)] +#[note("`doc({$name})` is now a no-op")] pub(crate) struct DocUnknownPasses { pub name: Symbol, - #[label] + #[label("no longer functions")] pub note_span: Span, } #[derive(LintDiagnostic)] -#[diag(lint_doc_unknown_plugins)] -#[note] -#[note(lint_no_op_note)] +#[diag("unknown `doc` attribute `plugins`")] +#[note( + "`doc` attribute `plugins` no longer functions; see issue #44136 and CVE-2018-1000622 " +)] +#[note("`doc(plugins)` is now a no-op")] pub(crate) struct DocUnknownPlugins { - #[label] + #[label("no longer functions")] pub label_span: Span, } #[derive(LintDiagnostic)] -#[diag(lint_doc_unknown_any)] +#[diag("unknown `doc` attribute `{$name}`")] pub(crate) struct DocUnknownAny { pub name: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_doc_auto_cfg_wrong_literal)] +#[diag("expected boolean for `#[doc(auto_cfg = ...)]`")] pub(crate) struct DocAutoCfgWrongLiteral; #[derive(LintDiagnostic)] -#[diag(lint_doc_test_takes_list)] +#[diag("`#[doc(test(...)]` takes a list of attributes")] pub(crate) struct DocTestTakesList; #[derive(LintDiagnostic)] -#[diag(lint_doc_test_unknown)] +#[diag("unknown `doc(test)` attribute `{$name}`")] pub(crate) struct DocTestUnknown { pub name: Symbol, } #[derive(LintDiagnostic)] -#[diag(lint_doc_test_literal)] +#[diag("`#![doc(test(...)]` does not take a literal")] pub(crate) struct DocTestLiteral; #[derive(LintDiagnostic)] -#[diag(lint_attr_crate_level)] -#[note] +#[diag("this attribute can only be applied at the crate level")] +#[note( + "read for more information" +)] pub(crate) struct AttrCrateLevelOnly; #[derive(LintDiagnostic)] -#[diag(lint_incorrect_do_not_recommend_args)] +#[diag("`#[diagnostic::do_not_recommend]` does not expect any arguments")] pub(crate) struct DoNotRecommendDoesNotExpectArgs; #[derive(LintDiagnostic)] -#[diag(lint_invalid_crate_type_value)] +#[diag("invalid `crate_type` value")] pub(crate) struct UnknownCrateTypes { #[subdiagnostic] pub sugg: Option, } #[derive(Subdiagnostic)] -#[suggestion(lint_suggestion, code = r#""{snippet}""#, applicability = "maybe-incorrect")] +#[suggestion("did you mean", code = r#""{snippet}""#, applicability = "maybe-incorrect")] pub(crate) struct UnknownCrateTypesSuggestion { #[primary_span] pub span: Span, @@ -3342,18 +3868,18 @@ pub(crate) struct UnknownCrateTypesSuggestion { } #[derive(LintDiagnostic)] -#[diag(lint_unreachable_cfg_select_predicate)] +#[diag("unreachable configuration predicate")] pub(crate) struct UnreachableCfgSelectPredicate { - #[label] + #[label("this configuration predicate is never reached")] pub span: Span, } #[derive(LintDiagnostic)] -#[diag(lint_unreachable_cfg_select_predicate_wildcard)] +#[diag("unreachable configuration predicate")] pub(crate) struct UnreachableCfgSelectPredicateWildcard { - #[label(lint_label2)] + #[label("this configuration predicate is never reached")] pub span: Span, - #[label] + #[label("always matches")] pub wildcard_span: Span, } diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index a07c3b372d34..daf62277693a 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -1,5 +1,5 @@ use rustc_ast as ast; -use rustc_errors::Applicability; +use rustc_errors::{Applicability, inline_fluent}; use rustc_hir::{self as hir, LangItem}; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::{bug, ty}; @@ -10,7 +10,7 @@ use rustc_span::{InnerSpan, Span, Symbol, hygiene, sym}; use rustc_trait_selection::infer::InferCtxtExt; use crate::lints::{NonFmtPanicBraces, NonFmtPanicUnused}; -use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent}; +use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { /// The `non_fmt_panics` lint detects `panic!(..)` invocations where the first @@ -121,20 +121,20 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc } cx.span_lint(NON_FMT_PANICS, arg_span, |lint| { - lint.primary_message(fluent::lint_non_fmt_panic); + lint.primary_message(inline_fluent!("panic message is not a string literal")); lint.arg("name", symbol); - lint.note(fluent::lint_note); - lint.note(fluent::lint_more_info_note); + lint.note(inline_fluent!("this usage of `{$name}!()` is deprecated; it will be a hard error in Rust 2021")); + lint.note(inline_fluent!("for more information, see ")); if !is_arg_inside_call(arg_span, span) { // No clue where this argument is coming from. return; } if arg_macro.is_some_and(|id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) { // A case of `panic!(format!(..))`. - lint.note(fluent::lint_supports_fmt_note); + lint.note(inline_fluent!("the `{$name}!()` macro supports formatting, so there's no need for the `format!()` macro here")); if let Some((open, close, _)) = find_delimiters(cx, arg_span) { lint.multipart_suggestion( - fluent::lint_supports_fmt_suggestion, + inline_fluent!("remove the `format!(..)` macro call"), vec![ (arg_span.until(open.shrink_to_hi()), "".into()), (close.until(arg_span.shrink_to_hi()), "".into()), @@ -178,7 +178,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc if suggest_display { lint.span_suggestion_verbose( arg_span.shrink_to_lo(), - fluent::lint_display_suggestion, + inline_fluent!(r#"add a "{"{"}{"}"}" format string to `Display` the message"#), "\"{}\", ", fmt_applicability, ); @@ -186,7 +186,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc lint.arg("ty", ty); lint.span_suggestion_verbose( arg_span.shrink_to_lo(), - fluent::lint_debug_suggestion, + inline_fluent!(r#"add a "{"{"}:?{"}"}" format string to use the `Debug` implementation of `{$ty}`"#), "\"{:?}\", ", fmt_applicability, ); @@ -196,7 +196,10 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc if let Some((open, close, del)) = find_delimiters(cx, span) { lint.arg("already_suggested", suggest_display || suggest_debug); lint.multipart_suggestion( - fluent::lint_panic_suggestion, + inline_fluent!("{$already_suggested -> + [true] or use + *[false] use + } std::panic::panic_any instead"), if del == '(' { vec![(span.until(open), "std::panic::panic_any".into())] } else { diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index bcf4d9ec3b29..fc7e5a821b02 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -1,4 +1,4 @@ -use rustc_errors::MultiSpan; +use rustc_errors::{MultiSpan, inline_fluent}; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{self, Visitor, VisitorExt}; @@ -9,7 +9,7 @@ use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::{ExpnKind, Span, kw}; use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag}; -use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent}; +use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { /// The `non_local_definitions` lint checks for `impl` blocks and `#[macro_export]` @@ -210,7 +210,12 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { if !doctest { ms.push_span_label( cx.tcx.def_span(parent), - fluent::lint_non_local_definitions_impl_move_help, + inline_fluent!( + "move the `impl` block outside of this {$body_kind_descr} {$depth -> + [one] `{$body_name}` + *[other] `{$body_name}` and up {$depth} bodies + }" + ), ); } diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 3f2ca92a021a..b5b57eaa3389 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -202,11 +202,11 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { } #[derive(LintDiagnostic)] -#[diag(lint_opaque_hidden_inferred_bound)] +#[diag("opaque type `{$ty}` does not satisfy its associated type bounds")] struct OpaqueHiddenInferredBoundLint<'tcx> { ty: Ty<'tcx>, proj_ty: Ty<'tcx>, - #[label(lint_specifically)] + #[label("this associated type bound is unsatisfied for `{$proj_ty}`")] assoc_pred_span: Span, #[subdiagnostic] add_bound: Option>, @@ -214,7 +214,7 @@ struct OpaqueHiddenInferredBoundLint<'tcx> { #[derive(Subdiagnostic)] #[suggestion( - lint_opaque_hidden_inferred_bound_sugg, + "add this bound", style = "verbose", applicability = "machine-applicable", code = " + {trait_ref}" diff --git a/compiler/rustc_lint/src/transmute.rs b/compiler/rustc_lint/src/transmute.rs index 6bc4617eb2dc..e4716c869c5f 100644 --- a/compiler/rustc_lint/src/transmute.rs +++ b/compiler/rustc_lint/src/transmute.rs @@ -369,8 +369,10 @@ fn check_unnecessary_transmute<'tcx>( } #[derive(LintDiagnostic)] -#[diag(lint_undefined_transmute)] -#[note] -#[note(lint_note2)] -#[help] +#[diag("pointers cannot be transmuted to integers during const eval")] +#[note("at compile-time, pointers do not have an integer value")] +#[note( + "avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior" +)] +#[help("for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html")] pub(crate) struct UndefinedTransmuteLint; diff --git a/compiler/rustc_lint/src/types/improper_ctypes.rs b/compiler/rustc_lint/src/types/improper_ctypes.rs index 38094c67c34a..fb9b55efa220 100644 --- a/compiler/rustc_lint/src/types/improper_ctypes.rs +++ b/compiler/rustc_lint/src/types/improper_ctypes.rs @@ -4,7 +4,7 @@ use std::ops::ControlFlow; use bitflags::bitflags; use rustc_abi::VariantIdx; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::DiagMessage; +use rustc_errors::{DiagMessage, inline_fluent}; use rustc_hir::def::CtorKind; use rustc_hir::intravisit::VisitorExt; use rustc_hir::{self as hir, AmbigArg}; @@ -21,7 +21,7 @@ use tracing::debug; use super::repr_nullable_ptr; use crate::lints::{ImproperCTypes, UsesPowerAlignment}; -use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent}; +use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { /// The `improper_ctypes` lint detects incorrect use of types in foreign @@ -158,12 +158,12 @@ pub(crate) fn check_non_exhaustive_variant( // with an enum like `#[repr(u8)] enum Enum { A(DataA), B(DataB), }` // but exempt enums with unit ctors like C's (e.g. from rust-bindgen) if variant_has_complex_ctor(variant) { - return ControlFlow::Break(fluent::lint_improper_ctypes_non_exhaustive); + return ControlFlow::Break(inline_fluent!("this enum is non-exhaustive")); } } if variant.field_list_has_applicable_non_exhaustive() { - return ControlFlow::Break(fluent::lint_improper_ctypes_non_exhaustive_variant); + return ControlFlow::Break(inline_fluent!("this enum has non-exhaustive variants")); } ControlFlow::Continue(()) @@ -424,7 +424,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if all_phantom { FfiPhantom(ty) } else if transparent_with_all_zst_fields { - FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_struct_zst, help: None } + FfiUnsafe { + ty, + reason: inline_fluent!("this struct contains only zero-sized fields"), + help: None, + } } else { FfiSafe } @@ -460,7 +464,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } else { return FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_box, + reason: inline_fluent!("box cannot be represented as a single pointer"), help: None, }; } @@ -476,8 +480,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { { return FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_cstr_reason, - help: Some(fluent::lint_improper_ctypes_cstr_help), + reason: inline_fluent!( + "`CStr`/`CString` do not have a guaranteed layout" + ), + help: Some(inline_fluent!( + "consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()`" + )), }; } @@ -485,14 +493,18 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiUnsafe { ty, reason: if def.is_struct() { - fluent::lint_improper_ctypes_struct_layout_reason + inline_fluent!("this struct has unspecified layout") } else { - fluent::lint_improper_ctypes_union_layout_reason + inline_fluent!("this union has unspecified layout") }, help: if def.is_struct() { - Some(fluent::lint_improper_ctypes_struct_layout_help) + Some(inline_fluent!( + "consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct" + )) } else { - Some(fluent::lint_improper_ctypes_union_layout_help) + Some(inline_fluent!( + "consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union" + )) }, }; } @@ -501,9 +513,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiUnsafe { ty, reason: if def.is_struct() { - fluent::lint_improper_ctypes_struct_non_exhaustive + inline_fluent!("this struct is non-exhaustive") } else { - fluent::lint_improper_ctypes_union_non_exhaustive + inline_fluent!("this union is non-exhaustive") }, help: None, }; @@ -513,14 +525,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiUnsafe { ty, reason: if def.is_struct() { - fluent::lint_improper_ctypes_struct_fieldless_reason + inline_fluent!("this struct has no fields") } else { - fluent::lint_improper_ctypes_union_fieldless_reason + inline_fluent!("this union has no fields") }, help: if def.is_struct() { - Some(fluent::lint_improper_ctypes_struct_fieldless_help) + Some(inline_fluent!("consider adding a member to this struct")) } else { - Some(fluent::lint_improper_ctypes_union_fieldless_help) + Some(inline_fluent!("consider adding a member to this union")) }, }; } @@ -545,8 +557,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_enum_repr_reason, - help: Some(fluent::lint_improper_ctypes_enum_repr_help), + reason: inline_fluent!("enum has no representation hint"), + help: Some(inline_fluent!( + "consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum" + )), }; } @@ -572,8 +586,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::Char => FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_char_reason, - help: Some(fluent::lint_improper_ctypes_char_help), + reason: inline_fluent!("the `char` type has no C equivalent"), + help: Some(inline_fluent!("consider using `u32` or `libc::wchar_t` instead")), }, // It's just extra invariants on the type that you need to uphold, @@ -585,24 +599,26 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::Slice(_) => FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_slice_reason, - help: Some(fluent::lint_improper_ctypes_slice_help), + reason: inline_fluent!("slices have no C equivalent"), + help: Some(inline_fluent!("consider using a raw pointer instead")), }, - ty::Dynamic(..) => { - FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_dyn, help: None } - } + ty::Dynamic(..) => FfiUnsafe { + ty, + reason: inline_fluent!("trait objects have no C equivalent"), + help: None, + }, ty::Str => FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_str_reason, - help: Some(fluent::lint_improper_ctypes_str_help), + reason: inline_fluent!("string slices have no C equivalent"), + help: Some(inline_fluent!("consider using `*const u8` and a length instead")), }, ty::Tuple(..) => FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_tuple_reason, - help: Some(fluent::lint_improper_ctypes_tuple_help), + reason: inline_fluent!("tuples have unspecified layout"), + help: Some(inline_fluent!("consider using a struct instead")), }, ty::RawPtr(ty, _) | ty::Ref(_, ty, _) @@ -632,8 +648,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if sig.abi().is_rustic_abi() { return FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_fnptr_reason, - help: Some(fluent::lint_improper_ctypes_fnptr_help), + reason: inline_fluent!( + "this function pointer has Rust-specific calling convention" + ), + help: Some(inline_fluent!( + "consider using an `extern fn(...) -> ...` function pointer instead" + )), }; } @@ -657,9 +677,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // While opaque types are checked for earlier, if a projection in a struct field // normalizes to an opaque type, then it will reach this branch. - ty::Alias(ty::Opaque, ..) => { - FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_opaque, help: None } - } + ty::Alias(ty::Opaque, ..) => FfiUnsafe { + ty, + reason: inline_fluent!("opaque types have no C equivalent"), + help: None, + }, // `extern "C" fn` functions can have type parameters, which may or may not be FFI-safe, // so they are currently ignored for the purposes of this lint. @@ -669,9 +691,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiSafe } - ty::UnsafeBinder(_) => { - FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_unsafe_binder, help: None } - } + ty::UnsafeBinder(_) => FfiUnsafe { + ty, + reason: inline_fluent!( + "unsafe binders are incompatible with foreign function interfaces" + ), + help: None, + }, ty::Param(..) | ty::Alias(ty::Projection | ty::Inherent | ty::Free, ..) @@ -715,7 +741,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { { Some(FfiResult::FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_opaque, + reason: inline_fluent!("opaque types have no C equivalent"), help: None, }) } else { @@ -728,8 +754,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if let ty::Array(..) = ty.kind() { Some(FfiResult::FfiUnsafe { ty, - reason: fluent::lint_improper_ctypes_array_reason, - help: Some(fluent::lint_improper_ctypes_array_help), + reason: inline_fluent!("passing raw arrays by value is not FFI-safe"), + help: Some(inline_fluent!("consider passing a pointer to the array")), }) } else { None @@ -908,7 +934,7 @@ impl<'tcx> ImproperCTypesLint { cx, ty, sp, - fluent::lint_improper_ctypes_only_phantomdata, + inline_fluent!("composed only of `PhantomData`"), None, fn_mode, ); From f35d734d3fc0105c4f130be961c86deac299dd6c Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 19:32:52 +0100 Subject: [PATCH 682/978] Remove `rustc_fluent_macro` --- Cargo.lock | 13 - compiler/rustc_fluent_macro/Cargo.toml | 18 - compiler/rustc_fluent_macro/src/fluent.rs | 315 ------------------ compiler/rustc_fluent_macro/src/lib.rs | 67 ---- .../builder/cli_paths/snapshots/x_bench.snap | 1 - .../cli_paths/snapshots/x_build_compiler.snap | 1 - .../builder/cli_paths/snapshots/x_check.snap | 1 - .../cli_paths/snapshots/x_check_compiler.snap | 1 - ...eck_compiletest_include_default_paths.snap | 1 - .../builder/cli_paths/snapshots/x_clippy.snap | 1 - .../builder/cli_paths/snapshots/x_fix.snap | 1 - .../builder/cli_paths/snapshots/x_test.snap | 1 - .../snapshots/x_test_skip_coverage.snap | 1 - .../snapshots/x_test_skip_tests.snap | 2 - .../snapshots/x_test_skip_tests_etc.snap | 2 - src/bootstrap/src/core/builder/tests.rs | 10 +- src/bootstrap/src/utils/proc_macro_deps.rs | 3 - 17 files changed, 5 insertions(+), 434 deletions(-) delete mode 100644 compiler/rustc_fluent_macro/Cargo.toml delete mode 100644 compiler/rustc_fluent_macro/src/fluent.rs delete mode 100644 compiler/rustc_fluent_macro/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 03cf3bcba894..545c776b4805 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3888,19 +3888,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "rustc_fluent_macro" -version = "0.0.0" -dependencies = [ - "annotate-snippets 0.11.5", - "fluent-bundle", - "fluent-syntax", - "proc-macro2", - "quote", - "syn 2.0.110", - "unic-langid", -] - [[package]] name = "rustc_fs_util" version = "0.0.0" diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml deleted file mode 100644 index d7ef4280aef0..000000000000 --- a/compiler/rustc_fluent_macro/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "rustc_fluent_macro" -version = "0.0.0" -edition = "2024" - -[lib] -proc-macro = true - -[dependencies] -# tidy-alphabetical-start -annotate-snippets = "0.11" -fluent-bundle = "0.16" -fluent-syntax = "0.12" -proc-macro2 = "1" -quote = "1" -syn = { version = "2", features = ["full"] } -unic-langid = { version = "0.9.0", features = ["macros"] } -# tidy-alphabetical-end diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs deleted file mode 100644 index 41357bb1ac76..000000000000 --- a/compiler/rustc_fluent_macro/src/fluent.rs +++ /dev/null @@ -1,315 +0,0 @@ -use std::collections::{HashMap, HashSet}; -use std::fs::read_to_string; -use std::path::{Path, PathBuf}; - -use annotate_snippets::{Renderer, Snippet}; -use fluent_bundle::{FluentBundle, FluentError, FluentResource}; -use fluent_syntax::ast::{ - Attribute, Entry, Expression, Identifier, InlineExpression, Message, Pattern, PatternElement, -}; -use fluent_syntax::parser::ParserError; -use proc_macro::tracked::path; -use proc_macro::{Diagnostic, Level, Span}; -use proc_macro2::TokenStream; -use quote::quote; -use syn::{Ident, LitStr, parse_macro_input}; -use unic_langid::langid; - -/// Helper function for returning an absolute path for macro-invocation relative file paths. -/// -/// If the input is already absolute, then the input is returned. If the input is not absolute, -/// then it is appended to the directory containing the source file with this macro invocation. -fn invocation_relative_path_to_absolute(span: Span, path: &str) -> PathBuf { - let path = Path::new(path); - if path.is_absolute() { - path.to_path_buf() - } else { - // `/a/b/c/foo/bar.rs` contains the current macro invocation - let mut source_file_path = span.local_file().unwrap(); - // `/a/b/c/foo/` - source_file_path.pop(); - // `/a/b/c/foo/../locales/en-US/example.ftl` - source_file_path.push(path); - source_file_path - } -} - -/// Final tokens. -fn finish(body: TokenStream, resource: TokenStream) -> proc_macro::TokenStream { - quote! { - /// Raw content of Fluent resource for this crate, generated by `fluent_messages` macro, - /// imported by `rustc_driver` to include all crates' resources in one bundle. - pub static DEFAULT_LOCALE_RESOURCE: &'static str = #resource; - - #[allow(non_upper_case_globals)] - #[doc(hidden)] - /// Auto-generated constants for type-checked references to Fluent messages. - pub(crate) mod fluent_generated { - #body - - /// Constants expected to exist by the diagnostic derive macros to use as default Fluent - /// identifiers for different subdiagnostic kinds. - pub mod _subdiag { - /// Default for `#[help]` - pub const help: rustc_errors::SubdiagMessage = - rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("help")); - /// Default for `#[note]` - pub const note: rustc_errors::SubdiagMessage = - rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("note")); - /// Default for `#[warn]` - pub const warn: rustc_errors::SubdiagMessage = - rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("warn")); - /// Default for `#[label]` - pub const label: rustc_errors::SubdiagMessage = - rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("label")); - /// Default for `#[suggestion]` - pub const suggestion: rustc_errors::SubdiagMessage = - rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion")); - } - } - } - .into() -} - -/// Tokens to be returned when the macro cannot proceed. -fn failed(crate_name: &Ident) -> proc_macro::TokenStream { - finish(quote! { pub mod #crate_name {} }, quote! { "" }) -} - -/// See [rustc_fluent_macro::fluent_messages]. -pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let crate_name = std::env::var("CARGO_CRATE_NAME") - // If `CARGO_CRATE_NAME` is missing, then we're probably running in a test, so use - // `no_crate`. - .unwrap_or_else(|_| "no_crate".to_string()) - .replace("rustc_", ""); - - // Cannot iterate over individual messages in a bundle, so do that using the - // `FluentResource` instead. Construct a bundle anyway to find out if there are conflicting - // messages in the resources. - let mut bundle = FluentBundle::new(vec![langid!("en-US")]); - - // Set of Fluent attribute names already output, to avoid duplicate type errors - any given - // constant created for a given attribute is the same. - let mut previous_attrs = HashSet::new(); - - let resource_str = parse_macro_input!(input as LitStr); - let resource_span = resource_str.span().unwrap(); - let relative_ftl_path = resource_str.value(); - let absolute_ftl_path = invocation_relative_path_to_absolute(resource_span, &relative_ftl_path); - - let crate_name = Ident::new(&crate_name, resource_str.span()); - - path(absolute_ftl_path.to_str().unwrap()); - let resource_contents = match read_to_string(absolute_ftl_path) { - Ok(resource_contents) => resource_contents, - Err(e) => { - Diagnostic::spanned( - resource_span, - Level::Error, - format!("could not open Fluent resource: {e}"), - ) - .emit(); - return failed(&crate_name); - } - }; - let mut bad = false; - for esc in ["\\n", "\\\"", "\\'"] { - for _ in resource_contents.matches(esc) { - bad = true; - Diagnostic::spanned(resource_span, Level::Error, format!("invalid escape `{esc}` in Fluent resource")) - .note("Fluent does not interpret these escape sequences ()") - .emit(); - } - } - if bad { - return failed(&crate_name); - } - - let resource = match FluentResource::try_new(resource_contents) { - Ok(resource) => resource, - Err((this, errs)) => { - Diagnostic::spanned(resource_span, Level::Error, "could not parse Fluent resource") - .help("see additional errors emitted") - .emit(); - for ParserError { pos, slice: _, kind } in errs { - let mut err = kind.to_string(); - // Entirely unnecessary string modification so that the error message starts - // with a lowercase as rustc errors do. - err.replace_range(0..1, &err.chars().next().unwrap().to_lowercase().to_string()); - - let message = annotate_snippets::Level::Error.title(&err).snippet( - Snippet::source(this.source()) - .origin(&relative_ftl_path) - .fold(true) - .annotation(annotate_snippets::Level::Error.span(pos.start..pos.end - 1)), - ); - let renderer = Renderer::plain(); - eprintln!("{}\n", renderer.render(message)); - } - - return failed(&crate_name); - } - }; - - let mut constants = TokenStream::new(); - let mut previous_defns = HashMap::new(); - let mut message_refs = Vec::new(); - for entry in resource.entries() { - if let Entry::Message(msg) = entry { - let Message { id: Identifier { name }, attributes, value, .. } = msg; - let _ = previous_defns.entry(name.to_string()).or_insert(resource_span); - if name.contains('-') { - Diagnostic::spanned( - resource_span, - Level::Error, - format!("name `{name}` contains a '-' character"), - ) - .help("replace any '-'s with '_'s") - .emit(); - } - - if let Some(Pattern { elements }) = value { - for elt in elements { - if let PatternElement::Placeable { - expression: - Expression::Inline(InlineExpression::MessageReference { id, .. }), - } = elt - { - message_refs.push((id.name, *name)); - } - } - } - - // `typeck_foo_bar` => `foo_bar` (in `typeck.ftl`) - // `const_eval_baz` => `baz` (in `const_eval.ftl`) - // `const-eval-hyphen-having` => `hyphen_having` (in `const_eval.ftl`) - // The last case we error about above, but we want to fall back gracefully - // so that only the error is being emitted and not also one about the macro - // failing. - let crate_prefix = format!("{crate_name}_"); - - let snake_name = name.replace('-', "_"); - if !snake_name.starts_with(&crate_prefix) { - Diagnostic::spanned( - resource_span, - Level::Error, - format!("name `{name}` does not start with the crate name"), - ) - .help(format!( - "prepend `{crate_prefix}` to the slug name: `{crate_prefix}{snake_name}`" - )) - .emit(); - }; - let snake_name = Ident::new(&snake_name, resource_str.span()); - - if !previous_attrs.insert(snake_name.clone()) { - continue; - } - - let docstr = - format!("Constant referring to Fluent message `{name}` from `{crate_name}`"); - constants.extend(quote! { - #[doc = #docstr] - pub const #snake_name: rustc_errors::DiagMessage = - rustc_errors::DiagMessage::FluentIdentifier( - std::borrow::Cow::Borrowed(#name), - None - ); - }); - - for Attribute { id: Identifier { name: attr_name }, .. } in attributes { - let snake_name = Ident::new( - &format!("{crate_prefix}{}", attr_name.replace('-', "_")), - resource_str.span(), - ); - if !previous_attrs.insert(snake_name.clone()) { - continue; - } - - if attr_name.contains('-') { - Diagnostic::spanned( - resource_span, - Level::Error, - format!("attribute `{attr_name}` contains a '-' character"), - ) - .help("replace any '-'s with '_'s") - .emit(); - } - - let msg = format!( - "Constant referring to Fluent message `{name}.{attr_name}` from `{crate_name}`" - ); - constants.extend(quote! { - #[doc = #msg] - pub const #snake_name: rustc_errors::SubdiagMessage = - rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed(#attr_name)); - }); - } - - // Record variables referenced by these messages so we can produce - // tests in the derive diagnostics to validate them. - let ident = quote::format_ident!("{snake_name}_refs"); - let vrefs = variable_references(msg); - constants.extend(quote! { - #[cfg(test)] - pub const #ident: &[&str] = &[#(#vrefs),*]; - }) - } - } - - for (mref, name) in message_refs.into_iter() { - if !previous_defns.contains_key(mref) { - Diagnostic::spanned( - resource_span, - Level::Error, - format!("referenced message `{mref}` does not exist (in message `{name}`)"), - ) - .help(format!("you may have meant to use a variable reference (`{{${mref}}}`)")) - .emit(); - } - } - - if let Err(errs) = bundle.add_resource(resource) { - for e in errs { - match e { - FluentError::Overriding { kind, id } => { - Diagnostic::spanned( - resource_span, - Level::Error, - format!("overrides existing {kind}: `{id}`"), - ) - .emit(); - } - FluentError::ResolverError(_) | FluentError::ParserError(_) => unreachable!(), - } - } - } - - finish(constants, quote! { include_str!(#relative_ftl_path) }) -} - -fn variable_references<'a>(msg: &Message<&'a str>) -> Vec<&'a str> { - let mut refs = vec![]; - if let Some(Pattern { elements }) = &msg.value { - for elt in elements { - if let PatternElement::Placeable { - expression: Expression::Inline(InlineExpression::VariableReference { id }), - } = elt - { - refs.push(id.name); - } - } - } - for attr in &msg.attributes { - for elt in &attr.value.elements { - if let PatternElement::Placeable { - expression: Expression::Inline(InlineExpression::VariableReference { id }), - } = elt - { - refs.push(id.name); - } - } - } - refs -} diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs deleted file mode 100644 index 9cd947c4c672..000000000000 --- a/compiler/rustc_fluent_macro/src/lib.rs +++ /dev/null @@ -1,67 +0,0 @@ -// tidy-alphabetical-start -#![allow(rustc::default_hash_types)] -#![feature(proc_macro_diagnostic)] -#![feature(proc_macro_tracked_path)] -// tidy-alphabetical-end - -use proc_macro::TokenStream; - -mod fluent; - -/// Implements the `fluent_messages` macro, which performs compile-time validation of the -/// compiler's Fluent resources (i.e. that the resources parse and don't multiply define the same -/// messages) and generates constants that make using those messages in diagnostics more ergonomic. -/// -/// For example, given the following invocation of the macro.. -/// -/// ```ignore (rust) -/// fluent_messages! { "./typeck.ftl" } -/// ``` -/// ..where `typeck.ftl` has the following contents.. -/// -/// ```fluent -/// typeck_field_multiply_specified_in_initializer = -/// field `{$ident}` specified more than once -/// .label = used more than once -/// .label_previous_use = first use of `{$ident}` -/// ``` -/// ...then the macro parse the Fluent resource, emitting a diagnostic if it fails to do so, and -/// will generate the following code: -/// -/// ```ignore (rust) -/// pub static DEFAULT_LOCALE_RESOURCE: &'static [&'static str] = include_str!("./typeck.ftl"); -/// -/// mod fluent_generated { -/// mod typeck { -/// pub const field_multiply_specified_in_initializer: DiagMessage = -/// DiagMessage::fluent("typeck_field_multiply_specified_in_initializer"); -/// pub const field_multiply_specified_in_initializer_label_previous_use: DiagMessage = -/// DiagMessage::fluent_attr( -/// "typeck_field_multiply_specified_in_initializer", -/// "previous_use_label" -/// ); -/// } -/// } -/// ``` -/// When emitting a diagnostic, the generated constants can be used as follows: -/// -/// ```ignore (rust) -/// let mut err = sess.struct_span_err( -/// span, -/// fluent::typeck::field_multiply_specified_in_initializer -/// ); -/// err.span_default_label(span); -/// err.span_label( -/// previous_use_span, -/// fluent::typeck::field_multiply_specified_in_initializer_label_previous_use -/// ); -/// err.emit(); -/// ``` -/// -/// Note: any crate using this macro must also have a dependency on -/// `rustc_errors`, because the generated code refers to things from that -/// crate. -#[proc_macro] -pub fn fluent_messages(input: TokenStream) -> TokenStream { - fluent::fluent_messages(input) -} diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap index 13a06e353d89..3adf952d66e0 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_bench.snap @@ -44,7 +44,6 @@ expression: bench - Set({bench::compiler/rustc_errors}) - Set({bench::compiler/rustc_expand}) - Set({bench::compiler/rustc_feature}) - - Set({bench::compiler/rustc_fluent_macro}) - Set({bench::compiler/rustc_fs_util}) - Set({bench::compiler/rustc_graphviz}) - Set({bench::compiler/rustc_hashes}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_build_compiler.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_build_compiler.snap index 721ecaf4c487..1d6e63696b06 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_build_compiler.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_build_compiler.snap @@ -26,7 +26,6 @@ expression: build compiler - Set({build::compiler/rustc_errors}) - Set({build::compiler/rustc_expand}) - Set({build::compiler/rustc_feature}) - - Set({build::compiler/rustc_fluent_macro}) - Set({build::compiler/rustc_fs_util}) - Set({build::compiler/rustc_graphviz}) - Set({build::compiler/rustc_hashes}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap index 4c3b6e11b0e4..6fc2e190290e 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check.snap @@ -28,7 +28,6 @@ expression: check - Set({check::compiler/rustc_errors}) - Set({check::compiler/rustc_expand}) - Set({check::compiler/rustc_feature}) - - Set({check::compiler/rustc_fluent_macro}) - Set({check::compiler/rustc_fs_util}) - Set({check::compiler/rustc_graphviz}) - Set({check::compiler/rustc_hashes}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiler.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiler.snap index 71d9c0fafb80..c0456f7f84d3 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiler.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiler.snap @@ -28,7 +28,6 @@ expression: check compiler - Set({check::compiler/rustc_errors}) - Set({check::compiler/rustc_expand}) - Set({check::compiler/rustc_feature}) - - Set({check::compiler/rustc_fluent_macro}) - Set({check::compiler/rustc_fs_util}) - Set({check::compiler/rustc_graphviz}) - Set({check::compiler/rustc_hashes}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap index 16348adc79df..10f36ffa6748 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_check_compiletest_include_default_paths.snap @@ -28,7 +28,6 @@ expression: check compiletest --include-default-paths - Set({check::compiler/rustc_errors}) - Set({check::compiler/rustc_expand}) - Set({check::compiler/rustc_feature}) - - Set({check::compiler/rustc_fluent_macro}) - Set({check::compiler/rustc_fs_util}) - Set({check::compiler/rustc_graphviz}) - Set({check::compiler/rustc_hashes}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_clippy.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_clippy.snap index fe8334641285..492a10d3862a 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_clippy.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_clippy.snap @@ -43,7 +43,6 @@ expression: clippy - Set({clippy::compiler/rustc_errors}) - Set({clippy::compiler/rustc_expand}) - Set({clippy::compiler/rustc_feature}) - - Set({clippy::compiler/rustc_fluent_macro}) - Set({clippy::compiler/rustc_fs_util}) - Set({clippy::compiler/rustc_graphviz}) - Set({clippy::compiler/rustc_hashes}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap index 8a11b4d89dde..41889cd12480 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_fix.snap @@ -28,7 +28,6 @@ expression: fix - Set({fix::compiler/rustc_errors}) - Set({fix::compiler/rustc_expand}) - Set({fix::compiler/rustc_feature}) - - Set({fix::compiler/rustc_fluent_macro}) - Set({fix::compiler/rustc_fs_util}) - Set({fix::compiler/rustc_graphviz}) - Set({fix::compiler/rustc_hashes}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap index 46e93aa667cc..51e2c270e3ba 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap @@ -94,7 +94,6 @@ expression: test - Set({test::compiler/rustc_errors}) - Set({test::compiler/rustc_expand}) - Set({test::compiler/rustc_feature}) - - Set({test::compiler/rustc_fluent_macro}) - Set({test::compiler/rustc_fs_util}) - Set({test::compiler/rustc_graphviz}) - Set({test::compiler/rustc_hashes}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap index c27da5a2a9e2..bc828c162bb0 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap @@ -93,7 +93,6 @@ expression: test --skip=coverage - Set({test::compiler/rustc_errors}) - Set({test::compiler/rustc_expand}) - Set({test::compiler/rustc_feature}) - - Set({test::compiler/rustc_fluent_macro}) - Set({test::compiler/rustc_fs_util}) - Set({test::compiler/rustc_graphviz}) - Set({test::compiler/rustc_hashes}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap index d5d709a60b49..ceb910e4cb36 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests.snap @@ -1,6 +1,5 @@ --- source: src/bootstrap/src/core/builder/cli_paths/tests.rs -assertion_line: 68 expression: test --skip=tests --- [Test] test::Tidy @@ -58,7 +57,6 @@ expression: test --skip=tests - Set({test::compiler/rustc_errors}) - Set({test::compiler/rustc_expand}) - Set({test::compiler/rustc_feature}) - - Set({test::compiler/rustc_fluent_macro}) - Set({test::compiler/rustc_fs_util}) - Set({test::compiler/rustc_graphviz}) - Set({test::compiler/rustc_hashes}) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap index 85ca8f6ef7a0..f0e8f1aee2c7 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_etc.snap @@ -1,6 +1,5 @@ --- source: src/bootstrap/src/core/builder/cli_paths/tests.rs -assertion_line: 68 expression: test --skip=tests --skip=coverage-map --skip=coverage-run --skip=library --skip=tidyselftest --- [Test] test::Tidy @@ -38,7 +37,6 @@ expression: test --skip=tests --skip=coverage-map --skip=coverage-run --skip=lib - Set({test::compiler/rustc_errors}) - Set({test::compiler/rustc_expand}) - Set({test::compiler/rustc_feature}) - - Set({test::compiler/rustc_fluent_macro}) - Set({test::compiler/rustc_fs_util}) - Set({test::compiler/rustc_graphviz}) - Set({test::compiler/rustc_hashes}) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index af26c2f87d02..61db494c8c18 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1815,7 +1815,7 @@ mod snapshot { insta::assert_snapshot!( ctx.config("check") .path("compiler") - .render_steps(), @"[check] rustc 0 -> rustc 1 (75 crates)"); + .render_steps(), @"[check] rustc 0 -> rustc 1 (74 crates)"); } #[test] @@ -1841,7 +1841,7 @@ mod snapshot { ctx.config("check") .path("compiler") .stage(1) - .render_steps(), @"[check] rustc 0 -> rustc 1 (75 crates)"); + .render_steps(), @"[check] rustc 0 -> rustc 1 (74 crates)"); } #[test] @@ -1855,7 +1855,7 @@ mod snapshot { [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 - [check] rustc 1 -> rustc 2 (75 crates) + [check] rustc 1 -> rustc 2 (74 crates) "); } @@ -1871,7 +1871,7 @@ mod snapshot { [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 [check] rustc 1 -> std 1 - [check] rustc 1 -> rustc 2 (75 crates) + [check] rustc 1 -> rustc 2 (74 crates) [check] rustc 1 -> rustc 2 [check] rustc 1 -> Rustdoc 2 [check] rustc 1 -> rustc_codegen_cranelift 2 @@ -1967,7 +1967,7 @@ mod snapshot { ctx.config("check") .paths(&["library", "compiler"]) .args(&args) - .render_steps(), @"[check] rustc 0 -> rustc 1 (75 crates)"); + .render_steps(), @"[check] rustc 0 -> rustc 1 (74 crates)"); } #[test] diff --git a/src/bootstrap/src/utils/proc_macro_deps.rs b/src/bootstrap/src/utils/proc_macro_deps.rs index f1bf6e399fb1..fee9b12aca06 100644 --- a/src/bootstrap/src/utils/proc_macro_deps.rs +++ b/src/bootstrap/src/utils/proc_macro_deps.rs @@ -3,8 +3,6 @@ /// See pub static CRATES: &[&str] = &[ // tidy-alphabetical-start - "annotate-snippets", - "anstyle", "askama_derive", "askama_parser", "basic-toml", @@ -59,7 +57,6 @@ pub static CRATES: &[&str] = &[ "unic-langid-impl", "unic-langid-macros", "unicode-ident", - "unicode-width", "version_check", "wasm-bindgen-macro-support", "wasm-bindgen-shared", From 38374315165c83e77008f4457b862fd7aeee7d6d Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 19:04:39 +0100 Subject: [PATCH 683/978] Remove `ui-fulldeps` tests for slugs --- .../fluent-messages/duplicate-a-b.ftl | 1 - .../fluent-messages/duplicate-a.ftl | 1 - .../ui-fulldeps/fluent-messages/duplicate.ftl | 3 - .../fluent-messages/invalid-escape.ftl | 1 - .../fluent-messages/label-with-hyphens.ftl | 2 - .../fluent-messages/many-lines.ftl | 11 - .../fluent-messages/missing-crate-name.ftl | 2 - .../fluent-messages/missing-message-ref.ftl | 1 - .../fluent-messages/missing-message.ftl | 1 - .../fluent-messages/slug-with-hyphens.ftl | 1 - tests/ui-fulldeps/fluent-messages/test.rs | 87 -- tests/ui-fulldeps/fluent-messages/test.stderr | 122 --- tests/ui-fulldeps/fluent-messages/valid.ftl | 1 - .../session-diagnostic/diagnostic-derive.rs | 827 ------------------ .../diagnostic-derive.stderr | 634 -------------- .../session-diagnostic/enforce_slug_naming.rs | 24 - .../enforce_slug_naming.stderr | 11 - .../session-diagnostic/example.ftl | 7 - .../session-diagnostic/invalid-variable.rs | 20 - .../subdiagnostic-derive-2.rs | 37 - .../subdiagnostic-derive-2.stderr | 9 - .../subdiagnostic-derive.rs | 809 ----------------- .../subdiagnostic-derive.stderr | 549 ------------ 23 files changed, 3161 deletions(-) delete mode 100644 tests/ui-fulldeps/fluent-messages/duplicate-a-b.ftl delete mode 100644 tests/ui-fulldeps/fluent-messages/duplicate-a.ftl delete mode 100644 tests/ui-fulldeps/fluent-messages/duplicate.ftl delete mode 100644 tests/ui-fulldeps/fluent-messages/invalid-escape.ftl delete mode 100644 tests/ui-fulldeps/fluent-messages/label-with-hyphens.ftl delete mode 100644 tests/ui-fulldeps/fluent-messages/many-lines.ftl delete mode 100644 tests/ui-fulldeps/fluent-messages/missing-crate-name.ftl delete mode 100644 tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl delete mode 100644 tests/ui-fulldeps/fluent-messages/missing-message.ftl delete mode 100644 tests/ui-fulldeps/fluent-messages/slug-with-hyphens.ftl delete mode 100644 tests/ui-fulldeps/fluent-messages/test.rs delete mode 100644 tests/ui-fulldeps/fluent-messages/test.stderr delete mode 100644 tests/ui-fulldeps/fluent-messages/valid.ftl delete mode 100644 tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs delete mode 100644 tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr delete mode 100644 tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs delete mode 100644 tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr delete mode 100644 tests/ui-fulldeps/session-diagnostic/example.ftl delete mode 100644 tests/ui-fulldeps/session-diagnostic/invalid-variable.rs delete mode 100644 tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-2.rs delete mode 100644 tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-2.stderr delete mode 100644 tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs delete mode 100644 tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr diff --git a/tests/ui-fulldeps/fluent-messages/duplicate-a-b.ftl b/tests/ui-fulldeps/fluent-messages/duplicate-a-b.ftl deleted file mode 100644 index 9407c5170450..000000000000 --- a/tests/ui-fulldeps/fluent-messages/duplicate-a-b.ftl +++ /dev/null @@ -1 +0,0 @@ -a_b_key = Value diff --git a/tests/ui-fulldeps/fluent-messages/duplicate-a.ftl b/tests/ui-fulldeps/fluent-messages/duplicate-a.ftl deleted file mode 100644 index 9407c5170450..000000000000 --- a/tests/ui-fulldeps/fluent-messages/duplicate-a.ftl +++ /dev/null @@ -1 +0,0 @@ -a_b_key = Value diff --git a/tests/ui-fulldeps/fluent-messages/duplicate.ftl b/tests/ui-fulldeps/fluent-messages/duplicate.ftl deleted file mode 100644 index 871550b231a3..000000000000 --- a/tests/ui-fulldeps/fluent-messages/duplicate.ftl +++ /dev/null @@ -1,3 +0,0 @@ -no_crate_a_b_key = Value - -no_crate_a_b_key = Another Value diff --git a/tests/ui-fulldeps/fluent-messages/invalid-escape.ftl b/tests/ui-fulldeps/fluent-messages/invalid-escape.ftl deleted file mode 100644 index e28852ea0050..000000000000 --- a/tests/ui-fulldeps/fluent-messages/invalid-escape.ftl +++ /dev/null @@ -1 +0,0 @@ -no_crate_bad_escape = don't use \n, \', or \" diff --git a/tests/ui-fulldeps/fluent-messages/label-with-hyphens.ftl b/tests/ui-fulldeps/fluent-messages/label-with-hyphens.ftl deleted file mode 100644 index 3088b1f8dc83..000000000000 --- a/tests/ui-fulldeps/fluent-messages/label-with-hyphens.ftl +++ /dev/null @@ -1,2 +0,0 @@ -no_crate_some_slug = hi - .label-has-hyphens = test diff --git a/tests/ui-fulldeps/fluent-messages/many-lines.ftl b/tests/ui-fulldeps/fluent-messages/many-lines.ftl deleted file mode 100644 index 43660ebeacdc..000000000000 --- a/tests/ui-fulldeps/fluent-messages/many-lines.ftl +++ /dev/null @@ -1,11 +0,0 @@ -no_crate_foo = foo - -# This file tests error reporting for -# fluent files with many lines. -# The error message should point to the correct line number -# and include no more context than necessary. - -no_crate_bar = - -no_crate_baz = - baz diff --git a/tests/ui-fulldeps/fluent-messages/missing-crate-name.ftl b/tests/ui-fulldeps/fluent-messages/missing-crate-name.ftl deleted file mode 100644 index 0a64e3894bd5..000000000000 --- a/tests/ui-fulldeps/fluent-messages/missing-crate-name.ftl +++ /dev/null @@ -1,2 +0,0 @@ -with-hyphens = 1234 -no-crate_foo = abcd diff --git a/tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl b/tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl deleted file mode 100644 index 4c6514a97700..000000000000 --- a/tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl +++ /dev/null @@ -1 +0,0 @@ -no_crate_missing_message_ref = {message} diff --git a/tests/ui-fulldeps/fluent-messages/missing-message.ftl b/tests/ui-fulldeps/fluent-messages/missing-message.ftl deleted file mode 100644 index 61f56fd4d57b..000000000000 --- a/tests/ui-fulldeps/fluent-messages/missing-message.ftl +++ /dev/null @@ -1 +0,0 @@ -no_crate_missing_message = diff --git a/tests/ui-fulldeps/fluent-messages/slug-with-hyphens.ftl b/tests/ui-fulldeps/fluent-messages/slug-with-hyphens.ftl deleted file mode 100644 index a64c85094f1d..000000000000 --- a/tests/ui-fulldeps/fluent-messages/slug-with-hyphens.ftl +++ /dev/null @@ -1 +0,0 @@ -no_crate_this-slug-has-hyphens = hi diff --git a/tests/ui-fulldeps/fluent-messages/test.rs b/tests/ui-fulldeps/fluent-messages/test.rs deleted file mode 100644 index c1f5fe730c76..000000000000 --- a/tests/ui-fulldeps/fluent-messages/test.rs +++ /dev/null @@ -1,87 +0,0 @@ -//@ normalize-stderr: "could not open Fluent resource:.*" -> "could not open Fluent resource: os-specific message" - -#![feature(rustc_private)] -#![crate_type = "lib"] -extern crate rustc_errors; -extern crate rustc_fluent_macro; - -/// Copy of the relevant `DiagMessage` variant constructed by `fluent_messages` as it -/// expects `crate::DiagMessage` to exist. -pub enum DiagMessage { - FluentIdentifier(std::borrow::Cow<'static, str>, Option>), -} - -/// Copy of the relevant `SubdiagMessage` variant constructed by `fluent_messages` as it -/// expects `crate::SubdiagMessage` to exist. -pub enum SubdiagMessage { - FluentAttr(std::borrow::Cow<'static, str>), -} - -mod missing_absolute { - rustc_fluent_macro::fluent_messages! { "/definitely_does_not_exist.ftl" } - //~^ ERROR could not open Fluent resource -} - -mod missing_relative { - rustc_fluent_macro::fluent_messages! { "../definitely_does_not_exist.ftl" } - //~^ ERROR could not open Fluent resource -} - -mod missing_message { - rustc_fluent_macro::fluent_messages! { "./missing-message.ftl" } - //~^ ERROR could not parse Fluent resource -} - -mod duplicate { - rustc_fluent_macro::fluent_messages! { "./duplicate.ftl" } - //~^ ERROR overrides existing message: `no_crate_a_b_key` -} - -mod slug_with_hyphens { - rustc_fluent_macro::fluent_messages! { "./slug-with-hyphens.ftl" } - //~^ ERROR name `no_crate_this-slug-has-hyphens` contains a '-' character -} - -mod label_with_hyphens { - rustc_fluent_macro::fluent_messages! { "./label-with-hyphens.ftl" } - //~^ ERROR attribute `label-has-hyphens` contains a '-' character -} - -mod valid { - rustc_fluent_macro::fluent_messages! { "./valid.ftl" } - - mod test_generated { - use super::{fluent_generated::no_crate_key, DEFAULT_LOCALE_RESOURCE}; - } -} - -mod missing_crate_name { - rustc_fluent_macro::fluent_messages! { "./missing-crate-name.ftl" } - //~^ ERROR name `no-crate_foo` contains a '-' character - //~| ERROR name `with-hyphens` contains a '-' character - //~| ERROR name `with-hyphens` does not start with the crate name - - mod test_generated { - use super::{ - fluent_generated::{no_crate_foo, with_hyphens}, - DEFAULT_LOCALE_RESOURCE, - }; - } -} - -mod missing_message_ref { - rustc_fluent_macro::fluent_messages! { "./missing-message-ref.ftl" } - //~^ ERROR referenced message `message` does not exist -} - -mod bad_escape { - rustc_fluent_macro::fluent_messages! { "./invalid-escape.ftl" } - //~^ ERROR invalid escape `\n` - //~| ERROR invalid escape `\"` - //~| ERROR invalid escape `\'` -} - -mod many_lines { - rustc_fluent_macro::fluent_messages! { "./many-lines.ftl" } - //~^ ERROR could not parse Fluent resource -} diff --git a/tests/ui-fulldeps/fluent-messages/test.stderr b/tests/ui-fulldeps/fluent-messages/test.stderr deleted file mode 100644 index 0b3bb14ce513..000000000000 --- a/tests/ui-fulldeps/fluent-messages/test.stderr +++ /dev/null @@ -1,122 +0,0 @@ -error: could not open Fluent resource: os-specific message - --> $DIR/test.rs:21:44 - | -LL | rustc_fluent_macro::fluent_messages! { "/definitely_does_not_exist.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: could not open Fluent resource: os-specific message - --> $DIR/test.rs:26:44 - | -LL | rustc_fluent_macro::fluent_messages! { "../definitely_does_not_exist.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: could not parse Fluent resource - --> $DIR/test.rs:31:44 - | -LL | rustc_fluent_macro::fluent_messages! { "./missing-message.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: see additional errors emitted - -error: expected a message field for "no_crate_missing_message" - --> ./missing-message.ftl:1:1 - | -1 | no_crate_missing_message = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - -error: overrides existing message: `no_crate_a_b_key` - --> $DIR/test.rs:36:44 - | -LL | rustc_fluent_macro::fluent_messages! { "./duplicate.ftl" } - | ^^^^^^^^^^^^^^^^^ - -error: name `no_crate_this-slug-has-hyphens` contains a '-' character - --> $DIR/test.rs:41:44 - | -LL | rustc_fluent_macro::fluent_messages! { "./slug-with-hyphens.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: replace any '-'s with '_'s - -error: attribute `label-has-hyphens` contains a '-' character - --> $DIR/test.rs:46:44 - | -LL | rustc_fluent_macro::fluent_messages! { "./label-with-hyphens.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: replace any '-'s with '_'s - -error: name `with-hyphens` contains a '-' character - --> $DIR/test.rs:59:44 - | -LL | rustc_fluent_macro::fluent_messages! { "./missing-crate-name.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: replace any '-'s with '_'s - -error: name `with-hyphens` does not start with the crate name - --> $DIR/test.rs:59:44 - | -LL | rustc_fluent_macro::fluent_messages! { "./missing-crate-name.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: prepend `no_crate_` to the slug name: `no_crate_with_hyphens` - -error: name `no-crate_foo` contains a '-' character - --> $DIR/test.rs:59:44 - | -LL | rustc_fluent_macro::fluent_messages! { "./missing-crate-name.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: replace any '-'s with '_'s - -error: referenced message `message` does not exist (in message `no_crate_missing_message_ref`) - --> $DIR/test.rs:73:44 - | -LL | rustc_fluent_macro::fluent_messages! { "./missing-message-ref.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: you may have meant to use a variable reference (`{$message}`) - -error: invalid escape `\n` in Fluent resource - --> $DIR/test.rs:78:44 - | -LL | rustc_fluent_macro::fluent_messages! { "./invalid-escape.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: Fluent does not interpret these escape sequences () - -error: invalid escape `\"` in Fluent resource - --> $DIR/test.rs:78:44 - | -LL | rustc_fluent_macro::fluent_messages! { "./invalid-escape.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: Fluent does not interpret these escape sequences () - -error: invalid escape `\'` in Fluent resource - --> $DIR/test.rs:78:44 - | -LL | rustc_fluent_macro::fluent_messages! { "./invalid-escape.ftl" } - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: Fluent does not interpret these escape sequences () - -error: could not parse Fluent resource - --> $DIR/test.rs:85:44 - | -LL | rustc_fluent_macro::fluent_messages! { "./many-lines.ftl" } - | ^^^^^^^^^^^^^^^^^^ - | - = help: see additional errors emitted - -error: expected a message field for "no_crate_bar" - --> ./many-lines.ftl:8:1 - | -8 | no_crate_bar = - | ^^^^^^^^^^^^^^ - | - -error: aborting due to 14 previous errors - diff --git a/tests/ui-fulldeps/fluent-messages/valid.ftl b/tests/ui-fulldeps/fluent-messages/valid.ftl deleted file mode 100644 index 598473adb680..000000000000 --- a/tests/ui-fulldeps/fluent-messages/valid.ftl +++ /dev/null @@ -1 +0,0 @@ -no_crate_key = Valid! diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs deleted file mode 100644 index 798eca68b1c9..000000000000 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ /dev/null @@ -1,827 +0,0 @@ -//@ check-fail -// Tests error conditions for specifying diagnostics using #[derive(Diagnostic)] -//@ normalize-stderr: "the following other types implement trait `IntoDiagArg`:(?:.*\n){0,9}\s+and \d+ others" -> "normalized in stderr" -//@ normalize-stderr: "(COMPILER_DIR/.*\.rs):[0-9]+:[0-9]+" -> "$1:LL:CC" - -// The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly, -// changing the output of this test. Since Diagnostic is strictly internal to the compiler -// the test is just ignored on stable and beta: -//@ ignore-stage1 -//@ ignore-beta -//@ ignore-stable - -#![feature(rustc_private)] -#![crate_type = "lib"] - -extern crate rustc_span; -use rustc_span::symbol::Ident; -use rustc_span::Span; - -extern crate rustc_fluent_macro; -extern crate rustc_macros; -use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; - -extern crate rustc_middle; -use rustc_middle::ty::Ty; - -extern crate rustc_errors; -use rustc_errors::{Applicability, DiagMessage, ErrCode, MultiSpan, SubdiagMessage}; - -extern crate rustc_session; - -extern crate core; - -rustc_fluent_macro::fluent_messages! { "./example.ftl" } - -// E0123 and E0456 are no longer used, so we define our own constants here just for this test. -const E0123: ErrCode = ErrCode::from_u32(0123); -const E0456: ErrCode = ErrCode::from_u32(0456); - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct Hello {} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct HelloWarn {} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -//~^ ERROR unsupported type attribute for diagnostic derive enum -enum DiagnosticOnEnum { - Foo, - //~^ ERROR diagnostic slug not specified - Bar, - //~^ ERROR diagnostic slug not specified -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -#[diag = "E0123"] -//~^ ERROR expected parentheses: #[diag(...)] -struct WrongStructAttrStyle {} - -#[derive(Diagnostic)] -#[nonsense(no_crate_example, code = E0123)] -//~^ ERROR `#[nonsense(...)]` is not a valid attribute -//~^^ ERROR diagnostic slug not specified -//~^^^ ERROR cannot find attribute `nonsense` in this scope -struct InvalidStructAttr {} - -#[derive(Diagnostic)] -#[diag(code = E0123)] -//~^ ERROR diagnostic slug not specified -struct InvalidLitNestedAttr {} - -#[derive(Diagnostic)] -#[diag(nonsense, code = E0123)] -//~^ ERROR cannot find value `nonsense` in module `crate::fluent_generated` -struct InvalidNestedStructAttr {} - -#[derive(Diagnostic)] -#[diag(nonsense("foo"), code = E0123, slug = "foo")] -//~^ ERROR derive(Diagnostic): diagnostic slug not specified -struct InvalidNestedStructAttr1 {} - -#[derive(Diagnostic)] -#[diag(nonsense = "...", code = E0123, slug = "foo")] -//~^ ERROR diagnostic slug not specified -struct InvalidNestedStructAttr2 {} - -#[derive(Diagnostic)] -#[diag(nonsense = 4, code = E0123, slug = "foo")] -//~^ ERROR diagnostic slug not specified -struct InvalidNestedStructAttr3 {} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123, slug = "foo")] -//~^ ERROR unknown argument -struct InvalidNestedStructAttr4 {} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct WrongPlaceField { - #[suggestion = "bar"] - //~^ ERROR `#[suggestion = ...]` is not a valid attribute - sp: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -#[diag(no_crate_example, code = E0456)] -//~^ ERROR specified multiple times -struct DiagSpecifiedTwice {} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123, code = E0456)] -//~^ ERROR specified multiple times -struct CodeSpecifiedTwice {} - -#[derive(Diagnostic)] -#[diag(no_crate_example, no_crate::example, code = E0123)] -//~^ ERROR diagnostic slug must be the first argument -struct SlugSpecifiedTwice {} - -#[derive(Diagnostic)] -struct KindNotProvided {} //~ ERROR diagnostic slug not specified - -#[derive(Diagnostic)] -#[diag(code = E0123)] -//~^ ERROR diagnostic slug not specified -struct SlugNotProvided {} - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct CodeNotProvided {} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct MessageWrongType { - #[primary_span] - //~^ ERROR `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - foo: String, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct InvalidPathFieldAttr { - #[nonsense] - //~^ ERROR `#[nonsense]` is not a valid attribute - //~^^ ERROR cannot find attribute `nonsense` in this scope - foo: String, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct ErrorWithField { - name: String, - #[label(no_crate_label)] - span: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct ErrorWithMessageAppliedToField { - #[label(no_crate_label)] - //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - name: String, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct ErrorWithNonexistentField { - #[suggestion(no_crate_suggestion, code = "{name}")] - //~^ ERROR `name` doesn't refer to a field on this type - suggestion: (Span, Applicability), -} - -#[derive(Diagnostic)] -//~^ ERROR invalid format string: expected `}` -#[diag(no_crate_example, code = E0123)] -struct ErrorMissingClosingBrace { - #[suggestion(no_crate_suggestion, code = "{name")] - suggestion: (Span, Applicability), - name: String, - val: usize, -} - -#[derive(Diagnostic)] -//~^ ERROR invalid format string: unmatched `}` -#[diag(no_crate_example, code = E0123)] -struct ErrorMissingOpeningBrace { - #[suggestion(no_crate_suggestion, code = "name}")] - suggestion: (Span, Applicability), - name: String, - val: usize, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct LabelOnSpan { - #[label(no_crate_label)] - sp: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct LabelOnNonSpan { - #[label(no_crate_label)] - //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - id: u32, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct Suggest { - #[suggestion(no_crate_suggestion, code = "This is the suggested code")] - #[suggestion(no_crate_suggestion, code = "This is the suggested code", style = "normal")] - #[suggestion(no_crate_suggestion, code = "This is the suggested code", style = "short")] - #[suggestion(no_crate_suggestion, code = "This is the suggested code", style = "hidden")] - #[suggestion(no_crate_suggestion, code = "This is the suggested code", style = "verbose")] - suggestion: (Span, Applicability), -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct SuggestWithoutCode { - #[suggestion(no_crate_suggestion)] - //~^ ERROR suggestion without `code = "..."` - suggestion: (Span, Applicability), -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct SuggestWithBadKey { - #[suggestion(nonsense = "bar")] - //~^ ERROR invalid nested attribute - //~| ERROR suggestion without `code = "..."` - suggestion: (Span, Applicability), -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct SuggestWithShorthandMsg { - #[suggestion(msg = "bar")] - //~^ ERROR invalid nested attribute - //~| ERROR suggestion without `code = "..."` - suggestion: (Span, Applicability), -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct SuggestWithoutMsg { - #[suggestion(code = "bar")] - suggestion: (Span, Applicability), -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct SuggestWithTypesSwapped { - #[suggestion(no_crate_suggestion, code = "This is suggested code")] - suggestion: (Applicability, Span), -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct SuggestWithWrongTypeApplicabilityOnly { - #[suggestion(no_crate_suggestion, code = "This is suggested code")] - //~^ ERROR wrong field type for suggestion - suggestion: Applicability, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct SuggestWithSpanOnly { - #[suggestion(no_crate_suggestion, code = "This is suggested code")] - suggestion: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct SuggestWithDuplicateSpanAndApplicability { - #[suggestion(no_crate_suggestion, code = "This is suggested code")] - suggestion: (Span, Span, Applicability), - //~^ ERROR specified multiple times -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct SuggestWithDuplicateApplicabilityAndSpan { - #[suggestion(no_crate_suggestion, code = "This is suggested code")] - suggestion: (Applicability, Applicability, Span), - //~^ ERROR specified multiple times -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct WrongKindOfAnnotation { - #[label = "bar"] - //~^ ERROR `#[label = ...]` is not a valid attribute - z: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct OptionsInErrors { - #[label(no_crate_label)] - label: Option, - #[suggestion(no_crate_suggestion, code = "...")] - opt_sugg: Option<(Span, Applicability)>, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct MoveOutOfBorrowError<'tcx> { - name: Ident, - ty: Ty<'tcx>, - #[primary_span] - #[label(no_crate_label)] - span: Span, - #[label(no_crate_label)] - other_span: Span, - #[suggestion(no_crate_suggestion, code = "{name}.clone()")] - opt_sugg: Option<(Span, Applicability)>, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct ErrorWithLifetime<'a> { - #[label(no_crate_label)] - span: Span, - name: &'a str, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct ErrorWithDefaultLabelAttr<'a> { - #[label] - span: Span, - name: &'a str, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct ArgFieldWithoutSkip { - #[primary_span] - span: Span, - other: Hello, - //~^ ERROR the trait bound `Hello: IntoDiagArg` is not satisfied -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct ArgFieldWithSkip { - #[primary_span] - span: Span, - // `Hello` does not implement `IntoDiagArg` so this would result in an error if - // not for `#[skip_arg]`. - #[skip_arg] - other: Hello, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct ErrorWithSpannedNote { - #[note] - span: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct ErrorWithSpannedNoteCustom { - #[note(no_crate_note)] - span: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -#[note] -struct ErrorWithNote { - val: String, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -#[note(no_crate_note)] -struct ErrorWithNoteCustom { - val: String, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct ErrorWithSpannedHelp { - #[help] - span: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct ErrorWithSpannedHelpCustom { - #[help(no_crate_help)] - span: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -#[help] -struct ErrorWithHelp { - val: String, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -#[help(no_crate_help)] -struct ErrorWithHelpCustom { - val: String, -} - -#[derive(Diagnostic)] -#[help] -#[diag(no_crate_example, code = E0123)] -struct ErrorWithHelpWrongOrder { - val: String, -} - -#[derive(Diagnostic)] -#[help(no_crate_help)] -#[diag(no_crate_example, code = E0123)] -struct ErrorWithHelpCustomWrongOrder { - val: String, -} - -#[derive(Diagnostic)] -#[note] -#[diag(no_crate_example, code = E0123)] -struct ErrorWithNoteWrongOrder { - val: String, -} - -#[derive(Diagnostic)] -#[note(no_crate_note)] -#[diag(no_crate_example, code = E0123)] -struct ErrorWithNoteCustomWrongOrder { - val: String, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct ApplicabilityInBoth { - #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")] - //~^ ERROR specified multiple times - suggestion: (Span, Applicability), -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct InvalidApplicability { - #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")] - //~^ ERROR invalid applicability - suggestion: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct ValidApplicability { - #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")] - suggestion: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct NoApplicability { - #[suggestion(no_crate_suggestion, code = "...")] - suggestion: Span, -} - -#[derive(Subdiagnostic)] -#[note(no_crate_example)] -struct Note; - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct Subdiagnostic { - #[subdiagnostic] - note: Note, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct VecField { - #[primary_span] - #[label] - spans: Vec, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct UnitField { - #[primary_span] - spans: Span, - #[help] - foo: (), - #[help(no_crate_help)] - bar: (), -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct OptUnitField { - #[primary_span] - spans: Span, - #[help] - foo: Option<()>, - #[help(no_crate_help)] - bar: Option<()>, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct BoolField { - #[primary_span] - spans: Span, - #[help] - foo: bool, - #[help(no_crate_help)] - //~^ ERROR the `#[help(...)]` attribute can only be applied to fields of type - // only allow plain 'bool' fields - bar: Option, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct LabelWithTrailingPath { - #[label(no_crate_label, foo)] - //~^ ERROR a diagnostic slug must be the first argument to the attribute - span: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct LabelWithTrailingNameValue { - #[label(no_crate_label, foo = "...")] - //~^ ERROR no nested attribute expected here - span: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct LabelWithTrailingList { - #[label(no_crate_label, foo("..."))] - //~^ ERROR no nested attribute expected here - span: Span, -} - -#[derive(LintDiagnostic)] -#[diag(no_crate_example)] -struct LintsGood {} - -#[derive(LintDiagnostic)] -#[diag(no_crate_example)] -struct PrimarySpanOnLint { - #[primary_span] - //~^ ERROR `#[primary_span]` is not a valid attribute - span: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct ErrorWithMultiSpan { - #[primary_span] - span: MultiSpan, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -#[warning] -struct ErrorWithWarn { - val: String, -} - -#[derive(Diagnostic)] -#[error(no_crate_example, code = E0123)] -//~^ ERROR `#[error(...)]` is not a valid attribute -//~| ERROR diagnostic slug not specified -//~| ERROR cannot find attribute `error` in this scope -struct ErrorAttribute {} - -#[derive(Diagnostic)] -#[warn_(no_crate_example, code = E0123)] -//~^ ERROR `#[warn_(...)]` is not a valid attribute -//~| ERROR diagnostic slug not specified -//~| ERROR cannot find attribute `warn_` in this scope -struct WarnAttribute {} - -#[derive(Diagnostic)] -#[lint(no_crate_example, code = E0123)] -//~^ ERROR `#[lint(...)]` is not a valid attribute -//~| ERROR diagnostic slug not specified -//~| ERROR cannot find attribute `lint` in this scope -struct LintAttributeOnSessionDiag {} - -#[derive(LintDiagnostic)] -#[lint(no_crate_example, code = E0123)] -//~^ ERROR `#[lint(...)]` is not a valid attribute -//~| ERROR diagnostic slug not specified -//~| ERROR cannot find attribute `lint` in this scope -struct LintAttributeOnLintDiag {} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct DuplicatedSuggestionCode { - #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] - //~^ ERROR specified multiple times - suggestion: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct InvalidTypeInSuggestionTuple { - #[suggestion(no_crate_suggestion, code = "...")] - suggestion: (Span, usize), - //~^ ERROR wrong types for suggestion -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct MissingApplicabilityInSuggestionTuple { - #[suggestion(no_crate_suggestion, code = "...")] - suggestion: (Span,), - //~^ ERROR wrong types for suggestion -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct MissingCodeInSuggestion { - #[suggestion(no_crate_suggestion)] - //~^ ERROR suggestion without `code = "..."` - suggestion: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -#[multipart_suggestion(no_crate_suggestion)] -//~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute -//~| ERROR cannot find attribute `multipart_suggestion` in this scope -#[multipart_suggestion()] -//~^ ERROR cannot find attribute `multipart_suggestion` in this scope -//~| ERROR `#[multipart_suggestion(...)]` is not a valid attribute -struct MultipartSuggestion { - #[multipart_suggestion(no_crate_suggestion)] - //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute - //~| ERROR cannot find attribute `multipart_suggestion` in this scope - suggestion: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -#[suggestion(no_crate_suggestion, code = "...")] -//~^ ERROR `#[suggestion(...)]` is not a valid attribute -struct SuggestionOnStruct { - #[primary_span] - suggestion: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -#[label] -//~^ ERROR `#[label]` is not a valid attribute -struct LabelOnStruct { - #[primary_span] - suggestion: Span, -} - -#[derive(Diagnostic)] -enum ExampleEnum { - #[diag(no_crate_example)] - Foo { - #[primary_span] - sp: Span, - #[note] - note_sp: Span, - }, - #[diag(no_crate_example)] - Bar { - #[primary_span] - sp: Span, - }, - #[diag(no_crate_example)] - Baz, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct RawIdentDiagnosticArg { - pub r#type: String, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct SubdiagnosticBad { - #[subdiagnostic(bad)] - //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute - note: Note, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct SubdiagnosticBadStr { - #[subdiagnostic = "bad"] - //~^ ERROR `#[subdiagnostic = ...]` is not a valid attribute - note: Note, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct SubdiagnosticBadTwice { - #[subdiagnostic(bad, bad)] - //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute - note: Note, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct SubdiagnosticBadLitStr { - #[subdiagnostic("bad")] - //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute - note: Note, -} - -#[derive(LintDiagnostic)] -#[diag(no_crate_example)] -struct SubdiagnosticEagerLint { - #[subdiagnostic(eager)] - //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute - note: Note, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct SubdiagnosticEagerFormerlyCorrect { - #[subdiagnostic(eager)] - //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute - note: Note, -} - -// Check that formatting of `correct` in suggestion doesn't move the binding for that field, making -// the `arg` call a compile error; and that isn't worked around by moving the `arg` call -// after the `span_suggestion` call - which breaks eager translation. - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, applicability = "machine-applicable", code = "{correct}")] -pub(crate) struct SubdiagnosticWithSuggestion { - #[primary_span] - span: Span, - invalid: String, - correct: String, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct SubdiagnosticEagerSuggestion { - #[subdiagnostic(eager)] - //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute - sub: SubdiagnosticWithSuggestion, -} - -/// with a doc comment on the type.. -#[derive(Diagnostic)] -#[diag(no_crate_example, code = E0123)] -struct WithDocComment { - /// ..and the field - #[primary_span] - span: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct SuggestionsGood { - #[suggestion(code("foo", "bar"))] - sub: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct SuggestionsSingleItem { - #[suggestion(code("foo"))] - sub: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct SuggestionsNoItem { - #[suggestion(code())] - //~^ ERROR expected at least one string literal for `code(...)` - sub: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct SuggestionsInvalidItem { - #[suggestion(code(foo))] - //~^ ERROR `code(...)` must contain only string literals - //~| ERROR unexpected token, expected `)` - sub: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct SuggestionsInvalidLiteral { - #[suggestion(code = 3)] - //~^ ERROR expected string literal - sub: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct SuggestionStyleGood { - #[suggestion(code = "", style = "hidden")] - sub: Span, -} - -#[derive(Diagnostic)] -#[diag(no_crate_example)] -struct SuggestionOnVec { - #[suggestion(no_crate_suggestion, code = "")] - //~^ ERROR `#[suggestion(...)]` is not a valid attribute - sub: Vec, -} diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr deleted file mode 100644 index 9ecb6c15767e..000000000000 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ /dev/null @@ -1,634 +0,0 @@ -error: derive(Diagnostic): unsupported type attribute for diagnostic derive enum - --> $DIR/diagnostic-derive.rs:49:1 - | -LL | #[diag(no_crate_example, code = E0123)] - | ^ - -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:52:5 - | -LL | Foo, - | ^^^ - | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` - -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:54:5 - | -LL | Bar, - | ^^^ - | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` - -error: expected parentheses: #[diag(...)] - --> $DIR/diagnostic-derive.rs:60:8 - | -LL | #[diag = "E0123"] - | ^ - -error: derive(Diagnostic): `#[nonsense(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:65:1 - | -LL | #[nonsense(no_crate_example, code = E0123)] - | ^ - -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:65:1 - | -LL | #[nonsense(no_crate_example, code = E0123)] - | ^ - | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` - -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:72:1 - | -LL | #[diag(code = E0123)] - | ^ - | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` - -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:82:1 - | -LL | #[diag(nonsense("foo"), code = E0123, slug = "foo")] - | ^ - | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` - -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:87:1 - | -LL | #[diag(nonsense = "...", code = E0123, slug = "foo")] - | ^ - | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` - -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:92:1 - | -LL | #[diag(nonsense = 4, code = E0123, slug = "foo")] - | ^ - | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` - -error: derive(Diagnostic): unknown argument - --> $DIR/diagnostic-derive.rs:97:40 - | -LL | #[diag(no_crate_example, code = E0123, slug = "foo")] - | ^^^^ - | - = note: only the `code` parameter is valid after the slug - -error: derive(Diagnostic): `#[suggestion = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:104:5 - | -LL | #[suggestion = "bar"] - | ^ - -error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive.rs:111:26 - | -LL | #[diag(no_crate_example, code = E0456)] - | ^^^^ - | -note: previously specified here - --> $DIR/diagnostic-derive.rs:110:26 - | -LL | #[diag(no_crate_example, code = E0123)] - | ^^^^ - -error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive.rs:116:40 - | -LL | #[diag(no_crate_example, code = E0123, code = E0456)] - | ^^^^ - | -note: previously specified here - --> $DIR/diagnostic-derive.rs:116:26 - | -LL | #[diag(no_crate_example, code = E0123, code = E0456)] - | ^^^^ - -error: derive(Diagnostic): diagnostic slug must be the first argument - --> $DIR/diagnostic-derive.rs:121:26 - | -LL | #[diag(no_crate_example, no_crate::example, code = E0123)] - | ^^^^^^^^ - -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:126:1 - | -LL | struct KindNotProvided {} - | ^^^^^^ - | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` - -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:129:1 - | -LL | #[diag(code = E0123)] - | ^ - | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` - -error: derive(Diagnostic): the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:140:5 - | -LL | #[primary_span] - | ^ - -error: derive(Diagnostic): `#[nonsense]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:148:5 - | -LL | #[nonsense] - | ^ - -error: derive(Diagnostic): the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:165:5 - | -LL | #[label(no_crate_label)] - | ^ - -error: derive(Diagnostic): `name` doesn't refer to a field on this type - --> $DIR/diagnostic-derive.rs:173:46 - | -LL | #[suggestion(no_crate_suggestion, code = "{name}")] - | ^^^^^^^^ - -error: invalid format string: expected `}` but string was terminated - --> $DIR/diagnostic-derive.rs:178:10 - | -LL | #[derive(Diagnostic)] - | ^^^^^^^^^^ expected `}` in format string - | - = note: if you intended to print `{`, you can escape it using `{{` - = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: invalid format string: unmatched `}` found - --> $DIR/diagnostic-derive.rs:188:10 - | -LL | #[derive(Diagnostic)] - | ^^^^^^^^^^ unmatched `}` in format string - | - = note: if you intended to print `}`, you can escape it using `}}` - = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: derive(Diagnostic): the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:208:5 - | -LL | #[label(no_crate_label)] - | ^ - -error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:227:5 - | -LL | #[suggestion(no_crate_suggestion)] - | ^ - -error: derive(Diagnostic): invalid nested attribute - --> $DIR/diagnostic-derive.rs:235:18 - | -LL | #[suggestion(nonsense = "bar")] - | ^^^^^^^^ - | - = help: only `style`, `code` and `applicability` are valid nested attributes - -error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:235:5 - | -LL | #[suggestion(nonsense = "bar")] - | ^ - -error: derive(Diagnostic): invalid nested attribute - --> $DIR/diagnostic-derive.rs:244:18 - | -LL | #[suggestion(msg = "bar")] - | ^^^ - | - = help: only `style`, `code` and `applicability` are valid nested attributes - -error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:244:5 - | -LL | #[suggestion(msg = "bar")] - | ^ - -error: derive(Diagnostic): wrong field type for suggestion - --> $DIR/diagnostic-derive.rs:267:5 - | -LL | #[suggestion(no_crate_suggestion, code = "This is suggested code")] - | ^ - | - = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` - -error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive.rs:283:24 - | -LL | suggestion: (Span, Span, Applicability), - | ^^^^ - | -note: previously specified here - --> $DIR/diagnostic-derive.rs:283:18 - | -LL | suggestion: (Span, Span, Applicability), - | ^^^^ - -error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive.rs:291:33 - | -LL | suggestion: (Applicability, Applicability, Span), - | ^^^^^^^^^^^^^ - | -note: previously specified here - --> $DIR/diagnostic-derive.rs:291:18 - | -LL | suggestion: (Applicability, Applicability, Span), - | ^^^^^^^^^^^^^ - -error: derive(Diagnostic): `#[label = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:298:5 - | -LL | #[label = "bar"] - | ^ - -error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive.rs:449:5 - | -LL | #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")] - | ^ - | -note: previously specified here - --> $DIR/diagnostic-derive.rs:451:24 - | -LL | suggestion: (Span, Applicability), - | ^^^^^^^^^^^^^ - -error: derive(Diagnostic): invalid applicability - --> $DIR/diagnostic-derive.rs:457:69 - | -LL | #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")] - | ^^^^^^^^ - -error: derive(Diagnostic): the `#[help(...)]` attribute can only be applied to fields of type `Span`, `MultiSpan`, `bool` or `()` - --> $DIR/diagnostic-derive.rs:524:5 - | -LL | #[help(no_crate_help)] - | ^ - -error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute - --> $DIR/diagnostic-derive.rs:533:29 - | -LL | #[label(no_crate_label, foo)] - | ^^^ - -error: derive(Diagnostic): no nested attribute expected here - --> $DIR/diagnostic-derive.rs:541:29 - | -LL | #[label(no_crate_label, foo = "...")] - | ^^^ - -error: derive(Diagnostic): no nested attribute expected here - --> $DIR/diagnostic-derive.rs:549:29 - | -LL | #[label(no_crate_label, foo("..."))] - | ^^^ - -error: derive(Diagnostic): `#[primary_span]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:561:5 - | -LL | #[primary_span] - | ^ - | - = help: the `primary_span` field attribute is not valid for lint diagnostics - -error: derive(Diagnostic): `#[error(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:581:1 - | -LL | #[error(no_crate_example, code = E0123)] - | ^ - -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:581:1 - | -LL | #[error(no_crate_example, code = E0123)] - | ^ - | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` - -error: derive(Diagnostic): `#[warn_(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:588:1 - | -LL | #[warn_(no_crate_example, code = E0123)] - | ^ - -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:588:1 - | -LL | #[warn_(no_crate_example, code = E0123)] - | ^ - | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` - -error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:595:1 - | -LL | #[lint(no_crate_example, code = E0123)] - | ^ - -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:595:1 - | -LL | #[lint(no_crate_example, code = E0123)] - | ^ - | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` - -error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:602:1 - | -LL | #[lint(no_crate_example, code = E0123)] - | ^ - -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:602:1 - | -LL | #[lint(no_crate_example, code = E0123)] - | ^ - | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` - -error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive.rs:611:53 - | -LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] - | ^^^^ - | -note: previously specified here - --> $DIR/diagnostic-derive.rs:611:39 - | -LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] - | ^^^^ - -error: derive(Diagnostic): wrong types for suggestion - --> $DIR/diagnostic-derive.rs:620:24 - | -LL | suggestion: (Span, usize), - | ^^^^^ - | - = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` - -error: derive(Diagnostic): wrong types for suggestion - --> $DIR/diagnostic-derive.rs:628:17 - | -LL | suggestion: (Span,), - | ^^^^^^^ - | - = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` - -error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:635:5 - | -LL | #[suggestion(no_crate_suggestion)] - | ^ - -error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:642:1 - | -LL | #[multipart_suggestion(no_crate_suggestion)] - | ^ - | - = help: consider creating a `Subdiagnostic` instead - -error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:645:1 - | -LL | #[multipart_suggestion()] - | ^ - | - = help: consider creating a `Subdiagnostic` instead - -error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:649:5 - | -LL | #[multipart_suggestion(no_crate_suggestion)] - | ^ - | - = help: consider creating a `Subdiagnostic` instead - -error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:657:1 - | -LL | #[suggestion(no_crate_suggestion, code = "...")] - | ^ - | - = help: `#[label]` and `#[suggestion]` can only be applied to fields - -error: derive(Diagnostic): `#[label]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:666:1 - | -LL | #[label] - | ^ - | - = help: `#[label]` and `#[suggestion]` can only be applied to fields - -error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:700:5 - | -LL | #[subdiagnostic(bad)] - | ^ - -error: derive(Diagnostic): `#[subdiagnostic = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:708:5 - | -LL | #[subdiagnostic = "bad"] - | ^ - -error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:716:5 - | -LL | #[subdiagnostic(bad, bad)] - | ^ - -error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:724:5 - | -LL | #[subdiagnostic("bad")] - | ^ - -error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:732:5 - | -LL | #[subdiagnostic(eager)] - | ^ - -error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:740:5 - | -LL | #[subdiagnostic(eager)] - | ^ - -error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:761:5 - | -LL | #[subdiagnostic(eager)] - | ^ - -error: derive(Diagnostic): expected at least one string literal for `code(...)` - --> $DIR/diagnostic-derive.rs:792:23 - | -LL | #[suggestion(code())] - | ^ - -error: derive(Diagnostic): `code(...)` must contain only string literals - --> $DIR/diagnostic-derive.rs:800:23 - | -LL | #[suggestion(code(foo))] - | ^^^ - -error: unexpected token, expected `)` - --> $DIR/diagnostic-derive.rs:800:23 - | -LL | #[suggestion(code(foo))] - | ^^^ - -error: expected string literal - --> $DIR/diagnostic-derive.rs:809:25 - | -LL | #[suggestion(code = 3)] - | ^ - -error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:824:5 - | -LL | #[suggestion(no_crate_suggestion, code = "")] - | ^ - | - = note: `#[suggestion(...)]` applied to `Vec` field is ambiguous - = help: to show a suggestion consisting of multiple parts, use a `Subdiagnostic` annotated with `#[multipart_suggestion(...)]` - = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]` - -error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:65:3 - | -LL | #[nonsense(no_crate_example, code = E0123)] - | ^^^^^^^^ - -error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:148:7 - | -LL | #[nonsense] - | ^^^^^^^^ - -error: cannot find attribute `error` in this scope - --> $DIR/diagnostic-derive.rs:581:3 - | -LL | #[error(no_crate_example, code = E0123)] - | ^^^^^ - | -help: `error` is an attribute that can be used by the derive macro `Error`, you might be missing a `derive` attribute - | -LL + #[derive(Error)] -LL | struct ErrorAttribute {} - | - -error: cannot find attribute `warn_` in this scope - --> $DIR/diagnostic-derive.rs:588:3 - | -LL | #[warn_(no_crate_example, code = E0123)] - | ^^^^^ - | -help: a built-in attribute with a similar name exists - | -LL - #[warn_(no_crate_example, code = E0123)] -LL + #[warn(no_crate_example, code = E0123)] - | - -error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:595:3 - | -LL | #[lint(no_crate_example, code = E0123)] - | ^^^^ - | -help: a built-in attribute with a similar name exists - | -LL - #[lint(no_crate_example, code = E0123)] -LL + #[link(no_crate_example, code = E0123)] - | - -error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:602:3 - | -LL | #[lint(no_crate_example, code = E0123)] - | ^^^^ - | -help: a built-in attribute with a similar name exists - | -LL - #[lint(no_crate_example, code = E0123)] -LL + #[link(no_crate_example, code = E0123)] - | - -error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:642:3 - | -LL | #[multipart_suggestion(no_crate_suggestion)] - | ^^^^^^^^^^^^^^^^^^^^ - | -help: `multipart_suggestion` is an attribute that can be used by the derive macro `Subdiagnostic`, you might be missing a `derive` attribute - | -LL + #[derive(Subdiagnostic)] -LL | struct MultipartSuggestion { - | - -error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:645:3 - | -LL | #[multipart_suggestion()] - | ^^^^^^^^^^^^^^^^^^^^ - | -help: `multipart_suggestion` is an attribute that can be used by the derive macro `Subdiagnostic`, you might be missing a `derive` attribute - | -LL + #[derive(Subdiagnostic)] -LL | struct MultipartSuggestion { - | - -error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:649:7 - | -LL | #[multipart_suggestion(no_crate_suggestion)] - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: `multipart_suggestion` is an attribute that can be used by the derive macro `Subdiagnostic`, you might be missing a `derive` attribute - -error[E0425]: cannot find value `nonsense` in module `crate::fluent_generated` - --> $DIR/diagnostic-derive.rs:77:8 - | -LL | #[diag(nonsense, code = E0123)] - | ^^^^^^^^ not found in `crate::fluent_generated` - -error[E0277]: the trait bound `Hello: IntoDiagArg` is not satisfied - --> $DIR/diagnostic-derive.rs:347:12 - | -LL | #[derive(Diagnostic)] - | ---------- required by a bound introduced by this call -... -LL | other: Hello, - | ^^^^^ unsatisfied trait bound - | -help: the nightly-only, unstable trait `IntoDiagArg` is not implemented for `Hello` - --> $DIR/diagnostic-derive.rs:42:1 - | -LL | struct Hello {} - | ^^^^^^^^^^^^ - = help: normalized in stderr -note: required by a bound in `Diag::<'a, G>::arg` - --> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC - ::: $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC - | - = note: in this macro invocation - = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 80 previous errors - -Some errors have detailed explanations: E0277, E0425. -For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs deleted file mode 100644 index 6402b00ef0a9..000000000000 --- a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ rustc-env:CARGO_CRATE_NAME=rustc_dummy - -#![feature(rustc_private)] -#![crate_type = "lib"] - -extern crate rustc_span; -use rustc_span::symbol::Ident; -use rustc_span::Span; - -extern crate rustc_macros; -use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; - -extern crate rustc_middle; -use rustc_middle::ty::Ty; - -extern crate rustc_errors; -use rustc_errors::{Applicability, MultiSpan}; - -extern crate rustc_session; - -#[derive(Diagnostic)] -#[diag(compiletest_example, code = E0123)] -//~^ ERROR diagnostic slug and crate name do not match -struct Hello {} diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr deleted file mode 100644 index 4f54239f0fa3..000000000000 --- a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: derive(Diagnostic): diagnostic slug and crate name do not match - --> $DIR/enforce_slug_naming.rs:22:8 - | -LL | #[diag(compiletest_example, code = E0123)] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: slug is `compiletest_example` but the crate name is `rustc_dummy` - = help: expected a slug starting with `dummy_...` - -error: aborting due to 1 previous error - diff --git a/tests/ui-fulldeps/session-diagnostic/example.ftl b/tests/ui-fulldeps/session-diagnostic/example.ftl deleted file mode 100644 index 1d1ba8e1bd5c..000000000000 --- a/tests/ui-fulldeps/session-diagnostic/example.ftl +++ /dev/null @@ -1,7 +0,0 @@ -no_crate_example = this is an example message used in testing - .note = with a note - .help = with a help - .suggestion = with a suggestion - .label = with a label - -no_crate_bad_reference = {$r} does not exist diff --git a/tests/ui-fulldeps/session-diagnostic/invalid-variable.rs b/tests/ui-fulldeps/session-diagnostic/invalid-variable.rs deleted file mode 100644 index cbe9e3f4ef4c..000000000000 --- a/tests/ui-fulldeps/session-diagnostic/invalid-variable.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ run-fail -//@ compile-flags: --test -// test that messages referencing non-existent fields cause test failures - -#![feature(rustc_private)] -#![crate_type = "lib"] - -extern crate rustc_driver; -extern crate rustc_fluent_macro; -extern crate rustc_macros; -extern crate rustc_errors; -use rustc_macros::Diagnostic; -use rustc_errors::{DiagMessage, SubdiagMessage}; -extern crate rustc_session; - -rustc_fluent_macro::fluent_messages! { "./example.ftl" } - -#[derive(Diagnostic)] -#[diag(no_crate_bad_reference)] -struct BadRef; diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-2.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-2.rs deleted file mode 100644 index f42fe1689842..000000000000 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-2.rs +++ /dev/null @@ -1,37 +0,0 @@ -//@ check-fail -// Tests error conditions for specifying subdiagnostics using #[derive(Subdiagnostic)]. -// This test is split off from the main `subdiagnostic-derive`, -// because this error is generated post-expansion. - -// The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly, -// changing the output of this test. Since Subdiagnostic is strictly internal to the compiler -// the test is just ignored on stable and beta: -//@ ignore-stage1 -//@ ignore-beta -//@ ignore-stable - -#![feature(rustc_private)] -#![crate_type = "lib"] - -extern crate rustc_errors; -extern crate rustc_fluent_macro; -extern crate rustc_macros; -extern crate rustc_session; -extern crate rustc_span; -extern crate core; - -use rustc_errors::{Applicability, DiagMessage, SubdiagMessage}; -use rustc_macros::Subdiagnostic; -use rustc_span::Span; - -rustc_fluent_macro::fluent_messages! { "./example.ftl" } - -#[derive(Subdiagnostic)] -#[label(slug)] -//~^ ERROR cannot find value `slug` in module `crate::fluent_generated` -//~^^ NOTE not found in `crate::fluent_generated` -struct L { - #[primary_span] - span: Span, - var: String, -} diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-2.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-2.stderr deleted file mode 100644 index 37566e39fcd6..000000000000 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-2.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0425]: cannot find value `slug` in module `crate::fluent_generated` - --> $DIR/subdiagnostic-derive-2.rs:30:9 - | -LL | #[label(slug)] - | ^^^^ not found in `crate::fluent_generated` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs deleted file mode 100644 index c06ea451b9bf..000000000000 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ /dev/null @@ -1,809 +0,0 @@ -//@ check-fail -// Tests error conditions for specifying subdiagnostics using #[derive(Subdiagnostic)] - -// The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly, -// changing the output of this test. Since Subdiagnostic is strictly internal to the compiler -// the test is just ignored on stable and beta: -//@ ignore-stage1 -//@ ignore-beta -//@ ignore-stable - -#![feature(rustc_private)] -#![crate_type = "lib"] - -extern crate rustc_errors; -extern crate rustc_fluent_macro; -extern crate rustc_macros; -extern crate rustc_session; -extern crate rustc_span; -extern crate core; - -use rustc_errors::{Applicability, DiagMessage, SubdiagMessage}; -use rustc_macros::Subdiagnostic; -use rustc_span::Span; - -rustc_fluent_macro::fluent_messages! { "./example.ftl" } - -#[derive(Subdiagnostic)] -#[label(no_crate_example)] -struct A { - #[primary_span] - span: Span, - var: String, -} - -#[derive(Subdiagnostic)] -enum B { - #[label(no_crate_example)] - A { - #[primary_span] - span: Span, - var: String, - }, - #[label(no_crate_example)] - B { - #[primary_span] - span: Span, - var: String, - }, -} - -#[derive(Subdiagnostic)] -#[label(no_crate_example)] -//~^ ERROR label without `#[primary_span]` field -struct C { - var: String, -} - -#[derive(Subdiagnostic)] -#[label] -//~^ ERROR diagnostic slug must be first argument -struct D { - #[primary_span] - span: Span, - var: String, -} - -#[derive(Subdiagnostic)] -#[foo] -//~^ ERROR `#[foo]` is not a valid attribute -//~^^ ERROR cannot find attribute `foo` in this scope -struct E { - #[primary_span] - span: Span, - var: String, -} - -#[derive(Subdiagnostic)] -#[label = "..."] -//~^ ERROR `#[label = ...]` is not a valid attribute -struct F { - #[primary_span] - span: Span, - var: String, -} - -#[derive(Subdiagnostic)] -#[label(bug = "...")] -//~^ ERROR no nested attribute expected here -//~| ERROR diagnostic slug must be first argument -struct G { - #[primary_span] - span: Span, - var: String, -} - -#[derive(Subdiagnostic)] -#[label(slug = 4)] -//~^ ERROR no nested attribute expected here -//~| ERROR diagnostic slug must be first argument -struct J { - #[primary_span] - span: Span, - var: String, -} - -#[derive(Subdiagnostic)] -#[label(slug("..."))] -//~^ ERROR no nested attribute expected here -//~| ERROR diagnostic slug must be first argument -struct K { - #[primary_span] - span: Span, - var: String, -} - -#[derive(Subdiagnostic)] -#[label()] -//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute -struct M { - #[primary_span] - span: Span, - var: String, -} - -#[derive(Subdiagnostic)] -#[label(no_crate_example, code = "...")] -//~^ ERROR no nested attribute expected here -struct N { - #[primary_span] - span: Span, - var: String, -} - -#[derive(Subdiagnostic)] -#[label(no_crate_example, applicability = "machine-applicable")] -//~^ ERROR no nested attribute expected here -struct O { - #[primary_span] - span: Span, - var: String, -} - -#[derive(Subdiagnostic)] -#[foo] -//~^ ERROR cannot find attribute `foo` in this scope -//~^^ ERROR unsupported type attribute for subdiagnostic enum -enum P { - #[label(no_crate_example)] - A { - #[primary_span] - span: Span, - var: String, - }, -} - -#[derive(Subdiagnostic)] -enum Q { - #[bar] - //~^ ERROR `#[bar]` is not a valid attribute - //~^^ ERROR cannot find attribute `bar` in this scope - A { - #[primary_span] - span: Span, - var: String, - }, -} - -#[derive(Subdiagnostic)] -enum R { - #[bar = "..."] - //~^ ERROR `#[bar = ...]` is not a valid attribute - //~^^ ERROR cannot find attribute `bar` in this scope - A { - #[primary_span] - span: Span, - var: String, - }, -} - -#[derive(Subdiagnostic)] -enum S { - #[bar = 4] - //~^ ERROR `#[bar = ...]` is not a valid attribute - //~^^ ERROR cannot find attribute `bar` in this scope - A { - #[primary_span] - span: Span, - var: String, - }, -} - -#[derive(Subdiagnostic)] -enum T { - #[bar("...")] - //~^ ERROR `#[bar(...)]` is not a valid attribute - //~^^ ERROR cannot find attribute `bar` in this scope - A { - #[primary_span] - span: Span, - var: String, - }, -} - -#[derive(Subdiagnostic)] -enum U { - #[label(code = "...")] - //~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute - //~| ERROR no nested attribute expected here - A { - #[primary_span] - span: Span, - var: String, - }, -} - -#[derive(Subdiagnostic)] -enum V { - #[label(no_crate_example)] - A { - #[primary_span] - span: Span, - var: String, - }, - B { - #[primary_span] - span: Span, - var: String, - }, -} - -#[derive(Subdiagnostic)] -#[label(no_crate_example)] -//~^ ERROR label without `#[primary_span]` field -struct W { - #[primary_span] - //~^ ERROR the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - span: String, -} - -#[derive(Subdiagnostic)] -#[label(no_crate_example)] -struct X { - #[primary_span] - span: Span, - #[applicability] - //~^ ERROR `#[applicability]` is only valid on suggestions - applicability: Applicability, -} - -#[derive(Subdiagnostic)] -#[label(no_crate_example)] -struct Y { - #[primary_span] - span: Span, - #[bar] - //~^ ERROR `#[bar]` is not a valid attribute - //~^^ ERROR cannot find attribute `bar` in this scope - bar: String, -} - -#[derive(Subdiagnostic)] -#[label(no_crate_example)] -struct Z { - #[primary_span] - span: Span, - #[bar = "..."] - //~^ ERROR `#[bar = ...]` is not a valid attribute - //~^^ ERROR cannot find attribute `bar` in this scope - bar: String, -} - -#[derive(Subdiagnostic)] -#[label(no_crate_example)] -struct AA { - #[primary_span] - span: Span, - #[bar("...")] - //~^ ERROR `#[bar(...)]` is not a valid attribute - //~^^ ERROR cannot find attribute `bar` in this scope - bar: String, -} - -#[derive(Subdiagnostic)] -#[label(no_crate_example)] -struct AB { - #[primary_span] - span: Span, - #[skip_arg] - z: Z, -} - -#[derive(Subdiagnostic)] -union AC { - //~^ ERROR unexpected unsupported untagged union - span: u32, - b: u64, -} - -#[derive(Subdiagnostic)] -#[label(no_crate_example)] -#[label(no_crate_example)] -struct AD { - #[primary_span] - span: Span, -} - -#[derive(Subdiagnostic)] -#[label(no_crate_example, no_crate::example)] -//~^ ERROR a diagnostic slug must be the first argument to the attribute -struct AE { - #[primary_span] - span: Span, -} - -#[derive(Subdiagnostic)] -#[label(no_crate_example)] -struct AF { - #[primary_span] - //~^ NOTE previously specified here - span_a: Span, - #[primary_span] - //~^ ERROR specified multiple times - span_b: Span, -} - -#[derive(Subdiagnostic)] -struct AG { - //~^ ERROR subdiagnostic kind not specified - #[primary_span] - span: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "...")] -struct AH { - #[primary_span] - span: Span, - #[applicability] - applicability: Applicability, - var: String, -} - -#[derive(Subdiagnostic)] -enum AI { - #[suggestion(no_crate_example, code = "...")] - A { - #[primary_span] - span: Span, - #[applicability] - applicability: Applicability, - var: String, - }, - #[suggestion(no_crate_example, code = "...")] - B { - #[primary_span] - span: Span, - #[applicability] - applicability: Applicability, - var: String, - }, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "...", code = "...")] -//~^ ERROR specified multiple times -//~^^ NOTE previously specified here -struct AJ { - #[primary_span] - span: Span, - #[applicability] - applicability: Applicability, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "...")] -struct AK { - #[primary_span] - span: Span, - #[applicability] - //~^ NOTE previously specified here - applicability_a: Applicability, - #[applicability] - //~^ ERROR specified multiple times - applicability_b: Applicability, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "...")] -struct AL { - #[primary_span] - span: Span, - #[applicability] - //~^ ERROR the `#[applicability]` attribute can only be applied to fields of type `Applicability` - applicability: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "...")] -struct AM { - #[primary_span] - span: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example)] -//~^ ERROR suggestion without `code = "..."` -struct AN { - #[primary_span] - span: Span, - #[applicability] - applicability: Applicability, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "...", applicability = "foo")] -//~^ ERROR invalid applicability -struct AO { - #[primary_span] - span: Span, -} - -#[derive(Subdiagnostic)] -#[help(no_crate_example)] -struct AP { - var: String, -} - -#[derive(Subdiagnostic)] -#[note(no_crate_example)] -struct AQ; - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "...")] -//~^ ERROR suggestion without `#[primary_span]` field -struct AR { - var: String, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] -struct AS { - #[primary_span] - span: Span, -} - -#[derive(Subdiagnostic)] -#[label] -//~^ ERROR unsupported type attribute for subdiagnostic enum -enum AT { - #[label(no_crate_example)] - A { - #[primary_span] - span: Span, - var: String, - }, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")] -struct AU { - #[primary_span] - span: Span, - var: String, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")] -//~^ ERROR `var` doesn't refer to a field on this type -struct AV { - #[primary_span] - span: Span, -} - -#[derive(Subdiagnostic)] -enum AW { - #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")] - A { - #[primary_span] - span: Span, - var: String, - }, -} - -#[derive(Subdiagnostic)] -enum AX { - #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")] - //~^ ERROR `var` doesn't refer to a field on this type - A { - #[primary_span] - span: Span, - }, -} - -#[derive(Subdiagnostic)] -#[warning(no_crate_example)] -struct AY {} - -#[derive(Subdiagnostic)] -#[warning(no_crate_example)] -struct AZ { - #[primary_span] - span: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "...")] -//~^ ERROR suggestion without `#[primary_span]` field -struct BA { - #[suggestion_part] - //~^ ERROR `#[suggestion_part]` is not a valid attribute - span: Span, - #[suggestion_part(code = "...")] - //~^ ERROR `#[suggestion_part(...)]` is not a valid attribute - span2: Span, - #[applicability] - applicability: Applicability, - var: String, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] -//~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields -//~| ERROR invalid nested attribute -struct BBa { - var: String, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(no_crate_example, applicability = "machine-applicable")] -struct BBb { - #[suggestion_part] - //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` - span1: Span, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(no_crate_example, applicability = "machine-applicable")] -struct BBc { - #[suggestion_part()] - //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` - span1: Span, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(no_crate_example)] -//~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields -struct BC { - #[primary_span] - //~^ ERROR `#[primary_span]` is not a valid attribute - span: Span, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(no_crate_example)] -struct BD { - #[suggestion_part] - //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` - span1: Span, - #[suggestion_part()] - //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` - span2: Span, - #[suggestion_part(foo = "bar")] - //~^ ERROR `code` is the only valid nested attribute - //~| ERROR expected `,` - span4: Span, - #[suggestion_part(code = "...")] - //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - s1: String, - #[suggestion_part()] - //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - s2: String, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(no_crate_example, applicability = "machine-applicable")] -struct BE { - #[suggestion_part(code = "...", code = ",,,")] - //~^ ERROR specified multiple times - //~| NOTE previously specified here - span: Span, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(no_crate_example, applicability = "machine-applicable")] -struct BF { - #[suggestion_part(code = "(")] - first: Span, - #[suggestion_part(code = ")")] - second: Span, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(no_crate_example)] -struct BG { - #[applicability] - appl: Applicability, - #[suggestion_part(code = "(")] - first: Span, - #[suggestion_part(code = ")")] - second: Span, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(no_crate_example, applicability = "machine-applicable")] -struct BH { - #[applicability] - //~^ ERROR `#[applicability]` has no effect - appl: Applicability, - #[suggestion_part(code = "(")] - first: Span, - #[suggestion_part(code = ")")] - second: Span, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(no_crate_example, applicability = "machine-applicable")] -struct BI { - #[suggestion_part(code = "")] - spans: Vec, -} - -#[derive(Subdiagnostic)] -#[label(no_crate_example)] -struct BJ { - #[primary_span] - span: Span, - r#type: String, -} - -/// with a doc comment on the type.. -#[derive(Subdiagnostic)] -#[label(no_crate_example)] -struct BK { - /// ..and the field - #[primary_span] - span: Span, -} - -/// with a doc comment on the type.. -#[derive(Subdiagnostic)] -enum BL { - /// ..and the variant.. - #[label(no_crate_example)] - Foo { - /// ..and the field - #[primary_span] - span: Span, - }, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(no_crate_example)] -struct BM { - #[suggestion_part(code("foo"))] - //~^ ERROR expected exactly one string literal for `code = ...` - //~| ERROR unexpected token, expected `)` - span: Span, - r#type: String, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(no_crate_example)] -struct BN { - #[suggestion_part(code("foo", "bar"))] - //~^ ERROR expected exactly one string literal for `code = ...` - //~| ERROR unexpected token, expected `)` - span: Span, - r#type: String, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(no_crate_example)] -struct BO { - #[suggestion_part(code(3))] - //~^ ERROR expected exactly one string literal for `code = ...` - //~| ERROR unexpected token, expected `)` - span: Span, - r#type: String, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(no_crate_example)] -struct BP { - #[suggestion_part(code())] - //~^ ERROR expected exactly one string literal for `code = ...` - span: Span, - r#type: String, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(no_crate_example)] -struct BQ { - #[suggestion_part(code = 3)] - //~^ ERROR expected string literal - span: Span, - r#type: String, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "")] -struct SuggestionStyleDefault { - #[primary_span] - sub: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "", style = "short")] -struct SuggestionStyleShort { - #[primary_span] - sub: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "", style = "hidden")] -struct SuggestionStyleHidden { - #[primary_span] - sub: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "", style = "verbose")] -struct SuggestionStyleVerbose { - #[primary_span] - sub: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "", style = "tool-only")] -struct SuggestionStyleToolOnly { - #[primary_span] - sub: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")] -//~^ ERROR specified multiple times -//~| NOTE previously specified here -struct SuggestionStyleTwice { - #[primary_span] - sub: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion_hidden(no_crate_example, code = "")] -//~^ ERROR #[suggestion_hidden(...)]` is not a valid attribute -struct SuggestionStyleOldSyntax { - #[primary_span] - sub: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion_hidden(no_crate_example, code = "", style = "normal")] -//~^ ERROR #[suggestion_hidden(...)]` is not a valid attribute -struct SuggestionStyleOldAndNewSyntax { - #[primary_span] - sub: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "", style = "foo")] -//~^ ERROR invalid suggestion style -struct SuggestionStyleInvalid1 { - #[primary_span] - sub: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "", style = 42)] -//~^ ERROR expected string literal -struct SuggestionStyleInvalid2 { - #[primary_span] - sub: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "", style)] -//~^ ERROR a diagnostic slug must be the first argument to the attribute -struct SuggestionStyleInvalid3 { - #[primary_span] - sub: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "", style("foo"))] -//~^ ERROR expected `=` -struct SuggestionStyleInvalid4 { - #[primary_span] - sub: Span, -} - -#[derive(Subdiagnostic)] -#[suggestion(no_crate_example, code = "")] -//~^ ERROR suggestion without `#[primary_span]` field -struct PrimarySpanOnVec { - #[primary_span] - //~^ ERROR `#[primary_span]` is not a valid attribute - //~| NOTE there must be exactly one primary span - sub: Vec, -} - -#[derive(Subdiagnostic)] -struct NestedParent { - #[subdiagnostic] - single_sub: A, - #[subdiagnostic] - option_sub: Option, - #[subdiagnostic] - vec_sub: Vec, -} diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr deleted file mode 100644 index 9f18f7ffabcc..000000000000 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ /dev/null @@ -1,549 +0,0 @@ -error: derive(Diagnostic): label without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:52:1 - | -LL | #[label(no_crate_example)] - | ^ - -error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:59:1 - | -LL | #[label] - | ^ - -error: derive(Diagnostic): `#[foo]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:68:1 - | -LL | #[foo] - | ^ - -error: derive(Diagnostic): `#[label = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:78:1 - | -LL | #[label = "..."] - | ^ - -error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive.rs:87:9 - | -LL | #[label(bug = "...")] - | ^^^ - -error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:87:1 - | -LL | #[label(bug = "...")] - | ^ - -error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive.rs:97:9 - | -LL | #[label(slug = 4)] - | ^^^^ - -error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:97:1 - | -LL | #[label(slug = 4)] - | ^ - -error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive.rs:107:9 - | -LL | #[label(slug("..."))] - | ^^^^ - -error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:107:1 - | -LL | #[label(slug("..."))] - | ^ - -error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:117:1 - | -LL | #[label()] - | ^ - -error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive.rs:126:27 - | -LL | #[label(no_crate_example, code = "...")] - | ^^^^ - -error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive.rs:135:27 - | -LL | #[label(no_crate_example, applicability = "machine-applicable")] - | ^^^^^^^^^^^^^ - -error: derive(Diagnostic): unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:144:1 - | -LL | #[foo] - | ^ - -error: derive(Diagnostic): `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:158:5 - | -LL | #[bar] - | ^ - -error: derive(Diagnostic): `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:170:5 - | -LL | #[bar = "..."] - | ^ - -error: derive(Diagnostic): `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:182:5 - | -LL | #[bar = 4] - | ^ - -error: derive(Diagnostic): `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:194:5 - | -LL | #[bar("...")] - | ^ - -error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive.rs:206:13 - | -LL | #[label(code = "...")] - | ^^^^ - -error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:206:5 - | -LL | #[label(code = "...")] - | ^ - -error: derive(Diagnostic): the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:235:5 - | -LL | #[primary_span] - | ^ - -error: derive(Diagnostic): label without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:232:1 - | -LL | #[label(no_crate_example)] - | ^ - -error: derive(Diagnostic): `#[applicability]` is only valid on suggestions - --> $DIR/subdiagnostic-derive.rs:245:5 - | -LL | #[applicability] - | ^ - -error: derive(Diagnostic): `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:255:5 - | -LL | #[bar] - | ^ - | - = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes - -error: derive(Diagnostic): `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:266:5 - | -LL | #[bar = "..."] - | ^ - -error: derive(Diagnostic): `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:277:5 - | -LL | #[bar("...")] - | ^ - | - = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes - -error: unexpected unsupported untagged union - --> $DIR/subdiagnostic-derive.rs:293:1 - | -LL | / union AC { -LL | | -LL | | span: u32, -LL | | b: u64, -LL | | } - | |_^ - -error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute - --> $DIR/subdiagnostic-derive.rs:308:27 - | -LL | #[label(no_crate_example, no_crate::example)] - | ^^^^^^^^ - -error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive.rs:321:5 - | -LL | #[primary_span] - | ^ - | -note: previously specified here - --> $DIR/subdiagnostic-derive.rs:318:5 - | -LL | #[primary_span] - | ^ - -error: derive(Diagnostic): subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:327:8 - | -LL | struct AG { - | ^^ - -error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive.rs:364:46 - | -LL | #[suggestion(no_crate_example, code = "...", code = "...")] - | ^^^^ - | -note: previously specified here - --> $DIR/subdiagnostic-derive.rs:364:32 - | -LL | #[suggestion(no_crate_example, code = "...", code = "...")] - | ^^^^ - -error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive.rs:382:5 - | -LL | #[applicability] - | ^ - | -note: previously specified here - --> $DIR/subdiagnostic-derive.rs:379:5 - | -LL | #[applicability] - | ^ - -error: derive(Diagnostic): the `#[applicability]` attribute can only be applied to fields of type `Applicability` - --> $DIR/subdiagnostic-derive.rs:392:5 - | -LL | #[applicability] - | ^ - -error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:405:1 - | -LL | #[suggestion(no_crate_example)] - | ^ - -error: derive(Diagnostic): invalid applicability - --> $DIR/subdiagnostic-derive.rs:415:62 - | -LL | #[suggestion(no_crate_example, code = "...", applicability = "foo")] - | ^^^^^ - -error: derive(Diagnostic): suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:433:1 - | -LL | #[suggestion(no_crate_example, code = "...")] - | ^ - -error: derive(Diagnostic): unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:447:1 - | -LL | #[label] - | ^ - -error: derive(Diagnostic): `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:467:39 - | -LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")] - | ^^^^^^^ - -error: derive(Diagnostic): `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:486:43 - | -LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")] - | ^^^^^^^ - -error: derive(Diagnostic): `#[suggestion_part]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:509:5 - | -LL | #[suggestion_part] - | ^ - | - = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead - -error: derive(Diagnostic): `#[suggestion_part(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:512:5 - | -LL | #[suggestion_part(code = "...")] - | ^ - | - = help: `#[suggestion_part(...)]` is only valid in multipart suggestions - -error: derive(Diagnostic): suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:506:1 - | -LL | #[suggestion(no_crate_example, code = "...")] - | ^ - -error: derive(Diagnostic): invalid nested attribute - --> $DIR/subdiagnostic-derive.rs:521:42 - | -LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] - | ^^^^ - | - = help: only `style` and `applicability` are valid nested attributes - -error: derive(Diagnostic): multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:521:1 - | -LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] - | ^ - -error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:531:5 - | -LL | #[suggestion_part] - | ^ - -error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:539:5 - | -LL | #[suggestion_part()] - | ^ - -error: derive(Diagnostic): `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:548:5 - | -LL | #[primary_span] - | ^ - | - = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]` - -error: derive(Diagnostic): multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:545:1 - | -LL | #[multipart_suggestion(no_crate_example)] - | ^ - -error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:556:5 - | -LL | #[suggestion_part] - | ^ - -error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:559:5 - | -LL | #[suggestion_part()] - | ^ - -error: derive(Diagnostic): `code` is the only valid nested attribute - --> $DIR/subdiagnostic-derive.rs:562:23 - | -LL | #[suggestion_part(foo = "bar")] - | ^^^ - -error: derive(Diagnostic): the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:566:5 - | -LL | #[suggestion_part(code = "...")] - | ^ - -error: derive(Diagnostic): the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:569:5 - | -LL | #[suggestion_part()] - | ^ - -error: expected `,` - --> $DIR/subdiagnostic-derive.rs:562:27 - | -LL | #[suggestion_part(foo = "bar")] - | ^ - -error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive.rs:577:37 - | -LL | #[suggestion_part(code = "...", code = ",,,")] - | ^^^^ - | -note: previously specified here - --> $DIR/subdiagnostic-derive.rs:577:23 - | -LL | #[suggestion_part(code = "...", code = ",,,")] - | ^^^^ - -error: derive(Diagnostic): `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."` - --> $DIR/subdiagnostic-derive.rs:606:5 - | -LL | #[applicability] - | ^ - -error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:654:28 - | -LL | #[suggestion_part(code("foo"))] - | ^^^^^ - -error: unexpected token, expected `)` - --> $DIR/subdiagnostic-derive.rs:654:28 - | -LL | #[suggestion_part(code("foo"))] - | ^^^^^ - -error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:664:28 - | -LL | #[suggestion_part(code("foo", "bar"))] - | ^^^^^ - -error: unexpected token, expected `)` - --> $DIR/subdiagnostic-derive.rs:664:28 - | -LL | #[suggestion_part(code("foo", "bar"))] - | ^^^^^ - -error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:674:28 - | -LL | #[suggestion_part(code(3))] - | ^ - -error: unexpected token, expected `)` - --> $DIR/subdiagnostic-derive.rs:674:28 - | -LL | #[suggestion_part(code(3))] - | ^ - -error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:684:28 - | -LL | #[suggestion_part(code())] - | ^ - -error: expected string literal - --> $DIR/subdiagnostic-derive.rs:693:30 - | -LL | #[suggestion_part(code = 3)] - | ^ - -error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive.rs:735:1 - | -LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")] - | ^ - | -note: previously specified here - --> $DIR/subdiagnostic-derive.rs:735:1 - | -LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")] - | ^ - -error: derive(Diagnostic): `#[suggestion_hidden(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:744:1 - | -LL | #[suggestion_hidden(no_crate_example, code = "")] - | ^ - | - = help: Use `#[suggestion(..., style = "hidden")]` instead - -error: derive(Diagnostic): `#[suggestion_hidden(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:752:1 - | -LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")] - | ^ - | - = help: Use `#[suggestion(..., style = "hidden")]` instead - -error: derive(Diagnostic): invalid suggestion style - --> $DIR/subdiagnostic-derive.rs:760:51 - | -LL | #[suggestion(no_crate_example, code = "", style = "foo")] - | ^^^^^ - | - = help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only` - -error: expected string literal - --> $DIR/subdiagnostic-derive.rs:768:51 - | -LL | #[suggestion(no_crate_example, code = "", style = 42)] - | ^^ - -error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute - --> $DIR/subdiagnostic-derive.rs:776:43 - | -LL | #[suggestion(no_crate_example, code = "", style)] - | ^^^^^ - -error: expected `=` - --> $DIR/subdiagnostic-derive.rs:784:48 - | -LL | #[suggestion(no_crate_example, code = "", style("foo"))] - | ^ - -error: derive(Diagnostic): `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:795:5 - | -LL | #[primary_span] - | ^ - | - = note: there must be exactly one primary span - = help: to create a suggestion with multiple spans, use `#[multipart_suggestion]` instead - -error: derive(Diagnostic): suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:792:1 - | -LL | #[suggestion(no_crate_example, code = "")] - | ^ - -error: cannot find attribute `foo` in this scope - --> $DIR/subdiagnostic-derive.rs:68:3 - | -LL | #[foo] - | ^^^ - -error: cannot find attribute `foo` in this scope - --> $DIR/subdiagnostic-derive.rs:144:3 - | -LL | #[foo] - | ^^^ - -error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:158:7 - | -LL | #[bar] - | ^^^ - -error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:170:7 - | -LL | #[bar = "..."] - | ^^^ - -error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:182:7 - | -LL | #[bar = 4] - | ^^^ - -error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:194:7 - | -LL | #[bar("...")] - | ^^^ - -error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:255:7 - | -LL | #[bar] - | ^^^ - -error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:266:7 - | -LL | #[bar = "..."] - | ^^^ - -error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:277:7 - | -LL | #[bar("...")] - | ^^^ - -error: aborting due to 82 previous errors - From 580c8d3c20ca3b363ece4ec34a9db1194bb9940d Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 7 Feb 2026 15:09:34 +0100 Subject: [PATCH 684/978] Update remaining session-diagnostics tests --- .../diagnostic-derive-doc-comment-field.rs | 7 +- ...diagnostic-derive-doc-comment-field.stderr | 8 +- .../diagnostic-derive-inline.rs | 1 - .../diagnostic-derive-inline.stderr | 174 +++++++++--------- .../subdiagnostic-derive-inline.rs | 1 - .../subdiagnostic-derive-inline.stderr | 174 +++++++++--------- 6 files changed, 180 insertions(+), 185 deletions(-) diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs index 4f08c5327c15..e63ab03cda47 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs @@ -14,7 +14,6 @@ #![crate_type = "lib"] extern crate rustc_errors; -extern crate rustc_fluent_macro; extern crate rustc_macros; extern crate rustc_session; extern crate rustc_span; @@ -24,12 +23,10 @@ use rustc_errors::{Applicability, DiagMessage, SubdiagMessage}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; -rustc_fluent_macro::fluent_messages! { "./example.ftl" } - struct NotIntoDiagArg; #[derive(Diagnostic)] -#[diag(no_crate_example)] +#[diag("example message")] struct Test { #[primary_span] span: Span, @@ -39,7 +36,7 @@ struct Test { } #[derive(Subdiagnostic)] -#[label(no_crate_example)] +#[label("example message")] struct SubTest { #[primary_span] span: Span, diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr index 0b00e098f6d4..2d90b2a96b01 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `NotIntoDiagArg: IntoDiagArg` is not satisfied - --> $DIR/diagnostic-derive-doc-comment-field.rs:37:10 + --> $DIR/diagnostic-derive-doc-comment-field.rs:34:10 | LL | #[derive(Diagnostic)] | ---------- required by a bound introduced by this call @@ -8,7 +8,7 @@ LL | arg: NotIntoDiagArg, | ^^^^^^^^^^^^^^ unsatisfied trait bound | help: the nightly-only, unstable trait `IntoDiagArg` is not implemented for `NotIntoDiagArg` - --> $DIR/diagnostic-derive-doc-comment-field.rs:29:1 + --> $DIR/diagnostic-derive-doc-comment-field.rs:26:1 | LL | struct NotIntoDiagArg; | ^^^^^^^^^^^^^^^^^^^^^ @@ -21,7 +21,7 @@ note: required by a bound in `Diag::<'a, G>::arg` = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `NotIntoDiagArg: IntoDiagArg` is not satisfied - --> $DIR/diagnostic-derive-doc-comment-field.rs:47:10 + --> $DIR/diagnostic-derive-doc-comment-field.rs:44:10 | LL | #[derive(Subdiagnostic)] | ------------- required by a bound introduced by this call @@ -30,7 +30,7 @@ LL | arg: NotIntoDiagArg, | ^^^^^^^^^^^^^^ unsatisfied trait bound | help: the nightly-only, unstable trait `IntoDiagArg` is not implemented for `NotIntoDiagArg` - --> $DIR/diagnostic-derive-doc-comment-field.rs:29:1 + --> $DIR/diagnostic-derive-doc-comment-field.rs:26:1 | LL | struct NotIntoDiagArg; | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs index babe3813e40b..1d2bfc66aaff 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs @@ -19,7 +19,6 @@ extern crate rustc_span; use rustc_span::symbol::Ident; use rustc_span::Span; -extern crate rustc_fluent_macro; extern crate rustc_macros; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr index 2ba307940280..71ed77804a6c 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr @@ -1,11 +1,11 @@ error: derive(Diagnostic): unsupported type attribute for diagnostic derive enum - --> $DIR/diagnostic-derive-inline.rs:45:1 + --> $DIR/diagnostic-derive-inline.rs:44:1 | LL | #[diag("this is an example message", code = E0123)] | ^ error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:48:5 + --> $DIR/diagnostic-derive-inline.rs:47:5 | LL | Foo, | ^^^ @@ -13,7 +13,7 @@ LL | Foo, = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:50:5 + --> $DIR/diagnostic-derive-inline.rs:49:5 | LL | Bar, | ^^^ @@ -21,19 +21,19 @@ LL | Bar, = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: expected parentheses: #[diag(...)] - --> $DIR/diagnostic-derive-inline.rs:56:8 + --> $DIR/diagnostic-derive-inline.rs:55:8 | LL | #[diag = "E0123"] | ^ error: derive(Diagnostic): `#[nonsense(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:61:1 + --> $DIR/diagnostic-derive-inline.rs:60:1 | LL | #[nonsense("this is an example message", code = E0123)] | ^ error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:61:1 + --> $DIR/diagnostic-derive-inline.rs:60:1 | LL | #[nonsense("this is an example message", code = E0123)] | ^ @@ -41,7 +41,7 @@ LL | #[nonsense("this is an example message", code = E0123)] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:68:1 + --> $DIR/diagnostic-derive-inline.rs:67:1 | LL | #[diag(code = E0123)] | ^ @@ -49,7 +49,7 @@ LL | #[diag(code = E0123)] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:73:1 + --> $DIR/diagnostic-derive-inline.rs:72:1 | LL | #[diag(nonsense("foo"), code = E0123, slug = "foo")] | ^ @@ -57,7 +57,7 @@ LL | #[diag(nonsense("foo"), code = E0123, slug = "foo")] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:78:1 + --> $DIR/diagnostic-derive-inline.rs:77:1 | LL | #[diag(nonsense = "...", code = E0123, slug = "foo")] | ^ @@ -65,7 +65,7 @@ LL | #[diag(nonsense = "...", code = E0123, slug = "foo")] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:83:1 + --> $DIR/diagnostic-derive-inline.rs:82:1 | LL | #[diag(nonsense = 4, code = E0123, slug = "foo")] | ^ @@ -73,7 +73,7 @@ LL | #[diag(nonsense = 4, code = E0123, slug = "foo")] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): unknown argument - --> $DIR/diagnostic-derive-inline.rs:88:52 + --> $DIR/diagnostic-derive-inline.rs:87:52 | LL | #[diag("this is an example message", code = E0123, slug = "foo")] | ^^^^ @@ -81,43 +81,43 @@ LL | #[diag("this is an example message", code = E0123, slug = "foo")] = note: only the `code` parameter is valid after the slug error: derive(Diagnostic): `#[suggestion = ...]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:95:5 + --> $DIR/diagnostic-derive-inline.rs:94:5 | LL | #[suggestion = "bar"] | ^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive-inline.rs:102:38 + --> $DIR/diagnostic-derive-inline.rs:101:38 | LL | #[diag("this is an example message", code = E0456)] | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive-inline.rs:101:38 + --> $DIR/diagnostic-derive-inline.rs:100:38 | LL | #[diag("this is an example message", code = E0123)] | ^^^^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive-inline.rs:107:52 + --> $DIR/diagnostic-derive-inline.rs:106:52 | LL | #[diag("this is an example message", code = E0123, code = E0456)] | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive-inline.rs:107:38 + --> $DIR/diagnostic-derive-inline.rs:106:38 | LL | #[diag("this is an example message", code = E0123, code = E0456)] | ^^^^ error: derive(Diagnostic): diagnostic slug must be the first argument - --> $DIR/diagnostic-derive-inline.rs:112:38 + --> $DIR/diagnostic-derive-inline.rs:111:38 | LL | #[diag("this is an example message", no_crate::example, code = E0123)] | ^^^^^^^^ error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:117:1 + --> $DIR/diagnostic-derive-inline.rs:116:1 | LL | struct KindNotProvided {} | ^^^^^^ @@ -125,7 +125,7 @@ LL | struct KindNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:120:1 + --> $DIR/diagnostic-derive-inline.rs:119:1 | LL | #[diag(code = E0123)] | ^ @@ -133,31 +133,31 @@ LL | #[diag(code = E0123)] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive-inline.rs:131:5 + --> $DIR/diagnostic-derive-inline.rs:130:5 | LL | #[primary_span] | ^ error: derive(Diagnostic): `#[nonsense]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:139:5 + --> $DIR/diagnostic-derive-inline.rs:138:5 | LL | #[nonsense] | ^ error: derive(Diagnostic): the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive-inline.rs:156:5 + --> $DIR/diagnostic-derive-inline.rs:155:5 | LL | #[label("with a label")] | ^ error: derive(Diagnostic): `name` doesn't refer to a field on this type - --> $DIR/diagnostic-derive-inline.rs:164:46 + --> $DIR/diagnostic-derive-inline.rs:163:46 | LL | #[suggestion("with a suggestion", code = "{name}")] | ^^^^^^^^ error: invalid format string: expected `}` but string was terminated - --> $DIR/diagnostic-derive-inline.rs:169:10 + --> $DIR/diagnostic-derive-inline.rs:168:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ expected `}` in format string @@ -166,7 +166,7 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: unmatched `}` found - --> $DIR/diagnostic-derive-inline.rs:179:10 + --> $DIR/diagnostic-derive-inline.rs:178:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ unmatched `}` in format string @@ -175,19 +175,19 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: derive(Diagnostic): the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive-inline.rs:199:5 + --> $DIR/diagnostic-derive-inline.rs:198:5 | LL | #[label("with a label")] | ^ error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive-inline.rs:218:5 + --> $DIR/diagnostic-derive-inline.rs:217:5 | LL | #[suggestion("with a suggestion")] | ^ error: derive(Diagnostic): invalid nested attribute - --> $DIR/diagnostic-derive-inline.rs:226:39 + --> $DIR/diagnostic-derive-inline.rs:225:39 | LL | #[suggestion("with a suggestion", nonsense = "bar")] | ^^^^^^^^ @@ -195,13 +195,13 @@ LL | #[suggestion("with a suggestion", nonsense = "bar")] = help: only `style`, `code` and `applicability` are valid nested attributes error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive-inline.rs:226:5 + --> $DIR/diagnostic-derive-inline.rs:225:5 | LL | #[suggestion("with a suggestion", nonsense = "bar")] | ^ error: derive(Diagnostic): invalid nested attribute - --> $DIR/diagnostic-derive-inline.rs:235:39 + --> $DIR/diagnostic-derive-inline.rs:234:39 | LL | #[suggestion("with a suggestion", msg = "bar")] | ^^^ @@ -209,13 +209,13 @@ LL | #[suggestion("with a suggestion", msg = "bar")] = help: only `style`, `code` and `applicability` are valid nested attributes error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive-inline.rs:235:5 + --> $DIR/diagnostic-derive-inline.rs:234:5 | LL | #[suggestion("with a suggestion", msg = "bar")] | ^ error: derive(Diagnostic): wrong field type for suggestion - --> $DIR/diagnostic-derive-inline.rs:258:5 + --> $DIR/diagnostic-derive-inline.rs:257:5 | LL | #[suggestion("with a suggestion", code = "This is suggested code")] | ^ @@ -223,79 +223,79 @@ LL | #[suggestion("with a suggestion", code = "This is suggested code")] = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive-inline.rs:274:24 + --> $DIR/diagnostic-derive-inline.rs:273:24 | LL | suggestion: (Span, Span, Applicability), | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive-inline.rs:274:18 + --> $DIR/diagnostic-derive-inline.rs:273:18 | LL | suggestion: (Span, Span, Applicability), | ^^^^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive-inline.rs:282:33 + --> $DIR/diagnostic-derive-inline.rs:281:33 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive-inline.rs:282:18 + --> $DIR/diagnostic-derive-inline.rs:281:18 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ error: derive(Diagnostic): `#[label = ...]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:289:5 + --> $DIR/diagnostic-derive-inline.rs:288:5 | LL | #[label = "bar"] | ^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive-inline.rs:390:5 + --> $DIR/diagnostic-derive-inline.rs:389:5 | LL | #[suggestion("with a suggestion", code = "...", applicability = "maybe-incorrect")] | ^ | note: previously specified here - --> $DIR/diagnostic-derive-inline.rs:392:24 + --> $DIR/diagnostic-derive-inline.rs:391:24 | LL | suggestion: (Span, Applicability), | ^^^^^^^^^^^^^ error: derive(Diagnostic): invalid applicability - --> $DIR/diagnostic-derive-inline.rs:398:69 + --> $DIR/diagnostic-derive-inline.rs:397:69 | LL | #[suggestion("with a suggestion", code = "...", applicability = "batman")] | ^^^^^^^^ error: derive(Diagnostic): the `#[help(...)]` attribute can only be applied to fields of type `Span`, `MultiSpan`, `bool` or `()` - --> $DIR/diagnostic-derive-inline.rs:461:5 + --> $DIR/diagnostic-derive-inline.rs:460:5 | LL | #[help("with a help")] | ^ error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute - --> $DIR/diagnostic-derive-inline.rs:470:29 + --> $DIR/diagnostic-derive-inline.rs:469:29 | LL | #[label("with a label", foo)] | ^^^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/diagnostic-derive-inline.rs:478:29 + --> $DIR/diagnostic-derive-inline.rs:477:29 | LL | #[label("with a label", foo = "...")] | ^^^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/diagnostic-derive-inline.rs:486:29 + --> $DIR/diagnostic-derive-inline.rs:485:29 | LL | #[label("with a label", foo("..."))] | ^^^ error: derive(Diagnostic): `#[primary_span]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:498:5 + --> $DIR/diagnostic-derive-inline.rs:497:5 | LL | #[primary_span] | ^ @@ -303,13 +303,13 @@ LL | #[primary_span] = help: the `primary_span` field attribute is not valid for lint diagnostics error: derive(Diagnostic): `#[error(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:518:1 + --> $DIR/diagnostic-derive-inline.rs:517:1 | LL | #[error("this is an example message", code = E0123)] | ^ error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:518:1 + --> $DIR/diagnostic-derive-inline.rs:517:1 | LL | #[error("this is an example message", code = E0123)] | ^ @@ -317,13 +317,13 @@ LL | #[error("this is an example message", code = E0123)] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): `#[warn_(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:525:1 + --> $DIR/diagnostic-derive-inline.rs:524:1 | LL | #[warn_("this is an example message", code = E0123)] | ^ error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:525:1 + --> $DIR/diagnostic-derive-inline.rs:524:1 | LL | #[warn_("this is an example message", code = E0123)] | ^ @@ -331,13 +331,13 @@ LL | #[warn_("this is an example message", code = E0123)] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:532:1 + --> $DIR/diagnostic-derive-inline.rs:531:1 | LL | #[lint("this is an example message", code = E0123)] | ^ error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:532:1 + --> $DIR/diagnostic-derive-inline.rs:531:1 | LL | #[lint("this is an example message", code = E0123)] | ^ @@ -345,13 +345,13 @@ LL | #[lint("this is an example message", code = E0123)] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:539:1 + --> $DIR/diagnostic-derive-inline.rs:538:1 | LL | #[lint("this is an example message", code = E0123)] | ^ error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:539:1 + --> $DIR/diagnostic-derive-inline.rs:538:1 | LL | #[lint("this is an example message", code = E0123)] | ^ @@ -359,19 +359,19 @@ LL | #[lint("this is an example message", code = E0123)] = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive-inline.rs:548:53 + --> $DIR/diagnostic-derive-inline.rs:547:53 | LL | #[suggestion("with a suggestion", code = "...", code = ",,,")] | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive-inline.rs:548:39 + --> $DIR/diagnostic-derive-inline.rs:547:39 | LL | #[suggestion("with a suggestion", code = "...", code = ",,,")] | ^^^^ error: derive(Diagnostic): wrong types for suggestion - --> $DIR/diagnostic-derive-inline.rs:557:24 + --> $DIR/diagnostic-derive-inline.rs:556:24 | LL | suggestion: (Span, usize), | ^^^^^ @@ -379,7 +379,7 @@ LL | suggestion: (Span, usize), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: derive(Diagnostic): wrong types for suggestion - --> $DIR/diagnostic-derive-inline.rs:565:17 + --> $DIR/diagnostic-derive-inline.rs:564:17 | LL | suggestion: (Span,), | ^^^^^^^ @@ -387,13 +387,13 @@ LL | suggestion: (Span,), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive-inline.rs:572:5 + --> $DIR/diagnostic-derive-inline.rs:571:5 | LL | #[suggestion("with a suggestion")] | ^ error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:579:1 + --> $DIR/diagnostic-derive-inline.rs:578:1 | LL | #[multipart_suggestion("with a suggestion")] | ^ @@ -401,7 +401,7 @@ LL | #[multipart_suggestion("with a suggestion")] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:582:1 + --> $DIR/diagnostic-derive-inline.rs:581:1 | LL | #[multipart_suggestion()] | ^ @@ -409,7 +409,7 @@ LL | #[multipart_suggestion()] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:586:5 + --> $DIR/diagnostic-derive-inline.rs:585:5 | LL | #[multipart_suggestion("with a suggestion")] | ^ @@ -417,7 +417,7 @@ LL | #[multipart_suggestion("with a suggestion")] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:594:1 + --> $DIR/diagnostic-derive-inline.rs:593:1 | LL | #[suggestion("with a suggestion", code = "...")] | ^ @@ -425,7 +425,7 @@ LL | #[suggestion("with a suggestion", code = "...")] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: derive(Diagnostic): `#[label]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:603:1 + --> $DIR/diagnostic-derive-inline.rs:602:1 | LL | #[label] | ^ @@ -433,73 +433,73 @@ LL | #[label] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:637:5 + --> $DIR/diagnostic-derive-inline.rs:636:5 | LL | #[subdiagnostic(bad)] | ^ error: derive(Diagnostic): `#[subdiagnostic = ...]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:645:5 + --> $DIR/diagnostic-derive-inline.rs:644:5 | LL | #[subdiagnostic = "bad"] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:653:5 + --> $DIR/diagnostic-derive-inline.rs:652:5 | LL | #[subdiagnostic(bad, bad)] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:661:5 + --> $DIR/diagnostic-derive-inline.rs:660:5 | LL | #[subdiagnostic("bad")] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:669:5 + --> $DIR/diagnostic-derive-inline.rs:668:5 | LL | #[subdiagnostic(eager)] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:677:5 + --> $DIR/diagnostic-derive-inline.rs:676:5 | LL | #[subdiagnostic(eager)] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:698:5 + --> $DIR/diagnostic-derive-inline.rs:697:5 | LL | #[subdiagnostic(eager)] | ^ error: derive(Diagnostic): expected at least one string literal for `code(...)` - --> $DIR/diagnostic-derive-inline.rs:729:44 + --> $DIR/diagnostic-derive-inline.rs:728:44 | LL | #[suggestion("with a suggestion", code())] | ^ error: derive(Diagnostic): `code(...)` must contain only string literals - --> $DIR/diagnostic-derive-inline.rs:737:44 + --> $DIR/diagnostic-derive-inline.rs:736:44 | LL | #[suggestion("with a suggestion", code(foo))] | ^^^ error: unexpected token, expected `)` - --> $DIR/diagnostic-derive-inline.rs:737:44 + --> $DIR/diagnostic-derive-inline.rs:736:44 | LL | #[suggestion("with a suggestion", code(foo))] | ^^^ error: expected string literal - --> $DIR/diagnostic-derive-inline.rs:746:46 + --> $DIR/diagnostic-derive-inline.rs:745:46 | LL | #[suggestion("with a suggestion", code = 3)] | ^ error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:761:5 + --> $DIR/diagnostic-derive-inline.rs:760:5 | LL | #[suggestion("with a suggestion", code = "")] | ^ @@ -509,7 +509,7 @@ LL | #[suggestion("with a suggestion", code = "")] = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]` error: derive(Diagnostic): Variable `nosub` not found in diagnostic - --> $DIR/diagnostic-derive-inline.rs:773:8 + --> $DIR/diagnostic-derive-inline.rs:772:8 | LL | #[diag("does not exist: {$nosub}")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -517,19 +517,19 @@ LL | #[diag("does not exist: {$nosub}")] = help: Available fields: "sub" error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive-inline.rs:61:3 + --> $DIR/diagnostic-derive-inline.rs:60:3 | LL | #[nonsense("this is an example message", code = E0123)] | ^^^^^^^^ error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive-inline.rs:139:7 + --> $DIR/diagnostic-derive-inline.rs:138:7 | LL | #[nonsense] | ^^^^^^^^ error: cannot find attribute `error` in this scope - --> $DIR/diagnostic-derive-inline.rs:518:3 + --> $DIR/diagnostic-derive-inline.rs:517:3 | LL | #[error("this is an example message", code = E0123)] | ^^^^^ @@ -541,7 +541,7 @@ LL | struct ErrorAttribute {} | error: cannot find attribute `warn_` in this scope - --> $DIR/diagnostic-derive-inline.rs:525:3 + --> $DIR/diagnostic-derive-inline.rs:524:3 | LL | #[warn_("this is an example message", code = E0123)] | ^^^^^ @@ -553,7 +553,7 @@ LL + #[warn("this is an example message", code = E0123)] | error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive-inline.rs:532:3 + --> $DIR/diagnostic-derive-inline.rs:531:3 | LL | #[lint("this is an example message", code = E0123)] | ^^^^ @@ -565,7 +565,7 @@ LL + #[link("this is an example message", code = E0123)] | error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive-inline.rs:539:3 + --> $DIR/diagnostic-derive-inline.rs:538:3 | LL | #[lint("this is an example message", code = E0123)] | ^^^^ @@ -577,7 +577,7 @@ LL + #[link("this is an example message", code = E0123)] | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive-inline.rs:579:3 + --> $DIR/diagnostic-derive-inline.rs:578:3 | LL | #[multipart_suggestion("with a suggestion")] | ^^^^^^^^^^^^^^^^^^^^ @@ -589,7 +589,7 @@ LL | struct MultipartSuggestion { | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive-inline.rs:582:3 + --> $DIR/diagnostic-derive-inline.rs:581:3 | LL | #[multipart_suggestion()] | ^^^^^^^^^^^^^^^^^^^^ @@ -601,7 +601,7 @@ LL | struct MultipartSuggestion { | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive-inline.rs:586:7 + --> $DIR/diagnostic-derive-inline.rs:585:7 | LL | #[multipart_suggestion("with a suggestion")] | ^^^^^^^^^^^^^^^^^^^^ @@ -609,7 +609,7 @@ LL | #[multipart_suggestion("with a suggestion")] = note: `multipart_suggestion` is an attribute that can be used by the derive macro `Subdiagnostic`, you might be missing a `derive` attribute error[E0277]: the trait bound `Hello: IntoDiagArg` is not satisfied - --> $DIR/diagnostic-derive-inline.rs:330:12 + --> $DIR/diagnostic-derive-inline.rs:329:12 | LL | #[derive(Diagnostic)] | ---------- required by a bound introduced by this call @@ -618,7 +618,7 @@ LL | other: Hello, | ^^^^^ unsatisfied trait bound | help: the nightly-only, unstable trait `IntoDiagArg` is not implemented for `Hello` - --> $DIR/diagnostic-derive-inline.rs:42:1 + --> $DIR/diagnostic-derive-inline.rs:41:1 | LL | struct Hello {} | ^^^^^^^^^^^^ diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs index eaa681d40be5..079c2a74c4a1 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs @@ -12,7 +12,6 @@ #![crate_type = "lib"] extern crate rustc_errors; -extern crate rustc_fluent_macro; extern crate rustc_macros; extern crate rustc_session; extern crate rustc_span; diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr index 11753b949bc7..8ff5ed00d0ba 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr @@ -1,143 +1,143 @@ error: derive(Diagnostic): label without `#[primary_span]` field - --> $DIR/subdiagnostic-derive-inline.rs:50:1 + --> $DIR/subdiagnostic-derive-inline.rs:49:1 | LL | #[label("example message")] | ^ error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive-inline.rs:57:1 + --> $DIR/subdiagnostic-derive-inline.rs:56:1 | LL | #[label] | ^ error: derive(Diagnostic): `#[foo]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:66:1 + --> $DIR/subdiagnostic-derive-inline.rs:65:1 | LL | #[foo] | ^ error: derive(Diagnostic): `#[label = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:76:1 + --> $DIR/subdiagnostic-derive-inline.rs:75:1 | LL | #[label = "..."] | ^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive-inline.rs:85:9 + --> $DIR/subdiagnostic-derive-inline.rs:84:9 | LL | #[label(bug = "...")] | ^^^ error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive-inline.rs:85:1 + --> $DIR/subdiagnostic-derive-inline.rs:84:1 | LL | #[label(bug = "...")] | ^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive-inline.rs:95:9 + --> $DIR/subdiagnostic-derive-inline.rs:94:9 | LL | #[label(slug = 4)] | ^^^^ error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive-inline.rs:95:1 + --> $DIR/subdiagnostic-derive-inline.rs:94:1 | LL | #[label(slug = 4)] | ^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive-inline.rs:105:9 + --> $DIR/subdiagnostic-derive-inline.rs:104:9 | LL | #[label(slug("..."))] | ^^^^ error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive-inline.rs:105:1 + --> $DIR/subdiagnostic-derive-inline.rs:104:1 | LL | #[label(slug("..."))] | ^ error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive-inline.rs:115:1 + --> $DIR/subdiagnostic-derive-inline.rs:114:1 | LL | #[label()] | ^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive-inline.rs:124:28 + --> $DIR/subdiagnostic-derive-inline.rs:123:28 | LL | #[label("example message", code = "...")] | ^^^^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive-inline.rs:133:28 + --> $DIR/subdiagnostic-derive-inline.rs:132:28 | LL | #[label("example message", applicability = "machine-applicable")] | ^^^^^^^^^^^^^ error: derive(Diagnostic): unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive-inline.rs:142:1 + --> $DIR/subdiagnostic-derive-inline.rs:141:1 | LL | #[foo] | ^ error: derive(Diagnostic): `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:156:5 + --> $DIR/subdiagnostic-derive-inline.rs:155:5 | LL | #[bar] | ^ error: derive(Diagnostic): `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:168:5 + --> $DIR/subdiagnostic-derive-inline.rs:167:5 | LL | #[bar = "..."] | ^ error: derive(Diagnostic): `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:180:5 + --> $DIR/subdiagnostic-derive-inline.rs:179:5 | LL | #[bar = 4] | ^ error: derive(Diagnostic): `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:192:5 + --> $DIR/subdiagnostic-derive-inline.rs:191:5 | LL | #[bar("...")] | ^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/subdiagnostic-derive-inline.rs:204:13 + --> $DIR/subdiagnostic-derive-inline.rs:203:13 | LL | #[label(code = "...")] | ^^^^ error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive-inline.rs:204:5 + --> $DIR/subdiagnostic-derive-inline.rs:203:5 | LL | #[label(code = "...")] | ^ error: derive(Diagnostic): the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive-inline.rs:233:5 + --> $DIR/subdiagnostic-derive-inline.rs:232:5 | LL | #[primary_span] | ^ error: derive(Diagnostic): label without `#[primary_span]` field - --> $DIR/subdiagnostic-derive-inline.rs:230:1 + --> $DIR/subdiagnostic-derive-inline.rs:229:1 | LL | #[label("example message")] | ^ error: derive(Diagnostic): `#[applicability]` is only valid on suggestions - --> $DIR/subdiagnostic-derive-inline.rs:243:5 + --> $DIR/subdiagnostic-derive-inline.rs:242:5 | LL | #[applicability] | ^ error: derive(Diagnostic): `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:253:5 + --> $DIR/subdiagnostic-derive-inline.rs:252:5 | LL | #[bar] | ^ @@ -145,13 +145,13 @@ LL | #[bar] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: derive(Diagnostic): `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:264:5 + --> $DIR/subdiagnostic-derive-inline.rs:263:5 | LL | #[bar = "..."] | ^ error: derive(Diagnostic): `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:275:5 + --> $DIR/subdiagnostic-derive-inline.rs:274:5 | LL | #[bar("...")] | ^ @@ -159,7 +159,7 @@ LL | #[bar("...")] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: unexpected unsupported untagged union - --> $DIR/subdiagnostic-derive-inline.rs:291:1 + --> $DIR/subdiagnostic-derive-inline.rs:290:1 | LL | / union AC { LL | | @@ -169,97 +169,97 @@ LL | | } | |_^ error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute - --> $DIR/subdiagnostic-derive-inline.rs:306:28 + --> $DIR/subdiagnostic-derive-inline.rs:305:28 | LL | #[label("example message", no_crate::example)] | ^^^^^^^^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive-inline.rs:319:5 + --> $DIR/subdiagnostic-derive-inline.rs:318:5 | LL | #[primary_span] | ^ | note: previously specified here - --> $DIR/subdiagnostic-derive-inline.rs:316:5 + --> $DIR/subdiagnostic-derive-inline.rs:315:5 | LL | #[primary_span] | ^ error: derive(Diagnostic): subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive-inline.rs:325:8 + --> $DIR/subdiagnostic-derive-inline.rs:324:8 | LL | struct AG { | ^^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive-inline.rs:362:47 + --> $DIR/subdiagnostic-derive-inline.rs:361:47 | LL | #[suggestion("example message", code = "...", code = "...")] | ^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive-inline.rs:362:33 + --> $DIR/subdiagnostic-derive-inline.rs:361:33 | LL | #[suggestion("example message", code = "...", code = "...")] | ^^^^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive-inline.rs:380:5 + --> $DIR/subdiagnostic-derive-inline.rs:379:5 | LL | #[applicability] | ^ | note: previously specified here - --> $DIR/subdiagnostic-derive-inline.rs:377:5 + --> $DIR/subdiagnostic-derive-inline.rs:376:5 | LL | #[applicability] | ^ error: derive(Diagnostic): the `#[applicability]` attribute can only be applied to fields of type `Applicability` - --> $DIR/subdiagnostic-derive-inline.rs:390:5 + --> $DIR/subdiagnostic-derive-inline.rs:389:5 | LL | #[applicability] | ^ error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/subdiagnostic-derive-inline.rs:403:1 + --> $DIR/subdiagnostic-derive-inline.rs:402:1 | LL | #[suggestion("example message")] | ^ error: derive(Diagnostic): invalid applicability - --> $DIR/subdiagnostic-derive-inline.rs:413:63 + --> $DIR/subdiagnostic-derive-inline.rs:412:63 | LL | #[suggestion("example message", code = "...", applicability = "foo")] | ^^^^^ error: derive(Diagnostic): suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive-inline.rs:431:1 + --> $DIR/subdiagnostic-derive-inline.rs:430:1 | LL | #[suggestion("example message", code = "...")] | ^ error: derive(Diagnostic): unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive-inline.rs:445:1 + --> $DIR/subdiagnostic-derive-inline.rs:444:1 | LL | #[label] | ^ error: derive(Diagnostic): `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive-inline.rs:465:40 + --> $DIR/subdiagnostic-derive-inline.rs:464:40 | LL | #[suggestion("example message", code = "{var}", applicability = "machine-applicable")] | ^^^^^^^ error: derive(Diagnostic): `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive-inline.rs:484:44 + --> $DIR/subdiagnostic-derive-inline.rs:483:44 | LL | #[suggestion("example message", code = "{var}", applicability = "machine-applicable")] | ^^^^^^^ error: derive(Diagnostic): `#[suggestion_part]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:507:5 + --> $DIR/subdiagnostic-derive-inline.rs:506:5 | LL | #[suggestion_part] | ^ @@ -267,7 +267,7 @@ LL | #[suggestion_part] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead error: derive(Diagnostic): `#[suggestion_part(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:510:5 + --> $DIR/subdiagnostic-derive-inline.rs:509:5 | LL | #[suggestion_part(code = "...")] | ^ @@ -275,13 +275,13 @@ LL | #[suggestion_part(code = "...")] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions error: derive(Diagnostic): suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive-inline.rs:504:1 + --> $DIR/subdiagnostic-derive-inline.rs:503:1 | LL | #[suggestion("example message", code = "...")] | ^ error: derive(Diagnostic): invalid nested attribute - --> $DIR/subdiagnostic-derive-inline.rs:519:43 + --> $DIR/subdiagnostic-derive-inline.rs:518:43 | LL | #[multipart_suggestion("example message", code = "...", applicability = "machine-applicable")] | ^^^^ @@ -289,25 +289,25 @@ LL | #[multipart_suggestion("example message", code = "...", applicability = "ma = help: only `style` and `applicability` are valid nested attributes error: derive(Diagnostic): multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive-inline.rs:519:1 + --> $DIR/subdiagnostic-derive-inline.rs:518:1 | LL | #[multipart_suggestion("example message", code = "...", applicability = "machine-applicable")] | ^ error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive-inline.rs:529:5 + --> $DIR/subdiagnostic-derive-inline.rs:528:5 | LL | #[suggestion_part] | ^ error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive-inline.rs:537:5 + --> $DIR/subdiagnostic-derive-inline.rs:536:5 | LL | #[suggestion_part()] | ^ error: derive(Diagnostic): `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:546:5 + --> $DIR/subdiagnostic-derive-inline.rs:545:5 | LL | #[primary_span] | ^ @@ -315,127 +315,127 @@ LL | #[primary_span] = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]` error: derive(Diagnostic): multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive-inline.rs:543:1 + --> $DIR/subdiagnostic-derive-inline.rs:542:1 | LL | #[multipart_suggestion("example message")] | ^ error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive-inline.rs:554:5 + --> $DIR/subdiagnostic-derive-inline.rs:553:5 | LL | #[suggestion_part] | ^ error: derive(Diagnostic): `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive-inline.rs:557:5 + --> $DIR/subdiagnostic-derive-inline.rs:556:5 | LL | #[suggestion_part()] | ^ error: derive(Diagnostic): `code` is the only valid nested attribute - --> $DIR/subdiagnostic-derive-inline.rs:560:23 + --> $DIR/subdiagnostic-derive-inline.rs:559:23 | LL | #[suggestion_part(foo = "bar")] | ^^^ error: derive(Diagnostic): the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive-inline.rs:564:5 + --> $DIR/subdiagnostic-derive-inline.rs:563:5 | LL | #[suggestion_part(code = "...")] | ^ error: derive(Diagnostic): the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive-inline.rs:567:5 + --> $DIR/subdiagnostic-derive-inline.rs:566:5 | LL | #[suggestion_part()] | ^ error: expected `,` - --> $DIR/subdiagnostic-derive-inline.rs:560:27 + --> $DIR/subdiagnostic-derive-inline.rs:559:27 | LL | #[suggestion_part(foo = "bar")] | ^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive-inline.rs:575:37 + --> $DIR/subdiagnostic-derive-inline.rs:574:37 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive-inline.rs:575:23 + --> $DIR/subdiagnostic-derive-inline.rs:574:23 | LL | #[suggestion_part(code = "...", code = ",,,")] | ^^^^ error: derive(Diagnostic): `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."` - --> $DIR/subdiagnostic-derive-inline.rs:604:5 + --> $DIR/subdiagnostic-derive-inline.rs:603:5 | LL | #[applicability] | ^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive-inline.rs:652:28 + --> $DIR/subdiagnostic-derive-inline.rs:651:28 | LL | #[suggestion_part(code("foo"))] | ^^^^^ error: unexpected token, expected `)` - --> $DIR/subdiagnostic-derive-inline.rs:652:28 + --> $DIR/subdiagnostic-derive-inline.rs:651:28 | LL | #[suggestion_part(code("foo"))] | ^^^^^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive-inline.rs:662:28 + --> $DIR/subdiagnostic-derive-inline.rs:661:28 | LL | #[suggestion_part(code("foo", "bar"))] | ^^^^^ error: unexpected token, expected `)` - --> $DIR/subdiagnostic-derive-inline.rs:662:28 + --> $DIR/subdiagnostic-derive-inline.rs:661:28 | LL | #[suggestion_part(code("foo", "bar"))] | ^^^^^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive-inline.rs:672:28 + --> $DIR/subdiagnostic-derive-inline.rs:671:28 | LL | #[suggestion_part(code(3))] | ^ error: unexpected token, expected `)` - --> $DIR/subdiagnostic-derive-inline.rs:672:28 + --> $DIR/subdiagnostic-derive-inline.rs:671:28 | LL | #[suggestion_part(code(3))] | ^ error: derive(Diagnostic): expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive-inline.rs:682:28 + --> $DIR/subdiagnostic-derive-inline.rs:681:28 | LL | #[suggestion_part(code())] | ^ error: expected string literal - --> $DIR/subdiagnostic-derive-inline.rs:691:30 + --> $DIR/subdiagnostic-derive-inline.rs:690:30 | LL | #[suggestion_part(code = 3)] | ^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/subdiagnostic-derive-inline.rs:733:1 + --> $DIR/subdiagnostic-derive-inline.rs:732:1 | LL | #[suggestion("example message", code = "", style = "hidden", style = "normal")] | ^ | note: previously specified here - --> $DIR/subdiagnostic-derive-inline.rs:733:1 + --> $DIR/subdiagnostic-derive-inline.rs:732:1 | LL | #[suggestion("example message", code = "", style = "hidden", style = "normal")] | ^ error: derive(Diagnostic): `#[suggestion_hidden(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:742:1 + --> $DIR/subdiagnostic-derive-inline.rs:741:1 | LL | #[suggestion_hidden("example message", code = "")] | ^ @@ -443,7 +443,7 @@ LL | #[suggestion_hidden("example message", code = "")] = help: Use `#[suggestion(..., style = "hidden")]` instead error: derive(Diagnostic): `#[suggestion_hidden(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:750:1 + --> $DIR/subdiagnostic-derive-inline.rs:749:1 | LL | #[suggestion_hidden("example message", code = "", style = "normal")] | ^ @@ -451,7 +451,7 @@ LL | #[suggestion_hidden("example message", code = "", style = "normal")] = help: Use `#[suggestion(..., style = "hidden")]` instead error: derive(Diagnostic): invalid suggestion style - --> $DIR/subdiagnostic-derive-inline.rs:758:52 + --> $DIR/subdiagnostic-derive-inline.rs:757:52 | LL | #[suggestion("example message", code = "", style = "foo")] | ^^^^^ @@ -459,25 +459,25 @@ LL | #[suggestion("example message", code = "", style = "foo")] = help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only` error: expected string literal - --> $DIR/subdiagnostic-derive-inline.rs:766:52 + --> $DIR/subdiagnostic-derive-inline.rs:765:52 | LL | #[suggestion("example message", code = "", style = 42)] | ^^ error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute - --> $DIR/subdiagnostic-derive-inline.rs:774:44 + --> $DIR/subdiagnostic-derive-inline.rs:773:44 | LL | #[suggestion("example message", code = "", style)] | ^^^^^ error: expected `=` - --> $DIR/subdiagnostic-derive-inline.rs:782:49 + --> $DIR/subdiagnostic-derive-inline.rs:781:49 | LL | #[suggestion("example message", code = "", style("foo"))] | ^ error: derive(Diagnostic): `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive-inline.rs:793:5 + --> $DIR/subdiagnostic-derive-inline.rs:792:5 | LL | #[primary_span] | ^ @@ -486,61 +486,61 @@ LL | #[primary_span] = help: to create a suggestion with multiple spans, use `#[multipart_suggestion]` instead error: derive(Diagnostic): suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive-inline.rs:790:1 + --> $DIR/subdiagnostic-derive-inline.rs:789:1 | LL | #[suggestion("example message", code = "")] | ^ error: cannot find attribute `foo` in this scope - --> $DIR/subdiagnostic-derive-inline.rs:66:3 + --> $DIR/subdiagnostic-derive-inline.rs:65:3 | LL | #[foo] | ^^^ error: cannot find attribute `foo` in this scope - --> $DIR/subdiagnostic-derive-inline.rs:142:3 + --> $DIR/subdiagnostic-derive-inline.rs:141:3 | LL | #[foo] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive-inline.rs:156:7 + --> $DIR/subdiagnostic-derive-inline.rs:155:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive-inline.rs:168:7 + --> $DIR/subdiagnostic-derive-inline.rs:167:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive-inline.rs:180:7 + --> $DIR/subdiagnostic-derive-inline.rs:179:7 | LL | #[bar = 4] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive-inline.rs:192:7 + --> $DIR/subdiagnostic-derive-inline.rs:191:7 | LL | #[bar("...")] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive-inline.rs:253:7 + --> $DIR/subdiagnostic-derive-inline.rs:252:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive-inline.rs:264:7 + --> $DIR/subdiagnostic-derive-inline.rs:263:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive-inline.rs:275:7 + --> $DIR/subdiagnostic-derive-inline.rs:274:7 | LL | #[bar("...")] | ^^^ From 236dac8d0e41ae9d4e31908c9a0a3fdf2789f5f6 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sat, 7 Feb 2026 14:02:33 -0500 Subject: [PATCH 685/978] fix: remove unnecessary trailing commas in format strings This PR makes the new comma-removing lint PR less noisy, allowing it focus only on the new functionality --- clippy_dev/src/new_lint.rs | 4 ++-- clippy_lints/src/cargo/lint_groups_priority.rs | 2 +- clippy_lints/src/casts/cast_possible_truncation.rs | 2 +- clippy_lints/src/doc/doc_suspicious_footnotes.rs | 2 +- clippy_lints/src/formatting.rs | 2 +- clippy_lints/src/implicit_hasher.rs | 4 ++-- clippy_lints/src/matches/manual_unwrap_or.rs | 2 +- clippy_lints/src/matches/match_like_matches.rs | 2 +- clippy_lints/src/methods/bytes_nth.rs | 2 +- clippy_lints/src/methods/into_iter_on_ref.rs | 2 +- clippy_lints/src/methods/manual_try_fold.rs | 2 +- clippy_lints/src/methods/unit_hash.rs | 2 +- clippy_lints/src/missing_asserts_for_indexing.rs | 6 +++--- clippy_lints/src/missing_enforced_import_rename.rs | 2 +- clippy_lints/src/ptr/cmp_null.rs | 2 +- clippy_lints/src/toplevel_ref_arg.rs | 2 +- clippy_lints/src/zero_div_zero.rs | 2 +- clippy_lints/src/zero_repeat_side_effects.rs | 2 +- rustc_tools_util/src/lib.rs | 2 +- 19 files changed, 23 insertions(+), 23 deletions(-) diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 0b6d702d7721..72f281ca4d9d 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -167,9 +167,9 @@ fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> { let camel_name = to_camel_case(lint.name); let new_lint = if enable_msrv { - format!("Box::new(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(conf))),\n ",) + format!("Box::new(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(conf))),\n ") } else { - format!("Box::new(|{ctor_arg}| Box::new({module_name}::{camel_name})),\n ",) + format!("Box::new(|{ctor_arg}| Box::new({module_name}::{camel_name})),\n ") }; lib_rs.insert_str(comment_start, &new_lint); diff --git a/clippy_lints/src/cargo/lint_groups_priority.rs b/clippy_lints/src/cargo/lint_groups_priority.rs index 14c5e22fb9cd..f937f065d6e0 100644 --- a/clippy_lints/src/cargo/lint_groups_priority.rs +++ b/clippy_lints/src/cargo/lint_groups_priority.rs @@ -100,7 +100,7 @@ fn check_table(cx: &LateContext<'_>, table: &DeTable<'_>, known_groups: &FxHashS "to have lints override the group set `{}` to a lower priority", group.as_ref() ), - format!("{{ level = {:?}, priority = {low_priority} }}", group_config.level,), + format!("{{ level = {:?}, priority = {low_priority} }}", group_config.level), Applicability::MaybeIncorrect, ); }, diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs index 2eebe8492327..0591afaa6c58 100644 --- a/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/clippy_lints/src/casts/cast_possible_truncation.rs @@ -117,7 +117,7 @@ pub(super) fn check( return; } - format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}",) + format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}") }, (ty::Adt(def, _), Some(to_nbits)) if def.is_enum() => { diff --git a/clippy_lints/src/doc/doc_suspicious_footnotes.rs b/clippy_lints/src/doc/doc_suspicious_footnotes.rs index deca29a1885f..dfa6c9637864 100644 --- a/clippy_lints/src/doc/doc_suspicious_footnotes.rs +++ b/clippy_lints/src/doc/doc_suspicious_footnotes.rs @@ -91,7 +91,7 @@ pub fn check(cx: &LateContext<'_>, doc: &str, range: Range, fragments: &F diag.span_suggestion_verbose( this_fragment.span.shrink_to_hi(), "add footnote definition", - format!("\n\n{label}: ", label = &doc[start..end],), + format!("\n\n{label}: ", label = &doc[start..end]), Applicability::HasPlaceholders, ); } else { diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 3b9c70e23e20..7a64d3135fa5 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -337,7 +337,7 @@ fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) { else_span, format!("this looks like {looks_like} but the `else` is missing"), None, - format!("to remove this lint, add the missing `else` or add a new line before {next_thing}",), + format!("to remove this lint, add the missing `else` or add a new line before {next_thing}"), ); } } diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs index 9dc74a157cbf..70176c62772b 100644 --- a/clippy_lints/src/implicit_hasher.rs +++ b/clippy_lints/src/implicit_hasher.rs @@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { ), ( target.span(), - format!("{}<{}, S>", target.type_name(), target.type_arguments(),), + format!("{}<{}, S>", target.type_name(), target.type_arguments()), ), ]; suggestions.extend(vis.suggestions); @@ -352,7 +352,7 @@ impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> { ); self.suggestions.insert( e.span, - format!("{container_name}::with_capacity_and_hasher({arg_snippet}, Default::default())",), + format!("{container_name}::with_capacity_and_hasher({arg_snippet}, Default::default())"), ); }, _ => {}, diff --git a/clippy_lints/src/matches/manual_unwrap_or.rs b/clippy_lints/src/matches/manual_unwrap_or.rs index abbc43d8e9b0..421c6064284d 100644 --- a/clippy_lints/src/matches/manual_unwrap_or.rs +++ b/clippy_lints/src/matches/manual_unwrap_or.rs @@ -173,7 +173,7 @@ fn handle( expr.span, format!("this pattern reimplements `{ty_name}::unwrap_or`"), "replace with", - format!("{suggestion}.unwrap_or({reindented_or_body})",), + format!("{suggestion}.unwrap_or({reindented_or_body})"), app, ); } diff --git a/clippy_lints/src/matches/match_like_matches.rs b/clippy_lints/src/matches/match_like_matches.rs index c26b2dbde7fc..347560b14eea 100644 --- a/clippy_lints/src/matches/match_like_matches.rs +++ b/clippy_lints/src/matches/match_like_matches.rs @@ -187,7 +187,7 @@ pub(super) fn check_match<'tcx>( diag.span_suggestion_verbose( e.span, "use `matches!` directly", - format!("{}matches!({snippet}, {pat_and_guard})", if b0 { "" } else { "!" },), + format!("{}matches!({snippet}, {pat_and_guard})", if b0 { "" } else { "!" }), applicability, ); }, diff --git a/clippy_lints/src/methods/bytes_nth.rs b/clippy_lints/src/methods/bytes_nth.rs index 40d521d61c11..0a3ea3005e72 100644 --- a/clippy_lints/src/methods/bytes_nth.rs +++ b/clippy_lints/src/methods/bytes_nth.rs @@ -34,7 +34,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E parent.span, format!("called `.bytes().nth().unwrap()` on a `{caller_type}`"), "try", - format!("{receiver}.as_bytes()[{n}]",), + format!("{receiver}.as_bytes()[{n}]"), applicability, ); } else { diff --git a/clippy_lints/src/methods/into_iter_on_ref.rs b/clippy_lints/src/methods/into_iter_on_ref.rs index c4b116af4871..5a062732721e 100644 --- a/clippy_lints/src/methods/into_iter_on_ref.rs +++ b/clippy_lints/src/methods/into_iter_on_ref.rs @@ -20,7 +20,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_span: Spa cx, INTO_ITER_ON_REF, method_span, - format!("this `.into_iter()` call is equivalent to `.{method_name}()` and will not consume the `{kind}`",), + format!("this `.into_iter()` call is equivalent to `.{method_name}()` and will not consume the `{kind}`"), "call directly", method_name.to_string(), Applicability::MachineApplicable, diff --git a/clippy_lints/src/methods/manual_try_fold.rs b/clippy_lints/src/methods/manual_try_fold.rs index f2e127bedde5..5f5944d5d423 100644 --- a/clippy_lints/src/methods/manual_try_fold.rs +++ b/clippy_lints/src/methods/manual_try_fold.rs @@ -47,7 +47,7 @@ pub(super) fn check<'tcx>( fold_span, "usage of `Iterator::fold` on a type that implements `Try`", "use `try_fold` instead", - format!("try_fold({init_snip}, {args_snip} ...)",), + format!("try_fold({init_snip}, {args_snip} ...)"), Applicability::HasPlaceholders, ); } diff --git a/clippy_lints/src/methods/unit_hash.rs b/clippy_lints/src/methods/unit_hash.rs index 9defd5626eb4..fb447a99abdc 100644 --- a/clippy_lints/src/methods/unit_hash.rs +++ b/clippy_lints/src/methods/unit_hash.rs @@ -19,7 +19,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &' diag.span_suggestion( expr.span, "remove the call to `hash` or consider using", - format!("0_u8.hash({})", snippet(cx, arg.span, ".."),), + format!("0_u8.hash({})", snippet(cx, arg.span, "..")), Applicability::MaybeIncorrect, ); diag.note("the implementation of `Hash` for `()` is a no-op"); diff --git a/clippy_lints/src/missing_asserts_for_indexing.rs b/clippy_lints/src/missing_asserts_for_indexing.rs index 87ee164a1760..651382fb4bfe 100644 --- a/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/clippy_lints/src/missing_asserts_for_indexing.rs @@ -364,15 +364,15 @@ fn report_indexes(cx: &LateContext<'_>, map: UnindexMap> // `v.len() < 5` and `v.len() <= 5` does nothing in terms of bounds checks. // The user probably meant `v.len() > 5` LengthComparison::LengthLessThanInt | LengthComparison::LengthLessThanOrEqualInt => { - Some(format!("assert!({slice_str}.len() > {highest_index})",)) + Some(format!("assert!({slice_str}.len() > {highest_index})")) }, // `5 < v.len()` == `v.len() > 5` LengthComparison::IntLessThanLength if asserted_len < highest_index => { - Some(format!("assert!({slice_str}.len() > {highest_index})",)) + Some(format!("assert!({slice_str}.len() > {highest_index})")) }, // `5 <= v.len() == `v.len() >= 5` LengthComparison::IntLessThanOrEqualLength if asserted_len <= highest_index => { - Some(format!("assert!({slice_str}.len() > {highest_index})",)) + Some(format!("assert!({slice_str}.len() > {highest_index})")) }, // `highest_index` here is rather a length, so we need to add 1 to it LengthComparison::LengthEqualInt if asserted_len < highest_index + 1 => match macro_call { diff --git a/clippy_lints/src/missing_enforced_import_rename.rs b/clippy_lints/src/missing_enforced_import_rename.rs index 5dd38cf059c2..1f9652a2bd38 100644 --- a/clippy_lints/src/missing_enforced_import_rename.rs +++ b/clippy_lints/src/missing_enforced_import_rename.rs @@ -97,7 +97,7 @@ impl LateLintPass<'_> for ImportRename { span_without_semi, "this import should be renamed", "try", - format!("{import} as {name}",), + format!("{import} as {name}"), Applicability::MachineApplicable, ); } diff --git a/clippy_lints/src/ptr/cmp_null.rs b/clippy_lints/src/ptr/cmp_null.rs index f2d1c855eddd..5e1c62316b7d 100644 --- a/clippy_lints/src/ptr/cmp_null.rs +++ b/clippy_lints/src/ptr/cmp_null.rs @@ -32,7 +32,7 @@ pub(super) fn check<'tcx>( expr.span, "comparing with null is better expressed by the `.is_null()` method", "try", - format!("{invert}{non_null_path_snippet}.is_null()",), + format!("{invert}{non_null_path_snippet}.is_null()"), applicability, ); true diff --git a/clippy_lints/src/toplevel_ref_arg.rs b/clippy_lints/src/toplevel_ref_arg.rs index 250c277ab5e1..bce2ede6589b 100644 --- a/clippy_lints/src/toplevel_ref_arg.rs +++ b/clippy_lints/src/toplevel_ref_arg.rs @@ -109,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for ToplevelRefArg { diag.span_suggestion( stmt.span, "try", - format!("let {name}{tyopt} = {initref};", name = snippet(cx, name.span, ".."),), + format!("let {name}{tyopt} = {initref};", name = snippet(cx, name.span, "..")), app, ); }, diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index bb0cab3a3075..e44c4dc9776e 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for ZeroDiv { expr.span, "constant division of `0.0` with `0.0` will always result in NaN", None, - format!("consider using `{float_type}::NAN` if you would like a constant representing NaN",), + format!("consider using `{float_type}::NAN` if you would like a constant representing NaN"), ); } } diff --git a/clippy_lints/src/zero_repeat_side_effects.rs b/clippy_lints/src/zero_repeat_side_effects.rs index 95085161c09c..cb254cc15629 100644 --- a/clippy_lints/src/zero_repeat_side_effects.rs +++ b/clippy_lints/src/zero_repeat_side_effects.rs @@ -168,7 +168,7 @@ fn assign_expr_suggestion( let indent = snippet_indent(cx, outer_expr.span).unwrap_or_default(); let var_name = snippet(cx, assign_expr_span.source_callsite(), ".."); if needs_curly { - format!("{{\n {indent}{inner_expr};\n {indent}{var_name} = {vec_str}[] as {return_type}\n{indent}}}",) + format!("{{\n {indent}{inner_expr};\n {indent}{var_name} = {vec_str}[] as {return_type}\n{indent}}}") } else { format!("{inner_expr};\n{indent}{var_name} = {vec_str}[] as {return_type}") } diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index 194ed84d04c2..3b7d2d4085d9 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -91,7 +91,7 @@ impl std::fmt::Debug for VersionInfo { self.crate_name, self.major, self.minor, self.patch, )?; if let Some(ref commit_hash) = self.commit_hash { - write!(f, ", commit_hash: \"{}\"", commit_hash.trim(),)?; + write!(f, ", commit_hash: \"{}\"", commit_hash.trim())?; } if let Some(ref commit_date) = self.commit_date { write!(f, ", commit_date: \"{}\"", commit_date.trim())?; From d53133eec22e1e7fc6c25dc595708500f36e9ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 7 Feb 2026 22:03:40 +0100 Subject: [PATCH 686/978] Remove rustdoc adhoc group --- triagebot.toml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 0ee3d0853034..4a4054391ce7 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1488,11 +1488,6 @@ infra-ci = [ "@jdno", "@jieyouxu", ] -rustdoc = [ - "@GuillaumeGomez", - "@notriddle", - "@fmease", -] docs = [ "@ehuss", "@GuillaumeGomez", From d5c6866dbadbf4c410faf6ab8b01c0f88631e171 Mon Sep 17 00:00:00 2001 From: ia0 Date: Sat, 7 Feb 2026 22:06:55 +0100 Subject: [PATCH 687/978] improve tests --- src/tools/rustfmt/tests/source/try_block.rs | 1 + src/tools/rustfmt/tests/source/try_blocks_heterogeneous.rs | 5 +++++ src/tools/rustfmt/tests/target/try_block.rs | 1 + src/tools/rustfmt/tests/target/try_blocks_heterogeneous.rs | 5 +++++ 4 files changed, 12 insertions(+) diff --git a/src/tools/rustfmt/tests/source/try_block.rs b/src/tools/rustfmt/tests/source/try_block.rs index 2e8d61f7e66a..e324a1331758 100644 --- a/src/tools/rustfmt/tests/source/try_block.rs +++ b/src/tools/rustfmt/tests/source/try_block.rs @@ -1,4 +1,5 @@ // rustfmt-edition: 2018 +#![feature(try_blocks)] fn main() -> Result<(), !> { let _x: Option<_> = try { diff --git a/src/tools/rustfmt/tests/source/try_blocks_heterogeneous.rs b/src/tools/rustfmt/tests/source/try_blocks_heterogeneous.rs index bae0060374d8..7a1135cfbc76 100644 --- a/src/tools/rustfmt/tests/source/try_blocks_heterogeneous.rs +++ b/src/tools/rustfmt/tests/source/try_blocks_heterogeneous.rs @@ -1,4 +1,5 @@ // rustfmt-edition: 2018 +#![feature(try_blocks_heterogeneous)] fn main() -> Result<(), !> { let _x = try bikeshed Option<_> { @@ -24,6 +25,10 @@ fn baz() -> Option { 6 }; // comment + let x = try /* Invisible comment */ bikeshed Option<()> {}; + let x = try bikeshed /* Invisible comment */ Option<()> {}; + let x = try bikeshed Option<()> /* Invisible comment */ {}; + let x = try bikeshed Option { baz()?; baz()?; baz()?; 7 }; let x = try bikeshed Foo { 1 + 1 + 1 }; diff --git a/src/tools/rustfmt/tests/target/try_block.rs b/src/tools/rustfmt/tests/target/try_block.rs index 19a3f3e14876..61da123b735d 100644 --- a/src/tools/rustfmt/tests/target/try_block.rs +++ b/src/tools/rustfmt/tests/target/try_block.rs @@ -1,4 +1,5 @@ // rustfmt-edition: 2018 +#![feature(try_blocks)] fn main() -> Result<(), !> { let _x: Option<_> = try { 4 }; diff --git a/src/tools/rustfmt/tests/target/try_blocks_heterogeneous.rs b/src/tools/rustfmt/tests/target/try_blocks_heterogeneous.rs index 6f910ed5d051..018d53ed35e4 100644 --- a/src/tools/rustfmt/tests/target/try_blocks_heterogeneous.rs +++ b/src/tools/rustfmt/tests/target/try_blocks_heterogeneous.rs @@ -1,4 +1,5 @@ // rustfmt-edition: 2018 +#![feature(try_blocks_heterogeneous)] fn main() -> Result<(), !> { let _x = try bikeshed Option<_> { 4 }; @@ -18,6 +19,10 @@ fn baz() -> Option { let y = try bikeshed Option { 6 }; // comment + let x = try /* Invisible comment */ bikeshed Option<()> {}; + let x = try bikeshed /* Invisible comment */ Option<()> {}; + let x = try bikeshed Option<()> /* Invisible comment */ {}; + let x = try bikeshed Option { baz()?; baz()?; From d0b3a0bdc02924cdd28e37f6209ddea0b6bd4727 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Mon, 2 Feb 2026 22:01:10 -0500 Subject: [PATCH 688/978] Add some conversion trait impls - `impl From<[MaybeUninit; N]> for MaybeUninit<[T; N]>` - `impl AsRef<[MaybeUninit; N]> for MaybeUninit<[T; N]>` - `impl AsRef<[MaybeUninit]> for MaybeUninit<[T; N]>` - `impl AsMut<[MaybeUninit; N]> for MaybeUninit<[T; N]>` - `impl AsMut<[MaybeUninit]> for MaybeUninit<[T; N]>` - `impl From> for [MaybeUninit; N]` - `impl AsRef<[Cell; N]> for Cell<[T; N]>` - `impl AsRef<[Cell]> for Cell<[T; N]>` - `impl AsRef<[Cell]> for Cell<[T]>` --- library/core/src/cell.rs | 24 +++++++++ library/core/src/mem/maybe_uninit.rs | 50 +++++++++++++++++++ .../issue-71394-no-from-impl.stderr | 2 +- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 661ea4ab6a27..a9e7c49515c7 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -689,6 +689,30 @@ impl, U> CoerceUnsized> for Cell {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl, U> DispatchFromDyn> for Cell {} +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsRef<[Cell; N]> for Cell<[T; N]> { + #[inline] + fn as_ref(&self) -> &[Cell; N] { + self.as_array_of_cells() + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsRef<[Cell]> for Cell<[T; N]> { + #[inline] + fn as_ref(&self) -> &[Cell] { + &*self.as_array_of_cells() + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsRef<[Cell]> for Cell<[T]> { + #[inline] + fn as_ref(&self) -> &[Cell] { + self.as_slice_of_cells() + } +} + impl Cell<[T]> { /// Returns a `&[Cell]` from a `&Cell<[T]>` /// diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 320eb97f83a4..594147720193 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -1532,6 +1532,56 @@ impl MaybeUninit<[T; N]> { } } +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl From<[MaybeUninit; N]> for MaybeUninit<[T; N]> { + #[inline] + fn from(arr: [MaybeUninit; N]) -> Self { + arr.transpose() + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsRef<[MaybeUninit; N]> for MaybeUninit<[T; N]> { + #[inline] + fn as_ref(&self) -> &[MaybeUninit; N] { + // SAFETY: T and MaybeUninit have the same layout + unsafe { &*ptr::from_ref(self).cast() } + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsRef<[MaybeUninit]> for MaybeUninit<[T; N]> { + #[inline] + fn as_ref(&self) -> &[MaybeUninit] { + &*AsRef::<[MaybeUninit; N]>::as_ref(self) + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsMut<[MaybeUninit; N]> for MaybeUninit<[T; N]> { + #[inline] + fn as_mut(&mut self) -> &mut [MaybeUninit; N] { + // SAFETY: T and MaybeUninit have the same layout + unsafe { &mut *ptr::from_mut(self).cast() } + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl AsMut<[MaybeUninit]> for MaybeUninit<[T; N]> { + #[inline] + fn as_mut(&mut self) -> &mut [MaybeUninit] { + &mut *AsMut::<[MaybeUninit; N]>::as_mut(self) + } +} + +#[stable(feature = "more_conversion_trait_impls", since = "CURRENT_RUSTC_VERSION")] +impl From> for [MaybeUninit; N] { + #[inline] + fn from(arr: MaybeUninit<[T; N]>) -> Self { + arr.transpose() + } +} + impl [MaybeUninit; N] { /// Transposes a `[MaybeUninit; N]` into a `MaybeUninit<[T; N]>`. /// diff --git a/tests/ui/suggestions/issue-71394-no-from-impl.stderr b/tests/ui/suggestions/issue-71394-no-from-impl.stderr index 9e068c311ae0..b8a240f7f07c 100644 --- a/tests/ui/suggestions/issue-71394-no-from-impl.stderr +++ b/tests/ui/suggestions/issue-71394-no-from-impl.stderr @@ -13,7 +13,7 @@ LL | let _: &[i8] = data.into(); `[T; 6]` implements `From<(T, T, T, T, T, T)>` `[T; 7]` implements `From<(T, T, T, T, T, T, T)>` `[T; 8]` implements `From<(T, T, T, T, T, T, T, T)>` - and 6 others + and 7 others = note: required for `&[u8]` to implement `Into<&[i8]>` error: aborting due to 1 previous error From 6de0591c0b62f23ebe8413de465540771ed80074 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Sat, 7 Feb 2026 17:34:39 -0800 Subject: [PATCH 689/978] Split ol mapper into more specific to/kernel/from mapper and move init_all_rtls into global ctor --- .../src/builder/gpu_offload.rs | 88 ++++++++++++------- .../codegen-llvm/gpu_offload/control_flow.rs | 4 +- tests/codegen-llvm/gpu_offload/gpu_host.rs | 53 ++++++----- 3 files changed, 92 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs index 16ab18a568e8..a60e2d1f0ab0 100644 --- a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs +++ b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs @@ -1,12 +1,13 @@ use std::ffi::CString; +use bitflags::Flags; use llvm::Linkage::*; use rustc_abi::Align; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods}; use rustc_middle::bug; -use rustc_middle::ty::offload_meta::OffloadMetadata; +use rustc_middle::ty::offload_meta::{MappingFlags, OffloadMetadata}; use crate::builder::Builder; use crate::common::CodegenCx; @@ -28,10 +29,6 @@ pub(crate) struct OffloadGlobals<'ll> { pub mapper_fn_ty: &'ll llvm::Type, pub ident_t_global: &'ll llvm::Value, - - // FIXME(offload): Drop this, once we fully automated our offload compilation pipeline, since - // LLVM will initialize them for us if it sees gpu kernels being registered. - pub init_rtls: &'ll llvm::Value, } impl<'ll> OffloadGlobals<'ll> { @@ -42,9 +39,6 @@ impl<'ll> OffloadGlobals<'ll> { let (begin_mapper, _, end_mapper, mapper_fn_ty) = gen_tgt_data_mappers(cx); let ident_t_global = generate_at_one(cx); - let init_ty = cx.type_func(&[], cx.type_void()); - let init_rtls = declare_offload_fn(cx, "__tgt_init_all_rtls", init_ty); - // We want LLVM's openmp-opt pass to pick up and optimize this module, since it covers both // openmp and offload optimizations. llvm::add_module_flag_u32(cx.llmod(), llvm::ModuleFlagMergeBehavior::Max, "openmp", 51); @@ -58,7 +52,6 @@ impl<'ll> OffloadGlobals<'ll> { end_mapper, mapper_fn_ty, ident_t_global, - init_rtls, } } } @@ -91,6 +84,11 @@ pub(crate) fn register_offload<'ll>(cx: &CodegenCx<'ll, '_>) { let atexit = cx.type_func(&[cx.type_ptr()], cx.type_i32()); let atexit_fn = declare_offload_fn(cx, "atexit", atexit); + // FIXME(offload): Drop this, once we fully automated our offload compilation pipeline, since + // LLVM will initialize them for us if it sees gpu kernels being registered. + let init_ty = cx.type_func(&[], cx.type_void()); + let init_rtls = declare_offload_fn(cx, "__tgt_init_all_rtls", init_ty); + let desc_ty = cx.type_func(&[], cx.type_void()); let reg_name = ".omp_offloading.descriptor_reg"; let unreg_name = ".omp_offloading.descriptor_unreg"; @@ -104,12 +102,14 @@ pub(crate) fn register_offload<'ll>(cx: &CodegenCx<'ll, '_>) { // define internal void @.omp_offloading.descriptor_reg() section ".text.startup" { // entry: // call void @__tgt_register_lib(ptr @.omp_offloading.descriptor) + // call void @__tgt_init_all_rtls() // %0 = call i32 @atexit(ptr @.omp_offloading.descriptor_unreg) // ret void // } let bb = Builder::append_block(cx, desc_reg_fn, "entry"); let mut a = Builder::build(cx, bb); a.call(reg_lib_decl, None, None, register_lib, &[omp_descriptor], None, None); + a.call(init_ty, None, None, init_rtls, &[], None, None); a.call(atexit, None, None, atexit_fn, &[desc_unreg_fn], None, None); a.ret_void(); @@ -345,7 +345,9 @@ impl KernelArgsTy { #[derive(Copy, Clone)] pub(crate) struct OffloadKernelGlobals<'ll> { pub offload_sizes: &'ll llvm::Value, - pub memtransfer_types: &'ll llvm::Value, + pub memtransfer_begin: &'ll llvm::Value, + pub memtransfer_kernel: &'ll llvm::Value, + pub memtransfer_end: &'ll llvm::Value, pub region_id: &'ll llvm::Value, } @@ -423,18 +425,38 @@ pub(crate) fn gen_define_handling<'ll>( let offload_entry_ty = offload_globals.offload_entry_ty; - // FIXME(Sa4dUs): add `OMP_MAP_TARGET_PARAM = 0x20` only if necessary let (sizes, transfer): (Vec<_>, Vec<_>) = - metadata.iter().map(|m| (m.payload_size, m.mode.bits() | 0x20)).unzip(); + metadata.iter().map(|m| (m.payload_size, m.mode)).unzip(); + // Our begin mapper should only see simplified information about which args have to be + // transferred to the device, the end mapper only about which args should be transferred back. + // Any information beyond that makes it harder for LLVM's opt pass to evaluate whether it can + // safely move (=optimize) the LLVM-IR location of this data transfer. Only the mapping types + // mentioned below are handled, so make sure that we don't generate any other ones. + let handled_mappings = MappingFlags::TO + | MappingFlags::FROM + | MappingFlags::TARGET_PARAM + | MappingFlags::LITERAL + | MappingFlags::IMPLICIT; + for arg in &transfer { + debug_assert!(!arg.contains_unknown_bits()); + debug_assert!(handled_mappings.contains(*arg)); + } + + let valid_begin_mappings = MappingFlags::TO | MappingFlags::LITERAL | MappingFlags::IMPLICIT; + let transfer_to: Vec = + transfer.iter().map(|m| m.intersection(valid_begin_mappings).bits()).collect(); + let transfer_from: Vec = + transfer.iter().map(|m| m.intersection(MappingFlags::FROM).bits()).collect(); + // FIXME(offload): add `OMP_MAP_TARGET_PARAM = 0x20` only if necessary + let transfer_kernel = vec![MappingFlags::TARGET_PARAM.bits(); transfer_to.len()]; let offload_sizes = add_priv_unnamed_arr(&cx, &format!(".offload_sizes.{symbol}"), &sizes); - // Here we figure out whether something needs to be copied to the gpu (=1), from the gpu (=2), - // or both to and from the gpu (=3). Other values shouldn't affect us for now. - // A non-mutable reference or pointer will be 1, an array that's not read, but fully overwritten - // will be 2. For now, everything is 3, until we have our frontend set up. - // 1+2+32: 1 (MapTo), 2 (MapFrom), 32 (Add one extra input ptr per function, to be used later). - let memtransfer_types = - add_priv_unnamed_arr(&cx, &format!(".offload_maptypes.{symbol}"), &transfer); + let memtransfer_begin = + add_priv_unnamed_arr(&cx, &format!(".offload_maptypes.{symbol}.begin"), &transfer_to); + let memtransfer_kernel = + add_priv_unnamed_arr(&cx, &format!(".offload_maptypes.{symbol}.kernel"), &transfer_kernel); + let memtransfer_end = + add_priv_unnamed_arr(&cx, &format!(".offload_maptypes.{symbol}.end"), &transfer_from); // Next: For each function, generate these three entries. A weak constant, // the llvm.rodata entry name, and the llvm_offload_entries value @@ -469,7 +491,13 @@ pub(crate) fn gen_define_handling<'ll>( cx.add_compiler_used_global(offload_entry); - let result = OffloadKernelGlobals { offload_sizes, memtransfer_types, region_id }; + let result = OffloadKernelGlobals { + offload_sizes, + memtransfer_begin, + memtransfer_kernel, + memtransfer_end, + region_id, + }; // FIXME(Sa4dUs): use this global for constant offload sizes cx.add_compiler_used_global(result.offload_sizes); @@ -535,7 +563,13 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( offload_dims: &OffloadKernelDims<'ll>, ) { let cx = builder.cx; - let OffloadKernelGlobals { memtransfer_types, region_id, .. } = offload_data; + let OffloadKernelGlobals { + memtransfer_begin, + memtransfer_kernel, + memtransfer_end, + region_id, + .. + } = offload_data; let OffloadKernelDims { num_workgroups, threads_per_block, workgroup_dims, thread_dims } = offload_dims; @@ -608,12 +642,6 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( geps.push(gep); } - let init_ty = cx.type_func(&[], cx.type_void()); - let init_rtls_decl = offload_globals.init_rtls; - - // call void @__tgt_init_all_rtls() - builder.call(init_ty, None, None, init_rtls_decl, &[], None, None); - for i in 0..num_args { let idx = cx.get_const_i32(i); let gep1 = builder.inbounds_gep(ty, a1, &[i32_0, idx]); @@ -668,14 +696,14 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( generate_mapper_call( builder, geps, - memtransfer_types, + memtransfer_begin, begin_mapper_decl, fn_ty, num_args, s_ident_t, ); let values = - KernelArgsTy::new(&cx, num_args, memtransfer_types, geps, workgroup_dims, thread_dims); + KernelArgsTy::new(&cx, num_args, memtransfer_kernel, geps, workgroup_dims, thread_dims); // Step 3) // Here we fill the KernelArgsTy, see the documentation above @@ -701,7 +729,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( generate_mapper_call( builder, geps, - memtransfer_types, + memtransfer_end, end_mapper_decl, fn_ty, num_args, diff --git a/tests/codegen-llvm/gpu_offload/control_flow.rs b/tests/codegen-llvm/gpu_offload/control_flow.rs index 1a3d3cd7a778..fb483db667b2 100644 --- a/tests/codegen-llvm/gpu_offload/control_flow.rs +++ b/tests/codegen-llvm/gpu_offload/control_flow.rs @@ -19,9 +19,9 @@ // CHECK: br label %bb3 // CHECK-NOT define // CHECK: bb3 -// CHECK: call void @__tgt_target_data_begin_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.foo, ptr null, ptr null) +// CHECK: call void @__tgt_target_data_begin_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.foo.begin, ptr null, ptr null) // CHECK: %10 = call i32 @__tgt_target_kernel(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 256, i32 32, ptr nonnull @.foo.region_id, ptr nonnull %kernel_args) -// CHECK-NEXT: call void @__tgt_target_data_end_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.foo, ptr null, ptr null) +// CHECK-NEXT: call void @__tgt_target_data_end_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.foo.end, ptr null, ptr null) #[unsafe(no_mangle)] unsafe fn main() { let A = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0]; diff --git a/tests/codegen-llvm/gpu_offload/gpu_host.rs b/tests/codegen-llvm/gpu_offload/gpu_host.rs index e12d7c792ae7..f25ba679abbd 100644 --- a/tests/codegen-llvm/gpu_offload/gpu_host.rs +++ b/tests/codegen-llvm/gpu_offload/gpu_host.rs @@ -14,19 +14,20 @@ #[unsafe(no_mangle)] fn main() { let mut x = [3.0; 256]; - kernel_1(&mut x); + let y = [1.0; 256]; + kernel_1(&mut x, &y); core::hint::black_box(&x); + core::hint::black_box(&y); } -pub fn kernel_1(x: &mut [f32; 256]) { - core::intrinsics::offload(kernel_1, [256, 1, 1], [32, 1, 1], (x,)) +pub fn kernel_1(x: &mut [f32; 256], y: &[f32; 256]) { + core::intrinsics::offload(_kernel_1, [256, 1, 1], [32, 1, 1], (x, y)) } -#[unsafe(no_mangle)] #[inline(never)] -pub fn _kernel_1(x: &mut [f32; 256]) { +pub fn _kernel_1(x: &mut [f32; 256], y: &[f32; 256]) { for i in 0..256 { - x[i] = 21.0; + x[i] = 21.0 + y[i]; } } @@ -39,8 +40,10 @@ pub fn _kernel_1(x: &mut [f32; 256]) { // CHECK-DAG: @.omp_offloading.descriptor = internal constant { i32, ptr, ptr, ptr } zeroinitializer // CHECK-DAG: @llvm.global_ctors = appending constant [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @.omp_offloading.descriptor_reg, ptr null }] -// CHECK-DAG: @.offload_sizes.[[K:[^ ]*kernel_1]] = private unnamed_addr constant [1 x i64] [i64 1024] -// CHECK-DAG: @.offload_maptypes.[[K]] = private unnamed_addr constant [1 x i64] [i64 35] +// CHECK-DAG: @.offload_sizes.[[K:[^ ]*kernel_1]] = private unnamed_addr constant [2 x i64] [i64 1024, i64 1024] +// CHECK-DAG: @.offload_maptypes.[[K]].begin = private unnamed_addr constant [2 x i64] [i64 1, i64 1] +// CHECK-DAG: @.offload_maptypes.[[K]].kernel = private unnamed_addr constant [2 x i64] [i64 32, i64 32] +// CHECK-DAG: @.offload_maptypes.[[K]].end = private unnamed_addr constant [2 x i64] [i64 2, i64 0] // CHECK-DAG: @.[[K]].region_id = internal constant i8 0 // CHECK-DAG: @.offloading.entry_name.[[K]] = internal unnamed_addr constant [{{[0-9]+}} x i8] c"[[K]]{{\\00}}", section ".llvm.rodata.offloading", align 1 // CHECK-DAG: @.offloading.entry.[[K]] = internal constant %struct.__tgt_offload_entry { i64 0, i16 1, i16 1, i32 0, ptr @.[[K]].region_id, ptr @.offloading.entry_name.[[K]], i64 0, i64 0, ptr null }, section "llvm_offload_entries", align 8 @@ -49,20 +52,27 @@ pub fn _kernel_1(x: &mut [f32; 256]) { // CHECK-LABEL: define{{( dso_local)?}} void @main() // CHECK-NEXT: start: -// CHECK-NEXT: %0 = alloca [8 x i8], align 8 -// CHECK-NEXT: %x = alloca [1024 x i8], align 16 -// CHECK-NEXT: %.offload_baseptrs = alloca [1 x ptr], align 8 -// CHECK-NEXT: %.offload_ptrs = alloca [1 x ptr], align 8 -// CHECK-NEXT: %.offload_sizes = alloca [1 x i64], align 8 +// CHECK-NEXT: %0 = alloca [8 x i8], align 8 +// CHECK-NEXT: %1 = alloca [8 x i8], align 8 +// CHECK-NEXT: %y = alloca [1024 x i8], align 16 +// CHECK-NEXT: %x = alloca [1024 x i8], align 16 +// CHECK-NEXT: %.offload_baseptrs = alloca [2 x ptr], align 8 +// CHECK-NEXT: %.offload_ptrs = alloca [2 x ptr], align 8 +// CHECK-NEXT: %.offload_sizes = alloca [2 x i64], align 8 // CHECK-NEXT: %kernel_args = alloca %struct.__tgt_kernel_arguments, align 8 -// CHECK: call void @__tgt_init_all_rtls() -// CHECK-NEXT: store ptr %x, ptr %.offload_baseptrs, align 8 +// CHECK: store ptr %x, ptr %.offload_baseptrs, align 8 // CHECK-NEXT: store ptr %x, ptr %.offload_ptrs, align 8 // CHECK-NEXT: store i64 1024, ptr %.offload_sizes, align 8 -// CHECK-NEXT: call void @__tgt_target_data_begin_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.[[K]], ptr null, ptr null) +// CHECK-NEXT: [[BPTRS_1:%.*]] = getelementptr inbounds nuw i8, ptr %.offload_baseptrs, i64 8 +// CHECK-NEXT: store ptr %y, ptr [[BPTRS_1]], align 8 +// CHECK-NEXT: [[PTRS_1:%.*]] = getelementptr inbounds nuw i8, ptr %.offload_ptrs, i64 8 +// CHECK-NEXT: store ptr %y, ptr [[PTRS_1]], align 8 +// CHECK-NEXT: [[SIZES_1:%.*]] = getelementptr inbounds nuw i8, ptr %.offload_sizes, i64 8 +// CHECK-NEXT: store i64 1024, ptr [[SIZES_1]], align 8 +// CHECK-NEXT: call void @__tgt_target_data_begin_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 2, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.[[K]].begin, ptr null, ptr null) // CHECK-NEXT: store i32 3, ptr %kernel_args, align 8 // CHECK-NEXT: [[P4:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %kernel_args, i64 4 -// CHECK-NEXT: store i32 1, ptr [[P4]], align 4 +// CHECK-NEXT: store i32 2, ptr [[P4]], align 4 // CHECK-NEXT: [[P8:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %kernel_args, i64 8 // CHECK-NEXT: store ptr %.offload_baseptrs, ptr [[P8]], align 8 // CHECK-NEXT: [[P16:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %kernel_args, i64 16 @@ -70,7 +80,7 @@ pub fn _kernel_1(x: &mut [f32; 256]) { // CHECK-NEXT: [[P24:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %kernel_args, i64 24 // CHECK-NEXT: store ptr %.offload_sizes, ptr [[P24]], align 8 // CHECK-NEXT: [[P32:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %kernel_args, i64 32 -// CHECK-NEXT: store ptr @.offload_maptypes.[[K]], ptr [[P32]], align 8 +// CHECK-NEXT: store ptr @.offload_maptypes.[[K]].kernel, ptr [[P32]], align 8 // CHECK-NEXT: [[P40:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %kernel_args, i64 40 // CHECK-NEXT: [[P72:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %kernel_args, i64 72 // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr noundef nonnull align 8 dereferenceable(32) [[P40]], i8 0, i64 32, i1 false) @@ -81,9 +91,9 @@ pub fn _kernel_1(x: &mut [f32; 256]) { // CHECK-NEXT: store i32 1, ptr [[P92]], align 4 // CHECK-NEXT: [[P96:%[^ ]+]] = getelementptr inbounds nuw i8, ptr %kernel_args, i64 96 // CHECK-NEXT: store i32 0, ptr [[P96]], align 8 -// CHECK-NEXT: {{%[^ ]+}} = call i32 @__tgt_target_kernel(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 256, i32 32, ptr nonnull @.[[K]].region_id, ptr nonnull %kernel_args) -// CHECK-NEXT: call void @__tgt_target_data_end_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.[[K]], ptr null, ptr null) -// CHECK: ret void +// CHECK-NEXT: [[TGT_RET:%.*]] = call i32 @__tgt_target_kernel(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 256, i32 32, ptr nonnull @.[[K]].region_id, ptr nonnull %kernel_args) +// CHECK-NEXT: call void @__tgt_target_data_end_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 2, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.[[K]].end, ptr null, ptr null) +// CHECK: ret void // CHECK-NEXT: } // CHECK: declare void @__tgt_register_lib(ptr) local_unnamed_addr @@ -92,6 +102,7 @@ pub fn _kernel_1(x: &mut [f32; 256]) { // CHECK-LABEL: define internal void @.omp_offloading.descriptor_reg() section ".text.startup" { // CHECK-NEXT: entry: // CHECK-NEXT: call void @__tgt_register_lib(ptr nonnull @.omp_offloading.descriptor) +// CHECK-NEXT: call void @__tgt_init_all_rtls() // CHECK-NEXT: %0 = {{tail }}call i32 @atexit(ptr nonnull @.omp_offloading.descriptor_unreg) // CHECK-NEXT: ret void // CHECK-NEXT: } From 7c5ea7ffd648cb1170510a7b50b0294a30891ffd Mon Sep 17 00:00:00 2001 From: Ruiyang Wang Date: Sat, 7 Feb 2026 17:57:53 +0000 Subject: [PATCH 690/978] Fix bound var resolution for trait aliases Handle DefKind::TraitAlias in resolve_bound_vars so that associated item constraints and return type notation work through trait aliases. --- .../src/collect/resolve_bound_vars.rs | 5 +++-- .../return-type-notation/trait-alias.rs | 13 +++++++++++++ .../trait-alias-bound-vars.rs | 14 ++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 tests/ui/associated-type-bounds/return-type-notation/trait-alias.rs create mode 100644 tests/ui/associated-type-bounds/trait-alias-bound-vars.rs 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 26f79d374075..d4a01d26a1fc 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1695,7 +1695,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { | DefKind::Union | DefKind::Enum | DefKind::TyAlias - | DefKind::Trait, + | DefKind::Trait + | DefKind::TraitAlias, def_id, ) if depth == 0 => Some(def_id), _ => None, @@ -1865,7 +1866,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { if constraint.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation { let bound_vars = if let Some(type_def_id) = type_def_id - && self.tcx.def_kind(type_def_id) == DefKind::Trait + && let DefKind::Trait | DefKind::TraitAlias = self.tcx.def_kind(type_def_id) && let Some((mut bound_vars, assoc_fn)) = BoundVarContext::supertrait_hrtb_vars( self.tcx, type_def_id, diff --git a/tests/ui/associated-type-bounds/return-type-notation/trait-alias.rs b/tests/ui/associated-type-bounds/return-type-notation/trait-alias.rs new file mode 100644 index 000000000000..88f60a72afa1 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/trait-alias.rs @@ -0,0 +1,13 @@ +// Regression test for . +//@ check-pass +#![feature(return_type_notation, trait_alias)] + +trait Tr { + fn f() -> impl Sized; +} + +trait Al = Tr; + +fn f>() {} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/trait-alias-bound-vars.rs b/tests/ui/associated-type-bounds/trait-alias-bound-vars.rs new file mode 100644 index 000000000000..4644cee21008 --- /dev/null +++ b/tests/ui/associated-type-bounds/trait-alias-bound-vars.rs @@ -0,0 +1,14 @@ +// Check that we're successfully collecting bound vars behind trait aliases. +// Regression test for . +//@ check-pass +//@ needs-rustc-debug-assertions +#![feature(trait_alias)] + +trait A<'a> { type X; } +trait B: for<'a> A<'a> {} +trait C = B; + +fn f() where T: C {} +fn g() where T: C A<'r>> {} + +fn main() {} From 58e4a341b634f21cf164e7636f4b8d63432dae7b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 5 Feb 2026 14:24:39 +1100 Subject: [PATCH 691/978] Move `try_get_cached` from `rustc_query_system` to `rustc_middle`. That's the only place it's used, so it no longer needs to be `pub`. --- compiler/rustc_middle/src/query/inner.rs | 21 ++++++++++++++++++- .../rustc_query_system/src/query/plumbing.rs | 20 ------------------ 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_middle/src/query/inner.rs b/compiler/rustc_middle/src/query/inner.rs index 32fe0737ec12..594286bfa574 100644 --- a/compiler/rustc_middle/src/query/inner.rs +++ b/compiler/rustc_middle/src/query/inner.rs @@ -2,7 +2,7 @@ //! `tcx.$query(..)` and its variations. use rustc_query_system::dep_graph::{DepKind, DepNodeKey}; -use rustc_query_system::query::{QueryCache, QueryMode, try_get_cached}; +use rustc_query_system::query::{QueryCache, QueryMode}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use crate::dep_graph; @@ -10,6 +10,25 @@ use crate::query::erase::{self, Erasable, Erased}; use crate::query::plumbing::QueryVTable; use crate::ty::TyCtxt; +/// Checks whether there is already a value for this key in the in-memory +/// query cache, returning that value if present. +/// +/// (Also performs some associated bookkeeping, if a value was found.) +#[inline(always)] +fn try_get_cached<'tcx, C>(tcx: TyCtxt<'tcx>, cache: &C, key: &C::Key) -> Option +where + C: QueryCache, +{ + match cache.lookup(key) { + Some((value, index)) => { + tcx.prof.query_cache_hit(index.into()); + tcx.dep_graph.read_index(index); + Some(value) + } + None => None, + } +} + /// Shared implementation of `tcx.$query(..)` and `tcx.at(span).$query(..)` /// for all queries. #[inline(always)] diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 32c4f6e1c847..795d36c7b808 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -266,26 +266,6 @@ impl<'tcx> CycleError> { } } -/// Checks whether there is already a value for this key in the in-memory -/// query cache, returning that value if present. -/// -/// (Also performs some associated bookkeeping, if a value was found.) -#[inline(always)] -pub fn try_get_cached(tcx: Tcx, cache: &C, key: &C::Key) -> Option -where - C: QueryCache, - Tcx: DepContext, -{ - match cache.lookup(key) { - Some((value, index)) => { - tcx.profiler().query_cache_hit(index.into()); - tcx.dep_graph().read_index(index); - Some(value) - } - None => None, - } -} - #[cold] #[inline(never)] fn cycle_error<'tcx, Q>( From 25df79ea5d5a9cc03d13018d7a3f86190c35dc2c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 5 Feb 2026 15:15:13 +1100 Subject: [PATCH 692/978] Derive `Clone` for `QueryJob`. Instead of writing it by hand. --- compiler/rustc_query_system/src/query/job.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 50cb58f0b4d5..0fd50128b544 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -65,7 +65,7 @@ pub struct QueryJobInfo<'tcx> { } /// Represents an active query job. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct QueryJob<'tcx> { pub id: QueryJobId, @@ -79,12 +79,6 @@ pub struct QueryJob<'tcx> { latch: Option>, } -impl<'tcx> Clone for QueryJob<'tcx> { - fn clone(&self) -> Self { - Self { id: self.id, span: self.span, parent: self.parent, latch: self.latch.clone() } - } -} - impl<'tcx> QueryJob<'tcx> { /// Creates a new query job. #[inline] From d3ec6a351a027a71bdfbd36429288c1357ccdbea Mon Sep 17 00:00:00 2001 From: Weixie Cui Date: Sun, 8 Feb 2026 11:40:56 +0800 Subject: [PATCH 693/978] fix: add continue --- compiler/rustc_borrowck/src/diagnostics/region_errors.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index ae389d1a6e10..6e35cf0ea28b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -872,6 +872,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { for alias_ty in alias_tys { if alias_ty.span.desugaring_kind().is_some() { // Skip `async` desugaring `impl Future`. + continue; } if let TyKind::TraitObject(_, lt) = alias_ty.kind { if lt.kind == hir::LifetimeKind::ImplicitObjectLifetimeDefault { From 6527b3404c7ce641d50f4bda7711903f30b3e34c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 8 Feb 2026 15:14:17 +1100 Subject: [PATCH 694/978] Move a lot of `rustc_query_system::plumbing` to `rustc_query_impl::execution` (part 1). [Note: this commit conceptually moves 75% of a file to another location, and leaves 25% of it behind. It's impossible to preserve all the git history. To preserve git history of the moved 75%, in this commit we rename the file and remove the 25% from it, leaving the code in an incomplete (uncompilable) state. In the next commit we add back the 25% in the old location.] We are in the process of eliminating `rustc_query_system`. Chunks of it are unused by `rustc_middle`, and so can be moved into `rustc_query_impl`. This commit does some of that. Mostly it's just moving code from one file to a new file. There are a couple of non-trivial changes. - `QueryState` and `ActiveKeyStatus` must remain in `rustc_query_system` because they are used by `rustc_middle`. But their inherent methods are not used by `rustc_middle`. So these methods are moved and converted to free functions. - The visibility of some things must increase. This includes `DepGraphData` and some of its methods, which are now used in `rustc_query_impl`. This is a bit annoying but seems hard to avoid. What little is left behind in `compiler/rustc_query_system/src/query/plumbing.rs` will be able to moved into `rustc_query_impl` or `rustc_middle` in the future. --- .../src/execution.rs} | 284 +++++------------- compiler/rustc_query_impl/src/lib.rs | 16 +- compiler/rustc_query_impl/src/plumbing.rs | 11 +- .../rustc_query_system/src/dep_graph/graph.rs | 18 +- .../rustc_query_system/src/dep_graph/mod.rs | 5 +- compiler/rustc_query_system/src/lib.rs | 1 - compiler/rustc_query_system/src/query/job.rs | 8 +- compiler/rustc_query_system/src/query/mod.rs | 6 +- 8 files changed, 100 insertions(+), 249 deletions(-) rename compiler/{rustc_query_system/src/query/plumbing.rs => rustc_query_impl/src/execution.rs} (73%) diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_impl/src/execution.rs similarity index 73% rename from compiler/rustc_query_system/src/query/plumbing.rs rename to compiler/rustc_query_impl/src/execution.rs index 795d36c7b808..9fa41f741e08 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -1,133 +1,83 @@ -//! The implementation of the query system itself. This defines the macros that -//! generate the actual methods on tcx which find and execute the provider, -//! manage the caches, and so forth. - -use std::cell::Cell; -use std::fmt::Debug; use std::hash::Hash; use std::mem; -use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::hash_table::{self, Entry, HashTable}; -use rustc_data_structures::sharded::{self, Sharded}; +use rustc_data_structures::hash_table::{Entry, HashTable}; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::{outline, sync}; +use rustc_data_structures::{outline, sharded, sync}; use rustc_errors::{Diag, FatalError, StashKey}; +use rustc_query_system::dep_graph::{DepGraphData, DepNodeKey, HasDepContext}; +use rustc_query_system::query::{ + ActiveKeyStatus, CycleError, CycleErrorHandling, QueryCache, QueryContext, QueryDispatcher, + QueryJob, QueryJobId, QueryJobInfo, QueryLatch, QueryMap, QueryMode, QueryStackDeferred, + QueryStackFrame, QueryState, incremental_verify_ich, report_cycle, +}; use rustc_span::{DUMMY_SP, Span}; -use tracing::instrument; -use super::{QueryDispatcher, QueryStackDeferred, QueryStackFrameExtra}; -use crate::dep_graph::{ - DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeKey, HasDepContext, -}; -use crate::ich::StableHashingContext; -use crate::query::caches::QueryCache; -use crate::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, report_cycle}; -use crate::query::{ - CycleErrorHandling, QueryContext, QueryMap, QueryStackFrame, SerializedDepNodeIndex, -}; +use crate::dep_graph::{DepContext, DepNode, DepNodeIndex}; #[inline] fn equivalent_key(k: &K) -> impl Fn(&(K, V)) -> bool + '_ { move |x| x.0 == *k } -/// For a particular query, keeps track of "active" keys, i.e. keys whose -/// evaluation has started but has not yet finished successfully. +/// Obtains the enclosed [`QueryJob`], or panics if this query evaluation +/// was poisoned by a panic. +fn expect_job<'tcx>(status: ActiveKeyStatus<'tcx>) -> QueryJob<'tcx> { + match status { + ActiveKeyStatus::Started(job) => job, + ActiveKeyStatus::Poisoned => { + panic!("job for query failed to start and was poisoned") + } + } +} + +pub(crate) fn all_inactive<'tcx, K>(state: &QueryState<'tcx, K>) -> bool { + state.active.lock_shards().all(|shard| shard.is_empty()) +} + +/// Internal plumbing for collecting the set of active jobs for this query. /// -/// (Successful query evaluation for a key is represented by an entry in the -/// query's in-memory cache.) -pub struct QueryState<'tcx, K> { - active: Sharded)>>, -} +/// Should only be called from `gather_active_jobs`. +pub(crate) fn gather_active_jobs_inner<'tcx, Qcx: Copy, K: Copy>( + state: &QueryState<'tcx, K>, + qcx: Qcx, + make_frame: fn(Qcx, K) -> QueryStackFrame>, + jobs: &mut QueryMap<'tcx>, + require_complete: bool, +) -> Option<()> { + let mut active = Vec::new(); -/// For a particular query and key, tracks the status of a query evaluation -/// that has started, but has not yet finished successfully. -/// -/// (Successful query evaluation for a key is represented by an entry in the -/// query's in-memory cache.) -enum ActiveKeyStatus<'tcx> { - /// Some thread is already evaluating the query for this key. - /// - /// The enclosed [`QueryJob`] can be used to wait for it to finish. - Started(QueryJob<'tcx>), - - /// The query panicked. Queries trying to wait on this will raise a fatal error which will - /// silently panic. - Poisoned, -} - -impl<'tcx> ActiveKeyStatus<'tcx> { - /// Obtains the enclosed [`QueryJob`], or panics if this query evaluation - /// was poisoned by a panic. - fn expect_job(self) -> QueryJob<'tcx> { - match self { - Self::Started(job) => job, - Self::Poisoned => { - panic!("job for query failed to start and was poisoned") + // Helper to gather active jobs from a single shard. + let mut gather_shard_jobs = |shard: &HashTable<(K, ActiveKeyStatus<'tcx>)>| { + for (k, v) in shard.iter() { + if let ActiveKeyStatus::Started(ref job) = *v { + active.push((*k, job.clone())); } } - } -} + }; -impl<'tcx, K> QueryState<'tcx, K> -where - K: Eq + Hash + Copy + Debug, -{ - pub fn all_inactive(&self) -> bool { - self.active.lock_shards().all(|shard| shard.is_empty()) - } - - /// Internal plumbing for collecting the set of active jobs for this query. - /// - /// Should only be called from `gather_active_jobs`. - pub fn gather_active_jobs_inner( - &self, - qcx: Qcx, - make_frame: fn(Qcx, K) -> QueryStackFrame>, - jobs: &mut QueryMap<'tcx>, - require_complete: bool, - ) -> Option<()> { - let mut active = Vec::new(); - - // Helper to gather active jobs from a single shard. - let mut gather_shard_jobs = |shard: &HashTable<(K, ActiveKeyStatus<'tcx>)>| { - for (k, v) in shard.iter() { - if let ActiveKeyStatus::Started(ref job) = *v { - active.push((*k, job.clone())); - } - } - }; - - // Lock shards and gather jobs from each shard. - if require_complete { - for shard in self.active.lock_shards() { - gather_shard_jobs(&shard); - } - } else { - // We use try_lock_shards here since we are called from the - // deadlock handler, and this shouldn't be locked. - for shard in self.active.try_lock_shards() { - let shard = shard?; - gather_shard_jobs(&shard); - } + // Lock shards and gather jobs from each shard. + if require_complete { + for shard in state.active.lock_shards() { + gather_shard_jobs(&shard); } - - // Call `make_frame` while we're not holding a `self.active` lock as `make_frame` may call - // queries leading to a deadlock. - for (key, job) in active { - let frame = make_frame(qcx, key); - jobs.insert(job.id, QueryJobInfo { frame, job }); + } else { + // We use try_lock_shards here since we are called from the + // deadlock handler, and this shouldn't be locked. + for shard in state.active.try_lock_shards() { + let shard = shard?; + gather_shard_jobs(&shard); } - - Some(()) } -} -impl<'tcx, K> Default for QueryState<'tcx, K> { - fn default() -> QueryState<'tcx, K> { - QueryState { active: Default::default() } + // Call `make_frame` while we're not holding a `state.active` lock as `make_frame` may call + // queries leading to a deadlock. + for (key, job) in active { + let frame = make_frame(qcx, key); + jobs.insert(job.id, QueryJobInfo { frame, job }); } + + Some(()) } /// A type representing the responsibility to execute the job in the `job` field. @@ -217,7 +167,7 @@ where Ok(occupied) => Some(occupied.remove().0.1), } }; - let job = job.expect("active query job entry").expect_job(); + let job = expect_job(job.expect("active query job entry")); job.signal_complete(); } @@ -240,7 +190,7 @@ where Ok(occupied) => { let ((key, value), vacant) = occupied.remove(); vacant.insert((key, ActiveKeyStatus::Poisoned)); - value.expect_job() + expect_job(value) } } }; @@ -250,22 +200,6 @@ where } } -#[derive(Clone, Debug)] -pub struct CycleError { - /// The query and related span that uses the cycle. - pub usage: Option<(Span, QueryStackFrame)>, - pub cycle: Vec>, -} - -impl<'tcx> CycleError> { - fn lift(&self) -> CycleError { - CycleError { - usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift())), - cycle: self.cycle.iter().map(|info| info.lift()).collect(), - } - } -} - #[cold] #[inline(never)] fn cycle_error<'tcx, Q>( @@ -664,89 +598,6 @@ where Some((result, dep_node_index)) } -#[inline] -#[instrument(skip(tcx, dep_graph_data, result, hash_result, format_value), level = "debug")] -pub(crate) fn incremental_verify_ich( - tcx: Tcx, - dep_graph_data: &DepGraphData, - result: &V, - prev_index: SerializedDepNodeIndex, - hash_result: Option, &V) -> Fingerprint>, - format_value: fn(&V) -> String, -) where - Tcx: DepContext, -{ - if !dep_graph_data.is_index_green(prev_index) { - incremental_verify_ich_not_green(tcx, prev_index) - } - - let new_hash = hash_result.map_or(Fingerprint::ZERO, |f| { - tcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, result)) - }); - - let old_hash = dep_graph_data.prev_fingerprint_of(prev_index); - - if new_hash != old_hash { - incremental_verify_ich_failed(tcx, prev_index, &|| format_value(result)); - } -} - -#[cold] -#[inline(never)] -fn incremental_verify_ich_not_green(tcx: Tcx, prev_index: SerializedDepNodeIndex) -where - Tcx: DepContext, -{ - panic!( - "fingerprint for green query instance not loaded from cache: {:?}", - tcx.dep_graph().data().unwrap().prev_node_of(prev_index) - ) -} - -// Note that this is marked #[cold] and intentionally takes `dyn Debug` for `result`, -// as we want to avoid generating a bunch of different implementations for LLVM to -// chew on (and filling up the final binary, too). -#[cold] -#[inline(never)] -fn incremental_verify_ich_failed( - tcx: Tcx, - prev_index: SerializedDepNodeIndex, - result: &dyn Fn() -> String, -) where - Tcx: DepContext, -{ - // When we emit an error message and panic, we try to debug-print the `DepNode` - // and query result. Unfortunately, this can cause us to run additional queries, - // which may result in another fingerprint mismatch while we're in the middle - // of processing this one. To avoid a double-panic (which kills the process - // before we can print out the query static), we print out a terse - // but 'safe' message if we detect a reentrant call to this method. - thread_local! { - static INSIDE_VERIFY_PANIC: Cell = const { Cell::new(false) }; - }; - - let old_in_panic = INSIDE_VERIFY_PANIC.replace(true); - - if old_in_panic { - tcx.sess().dcx().emit_err(crate::error::Reentrant); - } else { - let run_cmd = if let Some(crate_name) = &tcx.sess().opts.crate_name { - format!("`cargo clean -p {crate_name}` or `cargo clean`") - } else { - "`cargo clean`".to_string() - }; - - let dep_node = tcx.dep_graph().data().unwrap().prev_node_of(prev_index); - tcx.sess().dcx().emit_err(crate::error::IncrementCompilation { - run_cmd, - dep_node: format!("{dep_node:?}"), - }); - panic!("Found unstable fingerprints for {dep_node:?}: {}", result()); - } - - INSIDE_VERIFY_PANIC.set(old_in_panic); -} - /// Ensure that either this query has all green inputs or been executed. /// Executing `query::ensure(D)` is considered a read of the dep-node `D`. /// Returns true if the query should still run. @@ -801,14 +652,13 @@ where (!loadable, Some(dep_node)) } -#[derive(Debug)] -pub enum QueryMode { - Get, - Ensure { check_cache: bool }, -} - #[inline(always)] -pub fn get_query_non_incr<'tcx, Q>(query: Q, qcx: Q::Qcx, span: Span, key: Q::Key) -> Q::Value +pub(super) fn get_query_non_incr<'tcx, Q>( + query: Q, + qcx: Q::Qcx, + span: Span, + key: Q::Key, +) -> Q::Value where Q: QueryDispatcher<'tcx>, { @@ -818,7 +668,7 @@ where } #[inline(always)] -pub fn get_query_incr<'tcx, Q>( +pub(super) fn get_query_incr<'tcx, Q>( query: Q, qcx: Q::Qcx, span: Span, @@ -848,7 +698,7 @@ where Some(result) } -pub fn force_query<'tcx, Q>(query: Q, qcx: Q::Qcx, key: Q::Key, dep_node: DepNode) +pub(super) fn force_query<'tcx, Q>(query: Q, qcx: Q::Qcx, key: Q::Key, dep_node: DepNode) where Q: QueryDispatcher<'tcx>, { diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 19d43e9bb93d..228d0070b55b 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -3,6 +3,7 @@ // tidy-alphabetical-start #![allow(internal_features)] #![feature(adt_const_params)] +#![feature(core_intrinsics)] #![feature(min_specialization)] #![feature(rustc_attrs)] // tidy-alphabetical-end @@ -25,21 +26,20 @@ use rustc_query_system::dep_graph::SerializedDepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ CycleError, CycleErrorHandling, HashResult, QueryCache, QueryDispatcher, QueryMap, QueryMode, - QueryState, get_query_incr, get_query_non_incr, + QueryState, }; use rustc_span::{ErrorGuaranteed, Span}; +pub use crate::plumbing::{QueryCtxt, query_key_hash_verify_all}; use crate::plumbing::{encode_all_query_results, try_mark_green}; use crate::profiling_support::QueryKeyStringCache; - -#[macro_use] -mod plumbing; -pub use crate::plumbing::{QueryCtxt, query_key_hash_verify_all}; - -mod profiling_support; -pub use self::profiling_support::alloc_self_profile_query_strings; +pub use crate::profiling_support::alloc_self_profile_query_strings; mod error; +mod execution; +#[macro_use] +mod plumbing; +mod profiling_support; #[derive(ConstParamTy)] // Allow this struct to be used for const-generic values. #[derive(Clone, Copy, Debug, PartialEq, Eq)] diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index a71acae3096e..8738370dd1e7 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -29,13 +29,14 @@ use rustc_query_system::dep_graph::{DepNodeKey, FingerprintStyle, HasDepContext} use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ QueryCache, QueryContext, QueryDispatcher, QueryJobId, QueryMap, QuerySideEffect, - QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, force_query, + QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, }; use rustc_serialize::{Decodable, Encodable}; use rustc_span::def_id::LOCAL_CRATE; use crate::QueryDispatcherUnerased; use crate::error::{QueryOverflow, QueryOverflowNote}; +use crate::execution::{all_inactive, force_query}; /// Implements [`QueryContext`] for use by [`rustc_query_system`], since that /// crate does not have direct access to [`TyCtxt`]. @@ -387,7 +388,7 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>( { let _timer = qcx.tcx.prof.generic_activity_with_arg("encode_query_results_for", query.name()); - assert!(query.query_state(qcx).all_inactive()); + assert!(all_inactive(query.query_state(qcx))); let cache = query.query_cache(qcx); cache.iter(&mut |key, value, dep_node| { if query.will_cache_on_disk_for_key(qcx.tcx, key) { @@ -594,7 +595,7 @@ macro_rules! define_queries { ) -> Option>> { #[cfg(debug_assertions)] let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered(); - get_query_incr( + execution::get_query_incr( QueryType::query_dispatcher(tcx), QueryCtxt::new(tcx), span, @@ -614,7 +615,7 @@ macro_rules! define_queries { key: queries::$name::Key<'tcx>, __mode: QueryMode, ) -> Option>> { - Some(get_query_non_incr( + Some(execution::get_query_non_incr( QueryType::query_dispatcher(tcx), QueryCtxt::new(tcx), span, @@ -748,7 +749,7 @@ macro_rules! define_queries { }; // Call `gather_active_jobs_inner` to do the actual work. - let res = tcx.query_system.states.$name.gather_active_jobs_inner( + let res = crate::execution::gather_active_jobs_inner(&tcx.query_system.states.$name, tcx, make_frame, qmap, diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 06e576baf22a..31aafaea6450 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -82,7 +82,7 @@ pub(super) enum DepNodeColor { Unknown, } -pub(crate) struct DepGraphData { +pub struct DepGraphData { /// The new encoding of the dependency graph, optimized for red/green /// tracking. The `current` field is the dependency graph of only the /// current compilation session: We don't merge the previous dep-graph into @@ -171,7 +171,7 @@ impl DepGraph { } #[inline] - pub(crate) fn data(&self) -> Option<&DepGraphData> { + pub fn data(&self) -> Option<&DepGraphData> { self.data.as_deref() } @@ -323,7 +323,7 @@ impl DepGraphData { /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html #[inline(always)] - pub(crate) fn with_task, A: Debug, R>( + pub fn with_task, A: Debug, R>( &self, key: DepNode, cx: Ctxt, @@ -373,7 +373,7 @@ impl DepGraphData { /// FIXME: This could perhaps return a `WithDepNode` to ensure that the /// user of this function actually performs the read; we'll have to see /// how to make that work with `anon` in `execute_job_incr`, though. - pub(crate) fn with_anon_task_inner, OP, R>( + pub fn with_anon_task_inner, OP, R>( &self, cx: Tcx, dep_kind: DepKind, @@ -653,12 +653,12 @@ impl DepGraphData { /// Returns true if the given node has been marked as green during the /// current compilation session. Used in various assertions #[inline] - pub(crate) fn is_index_green(&self, prev_index: SerializedDepNodeIndex) -> bool { + pub fn is_index_green(&self, prev_index: SerializedDepNodeIndex) -> bool { matches!(self.colors.get(prev_index), DepNodeColor::Green(_)) } #[inline] - pub(crate) fn prev_fingerprint_of(&self, prev_index: SerializedDepNodeIndex) -> Fingerprint { + pub fn prev_fingerprint_of(&self, prev_index: SerializedDepNodeIndex) -> Fingerprint { self.previous.fingerprint_by_index(prev_index) } @@ -667,7 +667,7 @@ impl DepGraphData { self.previous.index_to_node(prev_index) } - pub(crate) fn mark_debug_loaded_from_disk(&self, dep_node: DepNode) { + pub fn mark_debug_loaded_from_disk(&self, dep_node: DepNode) { self.debug_loaded_from_disk.lock().insert(dep_node); } @@ -863,7 +863,7 @@ impl DepGraphData { /// A node will have an index, when it's already been marked green, or when we can mark it /// green. This function will mark the current task as a reader of the specified node, when /// a node index can be found for that node. - pub(crate) fn try_mark_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( + pub fn try_mark_green<'tcx, Qcx: QueryContext<'tcx, Deps = D>>( &self, qcx: Qcx, dep_node: &DepNode, @@ -1074,7 +1074,7 @@ impl DepGraph { if let Some(data) = &self.data { data.current.encoder.finish(&data.current) } else { Ok(0) } } - pub(crate) fn next_virtual_depnode_index(&self) -> DepNodeIndex { + pub fn next_virtual_depnode_index(&self) -> DepNodeIndex { debug_assert!(self.data.is_none()); let index = self.virtual_dep_node_index.fetch_add(1, Ordering::Relaxed); DepNodeIndex::from_u32(index) diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index f2cb01d5e9b4..da110ad2c77c 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -8,8 +8,9 @@ mod serialized; use std::panic; pub use dep_node::{DepKind, DepKindVTable, DepNode, DepNodeKey, WorkProductId}; -pub(crate) use graph::DepGraphData; -pub use graph::{DepGraph, DepNodeIndex, TaskDepsRef, WorkProduct, WorkProductMap, hash_result}; +pub use graph::{ + DepGraph, DepGraphData, DepNodeIndex, TaskDepsRef, WorkProduct, WorkProductMap, hash_result, +}; pub use query::DepGraphQuery; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sync::DynSync; diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index b61b9b71b528..7f6426e395f9 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -1,7 +1,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![feature(assert_matches)] -#![feature(core_intrinsics)] #![feature(min_specialization)] // tidy-alphabetical-end diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 0fd50128b544..bf7c480b05dd 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -86,7 +86,7 @@ impl<'tcx> QueryJob<'tcx> { QueryJob { id, span, parent, latch: None } } - pub(super) fn latch(&mut self) -> QueryLatch<'tcx> { + pub fn latch(&mut self) -> QueryLatch<'tcx> { if self.latch.is_none() { self.latch = Some(QueryLatch::new()); } @@ -106,7 +106,7 @@ impl<'tcx> QueryJob<'tcx> { } impl QueryJobId { - pub(super) fn find_cycle_in_stack<'tcx>( + pub fn find_cycle_in_stack<'tcx>( &self, query_map: QueryMap<'tcx>, current_job: &Option, @@ -182,7 +182,7 @@ struct QueryLatchInfo<'tcx> { } #[derive(Debug)] -pub(super) struct QueryLatch<'tcx> { +pub struct QueryLatch<'tcx> { info: Arc>>, } @@ -200,7 +200,7 @@ impl<'tcx> QueryLatch<'tcx> { } /// Awaits for the query job to complete. - pub(super) fn wait_on( + pub fn wait_on( &self, qcx: impl QueryContext<'tcx>, query: Option, diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index dbf7395bd61a..3eea0717f409 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -15,8 +15,8 @@ use rustc_span::def_id::DefId; pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache}; pub use self::dispatcher::{HashResult, QueryDispatcher}; pub use self::job::{ - QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryMap, break_query_cycles, print_query_stack, - report_cycle, + QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, QueryMap, break_query_cycles, + print_query_stack, report_cycle, }; pub use self::plumbing::*; use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; @@ -84,7 +84,7 @@ impl<'tcx> QueryStackFrame> { #[derive(Clone, Debug)] pub struct QueryStackFrameExtra { pub description: String, - span: Option, + pub span: Option, pub def_kind: Option, } From 563a2f04c7091335c508cddbf56b11f29b2a5ed5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 8 Feb 2026 15:25:49 +1100 Subject: [PATCH 695/978] Move a lot of `rustc_query_system::plumbing` to `rustc_query_impl::execution` (part 2). [Note: see the previous commit to understand this commit.] --- .../rustc_query_system/src/query/plumbing.rs | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 compiler/rustc_query_system/src/query/plumbing.rs diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs new file mode 100644 index 000000000000..d7a24d613583 --- /dev/null +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -0,0 +1,150 @@ +use std::cell::Cell; +use std::fmt::Debug; + +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::hash_table::HashTable; +use rustc_data_structures::sharded::Sharded; +use rustc_span::Span; +use tracing::instrument; + +use super::{QueryStackDeferred, QueryStackFrameExtra}; +use crate::dep_graph::{DepContext, DepGraphData}; +use crate::ich::StableHashingContext; +use crate::query::job::{QueryInfo, QueryJob}; +use crate::query::{QueryStackFrame, SerializedDepNodeIndex}; + +/// For a particular query, keeps track of "active" keys, i.e. keys whose +/// evaluation has started but has not yet finished successfully. +/// +/// (Successful query evaluation for a key is represented by an entry in the +/// query's in-memory cache.) +pub struct QueryState<'tcx, K> { + pub active: Sharded)>>, +} + +/// For a particular query and key, tracks the status of a query evaluation +/// that has started, but has not yet finished successfully. +/// +/// (Successful query evaluation for a key is represented by an entry in the +/// query's in-memory cache.) +pub enum ActiveKeyStatus<'tcx> { + /// Some thread is already evaluating the query for this key. + /// + /// The enclosed [`QueryJob`] can be used to wait for it to finish. + Started(QueryJob<'tcx>), + + /// The query panicked. Queries trying to wait on this will raise a fatal error which will + /// silently panic. + Poisoned, +} + +impl<'tcx, K> Default for QueryState<'tcx, K> { + fn default() -> QueryState<'tcx, K> { + QueryState { active: Default::default() } + } +} + +#[derive(Clone, Debug)] +pub struct CycleError { + /// The query and related span that uses the cycle. + pub usage: Option<(Span, QueryStackFrame)>, + pub cycle: Vec>, +} + +impl<'tcx> CycleError> { + pub fn lift(&self) -> CycleError { + CycleError { + usage: self.usage.as_ref().map(|(span, frame)| (*span, frame.lift())), + cycle: self.cycle.iter().map(|info| info.lift()).collect(), + } + } +} + +#[inline] +#[instrument(skip(tcx, dep_graph_data, result, hash_result, format_value), level = "debug")] +pub fn incremental_verify_ich( + tcx: Tcx, + dep_graph_data: &DepGraphData, + result: &V, + prev_index: SerializedDepNodeIndex, + hash_result: Option, &V) -> Fingerprint>, + format_value: fn(&V) -> String, +) where + Tcx: DepContext, +{ + if !dep_graph_data.is_index_green(prev_index) { + incremental_verify_ich_not_green(tcx, prev_index) + } + + let new_hash = hash_result.map_or(Fingerprint::ZERO, |f| { + tcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, result)) + }); + + let old_hash = dep_graph_data.prev_fingerprint_of(prev_index); + + if new_hash != old_hash { + incremental_verify_ich_failed(tcx, prev_index, &|| format_value(result)); + } +} + +#[cold] +#[inline(never)] +fn incremental_verify_ich_not_green(tcx: Tcx, prev_index: SerializedDepNodeIndex) +where + Tcx: DepContext, +{ + panic!( + "fingerprint for green query instance not loaded from cache: {:?}", + tcx.dep_graph().data().unwrap().prev_node_of(prev_index) + ) +} + +// Note that this is marked #[cold] and intentionally takes `dyn Debug` for `result`, +// as we want to avoid generating a bunch of different implementations for LLVM to +// chew on (and filling up the final binary, too). +#[cold] +#[inline(never)] +fn incremental_verify_ich_failed( + tcx: Tcx, + prev_index: SerializedDepNodeIndex, + result: &dyn Fn() -> String, +) where + Tcx: DepContext, +{ + // When we emit an error message and panic, we try to debug-print the `DepNode` + // and query result. Unfortunately, this can cause us to run additional queries, + // which may result in another fingerprint mismatch while we're in the middle + // of processing this one. To avoid a double-panic (which kills the process + // before we can print out the query static), we print out a terse + // but 'safe' message if we detect a reentrant call to this method. + thread_local! { + static INSIDE_VERIFY_PANIC: Cell = const { Cell::new(false) }; + }; + + let old_in_panic = INSIDE_VERIFY_PANIC.replace(true); + + if old_in_panic { + tcx.sess().dcx().emit_err(crate::error::Reentrant); + } else { + let run_cmd = if let Some(crate_name) = &tcx.sess().opts.crate_name { + format!("`cargo clean -p {crate_name}` or `cargo clean`") + } else { + "`cargo clean`".to_string() + }; + + let dep_node = tcx.dep_graph().data().unwrap().prev_node_of(prev_index); + tcx.sess().dcx().emit_err(crate::error::IncrementCompilation { + run_cmd, + dep_node: format!("{dep_node:?}"), + }); + panic!("Found unstable fingerprints for {dep_node:?}: {}", result()); + } + + INSIDE_VERIFY_PANIC.set(old_in_panic); +} + +#[derive(Debug)] +pub enum QueryMode { + Get, + Ensure { check_cache: bool }, +} From a6dd4d870ac48290294f7342366f2ff4cd031d97 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 8 Feb 2026 15:56:56 +1100 Subject: [PATCH 696/978] Remove now-unnecessary indirection. The previous commit moved some code from `rustc_query_system`, which doesn't have access to `TyCtxt` and `QueryCtxt`, to `rustc_query_impl`, which does. We can now remove quite a bit of indirection. - Three methods in `trait QueryContext` are no longer needed (`next_job_id`, `current_query_job`, `start_query`). As a result, `QueryCtxt`'s trait impls of these methods are changed to inherent methods. - `qcx: Q::Qcx` parameters are simplified to `qcx: QueryCtxt<'tcx>`. - `*qcx.dep_context()` occurrences are simplified to `qcx.tcx`, and things like `qcx.dep_context().profiler()` become `qcx.tcx.prof`. - `DepGraphData<::Deps>` becomes `DepGraphData`. In short, various layers of indirection and abstraction are cut away. The resulting code is simpler, more concrete, and easier to understand. It's a good demonstration of the benefits of eliminating `rustc_query_system`, and there will be more to come. --- compiler/rustc_query_impl/src/execution.rs | 149 +++++++++---------- compiler/rustc_query_impl/src/plumbing.rs | 99 ++++++------ compiler/rustc_query_system/src/query/mod.rs | 10 -- 3 files changed, 120 insertions(+), 138 deletions(-) diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 9fa41f741e08..e58e626a7dfa 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -5,6 +5,8 @@ use rustc_data_structures::hash_table::{Entry, HashTable}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::{outline, sharded, sync}; use rustc_errors::{Diag, FatalError, StashKey}; +use rustc_middle::dep_graph::DepsType; +use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::{DepGraphData, DepNodeKey, HasDepContext}; use rustc_query_system::query::{ ActiveKeyStatus, CycleError, CycleErrorHandling, QueryCache, QueryContext, QueryDispatcher, @@ -14,6 +16,7 @@ use rustc_query_system::query::{ use rustc_span::{DUMMY_SP, Span}; use crate::dep_graph::{DepContext, DepNode, DepNodeIndex}; +use crate::plumbing::QueryCtxt; #[inline] fn equivalent_key(k: &K) -> impl Fn(&(K, V)) -> bool + '_ { @@ -38,10 +41,10 @@ pub(crate) fn all_inactive<'tcx, K>(state: &QueryState<'tcx, K>) -> bool { /// Internal plumbing for collecting the set of active jobs for this query. /// /// Should only be called from `gather_active_jobs`. -pub(crate) fn gather_active_jobs_inner<'tcx, Qcx: Copy, K: Copy>( +pub(crate) fn gather_active_jobs_inner<'tcx, K: Copy>( state: &QueryState<'tcx, K>, - qcx: Qcx, - make_frame: fn(Qcx, K) -> QueryStackFrame>, + tcx: TyCtxt<'tcx>, + make_frame: fn(TyCtxt<'tcx>, K) -> QueryStackFrame>, jobs: &mut QueryMap<'tcx>, require_complete: bool, ) -> Option<()> { @@ -73,7 +76,7 @@ pub(crate) fn gather_active_jobs_inner<'tcx, Qcx: Copy, K: Copy>( // Call `make_frame` while we're not holding a `state.active` lock as `make_frame` may call // queries leading to a deadlock. for (key, job) in active { - let frame = make_frame(qcx, key); + let frame = make_frame(tcx, key); jobs.insert(job.id, QueryJobInfo { frame, job }); } @@ -92,36 +95,36 @@ where #[cold] #[inline(never)] -fn mk_cycle<'tcx, Q>(query: Q, qcx: Q::Qcx, cycle_error: CycleError) -> Q::Value +fn mk_cycle<'tcx, Q>(query: Q, qcx: QueryCtxt<'tcx>, cycle_error: CycleError) -> Q::Value where - Q: QueryDispatcher<'tcx>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { - let error = report_cycle(qcx.dep_context().sess(), &cycle_error); + let error = report_cycle(qcx.tcx.sess, &cycle_error); handle_cycle_error(query, qcx, &cycle_error, error) } fn handle_cycle_error<'tcx, Q>( query: Q, - qcx: Q::Qcx, + qcx: QueryCtxt<'tcx>, cycle_error: &CycleError, error: Diag<'_>, ) -> Q::Value where - Q: QueryDispatcher<'tcx>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { match query.cycle_error_handling() { CycleErrorHandling::Error => { let guar = error.emit(); - query.value_from_cycle_error(*qcx.dep_context(), cycle_error, guar) + query.value_from_cycle_error(qcx.tcx, cycle_error, guar) } CycleErrorHandling::Fatal => { error.emit(); - qcx.dep_context().sess().dcx().abort_if_errors(); + qcx.tcx.dcx().abort_if_errors(); unreachable!() } CycleErrorHandling::DelayBug => { let guar = error.delay_as_bug(); - query.value_from_cycle_error(*qcx.dep_context(), cycle_error, guar) + query.value_from_cycle_error(qcx.tcx, cycle_error, guar) } CycleErrorHandling::Stash => { let guar = if let Some(root) = cycle_error.cycle.first() @@ -131,7 +134,7 @@ where } else { error.emit() }; - query.value_from_cycle_error(*qcx.dep_context(), cycle_error, guar) + query.value_from_cycle_error(qcx.tcx, cycle_error, guar) } } } @@ -204,12 +207,12 @@ where #[inline(never)] fn cycle_error<'tcx, Q>( query: Q, - qcx: Q::Qcx, + qcx: QueryCtxt<'tcx>, try_execute: QueryJobId, span: Span, ) -> (Q::Value, Option) where - Q: QueryDispatcher<'tcx>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { // Ensure there was no errors collecting all active jobs. // We need the complete map to ensure we find a cycle to break. @@ -225,19 +228,19 @@ where #[inline(always)] fn wait_for_query<'tcx, Q>( query: Q, - qcx: Q::Qcx, + qcx: QueryCtxt<'tcx>, span: Span, key: Q::Key, latch: QueryLatch<'tcx>, current: Option, ) -> (Q::Value, Option) where - Q: QueryDispatcher<'tcx>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { // For parallel queries, we'll block and wait until the query running // in another thread has completed. Record how long we wait in the // self-profiler. - let query_blocked_prof_timer = qcx.dep_context().profiler().query_blocked(); + let query_blocked_prof_timer = qcx.tcx.prof.query_blocked(); // With parallel queries we might just have to wait on some other // thread. @@ -262,7 +265,7 @@ where }) }; - qcx.dep_context().profiler().query_cache_hit(index.into()); + qcx.tcx.prof.query_cache_hit(index.into()); query_blocked_prof_timer.finish_with_query_invocation_id(index.into()); (v, Some(index)) @@ -274,13 +277,13 @@ where #[inline(never)] fn try_execute_query<'tcx, Q, const INCR: bool>( query: Q, - qcx: Q::Qcx, + qcx: QueryCtxt<'tcx>, span: Span, key: Q::Key, dep_node: Option, ) -> (Q::Value, Option) where - Q: QueryDispatcher<'tcx>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { let state = query.query_state(qcx); let key_hash = sharded::make_hash(&key); @@ -292,9 +295,9 @@ where // re-executing the query since `try_start` only checks that the query is not currently // executing, but another thread may have already completed the query and stores it result // in the query cache. - if qcx.dep_context().sess().threads() > 1 { + if qcx.tcx.sess.threads() > 1 { if let Some((value, index)) = query.query_cache(qcx).lookup(&key) { - qcx.dep_context().profiler().query_cache_hit(index.into()); + qcx.tcx.prof.query_cache_hit(index.into()); return (value, Some(index)); } } @@ -343,7 +346,7 @@ where #[inline(always)] fn execute_job<'tcx, Q, const INCR: bool>( query: Q, - qcx: Q::Qcx, + qcx: QueryCtxt<'tcx>, state: &'tcx QueryState<'tcx, Q::Key>, key: Q::Key, key_hash: u64, @@ -351,22 +354,15 @@ fn execute_job<'tcx, Q, const INCR: bool>( dep_node: Option, ) -> (Q::Value, Option) where - Q: QueryDispatcher<'tcx>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { // Use `JobOwner` so the query will be poisoned if executing it panics. let job_owner = JobOwner { state, key }; - debug_assert_eq!(qcx.dep_context().dep_graph().is_fully_enabled(), INCR); + debug_assert_eq!(qcx.tcx.dep_graph.is_fully_enabled(), INCR); let (result, dep_node_index) = if INCR { - execute_job_incr( - query, - qcx, - qcx.dep_context().dep_graph().data().unwrap(), - key, - dep_node, - id, - ) + execute_job_incr(query, qcx, qcx.tcx.dep_graph.data().unwrap(), key, dep_node, id) } else { execute_job_non_incr(query, qcx, key, id) }; @@ -395,7 +391,7 @@ where // We have an inconsistency. This can happen if one of the two // results is tainted by errors. assert!( - qcx.dep_context().sess().dcx().has_errors().is_some(), + qcx.tcx.dcx().has_errors().is_some(), "Computed query value for {:?}({:?}) is inconsistent with fed value,\n\ computed={:#?}\nfed={:#?}", query.dep_kind(), @@ -415,24 +411,24 @@ where #[inline(always)] fn execute_job_non_incr<'tcx, Q>( query: Q, - qcx: Q::Qcx, + qcx: QueryCtxt<'tcx>, key: Q::Key, job_id: QueryJobId, ) -> (Q::Value, DepNodeIndex) where - Q: QueryDispatcher<'tcx>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { - debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled()); + debug_assert!(!qcx.tcx.dep_graph.is_fully_enabled()); // Fingerprint the key, just to assert that it doesn't // have anything we don't consider hashable if cfg!(debug_assertions) { - let _ = key.to_fingerprint(*qcx.dep_context()); + let _ = key.to_fingerprint(qcx.tcx); } - let prof_timer = qcx.dep_context().profiler().query_provider(); + let prof_timer = qcx.tcx.prof.query_provider(); let result = qcx.start_query(job_id, query.depth_limit(), || query.compute(qcx, key)); - let dep_node_index = qcx.dep_context().dep_graph().next_virtual_depnode_index(); + let dep_node_index = qcx.tcx.dep_graph.next_virtual_depnode_index(); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); // Similarly, fingerprint the result to assert that @@ -451,19 +447,18 @@ where #[inline(always)] fn execute_job_incr<'tcx, Q>( query: Q, - qcx: Q::Qcx, - dep_graph_data: &DepGraphData<::Deps>, + qcx: QueryCtxt<'tcx>, + dep_graph_data: &DepGraphData, key: Q::Key, mut dep_node_opt: Option, job_id: QueryJobId, ) -> (Q::Value, DepNodeIndex) where - Q: QueryDispatcher<'tcx>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { if !query.anon() && !query.eval_always() { // `to_dep_node` is expensive for some `DepKind`s. - let dep_node = - dep_node_opt.get_or_insert_with(|| query.construct_dep_node(*qcx.dep_context(), &key)); + let dep_node = dep_node_opt.get_or_insert_with(|| query.construct_dep_node(qcx.tcx, &key)); // The diagnostics for this query will be promoted to the current session during // `try_mark_green()`, so we can ignore them here. @@ -474,20 +469,16 @@ where } } - let prof_timer = qcx.dep_context().profiler().query_provider(); + let prof_timer = qcx.tcx.prof.query_provider(); let (result, dep_node_index) = qcx.start_query(job_id, query.depth_limit(), || { if query.anon() { - return dep_graph_data.with_anon_task_inner( - *qcx.dep_context(), - query.dep_kind(), - || query.compute(qcx, key), - ); + return dep_graph_data + .with_anon_task_inner(qcx.tcx, query.dep_kind(), || query.compute(qcx, key)); } // `to_dep_node` is expensive for some `DepKind`s. - let dep_node = - dep_node_opt.unwrap_or_else(|| query.construct_dep_node(*qcx.dep_context(), &key)); + let dep_node = dep_node_opt.unwrap_or_else(|| query.construct_dep_node(qcx.tcx, &key)); dep_graph_data.with_task( dep_node, @@ -506,13 +497,13 @@ where #[inline(always)] fn try_load_from_disk_and_cache_in_memory<'tcx, Q>( query: Q, - dep_graph_data: &DepGraphData<::Deps>, - qcx: Q::Qcx, + dep_graph_data: &DepGraphData, + qcx: QueryCtxt<'tcx>, key: &Q::Key, dep_node: &DepNode, ) -> Option<(Q::Value, DepNodeIndex)> where - Q: QueryDispatcher<'tcx>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { // Note this function can be called concurrently from the same query // We must ensure that this is handled correctly. @@ -524,7 +515,7 @@ where // First we try to load the result from the on-disk cache. // Some things are never cached on disk. if let Some(result) = query.try_load_from_disk(qcx, key, prev_dep_node_index, dep_node_index) { - if std::intrinsics::unlikely(qcx.dep_context().sess().opts.unstable_opts.query_dep_graph) { + if std::intrinsics::unlikely(qcx.tcx.sess.opts.unstable_opts.query_dep_graph) { dep_graph_data.mark_debug_loaded_from_disk(*dep_node) } @@ -538,10 +529,10 @@ where // give us some coverage of potential bugs though. let try_verify = prev_fingerprint.split().1.as_u64().is_multiple_of(32); if std::intrinsics::unlikely( - try_verify || qcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich, + try_verify || qcx.tcx.sess.opts.unstable_opts.incremental_verify_ich, ) { incremental_verify_ich( - *qcx.dep_context(), + qcx.tcx, dep_graph_data, &result, prev_dep_node_index, @@ -556,7 +547,7 @@ where // We always expect to find a cached result for things that // can be forced from `DepNode`. debug_assert!( - !query.will_cache_on_disk_for_key(*qcx.dep_context(), key) + !query.will_cache_on_disk_for_key(qcx.tcx, key) || !qcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(), "missing on-disk cache entry for {dep_node:?}" ); @@ -570,10 +561,10 @@ where // We could not load a result from the on-disk cache, so // recompute. - let prof_timer = qcx.dep_context().profiler().query_provider(); + let prof_timer = qcx.tcx.prof.query_provider(); // The dep-graph for this computation is already in-place. - let result = qcx.dep_context().dep_graph().with_ignore(|| query.compute(qcx, *key)); + let result = qcx.tcx.dep_graph.with_ignore(|| query.compute(qcx, *key)); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -587,7 +578,7 @@ where // See issue #82920 for an example of a miscompilation that would get turned into // an ICE by this check incremental_verify_ich( - *qcx.dep_context(), + qcx.tcx, dep_graph_data, &result, prev_dep_node_index, @@ -609,12 +600,12 @@ where #[inline(never)] fn ensure_must_run<'tcx, Q>( query: Q, - qcx: Q::Qcx, + qcx: QueryCtxt<'tcx>, key: &Q::Key, check_cache: bool, ) -> (bool, Option) where - Q: QueryDispatcher<'tcx>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { if query.eval_always() { return (true, None); @@ -623,9 +614,9 @@ where // Ensuring an anonymous query makes no sense assert!(!query.anon()); - let dep_node = query.construct_dep_node(*qcx.dep_context(), key); + let dep_node = query.construct_dep_node(qcx.tcx, key); - let dep_graph = qcx.dep_context().dep_graph(); + let dep_graph = &qcx.tcx.dep_graph; let serialized_dep_node_index = match dep_graph.try_mark_green(qcx, &dep_node) { None => { // A None return from `try_mark_green` means that this is either @@ -638,7 +629,7 @@ where } Some((serialized_dep_node_index, dep_node_index)) => { dep_graph.read_index(dep_node_index); - qcx.dep_context().profiler().query_cache_hit(dep_node_index.into()); + qcx.tcx.prof.query_cache_hit(dep_node_index.into()); serialized_dep_node_index } }; @@ -655,14 +646,14 @@ where #[inline(always)] pub(super) fn get_query_non_incr<'tcx, Q>( query: Q, - qcx: Q::Qcx, + qcx: QueryCtxt<'tcx>, span: Span, key: Q::Key, ) -> Q::Value where - Q: QueryDispatcher<'tcx>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { - debug_assert!(!qcx.dep_context().dep_graph().is_fully_enabled()); + debug_assert!(!qcx.tcx.dep_graph.is_fully_enabled()); ensure_sufficient_stack(|| try_execute_query::(query, qcx, span, key, None).0) } @@ -670,15 +661,15 @@ where #[inline(always)] pub(super) fn get_query_incr<'tcx, Q>( query: Q, - qcx: Q::Qcx, + qcx: QueryCtxt<'tcx>, span: Span, key: Q::Key, mode: QueryMode, ) -> Option where - Q: QueryDispatcher<'tcx>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { - debug_assert!(qcx.dep_context().dep_graph().is_fully_enabled()); + debug_assert!(qcx.tcx.dep_graph.is_fully_enabled()); let dep_node = if let QueryMode::Ensure { check_cache } = mode { let (must_run, dep_node) = ensure_must_run(query, qcx, &key, check_cache); @@ -693,19 +684,19 @@ where let (result, dep_node_index) = ensure_sufficient_stack(|| try_execute_query::(query, qcx, span, key, dep_node)); if let Some(dep_node_index) = dep_node_index { - qcx.dep_context().dep_graph().read_index(dep_node_index) + qcx.tcx.dep_graph.read_index(dep_node_index) } Some(result) } -pub(super) fn force_query<'tcx, Q>(query: Q, qcx: Q::Qcx, key: Q::Key, dep_node: DepNode) +pub(super) fn force_query<'tcx, Q>(query: Q, qcx: QueryCtxt<'tcx>, key: Q::Key, dep_node: DepNode) where - Q: QueryDispatcher<'tcx>, + Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, { // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. if let Some((_, index)) = query.query_cache(qcx).lookup(&key) { - qcx.dep_context().profiler().query_cache_hit(index.into()); + qcx.tcx.prof.query_cache_hit(index.into()); return; } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 8738370dd1e7..676d01be3385 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -14,7 +14,8 @@ use rustc_hir::limit::Limit; use rustc_index::Idx; use rustc_middle::bug; use rustc_middle::dep_graph::{ - self, DepContext, DepKindVTable, DepNode, DepNodeIndex, SerializedDepNodeIndex, dep_kinds, + self, DepContext, DepKindVTable, DepNode, DepNodeIndex, DepsType, SerializedDepNodeIndex, + dep_kinds, }; use rustc_middle::query::Key; use rustc_middle::query::on_disk_cache::{ @@ -69,10 +70,57 @@ impl<'tcx> QueryCtxt<'tcx> { crate_name: self.tcx.crate_name(LOCAL_CRATE), }); } + + #[inline] + pub(crate) fn next_job_id(self) -> QueryJobId { + QueryJobId( + NonZero::new( + self.tcx.query_system.jobs.fetch_add(1, std::sync::atomic::Ordering::Relaxed), + ) + .unwrap(), + ) + } + + #[inline] + pub(crate) fn current_query_job(self) -> Option { + tls::with_related_context(self.tcx, |icx| icx.query) + } + + /// Executes a job by changing the `ImplicitCtxt` to point to the + /// new query job while it executes. + #[inline(always)] + pub(crate) fn start_query( + self, + token: QueryJobId, + depth_limit: bool, + compute: impl FnOnce() -> R, + ) -> R { + // The `TyCtxt` stored in TLS has the same global interner lifetime + // as `self`, so we use `with_related_context` to relate the 'tcx lifetimes + // when accessing the `ImplicitCtxt`. + tls::with_related_context(self.tcx, move |current_icx| { + if depth_limit + && !self.tcx.recursion_limit().value_within_limit(current_icx.query_depth) + { + self.depth_limit_error(token); + } + + // Update the `ImplicitCtxt` to point to our new query job. + let new_icx = ImplicitCtxt { + tcx: self.tcx, + query: Some(token), + query_depth: current_icx.query_depth + depth_limit as usize, + task_deps: current_icx.task_deps, + }; + + // Use the `ImplicitCtxt` while we execute the query. + tls::enter_context(&new_icx, compute) + }) + } } impl<'tcx> HasDepContext for QueryCtxt<'tcx> { - type Deps = rustc_middle::dep_graph::DepsType; + type Deps = DepsType; type DepContext = TyCtxt<'tcx>; #[inline] @@ -87,21 +135,6 @@ impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> { &self.tcx.jobserver_proxy } - #[inline] - fn next_job_id(self) -> QueryJobId { - QueryJobId( - NonZero::new( - self.tcx.query_system.jobs.fetch_add(1, std::sync::atomic::Ordering::Relaxed), - ) - .unwrap(), - ) - } - - #[inline] - fn current_query_job(self) -> Option { - tls::with_related_context(self.tcx, |icx| icx.query) - } - /// Returns a map of currently active query jobs, collected from all queries. /// /// If `require_complete` is `true`, this function locks all shards of the @@ -147,38 +180,6 @@ impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> { c.store_side_effect(dep_node_index, side_effect) } } - - /// Executes a job by changing the `ImplicitCtxt` to point to the - /// new query job while it executes. - #[inline(always)] - fn start_query( - self, - token: QueryJobId, - depth_limit: bool, - compute: impl FnOnce() -> R, - ) -> R { - // The `TyCtxt` stored in TLS has the same global interner lifetime - // as `self`, so we use `with_related_context` to relate the 'tcx lifetimes - // when accessing the `ImplicitCtxt`. - tls::with_related_context(self.tcx, move |current_icx| { - if depth_limit - && !self.tcx.recursion_limit().value_within_limit(current_icx.query_depth) - { - self.depth_limit_error(token); - } - - // Update the `ImplicitCtxt` to point to our new query job. - let new_icx = ImplicitCtxt { - tcx: self.tcx, - query: Some(token), - query_depth: current_icx.query_depth + depth_limit as usize, - task_deps: current_icx.task_deps, - }; - - // Use the `ImplicitCtxt` while we execute the query. - tls::enter_context(&new_icx, compute) - }) - } } pub(super) fn try_mark_green<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool { diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 3eea0717f409..29a572b726f0 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -161,11 +161,6 @@ pub trait QueryContext<'tcx>: HasDepContext { /// a token while waiting on a query. fn jobserver_proxy(&self) -> &Proxy; - fn next_job_id(self) -> QueryJobId; - - /// Get the query information from the TLS context. - fn current_query_job(self) -> Option; - fn collect_active_jobs_from_all_queries( self, require_complete: bool, @@ -179,9 +174,4 @@ pub trait QueryContext<'tcx>: HasDepContext { /// Register a side effect for the given node, for use in next session. fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect); - - /// Executes a job by changing the `ImplicitCtxt` to point to the - /// new query job while it executes. - fn start_query(self, token: QueryJobId, depth_limit: bool, compute: impl FnOnce() -> R) - -> R; } From 118372ed1325f07ebc4ec9c3f28e3f00d4519a05 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 8 Feb 2026 18:15:53 +1100 Subject: [PATCH 697/978] Replace some `feature(core_intrinsics)` with stable hints --- compiler/rustc_arena/src/lib.rs | 5 ++--- compiler/rustc_data_structures/src/lib.rs | 2 +- compiler/rustc_data_structures/src/profiling.rs | 9 +++++---- compiler/rustc_data_structures/src/sync/freeze.rs | 5 +++-- compiler/rustc_data_structures/src/sync/lock.rs | 9 +++++---- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 6217bf46a942..97dd21db07e7 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -13,7 +13,6 @@ #![cfg_attr(test, feature(test))] #![deny(unsafe_op_in_unsafe_fn)] #![doc(test(no_crate_inject, attr(deny(warnings), allow(internal_features))))] -#![feature(core_intrinsics)] #![feature(decl_macro)] #![feature(dropck_eyepatch)] #![feature(never_type)] @@ -26,7 +25,7 @@ use std::cell::{Cell, RefCell}; use std::marker::PhantomData; use std::mem::{self, MaybeUninit}; use std::ptr::{self, NonNull}; -use std::{cmp, intrinsics, slice}; +use std::{cmp, hint, slice}; use smallvec::SmallVec; @@ -452,7 +451,7 @@ impl DroplessArena { let bytes = align_up(layout.size(), DROPLESS_ALIGNMENT); // Tell LLVM that `end` is aligned to DROPLESS_ALIGNMENT. - unsafe { intrinsics::assume(end == align_down(end, DROPLESS_ALIGNMENT)) }; + unsafe { hint::assert_unchecked(end == align_down(end, DROPLESS_ALIGNMENT)) }; if let Some(sub) = end.checked_sub(bytes) { let new_end = align_down(sub, layout.align()); diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 4467a2811181..bef19d77d1e7 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -10,6 +10,7 @@ #![allow(internal_features)] #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] +#![cfg_attr(bootstrap, feature(cold_path))] #![deny(unsafe_op_in_unsafe_fn)] #![feature(allocator_api)] #![feature(ascii_char)] @@ -19,7 +20,6 @@ #![feature(cfg_select)] #![feature(const_default)] #![feature(const_trait_impl)] -#![feature(core_intrinsics)] #![feature(dropck_eyepatch)] #![feature(extend_one)] #![feature(file_buffered)] diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index b04caa69adfb..cab57edb8946 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -85,12 +85,11 @@ use std::borrow::Borrow; use std::collections::hash_map::Entry; use std::error::Error; use std::fmt::Display; -use std::intrinsics::unlikely; use std::path::Path; use std::sync::Arc; use std::sync::atomic::Ordering; use std::time::{Duration, Instant}; -use std::{fs, process}; +use std::{fs, hint, process}; pub use measureme::EventId; use measureme::{EventIdBuilder, Profiler, SerializableString, StringId}; @@ -427,7 +426,8 @@ impl SelfProfilerRef { .unwrap() .increment_query_cache_hit_counters(QueryInvocationId(query_invocation_id.0)); } - if unlikely(profiler_ref.event_filter_mask.contains(EventFilter::QUERY_CACHE_HITS)) { + if profiler_ref.event_filter_mask.contains(EventFilter::QUERY_CACHE_HITS) { + hint::cold_path(); profiler_ref.instant_query_event( |profiler| profiler.query_cache_hit_event_kind, query_invocation_id, @@ -437,7 +437,8 @@ impl SelfProfilerRef { // We check both kinds of query cache hit events at once, to reduce overhead in the // common case (with self-profile disabled). - if unlikely(self.event_filter_mask.intersects(EventFilter::QUERY_CACHE_HIT_COMBINED)) { + if self.event_filter_mask.intersects(EventFilter::QUERY_CACHE_HIT_COMBINED) { + hint::cold_path(); cold_call(self, query_invocation_id); } } diff --git a/compiler/rustc_data_structures/src/sync/freeze.rs b/compiler/rustc_data_structures/src/sync/freeze.rs index 6338afb92c34..fb2dcb25556a 100644 --- a/compiler/rustc_data_structures/src/sync/freeze.rs +++ b/compiler/rustc_data_structures/src/sync/freeze.rs @@ -1,5 +1,5 @@ use std::cell::UnsafeCell; -use std::intrinsics::likely; +use std::hint; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::ptr::NonNull; @@ -60,10 +60,11 @@ impl FreezeLock { /// Get the inner value if frozen. #[inline] pub fn get(&self) -> Option<&T> { - if likely(self.frozen.load(Ordering::Acquire)) { + if self.frozen.load(Ordering::Acquire) { // SAFETY: This is frozen so the data cannot be modified. unsafe { Some(&*self.data.get()) } } else { + hint::cold_path(); None } } diff --git a/compiler/rustc_data_structures/src/sync/lock.rs b/compiler/rustc_data_structures/src/sync/lock.rs index a8161c515115..f183af0c0dab 100644 --- a/compiler/rustc_data_structures/src/sync/lock.rs +++ b/compiler/rustc_data_structures/src/sync/lock.rs @@ -1,7 +1,7 @@ //! This module implements a lock which only uses synchronization if `might_be_dyn_thread_safe` is true. //! It implements `DynSend` and `DynSync` instead of the typical `Send` and `Sync` traits. -use std::fmt; +use std::{fmt, hint}; #[derive(Clone, Copy, PartialEq)] pub enum Mode { @@ -10,7 +10,6 @@ pub enum Mode { } use std::cell::{Cell, UnsafeCell}; -use std::intrinsics::unlikely; use std::marker::PhantomData; use std::mem::ManuallyDrop; use std::ops::{Deref, DerefMut}; @@ -92,7 +91,8 @@ pub struct Lock { impl Lock { #[inline(always)] pub fn new(inner: T) -> Self { - let (mode, mode_union) = if unlikely(mode::might_be_dyn_thread_safe()) { + let (mode, mode_union) = if mode::might_be_dyn_thread_safe() { + hint::cold_path(); // Create the lock with synchronization enabled using the `RawMutex` type. (Mode::Sync, ModeUnion { sync: ManuallyDrop::new(RawMutex::INIT) }) } else { @@ -150,7 +150,8 @@ impl Lock { unsafe { match mode { Mode::NoSync => { - if unlikely(self.mode_union.no_sync.replace(LOCKED) == LOCKED) { + if self.mode_union.no_sync.replace(LOCKED) == LOCKED { + hint::cold_path(); lock_held() } } From 7c95f57bc95c36f44a50fffb07cb2b933184ee2b Mon Sep 17 00:00:00 2001 From: mikhailofff Date: Sun, 8 Feb 2026 11:25:51 +0400 Subject: [PATCH 698/978] fix outdated doc comments --- book/src/development/type_checking.md | 2 +- tests/ui/unconditional_recursion.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/book/src/development/type_checking.md b/book/src/development/type_checking.md index 578836ecc568..d1c88619d598 100644 --- a/book/src/development/type_checking.md +++ b/book/src/development/type_checking.md @@ -154,7 +154,7 @@ in this chapter: [expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.expr_ty [node_type]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.node_type [is_char]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.is_char -[is_char_source]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/ty/sty.rs.html#1831-1834 +[is_char_source]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/ty/sty.rs.html#1429-1432 [kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.kind [LateContext]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html [LateLintPass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html diff --git a/tests/ui/unconditional_recursion.rs b/tests/ui/unconditional_recursion.rs index d9f4c07dc902..09a0de21ccd0 100644 --- a/tests/ui/unconditional_recursion.rs +++ b/tests/ui/unconditional_recursion.rs @@ -334,7 +334,7 @@ mod issue12154 { } // Not necessarily related to the issue but another FP from the http crate that was fixed with it: - // https://docs.rs/http/latest/src/http/header/name.rs.html#1424 + // https://docs.rs/http/latest/src/http/header/name.rs.html#1408 // We used to simply peel refs from the LHS and RHS, so we couldn't differentiate // between `PartialEq for &T` and `PartialEq<&T> for T` impls. #[derive(PartialEq)] From 6b1ed212b70be56296d3aadba518028e6049eb56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 8 Feb 2026 09:16:31 +0100 Subject: [PATCH 699/978] Remove types adhoc group --- triagebot.toml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 4a4054391ce7..43db49873c4d 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1536,13 +1536,6 @@ mir-opt = [ "@wesleywiser", "@saethlin", ] -types = [ - "@jackh726", - "@lcnr", - "@oli-obk", - "@spastorino", - "@BoxyUwU", -] borrowck = [ "@davidtwco", "@matthewjasper" From c19c780d4557f4d1e2ee285c08184e9c37070c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 8 Feb 2026 09:22:24 +0100 Subject: [PATCH 700/978] Remove project-const-traits adhoc group --- triagebot.toml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 43db49873c4d..d6106024a1fd 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1555,11 +1555,6 @@ style-team = [ "@joshtriplett", "@traviscross", ] -project-const-traits = [ - "@fee1-dead", - "@fmease", - "@oli-obk", -] project-stable-mir = [ "@celinval", "@oli-obk", From 5e33ea7b926a8ed4f6228588564e036fba792897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 8 Feb 2026 09:23:04 +0100 Subject: [PATCH 701/978] Remove project-stable-mir adhoc group --- triagebot.toml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index d6106024a1fd..f2e69b625a81 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1555,12 +1555,6 @@ style-team = [ "@joshtriplett", "@traviscross", ] -project-stable-mir = [ - "@celinval", - "@oli-obk", - "@scottmcm", - "@makai410", -] project-exploit-mitigations = [ "@cuviper", "@rcvalle", From f46032089a94f7185823b0b519529d50311ff489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 8 Feb 2026 09:24:38 +0100 Subject: [PATCH 702/978] Remove project-exploit-mitigations adhoc group --- triagebot.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index f2e69b625a81..98e88f4e2e9b 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1555,10 +1555,6 @@ style-team = [ "@joshtriplett", "@traviscross", ] -project-exploit-mitigations = [ - "@cuviper", - "@rcvalle", -] compiletest = [ "@jieyouxu", ] From 5862618fab1bd3e6c904914db953bdf56720c28e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 8 Feb 2026 09:52:34 +0100 Subject: [PATCH 703/978] Remove the compiler adhoc group --- triagebot.toml | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 4a4054391ce7..43f56a71cf4e 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1449,29 +1449,6 @@ compiler_leads = [ "@davidtwco", "@wesleywiser", ] -compiler = [ - "@BoxyUwU", - "@chenyukang", - "@davidtwco", - "@eholk", - "@fee1-dead", - "@fmease", - "@jackh726", - "@jieyouxu", - "@jdonszelmann", - "@JonathanBrouwer", - "@madsmtm", - "@mati865", - "@Nadrieril", - "@nnethercote", - "@oli-obk", - "@petrochenkov", - "@SparrowLii", - "@TaKO8Ki", - "@tiif", - "@WaffleLapkin", - "@wesleywiser", -] libs = [ "@Mark-Simulacrum", "@workingjubilee", From 953aa57c7503177f494dfb168306503867aa26fc Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 8 Feb 2026 10:23:31 +0100 Subject: [PATCH 704/978] Fix suggestion on `AutoTraitItems` diagnostic --- compiler/rustc_ast_passes/src/errors.rs | 2 +- tests/ui/auto-traits/assoc-ty.current.stderr | 9 +++++---- tests/ui/auto-traits/assoc-ty.next.stderr | 11 ++++++----- tests/ui/auto-traits/assoc-ty.rs | 5 ++++- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index baf6f6beaeed..9f66641b550c 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -503,7 +503,7 @@ pub(crate) struct AutoTraitItems { #[primary_span] pub spans: Vec, #[suggestion( - "remove the super traits or lifetime bounds", + "remove the associated items", code = "", applicability = "machine-applicable", style = "tool-only" diff --git a/tests/ui/auto-traits/assoc-ty.current.stderr b/tests/ui/auto-traits/assoc-ty.current.stderr index d793ae665267..5d3df17d26b1 100644 --- a/tests/ui/auto-traits/assoc-ty.current.stderr +++ b/tests/ui/auto-traits/assoc-ty.current.stderr @@ -1,9 +1,9 @@ error[E0380]: auto traits cannot have associated items - --> $DIR/assoc-ty.rs:10:10 + --> $DIR/assoc-ty.rs:11:10 | LL | auto trait Trait { | ----- auto traits cannot have associated items -LL | +... LL | type Output; | ^^^^^^ @@ -12,8 +12,9 @@ error[E0658]: auto traits are experimental and possibly buggy | LL | / auto trait Trait { LL | | -LL | | type Output; LL | | +LL | | type Output; +... | LL | | } | |_^ | @@ -22,7 +23,7 @@ LL | | } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0308]: mismatched types - --> $DIR/assoc-ty.rs:15:36 + --> $DIR/assoc-ty.rs:17:36 | LL | let _: <() as Trait>::Output = (); | --------------------- ^^ expected associated type, found `()` diff --git a/tests/ui/auto-traits/assoc-ty.next.stderr b/tests/ui/auto-traits/assoc-ty.next.stderr index a41f7d992785..19621064aa42 100644 --- a/tests/ui/auto-traits/assoc-ty.next.stderr +++ b/tests/ui/auto-traits/assoc-ty.next.stderr @@ -1,9 +1,9 @@ error[E0380]: auto traits cannot have associated items - --> $DIR/assoc-ty.rs:10:10 + --> $DIR/assoc-ty.rs:11:10 | LL | auto trait Trait { | ----- auto traits cannot have associated items -LL | +... LL | type Output; | ^^^^^^ @@ -12,8 +12,9 @@ error[E0658]: auto traits are experimental and possibly buggy | LL | / auto trait Trait { LL | | -LL | | type Output; LL | | +LL | | type Output; +... | LL | | } | |_^ | @@ -22,13 +23,13 @@ LL | | } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0271]: type mismatch resolving `<() as Trait>::Output normalizes-to _` - --> $DIR/assoc-ty.rs:15:12 + --> $DIR/assoc-ty.rs:17:12 | LL | let _: <() as Trait>::Output = (); | ^^^^^^^^^^^^^^^^^^^^^ types differ error[E0271]: type mismatch resolving `<() as Trait>::Output normalizes-to _` - --> $DIR/assoc-ty.rs:15:12 + --> $DIR/assoc-ty.rs:17:12 | LL | let _: <() as Trait>::Output = (); | ^^^^^^^^^^^^^^^^^^^^^ types differ diff --git a/tests/ui/auto-traits/assoc-ty.rs b/tests/ui/auto-traits/assoc-ty.rs index efbfead9cd03..98a86d9a7540 100644 --- a/tests/ui/auto-traits/assoc-ty.rs +++ b/tests/ui/auto-traits/assoc-ty.rs @@ -7,13 +7,16 @@ auto trait Trait { //~^ ERROR auto traits are experimental and possibly buggy + //~| HELP add `#![feature(auto_traits)]` to the crate attributes to enable type Output; //~^ ERROR auto traits cannot have associated items + //~| HELP remove the associated items } fn main() { let _: <() as Trait>::Output = (); //[current]~^ ERROR mismatched types - //[next]~^^ ERROR type mismatch resolving `<() as Trait>::Output normalizes-to _` + //[current]~| HELP consider constraining the associated type `<() as Trait>::Output` to `()` or calling a method that returns `<() as Trait>::Output` + //[next]~^^^ ERROR type mismatch resolving `<() as Trait>::Output normalizes-to _` //[next]~| ERROR type mismatch resolving `<() as Trait>::Output normalizes-to _` } From ea8733133cacf4496a2766b3d002492cc29ea7bf Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 18:27:38 +0100 Subject: [PATCH 705/978] Remove `DiagMessage::FluentIdentifier` --- compiler/rustc_error_messages/src/lib.rs | 41 ++------------ compiler/rustc_errors/src/translation.rs | 72 ++---------------------- 2 files changed, 8 insertions(+), 105 deletions(-) diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 641defd1eabf..916a370659aa 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -230,9 +230,6 @@ pub fn fallback_fluent_bundle( }))) } -/// Identifier for the Fluent message/attribute corresponding to a diagnostic message. -type FluentId = Cow<'static, str>; - /// Abstraction over a message in a subdiagnostic (i.e. label, note, help, etc) to support both /// translatable and non-translatable diagnostic messages. /// @@ -244,18 +241,9 @@ type FluentId = Cow<'static, str>; pub enum SubdiagMessage { /// Non-translatable diagnostic message. Str(Cow<'static, str>), - /// Identifier of a Fluent message. Instances of this variant are generated by the - /// `Subdiagnostic` derive. - FluentIdentifier(FluentId), /// An inline Fluent message. Instances of this variant are generated by the /// `Subdiagnostic` derive. Inline(Cow<'static, str>), - /// Attribute of a Fluent message. Needs to be combined with a Fluent identifier to produce an - /// actual translated message. Instances of this variant are generated by the `fluent_messages` - /// macro. - /// - /// - FluentAttr(FluentId), } impl From for SubdiagMessage { @@ -288,12 +276,6 @@ pub enum DiagMessage { /// are translated when they are added to the parent diagnostic. This is one of the ways /// this variant of `DiagMessage` is produced. Str(Cow<'static, str>), - /// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic - /// message. Yet to be translated. - /// - /// - /// - FluentIdentifier(FluentId, Option), /// An inline Fluent message, containing the to be translated diagnostic message. Inline(Cow<'static, str>), } @@ -305,27 +287,16 @@ impl DiagMessage { /// - If the `SubdiagMessage` is non-translatable then return the message as a `DiagMessage`. /// - If `self` is non-translatable then return `self`'s message. pub fn with_subdiagnostic_message(&self, sub: SubdiagMessage) -> Self { - let attr = match sub { - SubdiagMessage::Str(s) => return DiagMessage::Str(s), - SubdiagMessage::FluentIdentifier(id) => { - return DiagMessage::FluentIdentifier(id, None); - } - SubdiagMessage::Inline(s) => return DiagMessage::Inline(s), - SubdiagMessage::FluentAttr(attr) => attr, - }; - - match self { - DiagMessage::FluentIdentifier(id, _) => { - DiagMessage::FluentIdentifier(id.clone(), Some(attr)) - } - _ => panic!("Tried to add a subdiagnostic to a message without a fluent identifier"), + match sub { + SubdiagMessage::Str(s) => DiagMessage::Str(s), + SubdiagMessage::Inline(s) => DiagMessage::Inline(s), } } pub fn as_str(&self) -> Option<&str> { match self { DiagMessage::Str(s) => Some(s), - DiagMessage::FluentIdentifier(_, _) | DiagMessage::Inline(_) => None, + DiagMessage::Inline(_) => None, } } } @@ -355,10 +326,6 @@ impl From for SubdiagMessage { fn from(val: DiagMessage) -> Self { match val { DiagMessage::Str(s) => SubdiagMessage::Str(s), - DiagMessage::FluentIdentifier(id, None) => SubdiagMessage::FluentIdentifier(id), - // There isn't really a sensible behaviour for this because it loses information but - // this is the most sensible of the behaviours. - DiagMessage::FluentIdentifier(_, Some(attr)) => SubdiagMessage::FluentAttr(attr), DiagMessage::Inline(s) => SubdiagMessage::Inline(s), } } diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index ed3f9a405342..0b9845772590 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -1,5 +1,4 @@ use std::borrow::Cow; -use std::env; use std::error::Report; use std::sync::Arc; @@ -7,7 +6,7 @@ pub use rustc_error_messages::{FluentArgs, LazyFallbackBundle}; use rustc_error_messages::{langid, register_functions}; use tracing::{debug, trace}; -use crate::error::{TranslateError, TranslateErrorKind}; +use crate::error::TranslateError; use crate::fluent_bundle::FluentResource; use crate::{DiagArg, DiagMessage, FluentBundle, Style, fluent_bundle}; @@ -76,11 +75,8 @@ impl Translator { args: &'a FluentArgs<'_>, ) -> Result, TranslateError<'a>> { trace!(?message, ?args); - let (identifier, attr) = match message { - DiagMessage::Str(msg) => { - return Ok(Cow::Borrowed(msg)); - } - DiagMessage::FluentIdentifier(identifier, attr) => (identifier, attr), + match message { + DiagMessage::Str(msg) => Ok(Cow::Borrowed(msg)), // This translates an inline fluent diagnostic message // It does this by creating a new `FluentBundle` with only one message, // and then translating using this bundle. @@ -98,71 +94,11 @@ impl Translator { let mut errs = vec![]; let translated = bundle.format_pattern(value, Some(args), &mut errs).to_string(); debug!(?translated, ?errs); - return if errs.is_empty() { + if errs.is_empty() { Ok(Cow::Owned(translated)) } else { Err(TranslateError::fluent(&Cow::Borrowed(GENERATED_MSG_ID), args, errs)) - }; - } - }; - let translate_with_bundle = - |bundle: &'a FluentBundle| -> Result, TranslateError<'_>> { - let message = bundle - .get_message(identifier) - .ok_or(TranslateError::message(identifier, args))?; - let value = match attr { - Some(attr) => message - .get_attribute(attr) - .ok_or(TranslateError::attribute(identifier, args, attr))? - .value(), - None => message.value().ok_or(TranslateError::value(identifier, args))?, - }; - debug!(?message, ?value); - - let mut errs = vec![]; - let translated = bundle.format_pattern(value, Some(args), &mut errs); - debug!(?translated, ?errs); - if errs.is_empty() { - Ok(translated) - } else { - Err(TranslateError::fluent(identifier, args, errs)) } - }; - - try { - match self.fluent_bundle.as_ref().map(|b| translate_with_bundle(b)) { - // The primary bundle was present and translation succeeded - Some(Ok(t)) => t, - - // If `translate_with_bundle` returns `Err` with the primary bundle, this is likely - // just that the primary bundle doesn't contain the message being translated, so - // proceed to the fallback bundle. - Some(Err( - primary @ TranslateError::One { - kind: TranslateErrorKind::MessageMissing, .. - }, - )) => translate_with_bundle(&self.fallback_fluent_bundle) - .map_err(|fallback| primary.and(fallback))?, - - // Always yeet out for errors on debug (unless - // `RUSTC_TRANSLATION_NO_DEBUG_ASSERT` is set in the environment - this allows - // local runs of the test suites, of builds with debug assertions, to test the - // behaviour in a normal build). - Some(Err(primary)) - if cfg!(debug_assertions) - && env::var("RUSTC_TRANSLATION_NO_DEBUG_ASSERT").is_err() => - { - do yeet primary - } - - // ..otherwise, for end users, an error about this wouldn't be useful or actionable, so - // just hide it and try with the fallback bundle. - Some(Err(primary)) => translate_with_bundle(&self.fallback_fluent_bundle) - .map_err(|fallback| primary.and(fallback))?, - - // The primary bundle is missing, proceed to the fallback bundle - None => translate_with_bundle(&self.fallback_fluent_bundle) - .map_err(|fallback| TranslateError::primary(identifier, args).and(fallback))?, } } } From 62dd37131f6f43d0dab3e26cf125cd841a08e003 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 19:04:18 +0100 Subject: [PATCH 706/978] Remove slugs from the `#[derive(Diagnostic)]` macro --- .../src/diagnostics/diagnostic.rs | 27 +---- .../src/diagnostics/diagnostic_builder.rs | 98 +++++-------------- .../rustc_macros/src/diagnostics/message.rs | 75 ++------------ .../src/diagnostics/subdiagnostic.rs | 22 ++--- .../rustc_macros/src/diagnostics/utils.rs | 43 +++----- 5 files changed, 60 insertions(+), 205 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index e8356655dd9f..dc8231e5f0b0 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -1,7 +1,5 @@ #![deny(unused_must_use)] -use std::cell::RefCell; - use proc_macro2::TokenStream; use quote::quote; use synstructure::Structure; @@ -22,7 +20,6 @@ impl<'a> DiagnosticDerive<'a> { pub(crate) fn into_tokens(self) -> TokenStream { let DiagnosticDerive { mut structure } = self; let kind = DiagnosticDeriveKind::Diagnostic; - let messages = RefCell::new(Vec::new()); let implementation = kind.each_variant(&mut structure, |mut builder, variant| { let preamble = builder.preamble(variant); let body = builder.body(variant); @@ -30,7 +27,6 @@ impl<'a> DiagnosticDerive<'a> { let Some(message) = builder.primary_message() else { return DiagnosticDeriveError::ErrorHandled.to_compile_error(); }; - messages.borrow_mut().push(message.clone()); let message = message.diag_message(Some(variant)); let init = quote! { @@ -52,9 +48,7 @@ impl<'a> DiagnosticDerive<'a> { }); // A lifetime of `'a` causes conflicts, but `_sess` is fine. - // FIXME(edition_2024): Fix the `keyword_idents_2024` lint to not trigger here? - #[allow(keyword_idents_2024)] - let mut imp = structure.gen_impl(quote! { + structure.gen_impl(quote! { gen impl<'_sess, G> rustc_errors::Diagnostic<'_sess, G> for @Self where G: rustc_errors::EmissionGuarantee { @@ -67,11 +61,7 @@ impl<'a> DiagnosticDerive<'a> { #implementation } } - }); - for test in messages.borrow().iter().map(|s| s.generate_test(&structure)) { - imp.extend(test); - } - imp + }) } } @@ -88,7 +78,6 @@ impl<'a> LintDiagnosticDerive<'a> { pub(crate) fn into_tokens(self) -> TokenStream { let LintDiagnosticDerive { mut structure } = self; let kind = DiagnosticDeriveKind::LintDiagnostic; - let messages = RefCell::new(Vec::new()); let implementation = kind.each_variant(&mut structure, |mut builder, variant| { let preamble = builder.preamble(variant); let body = builder.body(variant); @@ -96,7 +85,6 @@ impl<'a> LintDiagnosticDerive<'a> { let Some(message) = builder.primary_message() else { return DiagnosticDeriveError::ErrorHandled.to_compile_error(); }; - messages.borrow_mut().push(message.clone()); let message = message.diag_message(Some(variant)); let primary_message = quote! { diag.primary_message(#message); @@ -112,9 +100,7 @@ impl<'a> LintDiagnosticDerive<'a> { } }); - // FIXME(edition_2024): Fix the `keyword_idents_2024` lint to not trigger here? - #[allow(keyword_idents_2024)] - let mut imp = structure.gen_impl(quote! { + structure.gen_impl(quote! { gen impl<'__a> rustc_errors::LintDiagnostic<'__a, ()> for @Self { #[track_caller] fn decorate_lint<'__b>( @@ -124,11 +110,6 @@ impl<'a> LintDiagnosticDerive<'a> { #implementation; } } - }); - for test in messages.borrow().iter().map(|s| s.generate_test(&structure)) { - imp.extend(test); - } - - imp + }) } } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 6107b181eea2..b386408a1918 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -4,7 +4,7 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote, quote_spanned}; use syn::parse::ParseStream; use syn::spanned::Spanned; -use syn::{Attribute, LitStr, Meta, Path, Token, Type, parse_quote}; +use syn::{Attribute, LitStr, Meta, Path, Token, Type}; use synstructure::{BindingInfo, Structure, VariantInfo}; use super::utils::SubdiagnosticVariant; @@ -109,24 +109,14 @@ impl DiagnosticDeriveVariantBuilder { pub(crate) fn primary_message(&self) -> Option<&Message> { match self.message.as_ref() { None => { - span_err(self.span, "diagnostic slug not specified") + span_err(self.span, "diagnostic message not specified") .help( - "specify the slug as the first argument to the `#[diag(...)]` \ - attribute, such as `#[diag(hir_analysis_example_error)]`", + "specify the message as the first argument to the `#[diag(...)]` \ + attribute, such as `#[diag(\"Example error\")]`", ) .emit(); None } - Some(Message::Slug(slug)) - if let Some(Mismatch { slug_name, crate_name, slug_prefix }) = - Mismatch::check(slug) => - { - span_err(slug.span().unwrap(), "diagnostic slug and crate name do not match") - .note(format!("slug is `{slug_name}` but the crate name is `{crate_name}`")) - .help(format!("expected a slug starting with `{slug_prefix}_...`")) - .emit(); - None - } Some(msg) => Some(msg), } } @@ -177,25 +167,15 @@ impl DiagnosticDeriveVariantBuilder { .help("consider creating a `Subdiagnostic` instead")); } - // For subdiagnostics without a message specified, insert a placeholder slug - let slug = subdiag.slug.unwrap_or_else(|| { - Message::Slug(match subdiag.kind { - SubdiagnosticKind::Label => parse_quote! { _subdiag::label }, - SubdiagnosticKind::Note => parse_quote! { _subdiag::note }, - SubdiagnosticKind::NoteOnce => parse_quote! { _subdiag::note_once }, - SubdiagnosticKind::Help => parse_quote! { _subdiag::help }, - SubdiagnosticKind::HelpOnce => parse_quote! { _subdiag::help_once }, - SubdiagnosticKind::Warn => parse_quote! { _subdiag::warn }, - SubdiagnosticKind::Suggestion { .. } => parse_quote! { _subdiag::suggestion }, - SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(), - }) - }); + let Some(message) = subdiag.message else { + throw_invalid_attr!(attr, |diag| diag.help("subdiagnostic message is missing")) + }; - Ok(Some((subdiag.kind, slug, false))) + Ok(Some((subdiag.kind, message, false))) } /// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct - /// attributes like `#[diag(..)]`, such as the slug and error code. Generates + /// attributes like `#[diag(..)]`, such as the message and error code. Generates /// diagnostic builder calls for setting error code and creating note/help messages. fn generate_structure_code_for_attr( &mut self, @@ -213,9 +193,6 @@ impl DiagnosticDeriveVariantBuilder { if name == "diag" { let mut tokens = TokenStream::new(); attr.parse_args_with(|input: ParseStream<'_>| { - let mut input = &*input; - let slug_recovery_point = input.fork(); - if input.peek(LitStr) { // Parse an inline message let message = input.parse::()?; @@ -226,15 +203,8 @@ impl DiagnosticDeriveVariantBuilder { ) .emit(); } - self.message = Some(Message::Inline(message.span(), message.value())); - } else { - // Parse a slug - let slug = input.parse::()?; - if input.is_empty() || input.peek(Token![,]) { - self.message = Some(Message::Slug(slug)); - } else { - input = &slug_recovery_point; - } + self.message = + Some(Message { message_span: message.span(), value: message.value() }); } // Parse arguments @@ -248,7 +218,7 @@ impl DiagnosticDeriveVariantBuilder { if input.peek(Token![,]) { span_err( arg_name.span().unwrap(), - "diagnostic slug must be the first argument", + "diagnostic message must be the first argument", ) .emit(); continue; @@ -265,7 +235,7 @@ impl DiagnosticDeriveVariantBuilder { } _ => { span_err(arg_name.span().unwrap(), "unknown argument") - .note("only the `code` parameter is valid after the slug") + .note("only the `code` parameter is valid after the message") .emit(); } } @@ -276,7 +246,7 @@ impl DiagnosticDeriveVariantBuilder { return Ok(tokens); } - let Some((subdiag, slug, _no_span)) = self.parse_subdiag_attribute(attr)? else { + let Some((subdiag, message, _no_span)) = self.parse_subdiag_attribute(attr)? else { // Some attributes aren't errors - like documentation comments - but also aren't // subdiagnostics. return Ok(quote! {}); @@ -287,7 +257,7 @@ impl DiagnosticDeriveVariantBuilder { | SubdiagnosticKind::NoteOnce | SubdiagnosticKind::Help | SubdiagnosticKind::HelpOnce - | SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, slug, variant)), + | SubdiagnosticKind::Warn => Ok(self.add_subdiagnostic(&fn_ident, message, variant)), SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => { throw_invalid_attr!(attr, |diag| diag .help("`#[label]` and `#[suggestion]` can only be applied to fields")); @@ -406,7 +376,7 @@ impl DiagnosticDeriveVariantBuilder { _ => (), } - let Some((subdiag, slug, _no_span)) = self.parse_subdiag_attribute(attr)? else { + let Some((subdiag, message, _no_span)) = self.parse_subdiag_attribute(attr)? else { // Some attributes aren't errors - like documentation comments - but also aren't // subdiagnostics. return Ok(quote! {}); @@ -415,7 +385,7 @@ impl DiagnosticDeriveVariantBuilder { match subdiag { SubdiagnosticKind::Label => { report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug, variant)) + Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, message, variant)) } SubdiagnosticKind::Note | SubdiagnosticKind::NoteOnce @@ -426,11 +396,11 @@ impl DiagnosticDeriveVariantBuilder { if type_matches_path(inner, &["rustc_span", "Span"]) || type_matches_path(inner, &["rustc_span", "MultiSpan"]) { - Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug, variant)) + Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, message, variant)) } else if type_is_unit(inner) || (matches!(info.ty, FieldInnerTy::Plain(_)) && type_is_bool(inner)) { - Ok(self.add_subdiagnostic(&fn_ident, slug, variant)) + Ok(self.add_subdiagnostic(&fn_ident, message, variant)) } else { report_type_error(attr, "`Span`, `MultiSpan`, `bool` or `()`")? } @@ -456,7 +426,7 @@ impl DiagnosticDeriveVariantBuilder { applicability.set_once(quote! { #static_applicability }, span); } - let message = slug.diag_message(Some(variant)); + let message = message.diag_message(Some(variant)); let applicability = applicability .value() .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified }); @@ -477,7 +447,7 @@ impl DiagnosticDeriveVariantBuilder { } } - /// Adds a spanned subdiagnostic by generating a `diag.span_$kind` call with the current slug + /// Adds a spanned subdiagnostic by generating a `diag.span_$kind` call with the current message /// and `fluent_attr_identifier`. fn add_spanned_subdiagnostic( &self, @@ -496,7 +466,7 @@ impl DiagnosticDeriveVariantBuilder { } } - /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug + /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current message /// and `fluent_attr_identifier`. fn add_subdiagnostic( &self, @@ -567,27 +537,3 @@ impl DiagnosticDeriveVariantBuilder { } } } - -struct Mismatch { - slug_name: String, - crate_name: String, - slug_prefix: String, -} - -impl Mismatch { - /// Checks whether the slug starts with the crate name it's in. - fn check(slug: &syn::Path) -> Option { - // If this is missing we're probably in a test, so bail. - let crate_name = std::env::var("CARGO_CRATE_NAME").ok()?; - - // If we're not in a "rustc_" crate, bail. - let Some(("rustc", slug_prefix)) = crate_name.split_once('_') else { return None }; - - let slug_name = slug.segments.first()?.ident.to_string(); - if slug_name.starts_with(slug_prefix) { - return None; - } - - Some(Mismatch { slug_name, slug_prefix: slug_prefix.to_string(), crate_name }) - } -} diff --git a/compiler/rustc_macros/src/diagnostics/message.rs b/compiler/rustc_macros/src/diagnostics/message.rs index 2db8df2f69ae..18d4d60dde3e 100644 --- a/compiler/rustc_macros/src/diagnostics/message.rs +++ b/compiler/rustc_macros/src/diagnostics/message.rs @@ -2,16 +2,15 @@ use fluent_bundle::FluentResource; use fluent_syntax::ast::{Expression, InlineExpression, Pattern, PatternElement}; use proc_macro2::{Span, TokenStream}; use quote::quote; -use syn::Path; use syn::ext::IdentExt; -use synstructure::{Structure, VariantInfo}; +use synstructure::VariantInfo; use crate::diagnostics::error::span_err; #[derive(Clone)] -pub(crate) enum Message { - Slug(Path), - Inline(Span, String), +pub(crate) struct Message { + pub message_span: Span, + pub value: String, } impl Message { @@ -19,69 +18,9 @@ impl Message { /// The passed `variant` is used to check whether all variables in the message are used. /// For subdiagnostics, we cannot check this. pub(crate) fn diag_message(&self, variant: Option<&VariantInfo<'_>>) -> TokenStream { - match self { - Message::Slug(slug) => { - quote! { crate::fluent_generated::#slug } - } - Message::Inline(message_span, message) => { - verify_fluent_message(*message_span, &message, variant); - quote! { rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed(#message)) } - } - } - } - - /// Generates a `#[test]` that verifies that all referenced variables - /// exist on this structure. - pub(crate) fn generate_test(&self, structure: &Structure<'_>) -> TokenStream { - match self { - Message::Slug(slug) => { - // FIXME: We can't identify variables in a subdiagnostic - for field in structure.variants().iter().flat_map(|v| v.ast().fields.iter()) { - for attr_name in field.attrs.iter().filter_map(|at| at.path().get_ident()) { - if attr_name == "subdiagnostic" { - return quote!(); - } - } - } - 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. - 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) - ); - let ref_slug = quote::format_ident!("{slug}_refs"); - let struct_name = &structure.ast().ident; - let variables: Vec<_> = structure - .variants() - .iter() - .flat_map(|v| { - v.ast() - .fields - .iter() - .filter_map(|f| f.ident.as_ref().map(|i| i.to_string())) - }) - .collect(); - // tidy errors on `#[test]` outside of test files, so we use `#[test ]` to work around this - quote! { - #[cfg(test)] - #[test ] - fn #ident() { - let variables = [#(#variables),*]; - for vref in crate::fluent_generated::#ref_slug { - assert!(variables.contains(vref), "{}: variable `{vref}` not found ({})", stringify!(#struct_name), stringify!(#slug)); - } - } - } - } - Message::Inline(..) => { - // We don't generate a test for inline diagnostics, we can verify these at compile-time! - // This verification is done in the `diag_message` function above - quote! {} - } - } + let message = &self.value; + verify_fluent_message(self.message_span, &message, variant); + quote! { rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed(#message)) } } } diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index ac1fa984664c..7eb170ec236a 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -186,10 +186,10 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { fn identify_kind( &mut self, ) -> Result, DiagnosticDeriveError> { - let mut kind_slugs = vec![]; + let mut kind_messages = vec![]; for attr in self.variant.ast().attrs { - let Some(SubdiagnosticVariant { kind, slug }) = + let Some(SubdiagnosticVariant { kind, message }) = SubdiagnosticVariant::from_attr(attr, &self.fields)? else { // Some attributes aren't errors - like documentation comments - but also aren't @@ -197,22 +197,22 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { continue; }; - let Some(slug) = slug else { + let Some(message) = message else { let name = attr.path().segments.last().unwrap().ident.to_string(); let name = name.as_str(); throw_span_err!( attr.span().unwrap(), format!( - "diagnostic slug must be first argument of a `#[{name}(...)]` attribute" + "diagnostic message must be first argument of a `#[{name}(...)]` attribute" ) ); }; - kind_slugs.push((kind, slug)); + kind_messages.push((kind, message)); } - Ok(kind_slugs) + Ok(kind_messages) } /// Generates the code for a field with no attributes. @@ -498,9 +498,9 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } pub(crate) fn into_tokens(&mut self) -> Result { - let kind_slugs = self.identify_kind()?; + let kind_messages = self.identify_kind()?; - let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect(); + let kind_stats: KindsStatistics = kind_messages.iter().map(|(kind, _msg)| kind).collect(); let init = if kind_stats.has_multipart_suggestion { quote! { let mut suggestions = Vec::new(); } @@ -516,7 +516,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { .map(|binding| self.generate_field_attr_code(binding, kind_stats)) .collect(); - if kind_slugs.is_empty() && !self.has_subdiagnostic { + if kind_messages.is_empty() && !self.has_subdiagnostic { if self.is_enum { // It's okay for a variant to not be a subdiagnostic at all.. return Ok(quote! {}); @@ -533,9 +533,9 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let diag = &self.parent.diag; let mut calls = TokenStream::new(); - for (kind, slug) in kind_slugs { + for (kind, messages) in kind_messages { let message = format_ident!("__message"); - let message_stream = slug.diag_message(None); + let message_stream = messages.diag_message(None); calls.extend(quote! { let #message = #diag.eagerly_translate(#message_stream); }); let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index a5265a847a9c..c308f6126325 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -267,7 +267,7 @@ pub(super) type FieldMap = HashMap; /// /// ```ignore (not-usage-example) /// /// Suggest `==` when users wrote `===`. -/// #[suggestion(slug = "parser-not-javascript-eq", code = "{lhs} == {rhs}")] +/// #[suggestion("example message", code = "{lhs} == {rhs}")] /// struct NotJavaScriptEq { /// #[primary_span] /// span: Span, @@ -588,13 +588,13 @@ pub(super) enum SubdiagnosticKind { pub(super) struct SubdiagnosticVariant { pub(super) kind: SubdiagnosticKind, - pub(super) slug: Option, + pub(super) message: Option, } impl SubdiagnosticVariant { /// Constructs a `SubdiagnosticVariant` from a field or type attribute such as `#[note]`, - /// `#[error(parser::add_paren)]` or `#[suggestion(code = "...")]`. Returns the - /// `SubdiagnosticKind` and the diagnostic slug, if specified. + /// `#[error("add parenthesis")]` or `#[suggestion(code = "...")]`. Returns the + /// `SubdiagnosticKind` and the diagnostic message, if specified. pub(super) fn from_attr( attr: &Attribute, fields: &FieldMap, @@ -660,11 +660,11 @@ impl SubdiagnosticVariant { let list = match &attr.meta { Meta::List(list) => { // An attribute with properties, such as `#[suggestion(code = "...")]` or - // `#[error(some::slug)]` + // `#[error("message")]` list } Meta::Path(_) => { - // An attribute without a slug or other properties, such as `#[note]` - return + // An attribute without a message or other properties, such as `#[note]` - return // without further processing. // // Only allow this if there are no mandatory properties, such as `code = "..."` in @@ -677,7 +677,7 @@ impl SubdiagnosticVariant { | SubdiagnosticKind::HelpOnce | SubdiagnosticKind::Warn | SubdiagnosticKind::MultipartSuggestion { .. } => { - return Ok(Some(SubdiagnosticVariant { kind, slug: None })); + return Ok(Some(SubdiagnosticVariant { kind, message: None })); } SubdiagnosticKind::Suggestion { .. } => { throw_span_err!(span, "suggestion without `code = \"...\"`") @@ -692,45 +692,34 @@ impl SubdiagnosticVariant { let mut code = None; let mut suggestion_kind = None; - let mut slug = None; + let mut message = None; list.parse_args_with(|input: ParseStream<'_>| { let mut is_first = true; while !input.is_empty() { // Try to parse an inline diagnostic message if input.peek(LitStr) { - let message = input.parse::()?; - if !message.suffix().is_empty() { + let inline_message = input.parse::()?; + if !inline_message.suffix().is_empty() { span_err( - message.span().unwrap(), + inline_message.span().unwrap(), "Inline message is not allowed to have a suffix", ).emit(); } if !input.is_empty() { input.parse::()?; } if is_first { - slug = Some(Message::Inline(message.span(), message.value())); + message = Some(Message { message_span: inline_message.span(), value: inline_message.value() }); is_first = false; } else { - span_err(message.span().unwrap(), "a diagnostic message must be the first argument to the attribute").emit(); - } - continue - } - - // Try to parse a slug instead - let arg_name: Path = input.parse::()?; - let arg_name_span = arg_name.span().unwrap(); - if input.is_empty() || input.parse::().is_ok() { - if is_first { - slug = Some(Message::Slug(arg_name)); - is_first = false; - } else { - span_err(arg_name_span, "a diagnostic slug must be the first argument to the attribute").emit(); + span_err(inline_message.span().unwrap(), "a diagnostic message must be the first argument to the attribute").emit(); } continue } is_first = false; // Try to parse an argument + let arg_name: Path = input.parse::()?; + let arg_name_span = arg_name.span().unwrap(); match (arg_name.require_ident()?.to_string().as_str(), &mut kind) { ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => { let code_init = build_suggestion_code( @@ -836,7 +825,7 @@ impl SubdiagnosticVariant { | SubdiagnosticKind::Warn => {} } - Ok(Some(SubdiagnosticVariant { kind, slug })) + Ok(Some(SubdiagnosticVariant { kind, message })) } } From 2289e6cfb7e379eba777a10df0a6f474f9450b02 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 8 Feb 2026 11:04:30 +0100 Subject: [PATCH 707/978] Adjust expected uitests results for the updated `derive(Diagnostic)` macro --- .../diagnostic-derive-inline.rs | 38 +++-- .../diagnostic-derive-inline.stderr | 158 +++++++++--------- .../subdiagnostic-derive-inline.rs | 16 +- .../subdiagnostic-derive-inline.stderr | 22 +-- 4 files changed, 124 insertions(+), 110 deletions(-) diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs index 1d2bfc66aaff..ca803d450b92 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs @@ -45,9 +45,9 @@ struct Hello {} //~^ ERROR unsupported type attribute for diagnostic derive enum enum DiagnosticOnEnum { Foo, - //~^ ERROR diagnostic slug not specified + //~^ ERROR diagnostic message not specified Bar, - //~^ ERROR diagnostic slug not specified + //~^ ERROR diagnostic message not specified } #[derive(Diagnostic)] @@ -59,28 +59,28 @@ struct WrongStructAttrStyle {} #[derive(Diagnostic)] #[nonsense("this is an example message", code = E0123)] //~^ ERROR `#[nonsense(...)]` is not a valid attribute -//~^^ ERROR diagnostic slug not specified +//~^^ ERROR diagnostic message not specified //~^^^ ERROR cannot find attribute `nonsense` in this scope struct InvalidStructAttr {} #[derive(Diagnostic)] #[diag(code = E0123)] -//~^ ERROR diagnostic slug not specified +//~^ ERROR diagnostic message not specified struct InvalidLitNestedAttr {} #[derive(Diagnostic)] #[diag(nonsense("foo"), code = E0123, slug = "foo")] -//~^ ERROR derive(Diagnostic): diagnostic slug not specified +//~^ ERROR derive(Diagnostic): diagnostic message not specified struct InvalidNestedStructAttr1 {} #[derive(Diagnostic)] #[diag(nonsense = "...", code = E0123, slug = "foo")] -//~^ ERROR diagnostic slug not specified +//~^ ERROR diagnostic message not specified struct InvalidNestedStructAttr2 {} #[derive(Diagnostic)] #[diag(nonsense = 4, code = E0123, slug = "foo")] -//~^ ERROR diagnostic slug not specified +//~^ ERROR diagnostic message not specified struct InvalidNestedStructAttr3 {} #[derive(Diagnostic)] @@ -109,15 +109,15 @@ struct CodeSpecifiedTwice {} #[derive(Diagnostic)] #[diag("this is an example message", no_crate::example, code = E0123)] -//~^ ERROR diagnostic slug must be the first argument +//~^ ERROR diagnostic message must be the first argument struct SlugSpecifiedTwice {} #[derive(Diagnostic)] -struct KindNotProvided {} //~ ERROR diagnostic slug not specified +struct KindNotProvided {} //~ ERROR diagnostic message not specified #[derive(Diagnostic)] #[diag(code = E0123)] -//~^ ERROR diagnostic slug not specified +//~^ ERROR diagnostic message not specified struct SlugNotProvided {} #[derive(Diagnostic)] @@ -467,7 +467,15 @@ struct BoolField { #[diag("this is an example message", code = E0123)] struct LabelWithTrailingPath { #[label("with a label", foo)] - //~^ ERROR a diagnostic slug must be the first argument to the attribute + //~^ ERROR derive(Diagnostic): no nested attribute expected here + span: Span, +} + +#[derive(Diagnostic)] +#[diag("this is an example message", code = E0123)] +struct LabelWithTrailingMessage { + #[label("with a label", "and another one?")] + //~^ ERROR derive(Diagnostic): a diagnostic message must be the first argument to the attribute span: Span, } @@ -516,28 +524,28 @@ struct ErrorWithWarn { #[derive(Diagnostic)] #[error("this is an example message", code = E0123)] //~^ ERROR `#[error(...)]` is not a valid attribute -//~| ERROR diagnostic slug not specified +//~| ERROR diagnostic message not specified //~| ERROR cannot find attribute `error` in this scope struct ErrorAttribute {} #[derive(Diagnostic)] #[warn_("this is an example message", code = E0123)] //~^ ERROR `#[warn_(...)]` is not a valid attribute -//~| ERROR diagnostic slug not specified +//~| ERROR diagnostic message not specified //~| ERROR cannot find attribute `warn_` in this scope struct WarnAttribute {} #[derive(Diagnostic)] #[lint("this is an example message", code = E0123)] //~^ ERROR `#[lint(...)]` is not a valid attribute -//~| ERROR diagnostic slug not specified +//~| ERROR diagnostic message not specified //~| ERROR cannot find attribute `lint` in this scope struct LintAttributeOnSessionDiag {} #[derive(LintDiagnostic)] #[lint("this is an example message", code = E0123)] //~^ ERROR `#[lint(...)]` is not a valid attribute -//~| ERROR diagnostic slug not specified +//~| ERROR diagnostic message not specified //~| ERROR cannot find attribute `lint` in this scope struct LintAttributeOnLintDiag {} diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr index 71ed77804a6c..b32235c02b07 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr @@ -4,21 +4,21 @@ error: derive(Diagnostic): unsupported type attribute for diagnostic derive enum LL | #[diag("this is an example message", code = E0123)] | ^ -error: derive(Diagnostic): diagnostic slug not specified +error: derive(Diagnostic): diagnostic message not specified --> $DIR/diagnostic-derive-inline.rs:47:5 | LL | Foo, | ^^^ | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` -error: derive(Diagnostic): diagnostic slug not specified +error: derive(Diagnostic): diagnostic message not specified --> $DIR/diagnostic-derive-inline.rs:49:5 | LL | Bar, | ^^^ | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: expected parentheses: #[diag(...)] --> $DIR/diagnostic-derive-inline.rs:55:8 @@ -32,45 +32,45 @@ error: derive(Diagnostic): `#[nonsense(...)]` is not a valid attribute LL | #[nonsense("this is an example message", code = E0123)] | ^ -error: derive(Diagnostic): diagnostic slug not specified +error: derive(Diagnostic): diagnostic message not specified --> $DIR/diagnostic-derive-inline.rs:60:1 | LL | #[nonsense("this is an example message", code = E0123)] | ^ | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` -error: derive(Diagnostic): diagnostic slug not specified +error: derive(Diagnostic): diagnostic message not specified --> $DIR/diagnostic-derive-inline.rs:67:1 | LL | #[diag(code = E0123)] | ^ | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` -error: derive(Diagnostic): diagnostic slug not specified +error: derive(Diagnostic): diagnostic message not specified --> $DIR/diagnostic-derive-inline.rs:72:1 | LL | #[diag(nonsense("foo"), code = E0123, slug = "foo")] | ^ | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` -error: derive(Diagnostic): diagnostic slug not specified +error: derive(Diagnostic): diagnostic message not specified --> $DIR/diagnostic-derive-inline.rs:77:1 | LL | #[diag(nonsense = "...", code = E0123, slug = "foo")] | ^ | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` -error: derive(Diagnostic): diagnostic slug not specified +error: derive(Diagnostic): diagnostic message not specified --> $DIR/diagnostic-derive-inline.rs:82:1 | LL | #[diag(nonsense = 4, code = E0123, slug = "foo")] | ^ | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: derive(Diagnostic): unknown argument --> $DIR/diagnostic-derive-inline.rs:87:52 @@ -78,7 +78,7 @@ error: derive(Diagnostic): unknown argument LL | #[diag("this is an example message", code = E0123, slug = "foo")] | ^^^^ | - = note: only the `code` parameter is valid after the slug + = note: only the `code` parameter is valid after the message error: derive(Diagnostic): `#[suggestion = ...]` is not a valid attribute --> $DIR/diagnostic-derive-inline.rs:94:5 @@ -110,27 +110,27 @@ note: previously specified here LL | #[diag("this is an example message", code = E0123, code = E0456)] | ^^^^ -error: derive(Diagnostic): diagnostic slug must be the first argument +error: derive(Diagnostic): diagnostic message must be the first argument --> $DIR/diagnostic-derive-inline.rs:111:38 | LL | #[diag("this is an example message", no_crate::example, code = E0123)] | ^^^^^^^^ -error: derive(Diagnostic): diagnostic slug not specified +error: derive(Diagnostic): diagnostic message not specified --> $DIR/diagnostic-derive-inline.rs:116:1 | LL | struct KindNotProvided {} | ^^^^^^ | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` -error: derive(Diagnostic): diagnostic slug not specified +error: derive(Diagnostic): diagnostic message not specified --> $DIR/diagnostic-derive-inline.rs:119:1 | LL | #[diag(code = E0123)] | ^ | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: derive(Diagnostic): the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` --> $DIR/diagnostic-derive-inline.rs:130:5 @@ -276,26 +276,32 @@ error: derive(Diagnostic): the `#[help(...)]` attribute can only be applied to f LL | #[help("with a help")] | ^ -error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute +error: derive(Diagnostic): no nested attribute expected here --> $DIR/diagnostic-derive-inline.rs:469:29 | LL | #[label("with a label", foo)] | ^^^ -error: derive(Diagnostic): no nested attribute expected here +error: derive(Diagnostic): a diagnostic message must be the first argument to the attribute --> $DIR/diagnostic-derive-inline.rs:477:29 | +LL | #[label("with a label", "and another one?")] + | ^^^^^^^^^^^^^^^^^^ + +error: derive(Diagnostic): no nested attribute expected here + --> $DIR/diagnostic-derive-inline.rs:485:29 + | LL | #[label("with a label", foo = "...")] | ^^^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/diagnostic-derive-inline.rs:485:29 + --> $DIR/diagnostic-derive-inline.rs:493:29 | LL | #[label("with a label", foo("..."))] | ^^^ error: derive(Diagnostic): `#[primary_span]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:497:5 + --> $DIR/diagnostic-derive-inline.rs:505:5 | LL | #[primary_span] | ^ @@ -303,75 +309,75 @@ LL | #[primary_span] = help: the `primary_span` field attribute is not valid for lint diagnostics error: derive(Diagnostic): `#[error(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:517:1 + --> $DIR/diagnostic-derive-inline.rs:525:1 | LL | #[error("this is an example message", code = E0123)] | ^ -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:517:1 +error: derive(Diagnostic): diagnostic message not specified + --> $DIR/diagnostic-derive-inline.rs:525:1 | LL | #[error("this is an example message", code = E0123)] | ^ | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: derive(Diagnostic): `#[warn_(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:524:1 + --> $DIR/diagnostic-derive-inline.rs:532:1 | LL | #[warn_("this is an example message", code = E0123)] | ^ -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:524:1 +error: derive(Diagnostic): diagnostic message not specified + --> $DIR/diagnostic-derive-inline.rs:532:1 | LL | #[warn_("this is an example message", code = E0123)] | ^ | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:531:1 + --> $DIR/diagnostic-derive-inline.rs:539:1 | LL | #[lint("this is an example message", code = E0123)] | ^ -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:531:1 +error: derive(Diagnostic): diagnostic message not specified + --> $DIR/diagnostic-derive-inline.rs:539:1 | LL | #[lint("this is an example message", code = E0123)] | ^ | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:538:1 + --> $DIR/diagnostic-derive-inline.rs:546:1 | LL | #[lint("this is an example message", code = E0123)] | ^ -error: derive(Diagnostic): diagnostic slug not specified - --> $DIR/diagnostic-derive-inline.rs:538:1 +error: derive(Diagnostic): diagnostic message not specified + --> $DIR/diagnostic-derive-inline.rs:546:1 | LL | #[lint("this is an example message", code = E0123)] | ^ | - = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` + = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive-inline.rs:547:53 + --> $DIR/diagnostic-derive-inline.rs:555:53 | LL | #[suggestion("with a suggestion", code = "...", code = ",,,")] | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive-inline.rs:547:39 + --> $DIR/diagnostic-derive-inline.rs:555:39 | LL | #[suggestion("with a suggestion", code = "...", code = ",,,")] | ^^^^ error: derive(Diagnostic): wrong types for suggestion - --> $DIR/diagnostic-derive-inline.rs:556:24 + --> $DIR/diagnostic-derive-inline.rs:564:24 | LL | suggestion: (Span, usize), | ^^^^^ @@ -379,7 +385,7 @@ LL | suggestion: (Span, usize), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: derive(Diagnostic): wrong types for suggestion - --> $DIR/diagnostic-derive-inline.rs:564:17 + --> $DIR/diagnostic-derive-inline.rs:572:17 | LL | suggestion: (Span,), | ^^^^^^^ @@ -387,13 +393,13 @@ LL | suggestion: (Span,), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive-inline.rs:571:5 + --> $DIR/diagnostic-derive-inline.rs:579:5 | LL | #[suggestion("with a suggestion")] | ^ error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:578:1 + --> $DIR/diagnostic-derive-inline.rs:586:1 | LL | #[multipart_suggestion("with a suggestion")] | ^ @@ -401,7 +407,7 @@ LL | #[multipart_suggestion("with a suggestion")] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:581:1 + --> $DIR/diagnostic-derive-inline.rs:589:1 | LL | #[multipart_suggestion()] | ^ @@ -409,7 +415,7 @@ LL | #[multipart_suggestion()] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:585:5 + --> $DIR/diagnostic-derive-inline.rs:593:5 | LL | #[multipart_suggestion("with a suggestion")] | ^ @@ -417,7 +423,7 @@ LL | #[multipart_suggestion("with a suggestion")] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:593:1 + --> $DIR/diagnostic-derive-inline.rs:601:1 | LL | #[suggestion("with a suggestion", code = "...")] | ^ @@ -425,41 +431,35 @@ LL | #[suggestion("with a suggestion", code = "...")] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: derive(Diagnostic): `#[label]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:602:1 + --> $DIR/diagnostic-derive-inline.rs:610:1 | LL | #[label] | ^ | - = help: `#[label]` and `#[suggestion]` can only be applied to fields + = help: subdiagnostic message is missing error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:636:5 + --> $DIR/diagnostic-derive-inline.rs:644:5 | LL | #[subdiagnostic(bad)] | ^ error: derive(Diagnostic): `#[subdiagnostic = ...]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:644:5 + --> $DIR/diagnostic-derive-inline.rs:652:5 | LL | #[subdiagnostic = "bad"] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:652:5 + --> $DIR/diagnostic-derive-inline.rs:660:5 | LL | #[subdiagnostic(bad, bad)] | ^ -error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:660:5 - | -LL | #[subdiagnostic("bad")] - | ^ - error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute --> $DIR/diagnostic-derive-inline.rs:668:5 | -LL | #[subdiagnostic(eager)] +LL | #[subdiagnostic("bad")] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute @@ -469,37 +469,43 @@ LL | #[subdiagnostic(eager)] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:697:5 + --> $DIR/diagnostic-derive-inline.rs:684:5 + | +LL | #[subdiagnostic(eager)] + | ^ + +error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive-inline.rs:705:5 | LL | #[subdiagnostic(eager)] | ^ error: derive(Diagnostic): expected at least one string literal for `code(...)` - --> $DIR/diagnostic-derive-inline.rs:728:44 + --> $DIR/diagnostic-derive-inline.rs:736:44 | LL | #[suggestion("with a suggestion", code())] | ^ error: derive(Diagnostic): `code(...)` must contain only string literals - --> $DIR/diagnostic-derive-inline.rs:736:44 + --> $DIR/diagnostic-derive-inline.rs:744:44 | LL | #[suggestion("with a suggestion", code(foo))] | ^^^ error: unexpected token, expected `)` - --> $DIR/diagnostic-derive-inline.rs:736:44 + --> $DIR/diagnostic-derive-inline.rs:744:44 | LL | #[suggestion("with a suggestion", code(foo))] | ^^^ error: expected string literal - --> $DIR/diagnostic-derive-inline.rs:745:46 + --> $DIR/diagnostic-derive-inline.rs:753:46 | LL | #[suggestion("with a suggestion", code = 3)] | ^ error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:760:5 + --> $DIR/diagnostic-derive-inline.rs:768:5 | LL | #[suggestion("with a suggestion", code = "")] | ^ @@ -509,7 +515,7 @@ LL | #[suggestion("with a suggestion", code = "")] = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]` error: derive(Diagnostic): Variable `nosub` not found in diagnostic - --> $DIR/diagnostic-derive-inline.rs:772:8 + --> $DIR/diagnostic-derive-inline.rs:780:8 | LL | #[diag("does not exist: {$nosub}")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -529,7 +535,7 @@ LL | #[nonsense] | ^^^^^^^^ error: cannot find attribute `error` in this scope - --> $DIR/diagnostic-derive-inline.rs:517:3 + --> $DIR/diagnostic-derive-inline.rs:525:3 | LL | #[error("this is an example message", code = E0123)] | ^^^^^ @@ -541,7 +547,7 @@ LL | struct ErrorAttribute {} | error: cannot find attribute `warn_` in this scope - --> $DIR/diagnostic-derive-inline.rs:524:3 + --> $DIR/diagnostic-derive-inline.rs:532:3 | LL | #[warn_("this is an example message", code = E0123)] | ^^^^^ @@ -553,7 +559,7 @@ LL + #[warn("this is an example message", code = E0123)] | error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive-inline.rs:531:3 + --> $DIR/diagnostic-derive-inline.rs:539:3 | LL | #[lint("this is an example message", code = E0123)] | ^^^^ @@ -565,7 +571,7 @@ LL + #[link("this is an example message", code = E0123)] | error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive-inline.rs:538:3 + --> $DIR/diagnostic-derive-inline.rs:546:3 | LL | #[lint("this is an example message", code = E0123)] | ^^^^ @@ -577,7 +583,7 @@ LL + #[link("this is an example message", code = E0123)] | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive-inline.rs:578:3 + --> $DIR/diagnostic-derive-inline.rs:586:3 | LL | #[multipart_suggestion("with a suggestion")] | ^^^^^^^^^^^^^^^^^^^^ @@ -589,7 +595,7 @@ LL | struct MultipartSuggestion { | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive-inline.rs:581:3 + --> $DIR/diagnostic-derive-inline.rs:589:3 | LL | #[multipart_suggestion()] | ^^^^^^^^^^^^^^^^^^^^ @@ -601,7 +607,7 @@ LL | struct MultipartSuggestion { | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive-inline.rs:585:7 + --> $DIR/diagnostic-derive-inline.rs:593:7 | LL | #[multipart_suggestion("with a suggestion")] | ^^^^^^^^^^^^^^^^^^^^ @@ -630,6 +636,6 @@ note: required by a bound in `Diag::<'a, G>::arg` = note: in this macro invocation = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 80 previous errors +error: aborting due to 81 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs index 079c2a74c4a1..99b2cba89da4 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs @@ -54,7 +54,7 @@ struct C { #[derive(Subdiagnostic)] #[label] -//~^ ERROR diagnostic slug must be first argument +//~^ ERROR diagnostic message must be first argument struct D { #[primary_span] span: Span, @@ -83,7 +83,7 @@ struct F { #[derive(Subdiagnostic)] #[label(bug = "...")] //~^ ERROR no nested attribute expected here -//~| ERROR diagnostic slug must be first argument +//~| ERROR diagnostic message must be first argument struct G { #[primary_span] span: Span, @@ -93,7 +93,7 @@ struct G { #[derive(Subdiagnostic)] #[label(slug = 4)] //~^ ERROR no nested attribute expected here -//~| ERROR diagnostic slug must be first argument +//~| ERROR diagnostic message must be first argument struct J { #[primary_span] span: Span, @@ -103,7 +103,7 @@ struct J { #[derive(Subdiagnostic)] #[label(slug("..."))] //~^ ERROR no nested attribute expected here -//~| ERROR diagnostic slug must be first argument +//~| ERROR diagnostic message must be first argument struct K { #[primary_span] span: Span, @@ -112,7 +112,7 @@ struct K { #[derive(Subdiagnostic)] #[label()] -//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute +//~^ ERROR diagnostic message must be first argument of a `#[label(...)]` attribute struct M { #[primary_span] span: Span, @@ -201,7 +201,7 @@ enum T { #[derive(Subdiagnostic)] enum U { #[label(code = "...")] - //~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute + //~^ ERROR diagnostic message must be first argument of a `#[label(...)]` attribute //~| ERROR no nested attribute expected here A { #[primary_span] @@ -303,7 +303,7 @@ struct AD { #[derive(Subdiagnostic)] #[label("example message", no_crate::example)] -//~^ ERROR a diagnostic slug must be the first argument to the attribute +//~^ ERROR expected this path to be an identifier struct AE { #[primary_span] span: Span, @@ -771,7 +771,7 @@ struct SuggestionStyleInvalid2 { #[derive(Subdiagnostic)] #[suggestion("example message", code = "", style)] -//~^ ERROR a diagnostic slug must be the first argument to the attribute +//~^ ERROR expected `=` struct SuggestionStyleInvalid3 { #[primary_span] sub: Span, diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr index 8ff5ed00d0ba..90e0c285ee74 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.stderr @@ -4,7 +4,7 @@ error: derive(Diagnostic): label without `#[primary_span]` field LL | #[label("example message")] | ^ -error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute +error: derive(Diagnostic): diagnostic message must be first argument of a `#[label(...)]` attribute --> $DIR/subdiagnostic-derive-inline.rs:56:1 | LL | #[label] @@ -28,7 +28,7 @@ error: derive(Diagnostic): no nested attribute expected here LL | #[label(bug = "...")] | ^^^ -error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute +error: derive(Diagnostic): diagnostic message must be first argument of a `#[label(...)]` attribute --> $DIR/subdiagnostic-derive-inline.rs:84:1 | LL | #[label(bug = "...")] @@ -40,7 +40,7 @@ error: derive(Diagnostic): no nested attribute expected here LL | #[label(slug = 4)] | ^^^^ -error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute +error: derive(Diagnostic): diagnostic message must be first argument of a `#[label(...)]` attribute --> $DIR/subdiagnostic-derive-inline.rs:94:1 | LL | #[label(slug = 4)] @@ -52,13 +52,13 @@ error: derive(Diagnostic): no nested attribute expected here LL | #[label(slug("..."))] | ^^^^ -error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute +error: derive(Diagnostic): diagnostic message must be first argument of a `#[label(...)]` attribute --> $DIR/subdiagnostic-derive-inline.rs:104:1 | LL | #[label(slug("..."))] | ^ -error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute +error: derive(Diagnostic): diagnostic message must be first argument of a `#[label(...)]` attribute --> $DIR/subdiagnostic-derive-inline.rs:114:1 | LL | #[label()] @@ -112,7 +112,7 @@ error: derive(Diagnostic): no nested attribute expected here LL | #[label(code = "...")] | ^^^^ -error: derive(Diagnostic): diagnostic slug must be first argument of a `#[label(...)]` attribute +error: derive(Diagnostic): diagnostic message must be first argument of a `#[label(...)]` attribute --> $DIR/subdiagnostic-derive-inline.rs:203:5 | LL | #[label(code = "...")] @@ -168,11 +168,11 @@ LL | | b: u64, LL | | } | |_^ -error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute +error: expected this path to be an identifier --> $DIR/subdiagnostic-derive-inline.rs:305:28 | LL | #[label("example message", no_crate::example)] - | ^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ error: derive(Diagnostic): attribute specified multiple times --> $DIR/subdiagnostic-derive-inline.rs:318:5 @@ -464,11 +464,11 @@ error: expected string literal LL | #[suggestion("example message", code = "", style = 42)] | ^^ -error: derive(Diagnostic): a diagnostic slug must be the first argument to the attribute - --> $DIR/subdiagnostic-derive-inline.rs:773:44 +error: expected `=` + --> $DIR/subdiagnostic-derive-inline.rs:773:49 | LL | #[suggestion("example message", code = "", style)] - | ^^^^^ + | ^ error: expected `=` --> $DIR/subdiagnostic-derive-inline.rs:781:49 From 0db0acd6993cbdf84384b00773d7509df6bc20fb Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 20:08:45 +0100 Subject: [PATCH 708/978] Remove the fallback bundle --- compiler/rustc_driver_impl/src/lib.rs | 7 ++----- compiler/rustc_errors/src/json/tests.rs | 2 +- compiler/rustc_errors/src/translation.rs | 17 ++-------------- compiler/rustc_interface/src/interface.rs | 4 ---- compiler/rustc_interface/src/tests.rs | 1 - compiler/rustc_parse/src/parser/tests.rs | 20 +++++++++---------- compiler/rustc_session/src/parse.rs | 6 +++--- compiler/rustc_session/src/session.rs | 13 +++--------- src/librustdoc/clean/render_macro_matchers.rs | 2 +- src/librustdoc/core.rs | 1 - src/librustdoc/doctest.rs | 1 - .../ui-fulldeps/mod_dir_path_canonicalized.rs | 2 +- tests/ui-fulldeps/pprust-expr-roundtrip.rs | 2 +- .../pprust-parenthesis-insertion.rs | 2 +- tests/ui-fulldeps/run-compiler-twice.rs | 1 - 15 files changed, 25 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index d72913764e9d..83b27520457b 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -108,11 +108,9 @@ use crate::session_diagnostics::{ }; pub fn default_translator() -> Translator { - Translator::with_fallback_bundle(DEFAULT_LOCALE_RESOURCES.to_vec(), false) + Translator::new() } -pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[]; - /// Exit status code used for successful compilation and help output. pub const EXIT_SUCCESS: i32 = 0; @@ -219,7 +217,6 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) output_dir: odir, ice_file, file_loader: None, - locale_resources: DEFAULT_LOCALE_RESOURCES.to_vec(), lint_caps: Default::default(), psess_created: None, hash_untracked_state: None, @@ -1528,7 +1525,7 @@ fn report_ice( extra_info: fn(&DiagCtxt), using_internal_features: &AtomicBool, ) { - let translator = default_translator(); + let translator = Translator::new(); let emitter = Box::new(rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter::new( stderr_destination(rustc_errors::ColorConfig::Auto), diff --git a/compiler/rustc_errors/src/json/tests.rs b/compiler/rustc_errors/src/json/tests.rs index 6f99930c433b..ffcf9947a7a8 100644 --- a/compiler/rustc_errors/src/json/tests.rs +++ b/compiler/rustc_errors/src/json/tests.rs @@ -45,7 +45,7 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) { rustc_span::create_default_session_globals_then(|| { let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); sm.new_source_file(filename(&sm, "test.rs"), code.to_owned()); - let translator = Translator::with_fallback_bundle(vec![], false); + let translator = Translator::new(); let output = Arc::new(Mutex::new(Vec::new())); let je = JsonEmitter::new( diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index 0b9845772590..b5de3f87e9f3 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -34,24 +34,11 @@ pub struct Translator { /// Localized diagnostics for the locale requested by the user. If no language was requested by /// the user then this will be `None` and `fallback_fluent_bundle` should be used. pub fluent_bundle: Option>, - /// Return `FluentBundle` with localized diagnostics for the default locale of the compiler. - /// Used when the user has not requested a specific language or when a localized diagnostic is - /// unavailable for the requested locale. - pub fallback_fluent_bundle: LazyFallbackBundle, } impl Translator { - pub fn with_fallback_bundle( - resources: Vec<&'static str>, - with_directionality_markers: bool, - ) -> Translator { - Translator { - fluent_bundle: None, - fallback_fluent_bundle: crate::fallback_fluent_bundle( - resources, - with_directionality_markers, - ), - } + pub fn new() -> Translator { + Translator { fluent_bundle: None } } /// Convert `DiagMessage`s to a string, performing translation if necessary. diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 722e9a420540..72080c5f5369 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -332,9 +332,6 @@ pub struct Config { /// bjorn3 for "hooking rust-analyzer's VFS into rustc at some point for /// running rustc without having to save". (See #102759.) pub file_loader: Option>, - /// The list of fluent resources, used for lints declared with - /// [`Diagnostic`](rustc_errors::Diagnostic) and [`LintDiagnostic`](rustc_errors::LintDiagnostic). - pub locale_resources: Vec<&'static str>, pub lint_caps: FxHashMap, @@ -458,7 +455,6 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se temps_dir, }, bundle, - config.locale_resources, config.lint_caps, target, util::rustc_version_str().unwrap_or("unknown"), diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 4241af244941..5ebf898f45a3 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -72,7 +72,6 @@ where sessopts, io, None, - vec![], Default::default(), target, "", diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 1b17f422345f..ac9c3e63e853 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -42,7 +42,7 @@ fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> { fn create_test_handler(theme: OutputTheme) -> (DiagCtxt, Arc, Arc>>) { let output = Arc::new(Mutex::new(Vec::new())); let source_map = Arc::new(SourceMap::new(FilePathMapping::empty())); - let translator = Translator::with_fallback_bundle(vec![], false); + let translator = Translator::new(); let shared: Box = Box::new(Shared { data: output.clone() }); let auto_stream = AutoStream::never(shared); let dcx = DiagCtxt::new(Box::new( @@ -89,7 +89,7 @@ where /// Maps a string to tts, using a made-up filename. pub(crate) fn string_to_stream(source_str: String) -> TokenStream { - let psess = ParseSess::new(vec![]); + let psess = ParseSess::new(); unwrap_or_emit_fatal(source_str_to_stream( &psess, filename(psess.source_map(), "bogofile"), @@ -2239,12 +2239,12 @@ fn sp(a: u32, b: u32) -> Span { /// Parses a string, return an expression. fn string_to_expr(source_str: String) -> Box { - with_error_checking_parse(source_str, &ParseSess::new(vec![]), |p| p.parse_expr()) + with_error_checking_parse(source_str, &ParseSess::new(), |p| p.parse_expr()) } /// Parses a string, returns an item. fn string_to_item(source_str: String) -> Option> { - with_error_checking_parse(source_str, &ParseSess::new(vec![]), |p| { + with_error_checking_parse(source_str, &ParseSess::new(), |p| { p.parse_item(ForceCollect::No, AllowConstBlockItems::Yes) }) } @@ -2480,7 +2480,7 @@ let mut fflags: c_int = wb(); #[test] fn crlf_doc_comments() { create_default_session_globals_then(|| { - let psess = ParseSess::new(vec![]); + let psess = ParseSess::new(); let name_1 = FileName::Custom("crlf_source_1".to_string()); let source = "/// doc comment\r\nfn foo() {}".to_string(); @@ -2515,7 +2515,7 @@ fn ttdelim_span() { } create_default_session_globals_then(|| { - let psess = ParseSess::new(vec![]); + let psess = ParseSess::new(); let expr = parse_expr_from_source_str( filename(psess.source_map(), "foo"), "foo!( fn main() { body } )".to_string(), @@ -2551,7 +2551,7 @@ fn look_ahead() { let sym_S = Symbol::intern("S"); let raw_no = IdentIsRaw::No; - let psess = ParseSess::new(vec![]); + let psess = ParseSess::new(); let mut p = string_to_parser(&psess, "fn f(x: u32) { x } struct S;".to_string()); // Current position is the `fn`. @@ -2626,7 +2626,7 @@ fn look_ahead_non_outermost_stream() { let sym_S = Symbol::intern("S"); let raw_no = IdentIsRaw::No; - let psess = ParseSess::new(vec![]); + let psess = ParseSess::new(); let mut p = string_to_parser(&psess, "mod m { fn f(x: u32) { x } struct S; }".to_string()); // Move forward to the `fn`, which is not within the outermost token @@ -2658,7 +2658,7 @@ fn look_ahead_non_outermost_stream() { #[test] fn debug_lookahead() { create_default_session_globals_then(|| { - let psess = ParseSess::new(vec![]); + let psess = ParseSess::new(); let mut p = string_to_parser(&psess, "fn f(x: u32) { x } struct S;".to_string()); // Current position is the `fn`. @@ -2879,7 +2879,7 @@ fn debug_lookahead() { #[test] fn out_of_line_mod() { create_default_session_globals_then(|| { - let psess = ParseSess::new(vec![]); + let psess = ParseSess::new(); let item = parse_item_from_source_str( filename(psess.source_map(), "foo"), "mod foo { struct S; mod this_does_not_exist; }".to_owned(), diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 7bebbc579c43..62c23424f371 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -280,8 +280,8 @@ pub struct ParseSess { impl ParseSess { /// Used for testing. - pub fn new(locale_resources: Vec<&'static str>) -> Self { - let translator = Translator::with_fallback_bundle(locale_resources, false); + pub fn new() -> Self { + let translator = Translator::new(); let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); let emitter = Box::new( AnnotateSnippetEmitter::new(stderr_destination(ColorConfig::Auto), translator) @@ -314,7 +314,7 @@ impl ParseSess { } pub fn emitter_with_note(note: String) -> Self { - let translator = Translator::with_fallback_bundle(vec![], false); + let translator = Translator::new(); let sm = Arc::new(SourceMap::new(FilePathMapping::empty())); let emitter = Box::new(AnnotateSnippetEmitter::new( stderr_destination(ColorConfig::Auto), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 92c47e3bfb36..ed37e9e960cd 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -19,7 +19,7 @@ use rustc_errors::timings::TimingSectionHandler; use rustc_errors::translation::Translator; use rustc_errors::{ Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic, ErrorGuaranteed, FatalAbort, - TerminalUrl, fallback_fluent_bundle, + TerminalUrl, }; use rustc_hir::limit::Limit; use rustc_macros::HashStable_Generic; @@ -967,7 +967,6 @@ pub fn build_session( sopts: config::Options, io: CompilerIO, fluent_bundle: Option>, - fluent_resources: Vec<&'static str>, driver_lint_caps: FxHashMap, target: Target, cfg_version: &'static str, @@ -985,13 +984,7 @@ pub fn build_session( let cap_lints_allow = sopts.lint_cap.is_some_and(|cap| cap == lint::Allow); let can_emit_warnings = !(warnings_allow || cap_lints_allow); - let translator = Translator { - fluent_bundle, - fallback_fluent_bundle: fallback_fluent_bundle( - fluent_resources, - sopts.unstable_opts.translate_directionality_markers, - ), - }; + let translator = Translator { fluent_bundle }; let source_map = rustc_span::source_map::get_source_map().unwrap(); let emitter = default_emitter(&sopts, Arc::clone(&source_map), translator); @@ -1430,7 +1423,7 @@ impl EarlyDiagCtxt { fn mk_emitter(output: ErrorOutputType) -> Box { // FIXME(#100717): early errors aren't translated at the moment, so this is fine, but it will // need to reference every crate that might emit an early error for translation to work. - let translator = Translator::with_fallback_bundle(vec![], false); + let translator = Translator::new(); let emitter: Box = match output { config::ErrorOutputType::HumanReadable { kind, color_config } => match kind { HumanReadableErrorType { short, unicode } => Box::new( diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs index b5a8d64ff4f5..a69e3808bd7f 100644 --- a/src/librustdoc/clean/render_macro_matchers.rs +++ b/src/librustdoc/clean/render_macro_matchers.rs @@ -63,7 +63,7 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option, input: Input, options: RustdocOptions output_file: None, output_dir: None, file_loader: None, - locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), lint_caps, psess_created: None, hash_untracked_state: None, diff --git a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs index 894fec248f1f..806d395a90ad 100644 --- a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs +++ b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs @@ -29,7 +29,7 @@ pub fn main() { } fn parse() { - let psess = ParseSess::new(vec![]); + let psess = ParseSess::new(); let path = Path::new(file!()); let path = path.canonicalize().unwrap(); diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs index 7fe71004522a..8d7425186680 100644 --- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs @@ -219,7 +219,7 @@ fn main() { } fn run() { - let psess = ParseSess::new(vec![]); + let psess = ParseSess::new(); iter_exprs(2, &mut |mut e| { // If the pretty printer is correct, then `parse(print(e))` should be identical to `e`, diff --git a/tests/ui-fulldeps/pprust-parenthesis-insertion.rs b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs index 90cf9b89a293..85ee87155a7a 100644 --- a/tests/ui-fulldeps/pprust-parenthesis-insertion.rs +++ b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs @@ -196,7 +196,7 @@ fn main() -> ExitCode { }; rustc_span::create_default_session_globals_then(|| { - let psess = &ParseSess::new(vec![]); + let psess = &ParseSess::new(); for &source_code in EXPRS { let Some(expr) = parse_expr(psess, source_code) else { diff --git a/tests/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs index 8b5e99cbee8d..bd92cc6218f1 100644 --- a/tests/ui-fulldeps/run-compiler-twice.rs +++ b/tests/ui-fulldeps/run-compiler-twice.rs @@ -64,7 +64,6 @@ fn compile(code: String, output: PathBuf, sysroot: Sysroot, linker: Option<&Path output_dir: None, ice_file: None, file_loader: None, - locale_resources: Vec::new(), lint_caps: Default::default(), psess_created: None, hash_untracked_state: None, From 81d42146040c4a6b3d252e3dc3ac32e563694796 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Feb 2026 20:09:13 +0100 Subject: [PATCH 709/978] Remove fluent tests in `rustc_error` --- compiler/rustc_errors/src/lib.rs | 2 - compiler/rustc_errors/src/tests.rs | 182 ----------------------------- 2 files changed, 184 deletions(-) delete mode 100644 compiler/rustc_errors/src/tests.rs diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 534fe32a897f..2e0afb8fc4c2 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -83,8 +83,6 @@ pub mod error; pub mod json; mod lock; pub mod markdown; -#[cfg(test)] -mod tests; pub mod timings; pub mod translation; diff --git a/compiler/rustc_errors/src/tests.rs b/compiler/rustc_errors/src/tests.rs deleted file mode 100644 index 34ebac0fde11..000000000000 --- a/compiler/rustc_errors/src/tests.rs +++ /dev/null @@ -1,182 +0,0 @@ -use std::sync::{Arc, LazyLock}; - -use rustc_data_structures::sync::IntoDynSyncSend; -use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError}; -use rustc_error_messages::{DiagMessage, langid}; - -use crate::FluentBundle; -use crate::error::{TranslateError, TranslateErrorKind}; -use crate::fluent_bundle::*; -use crate::translation::Translator; - -fn make_translator(ftl: &'static str) -> Translator { - let resource = FluentResource::try_new(ftl.into()).expect("Failed to parse an FTL string."); - - let langid_en = langid!("en-US"); - - let mut bundle: FluentBundle = - IntoDynSyncSend(crate::fluent_bundle::bundle::FluentBundle::new_concurrent(vec![ - langid_en, - ])); - - bundle.add_resource(resource).expect("Failed to add FTL resources to the bundle."); - - Translator { - fluent_bundle: None, - fallback_fluent_bundle: Arc::new(LazyLock::new(Box::new(|| bundle))), - } -} - -#[test] -fn wellformed_fluent() { - let translator = make_translator("mir_build_borrow_of_moved_value = borrow of moved value - .label = value moved into `{$name}` here - .occurs_because_label = move occurs because `{$name}` has type `{$ty}` which does not implement the `Copy` trait - .value_borrowed_label = value borrowed here after move - .suggestion = borrow this binding in the pattern to avoid moving the value"); - - let mut args = FluentArgs::new(); - args.set("name", "Foo"); - args.set("ty", "std::string::String"); - { - let message = DiagMessage::FluentIdentifier( - "mir_build_borrow_of_moved_value".into(), - Some("suggestion".into()), - ); - - assert_eq!( - translator.translate_message(&message, &args).unwrap(), - "borrow this binding in the pattern to avoid moving the value" - ); - } - - { - let message = DiagMessage::FluentIdentifier( - "mir_build_borrow_of_moved_value".into(), - Some("value_borrowed_label".into()), - ); - - assert_eq!( - translator.translate_message(&message, &args).unwrap(), - "value borrowed here after move" - ); - } - - { - let message = DiagMessage::FluentIdentifier( - "mir_build_borrow_of_moved_value".into(), - Some("occurs_because_label".into()), - ); - - assert_eq!( - translator.translate_message(&message, &args).unwrap(), - "move occurs because `\u{2068}Foo\u{2069}` has type `\u{2068}std::string::String\u{2069}` which does not implement the `Copy` trait" - ); - - { - let message = DiagMessage::FluentIdentifier( - "mir_build_borrow_of_moved_value".into(), - Some("label".into()), - ); - - assert_eq!( - translator.translate_message(&message, &args).unwrap(), - "value moved into `\u{2068}Foo\u{2069}` here" - ); - } - } -} - -#[test] -fn misformed_fluent() { - let translator = make_translator("mir_build_borrow_of_moved_value = borrow of moved value - .label = value moved into `{name}` here - .occurs_because_label = move occurs because `{$oops}` has type `{$ty}` which does not implement the `Copy` trait - .suggestion = borrow this binding in the pattern to avoid moving the value"); - - let mut args = FluentArgs::new(); - args.set("name", "Foo"); - args.set("ty", "std::string::String"); - { - let message = DiagMessage::FluentIdentifier( - "mir_build_borrow_of_moved_value".into(), - Some("value_borrowed_label".into()), - ); - - let err = translator.translate_message(&message, &args).unwrap_err(); - assert!( - matches!( - &err, - TranslateError::Two { - primary: box TranslateError::One { - kind: TranslateErrorKind::PrimaryBundleMissing, - .. - }, - fallback: box TranslateError::One { - kind: TranslateErrorKind::AttributeMissing { attr: "value_borrowed_label" }, - .. - } - } - ), - "{err:#?}" - ); - assert_eq!( - format!("{err}"), - "failed while formatting fluent string `mir_build_borrow_of_moved_value`: \nthe attribute `value_borrowed_label` was missing\nhelp: add `.value_borrowed_label = `\n" - ); - } - - { - let message = DiagMessage::FluentIdentifier( - "mir_build_borrow_of_moved_value".into(), - Some("label".into()), - ); - - let err = translator.translate_message(&message, &args).unwrap_err(); - if let TranslateError::Two { - primary: box TranslateError::One { kind: TranslateErrorKind::PrimaryBundleMissing, .. }, - fallback: box TranslateError::One { kind: TranslateErrorKind::Fluent { errs }, .. }, - } = &err - && let [ - FluentError::ResolverError(ResolverError::Reference( - ReferenceKind::Message { id, .. } | ReferenceKind::Variable { id, .. }, - )), - ] = &**errs - && id == "name" - { - } else { - panic!("{err:#?}") - }; - assert_eq!( - format!("{err}"), - "failed while formatting fluent string `mir_build_borrow_of_moved_value`: \nargument `name` exists but was not referenced correctly\nhelp: try using `{$name}` instead\n" - ); - } - - { - let message = DiagMessage::FluentIdentifier( - "mir_build_borrow_of_moved_value".into(), - Some("occurs_because_label".into()), - ); - - let err = translator.translate_message(&message, &args).unwrap_err(); - if let TranslateError::Two { - primary: box TranslateError::One { kind: TranslateErrorKind::PrimaryBundleMissing, .. }, - fallback: box TranslateError::One { kind: TranslateErrorKind::Fluent { errs }, .. }, - } = &err - && let [ - FluentError::ResolverError(ResolverError::Reference( - ReferenceKind::Message { id, .. } | ReferenceKind::Variable { id, .. }, - )), - ] = &**errs - && id == "oops" - { - } else { - panic!("{err:#?}") - }; - assert_eq!( - format!("{err}"), - "failed while formatting fluent string `mir_build_borrow_of_moved_value`: \nthe fluent string has an argument `oops` that was not found.\nhelp: the arguments `name` and `ty` are available\n" - ); - } -} From 0f3108327b7679e13da6e07957508a1ab3ce2043 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Feb 2026 13:53:29 +1100 Subject: [PATCH 710/978] Streamline `rustc_span::HashStableContext`. Currently this trait has five methods. But it only really needs three. For example, currently stable hashing of spans is implemented in `rustc_span`, except a couple of sub-operations are delegated to `rustc_query_system`: `def_span` and `span_data_to_lines_and_cols`. These two delegated sub-operations can be reduced to a single delegated operation that does the full hash computation. Likewise, `assert_default_hashing_controls` depends on two delegated sub-operations, `hashing_controls` and `unstable_opts_incremental_ignore_spans`, and can be simplified. I find the resulting code simpler and clearer -- when necessary, we do a whole operation in `rustc_query_system` instead of doing it partly in `rustc_span` and partly in `rustc_query_system`. --- compiler/rustc_query_system/src/ich/hcx.rs | 126 ++++++++++++++++++--- compiler/rustc_span/src/hygiene.rs | 29 +---- compiler/rustc_span/src/lib.rs | 102 ++--------------- 3 files changed, 121 insertions(+), 136 deletions(-) diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs index 397ec7994f18..2e118dc3359f 100644 --- a/compiler/rustc_query_system/src/ich/hcx.rs +++ b/compiler/rustc_query_system/src/ich/hcx.rs @@ -1,10 +1,12 @@ -use rustc_data_structures::stable_hasher::HashingControls; +use std::hash::Hash; + +use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::definitions::DefPathHash; use rustc_session::Session; use rustc_session::cstore::Untracked; use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, CachingSourceMapView, DUMMY_SP, SourceFile, Span, SpanData}; +use rustc_span::{CachingSourceMapView, DUMMY_SP, Pos, Span}; // Very often, we are hashing something that does not need the `CachingSourceMapView`, so we // initialize it lazily. @@ -60,6 +62,11 @@ impl<'a> StableHashingContext<'a> { } } + #[inline] + fn def_span(&self, def_id: LocalDefId) -> Span { + self.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP) + } + #[inline] pub fn hashing_controls(&self) -> HashingControls { self.hashing_controls @@ -67,9 +74,88 @@ impl<'a> StableHashingContext<'a> { } impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { + /// Hashes a span in a stable way. We can't directly hash the span's `BytePos` fields (that + /// would be similar to hashing pointers, since those are just offsets into the `SourceMap`). + /// Instead, we hash the (file name, line, column) triple, which stays the same even if the + /// containing `SourceFile` has moved within the `SourceMap`. + /// + /// Also note that we are hashing byte offsets for the column, not unicode codepoint offsets. + /// For the purpose of the hash that's sufficient. Also, hashing filenames is expensive so we + /// avoid doing it twice when the span starts and ends in the same file, which is almost always + /// the case. + /// + /// IMPORTANT: changes to this method should be reflected in implementations of `SpanEncoder`. #[inline] - fn unstable_opts_incremental_ignore_spans(&self) -> bool { - self.incremental_ignore_spans + fn span_hash_stable(&mut self, span: Span, hasher: &mut StableHasher) { + const TAG_VALID_SPAN: u8 = 0; + const TAG_INVALID_SPAN: u8 = 1; + const TAG_RELATIVE_SPAN: u8 = 2; + + if !self.hashing_controls().hash_spans { + return; + } + + let span = span.data_untracked(); + span.ctxt.hash_stable(self, hasher); + span.parent.hash_stable(self, hasher); + + if span.is_dummy() { + Hash::hash(&TAG_INVALID_SPAN, hasher); + return; + } + + let parent = span.parent.map(|parent| self.def_span(parent).data_untracked()); + if let Some(parent) = parent + && parent.contains(span) + { + // This span is enclosed in a definition: only hash the relative position. This catches + // a subset of the cases from the `file.contains(parent.lo)`. But we can do this check + // cheaply without the expensive `span_data_to_lines_and_cols` query. + Hash::hash(&TAG_RELATIVE_SPAN, hasher); + (span.lo - parent.lo).to_u32().hash_stable(self, hasher); + (span.hi - parent.lo).to_u32().hash_stable(self, hasher); + return; + } + + // If this is not an empty or invalid span, we want to hash the last position that belongs + // to it, as opposed to hashing the first position past it. + let Some((file, line_lo, col_lo, line_hi, col_hi)) = + self.source_map().span_data_to_lines_and_cols(&span) + else { + Hash::hash(&TAG_INVALID_SPAN, hasher); + return; + }; + + if let Some(parent) = parent + && file.contains(parent.lo) + { + // This span is relative to another span in the same file, + // only hash the relative position. + Hash::hash(&TAG_RELATIVE_SPAN, hasher); + Hash::hash(&(span.lo.0.wrapping_sub(parent.lo.0)), hasher); + Hash::hash(&(span.hi.0.wrapping_sub(parent.lo.0)), hasher); + return; + } + + Hash::hash(&TAG_VALID_SPAN, hasher); + Hash::hash(&file.stable_id, hasher); + + // Hash both the length and the end location (line/column) of a span. If we hash only the + // length, for example, then two otherwise equal spans with different end locations will + // have the same hash. This can cause a problem during incremental compilation wherein a + // previous result for a query that depends on the end location of a span will be + // incorrectly reused when the end location of the span it depends on has changed (see + // issue #74890). A similar analysis applies if some query depends specifically on the + // length of the span, but we only hash the end location. So hash both. + + let col_lo_trunc = (col_lo.0 as u64) & 0xFF; + let line_lo_trunc = ((line_lo as u64) & 0xFF_FF_FF) << 8; + let col_hi_trunc = (col_hi.0 as u64) & 0xFF << 32; + let line_hi_trunc = ((line_hi as u64) & 0xFF_FF_FF) << 40; + let col_line = col_lo_trunc | line_lo_trunc | col_hi_trunc | line_hi_trunc; + let len = (span.hi - span.lo).0; + Hash::hash(&col_line, hasher); + Hash::hash(&len, hasher); } #[inline] @@ -81,22 +167,26 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { } } + /// Assert that the provided `HashStableContext` is configured with the default + /// `HashingControls`. We should always have bailed out before getting to here with a + /// non-default mode. With this check in place, we can avoid the need to maintain separate + /// versions of `ExpnData` hashes for each permutation of `HashingControls` settings. #[inline] - fn def_span(&self, def_id: LocalDefId) -> Span { - self.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP) - } + fn assert_default_hashing_controls(&self, msg: &str) { + let hashing_controls = self.hashing_controls; + let HashingControls { hash_spans } = hashing_controls; - #[inline] - fn span_data_to_lines_and_cols( - &mut self, - span: &SpanData, - ) -> Option<(&SourceFile, usize, BytePos, usize, BytePos)> { - self.source_map().span_data_to_lines_and_cols(span) - } - - #[inline] - fn hashing_controls(&self) -> HashingControls { - self.hashing_controls + // Note that we require that `hash_spans` be the inverse of the global `-Z + // incremental-ignore-spans` option. Normally, this option is disabled, in which case + // `hash_spans` must be true. + // + // Span hashing can also be disabled without `-Z incremental-ignore-spans`. This is the + // case for instance when building a hash for name mangling. Such configuration must not be + // used for metadata. + assert_eq!( + hash_spans, !self.incremental_ignore_spans, + "Attempted hashing of {msg} with non-default HashingControls: {hashing_controls:?}" + ); } } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 07a85ad75daa..25834f03af5e 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -30,7 +30,7 @@ use std::{fmt, iter, mem}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lock; use rustc_data_structures::unhash::UnhashMap; use rustc_hashes::Hash64; @@ -126,29 +126,6 @@ rustc_index::newtype_index! { impl !Ord for LocalExpnId {} impl !PartialOrd for LocalExpnId {} -/// Assert that the provided `HashStableContext` is configured with the 'default' -/// `HashingControls`. We should always have bailed out before getting to here -/// with a non-default mode. With this check in place, we can avoid the need -/// to maintain separate versions of `ExpnData` hashes for each permutation -/// of `HashingControls` settings. -fn assert_default_hashing_controls(ctx: &impl HashStableContext, msg: &str) { - let hashing_controls = ctx.hashing_controls(); - let HashingControls { hash_spans } = hashing_controls; - - // Note that we require that `hash_spans` be the inverse of the global - // `-Z incremental-ignore-spans` option. Normally, this option is disabled, - // in which case `hash_spans` must be true. - // - // Span hashing can also be disabled without `-Z incremental-ignore-spans`. - // This is the case for instance when building a hash for name mangling. - // Such configuration must not be used for metadata. - assert_eq!( - hash_spans, - !ctx.unstable_opts_incremental_ignore_spans(), - "Attempted hashing of {msg} with non-default HashingControls: {hashing_controls:?}" - ); -} - /// A unique hash value associated to an expansion. #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)] pub struct ExpnHash(Fingerprint); @@ -1508,7 +1485,7 @@ pub fn raw_encode_syntax_context( fn update_disambiguator(expn_data: &mut ExpnData, mut ctx: impl HashStableContext) -> ExpnHash { // This disambiguator should not have been set yet. assert_eq!(expn_data.disambiguator, 0, "Already set disambiguator for ExpnData: {expn_data:?}"); - assert_default_hashing_controls(&ctx, "ExpnData (disambiguator)"); + ctx.assert_default_hashing_controls("ExpnData (disambiguator)"); let mut expn_hash = expn_data.hash_expn(&mut ctx); let disambiguator = HygieneData::with(|data| { @@ -1558,7 +1535,7 @@ impl HashStable for SyntaxContext { impl HashStable for ExpnId { fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - assert_default_hashing_controls(ctx, "ExpnId"); + ctx.assert_default_hashing_controls("ExpnId"); let hash = if *self == ExpnId::root() { // Avoid fetching TLS storage for a trivial often-used value. Fingerprint::ZERO diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 0ad80b9d7879..bececc548494 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -54,7 +54,6 @@ use hygiene::Transparency; pub use hygiene::{ DesugaringKind, ExpnData, ExpnHash, ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext, }; -use rustc_data_structures::stable_hasher::HashingControls; pub mod def_id; use def_id::{CrateNum, DefId, DefIndex, DefPathHash, LOCAL_CRATE, LocalDefId, StableCrateId}; pub mod edit_distance; @@ -2798,105 +2797,24 @@ impl InnerSpan { /// This is a hack to allow using the [`HashStable_Generic`] derive macro /// instead of implementing everything in rustc_middle. pub trait HashStableContext { + /// The main event: stable hashing of a span. + fn span_hash_stable(&mut self, span: Span, hasher: &mut StableHasher); + + /// Compute a `DefPathHash`. fn def_path_hash(&self, def_id: DefId) -> DefPathHash; - /// Accesses `sess.opts.unstable_opts.incremental_ignore_spans` since - /// we don't have easy access to a `Session` - fn unstable_opts_incremental_ignore_spans(&self) -> bool; - fn def_span(&self, def_id: LocalDefId) -> Span; - fn span_data_to_lines_and_cols( - &mut self, - span: &SpanData, - ) -> Option<(&SourceFile, usize, BytePos, usize, BytePos)>; - fn hashing_controls(&self) -> HashingControls; + + /// Assert that the provided `HashStableContext` is configured with the default + /// `HashingControls`. We should always have bailed out before getting to here with a + fn assert_default_hashing_controls(&self, msg: &str); } impl HashStable for Span where CTX: HashStableContext, { - /// Hashes a span in a stable way. We can't directly hash the span's `BytePos` - /// fields (that would be similar to hashing pointers, since those are just - /// offsets into the `SourceMap`). Instead, we hash the (file name, line, column) - /// triple, which stays the same even if the containing `SourceFile` has moved - /// within the `SourceMap`. - /// - /// Also note that we are hashing byte offsets for the column, not unicode - /// codepoint offsets. For the purpose of the hash that's sufficient. - /// Also, hashing filenames is expensive so we avoid doing it twice when the - /// span starts and ends in the same file, which is almost always the case. - /// - /// IMPORTANT: changes to this method should be reflected in implementations of `SpanEncoder`. fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - const TAG_VALID_SPAN: u8 = 0; - const TAG_INVALID_SPAN: u8 = 1; - const TAG_RELATIVE_SPAN: u8 = 2; - - if !ctx.hashing_controls().hash_spans { - return; - } - - let span = self.data_untracked(); - span.ctxt.hash_stable(ctx, hasher); - span.parent.hash_stable(ctx, hasher); - - if span.is_dummy() { - Hash::hash(&TAG_INVALID_SPAN, hasher); - return; - } - - let parent = span.parent.map(|parent| ctx.def_span(parent).data_untracked()); - if let Some(parent) = parent - && parent.contains(span) - { - // This span is enclosed in a definition: only hash the relative position. - // This catches a subset of the cases from the `file.contains(parent.lo)`, - // But we can do this check cheaply without the expensive `span_data_to_lines_and_cols` query. - Hash::hash(&TAG_RELATIVE_SPAN, hasher); - (span.lo - parent.lo).to_u32().hash_stable(ctx, hasher); - (span.hi - parent.lo).to_u32().hash_stable(ctx, hasher); - return; - } - - // If this is not an empty or invalid span, we want to hash the last - // position that belongs to it, as opposed to hashing the first - // position past it. - let Some((file, line_lo, col_lo, line_hi, col_hi)) = ctx.span_data_to_lines_and_cols(&span) - else { - Hash::hash(&TAG_INVALID_SPAN, hasher); - return; - }; - - if let Some(parent) = parent - && file.contains(parent.lo) - { - // This span is relative to another span in the same file, - // only hash the relative position. - Hash::hash(&TAG_RELATIVE_SPAN, hasher); - Hash::hash(&(span.lo.0.wrapping_sub(parent.lo.0)), hasher); - Hash::hash(&(span.hi.0.wrapping_sub(parent.lo.0)), hasher); - return; - } - - Hash::hash(&TAG_VALID_SPAN, hasher); - Hash::hash(&file.stable_id, hasher); - - // Hash both the length and the end location (line/column) of a span. If we - // hash only the length, for example, then two otherwise equal spans with - // different end locations will have the same hash. This can cause a problem - // during incremental compilation wherein a previous result for a query that - // depends on the end location of a span will be incorrectly reused when the - // end location of the span it depends on has changed (see issue #74890). A - // similar analysis applies if some query depends specifically on the length - // of the span, but we only hash the end location. So hash both. - - let col_lo_trunc = (col_lo.0 as u64) & 0xFF; - let line_lo_trunc = ((line_lo as u64) & 0xFF_FF_FF) << 8; - let col_hi_trunc = (col_hi.0 as u64) & 0xFF << 32; - let line_hi_trunc = ((line_hi as u64) & 0xFF_FF_FF) << 40; - let col_line = col_lo_trunc | line_lo_trunc | col_hi_trunc | line_hi_trunc; - let len = (span.hi - span.lo).0; - Hash::hash(&col_line, hasher); - Hash::hash(&len, hasher); + // `span_hash_stable` does all the work. + ctx.span_hash_stable(*self, hasher) } } From 842bed6f939f74c8c005bc223acb50e22464d108 Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Wed, 4 Feb 2026 20:32:49 +0000 Subject: [PATCH 711/978] Parse #[rustc_delayed_bug_from_inside_query] --- compiler/rustc_attr_parsing/src/attributes/test_attrs.rs | 9 +++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ compiler/rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_interface/src/passes.rs | 4 ++-- compiler/rustc_passes/src/check_attr.rs | 2 +- 6 files changed, 17 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 908941c2b335..504466d3795a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -190,3 +190,12 @@ impl SingleAttributeParser for RustcAbiParser { Some(AttributeKind::RustcAbi { attr_span: cx.attr_span, kind }) } } + +pub(crate) struct RustcDelayedBugFromInsideQueryParser; + +impl NoArgsAttributeParser for RustcDelayedBugFromInsideQueryParser { + const PATH: &[Symbol] = &[sym::rustc_delayed_bug_from_inside_query]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDelayedBugFromInsideQuery; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index ad39b0ec26d9..704a2f3c8d10 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -262,6 +262,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 79452913c259..ca1913faeea1 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1084,6 +1084,9 @@ pub enum AttributeKind { /// Represents `#[rustc_def_path]` RustcDefPath(Span), + /// Represents `#[rustc_delayed_bug_from_inside_query]` + RustcDelayedBugFromInsideQuery, + /// Represents `#[rustc_deny_explicit_impl]`. RustcDenyExplicitImpl(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index ba351d80544c..33661807e1a9 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -106,6 +106,7 @@ impl AttributeKind { RustcConstStabilityIndirect => No, RustcDeallocator => No, RustcDefPath(..) => No, + RustcDelayedBugFromInsideQuery => No, RustcDenyExplicitImpl(..) => No, RustcDummy => No, RustcDumpDefParents => No, diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index f5fb8031ab0f..fe406f79f8dc 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -18,11 +18,11 @@ use rustc_errors::timings::TimingSection; use rustc_expand::base::{ExtCtxt, LintStoreExpand}; use rustc_feature::Features; use rustc_fs_util::try_canonicalize; -use rustc_hir::Attribute; use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::{LOCAL_CRATE, StableCrateId, StableCrateIdMap}; use rustc_hir::definitions::Definitions; use rustc_hir::limit::Limit; +use rustc_hir::{Attribute, find_attr}; use rustc_incremental::setup_dep_graph; use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_store}; use rustc_metadata::EncodedMetadata; @@ -1227,7 +1227,7 @@ pub(crate) fn start_codegen<'tcx>( // Hook for tests. if let Some((def_id, _)) = tcx.entry_fn(()) - && tcx.has_attr(def_id, sym::rustc_delayed_bug_from_inside_query) + && find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcDelayedBugFromInsideQuery) { tcx.ensure_ok().trigger_delayed_bug(def_id); } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 6c4b76a08ad2..a67ee43a9b2e 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -301,6 +301,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcConstStabilityIndirect | AttributeKind::RustcDeallocator | AttributeKind::RustcDefPath(..) + | AttributeKind::RustcDelayedBugFromInsideQuery | AttributeKind::RustcDenyExplicitImpl(..) | AttributeKind::RustcDummy | AttributeKind::RustcDumpDefParents @@ -406,7 +407,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_mir | sym::rustc_outlives | sym::rustc_evaluate_where_clauses - | sym::rustc_delayed_bug_from_inside_query | sym::rustc_partition_reused | sym::rustc_partition_codegened | sym::rustc_expected_cgu_reuse From 76684962741d4647638d61b5466a4f0e4ca76258 Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Wed, 4 Feb 2026 20:51:17 +0000 Subject: [PATCH 712/978] Parse #[rustc_evaluate_where_clauses] --- .../src/attributes/test_attrs.rs | 15 +++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_hir_typeck/src/callee.rs | 8 ++++++-- compiler/rustc_passes/src/check_attr.rs | 2 +- 6 files changed, 27 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 504466d3795a..9effba39571c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -199,3 +199,18 @@ impl NoArgsAttributeParser for RustcDelayedBugFromInsideQueryParser const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDelayedBugFromInsideQuery; } + +pub(crate) struct RustcEvaluateWhereClausesParser; + +impl NoArgsAttributeParser for RustcEvaluateWhereClausesParser { + const PATH: &[Symbol] = &[sym::rustc_evaluate_where_clauses]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Trait { body: false })), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEvaluateWhereClauses; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 704a2f3c8d10..d714a6399b82 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -269,6 +269,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index ca1913faeea1..39f76002c419 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1114,6 +1114,9 @@ pub enum AttributeKind { /// Represents `#[rustc_effective_visibility]`. RustcEffectiveVisibility, + /// Represents `#[rustc_evaluate_where_clauses]` + RustcEvaluateWhereClauses, + /// Represents `#[rustc_has_incoherent_inherent_impls]` RustcHasIncoherentInherentImpls, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 33661807e1a9..0b223c82c9b7 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -116,6 +116,7 @@ impl AttributeKind { RustcDumpVtable(..) => No, RustcDynIncompatibleTrait(..) => No, RustcEffectiveVisibility => Yes, + RustcEvaluateWhereClauses => Yes, RustcHasIncoherentInherentImpls => Yes, RustcHiddenTypeOfOpaques => No, RustcIfThisChanged(..) => No, diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index d04bd6f2295a..e20d5cdf2889 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -3,9 +3,10 @@ use std::iter; use rustc_abi::{CanonAbi, ExternAbi}; use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey, inline_fluent}; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, HirId, LangItem}; +use rustc_hir::{self as hir, HirId, LangItem, find_attr}; use rustc_hir_analysis::autoderef::Autoderef; use rustc_infer::infer::BoundRegionConversionTime; use rustc_infer::traits::{Obligation, ObligationCause, ObligationCauseCode}; @@ -526,7 +527,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `#[rustc_evaluate_where_clauses]` trigger special output // to let us test the trait evaluation system. if self.has_rustc_attrs - && self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses) + && find_attr!( + self.tcx.get_all_attrs(def_id), + AttributeKind::RustcEvaluateWhereClauses + ) { let predicates = self.tcx.predicates_of(def_id); let predicates = predicates.instantiate(self.tcx, args); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index a67ee43a9b2e..47dce81b8f5a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -311,6 +311,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcDumpVtable(..) | AttributeKind::RustcDynIncompatibleTrait(..) | AttributeKind::RustcEffectiveVisibility + | AttributeKind::RustcEvaluateWhereClauses | AttributeKind::RustcHasIncoherentInherentImpls | AttributeKind::RustcHiddenTypeOfOpaques | AttributeKind::RustcIfThisChanged(..) @@ -406,7 +407,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_strict_coherence | sym::rustc_mir | sym::rustc_outlives - | sym::rustc_evaluate_where_clauses | sym::rustc_partition_reused | sym::rustc_partition_codegened | sym::rustc_expected_cgu_reuse From 6361d5f279058c287d8684b232df512fe2562512 Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Wed, 4 Feb 2026 21:32:14 +0000 Subject: [PATCH 713/978] Parse #[rustc_outlives] --- .../src/attributes/test_attrs.rs | 14 ++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ compiler/rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_hir_analysis/src/outlives/dump.rs | 4 +++- compiler/rustc_passes/src/check_attr.rs | 2 +- 6 files changed, 23 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 9effba39571c..18d700a20d31 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -214,3 +214,17 @@ impl NoArgsAttributeParser for RustcEvaluateWhereClausesParser { ]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEvaluateWhereClauses; } + +pub(crate) struct RustcOutlivesParser; + +impl NoArgsAttributeParser for RustcOutlivesParser { + const PATH: &[Symbol] = &[sym::rustc_outlives]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Struct), + Allow(Target::Enum), + Allow(Target::Union), + Allow(Target::TyAlias), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOutlives; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index d714a6399b82..f2d5d1c8c37e 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -283,6 +283,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 39f76002c419..4208da6ce722 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1192,6 +1192,9 @@ pub enum AttributeKind { /// Represents `#[rustc_offload_kernel]` RustcOffloadKernel, + /// Represents `#[rustc_outlives]` + RustcOutlives, + /// Represents `#[rustc_paren_sugar]`. RustcParenSugar(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 0b223c82c9b7..c87f31209ce5 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -142,6 +142,7 @@ impl AttributeKind { RustcObjcSelector { .. } => No, RustcObjectLifetimeDefault => No, RustcOffloadKernel => Yes, + RustcOutlives => No, RustcParenSugar(..) => No, RustcPassByValue(..) => Yes, RustcPassIndirectlyInNonRusticAbis(..) => No, diff --git a/compiler/rustc_hir_analysis/src/outlives/dump.rs b/compiler/rustc_hir_analysis/src/outlives/dump.rs index 4233896c3720..cf770a2561db 100644 --- a/compiler/rustc_hir_analysis/src/outlives/dump.rs +++ b/compiler/rustc_hir_analysis/src/outlives/dump.rs @@ -1,10 +1,12 @@ +use rustc_hir::attrs::AttributeKind; +use rustc_hir::find_attr; use rustc_middle::bug; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::sym; pub(crate) fn inferred_outlives(tcx: TyCtxt<'_>) { for id in tcx.hir_free_items() { - if !tcx.has_attr(id.owner_id, sym::rustc_outlives) { + if !find_attr!(tcx.get_all_attrs(id.owner_id), AttributeKind::RustcOutlives) { continue; } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 47dce81b8f5a..5f8e887675d0 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -334,6 +334,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcObjcClass { .. } | AttributeKind::RustcObjcSelector { .. } | AttributeKind::RustcOffloadKernel + | AttributeKind::RustcOutlives | AttributeKind::RustcParenSugar(..) | AttributeKind::RustcPassByValue (..) | AttributeKind::RustcPassIndirectlyInNonRusticAbis(..) @@ -406,7 +407,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_capture_analysis | sym::rustc_strict_coherence | sym::rustc_mir - | sym::rustc_outlives | sym::rustc_partition_reused | sym::rustc_partition_codegened | sym::rustc_expected_cgu_reuse From fb55b5dcf33c3f134a41851771c3b13710a8a048 Mon Sep 17 00:00:00 2001 From: Jonatan Lindh Date: Sun, 8 Feb 2026 13:20:13 +0100 Subject: [PATCH 714/978] diagnostics: fix ICE in closure signature mismatch This fixes the ICE by renaming conflicting arguments in the diagnostic. --- compiler/rustc_trait_selection/src/errors.rs | 8 ++--- .../closure-arg-borrow-ice-issue-152331.rs | 10 ++++++ ...closure-arg-borrow-ice-issue-152331.stderr | 32 +++++++++++++++++++ 3 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 tests/ui/closures/closure-arg-borrow-ice-issue-152331.rs create mode 100644 tests/ui/closures/closure-arg-borrow-ice-issue-152331.stderr diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index e0690b8a6245..c904eb83896d 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -153,10 +153,10 @@ impl Subdiagnostic for AdjustSignatureBorrow { fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { AdjustSignatureBorrow::Borrow { to_borrow } => { - diag.arg("len", to_borrow.len()); + diag.arg("borrow_len", to_borrow.len()); diag.multipart_suggestion_verbose( inline_fluent!( - "consider adjusting the signature so it borrows its {$len -> + "consider adjusting the signature so it borrows its {$borrow_len -> [one] argument *[other] arguments }" @@ -166,10 +166,10 @@ impl Subdiagnostic for AdjustSignatureBorrow { ); } AdjustSignatureBorrow::RemoveBorrow { remove_borrow } => { - diag.arg("len", remove_borrow.len()); + diag.arg("remove_borrow_len", remove_borrow.len()); diag.multipart_suggestion_verbose( inline_fluent!( - "consider adjusting the signature so it does not borrow its {$len -> + "consider adjusting the signature so it does not borrow its {$remove_borrow_len -> [one] argument *[other] arguments }" diff --git a/tests/ui/closures/closure-arg-borrow-ice-issue-152331.rs b/tests/ui/closures/closure-arg-borrow-ice-issue-152331.rs new file mode 100644 index 000000000000..261f8fedc38f --- /dev/null +++ b/tests/ui/closures/closure-arg-borrow-ice-issue-152331.rs @@ -0,0 +1,10 @@ +fn main() { + h2(|_: (), _: (), _: (), x: &_| {}); + //~^ ERROR type mismatch in closure arguments +} + +fn h2(_: F) +where + F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())), +{ +} diff --git a/tests/ui/closures/closure-arg-borrow-ice-issue-152331.stderr b/tests/ui/closures/closure-arg-borrow-ice-issue-152331.stderr new file mode 100644 index 000000000000..7cfc9f0576ec --- /dev/null +++ b/tests/ui/closures/closure-arg-borrow-ice-issue-152331.stderr @@ -0,0 +1,32 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-borrow-ice-issue-152331.rs:2:5 + | +LL | h2(|_: (), _: (), _: (), x: &_| {}); + | ^^^----------------------------^^^^ + | | | + | | found signature defined here + | expected due to this + | + = note: expected closure signature `for<'a, 't0> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'t0 (), for<'a, 'b> fn(&'a (), &'b ())) -> _` + found closure signature `fn((), (), (), &_) -> _` +note: required by a bound in `h2` + --> $DIR/closure-arg-borrow-ice-issue-152331.rs:8:8 + | +LL | fn h2(_: F) + | -- required by a bound in this function +LL | where +LL | F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `h2` +help: consider adjusting the signature so it borrows its arguments + | +LL | h2(|_: &(), _: (), _: &(), x: &_| {}); + | + + +help: consider adjusting the signature so it does not borrow its argument + | +LL - h2(|_: (), _: (), _: (), x: &_| {}); +LL + h2(|_: (), _: (), _: (), x: _| {}); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0631`. From 053f76e9f07c1e307cd343a59cff6ed3276fc4ad Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 8 Feb 2026 13:46:29 +0100 Subject: [PATCH 715/978] `cfg_select!`: allow optional comma after { /* ... */ } --- compiler/rustc_parse/src/parser/cfg_select.rs | 13 +++++--- tests/ui/macros/cfg_select.rs | 7 ++-- tests/ui/macros/cfg_select.stderr | 32 +++++++++---------- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_parse/src/parser/cfg_select.rs b/compiler/rustc_parse/src/parser/cfg_select.rs index 9692d2c70893..b12209f0b92e 100644 --- a/compiler/rustc_parse/src/parser/cfg_select.rs +++ b/compiler/rustc_parse/src/parser/cfg_select.rs @@ -7,14 +7,19 @@ use crate::exp; use crate::parser::{AttrWrapper, ForceCollect, Parser, Restrictions, Trailing, UsePreAttrPos}; impl<'a> Parser<'a> { - /// Parses a `TokenTree` consisting either of `{ /* ... */ }` (and strip the braces) or an - /// expression followed by a comma (and strip the comma). + /// Parses a `TokenTree` consisting either of `{ /* ... */ }` optionally followed by a comma + /// (and strip the braces and the optional comma) or an expression followed by a comma + /// (and strip the comma). pub fn parse_delimited_token_tree(&mut self) -> PResult<'a, TokenStream> { if self.token == token::OpenBrace { // Strip the outer '{' and '}'. match self.parse_token_tree() { - TokenTree::Token(..) => unreachable!("because of the expect above"), - TokenTree::Delimited(.., tts) => return Ok(tts), + TokenTree::Token(..) => unreachable!("because the current token is a '{{'"), + TokenTree::Delimited(.., tts) => { + // Optionally end with a comma. + let _ = self.eat(exp!(Comma)); + return Ok(tts); + } } } let expr = self.collect_tokens(None, AttrWrapper::empty(), ForceCollect::Yes, |p, _| { diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs index 0f009756e211..693e27daad7a 100644 --- a/tests/ui/macros/cfg_select.rs +++ b/tests/ui/macros/cfg_select.rs @@ -34,6 +34,7 @@ fn arm_rhs_expr_3() -> i32 { any(true) => 1, any(false) => 2, any(true) => { 42 } + any(true) => { 42 }, any(false) => -1 as i32, any(true) => 2 + 2, any(false) => "", @@ -62,7 +63,7 @@ fn expand_to_statements() -> i32 { } type ExpandToType = cfg_select! { - unix => u32, + unix => { u32 }, _ => i32, }; @@ -113,7 +114,7 @@ impl T for S { cfg_select! { false => { fn a() {} - } + }, _ => { fn b() {} } @@ -145,7 +146,7 @@ cfg_select! { cfg_select! { unix => {} - not(unix) => {} + not(unix) => {}, _ => {} //~^ WARN unreachable configuration predicate } diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index 5878708668d3..2da0c2169497 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -1,5 +1,5 @@ error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:161:1 + --> $DIR/cfg_select.rs:162:1 | LL | / cfg_select! { LL | | @@ -8,55 +8,55 @@ LL | | } | |_^ error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:166:1 + --> $DIR/cfg_select.rs:167:1 | LL | cfg_select! {} | ^^^^^^^^^^^^^^ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `=>` - --> $DIR/cfg_select.rs:170:5 + --> $DIR/cfg_select.rs:171:5 | LL | => {} | ^^ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression - --> $DIR/cfg_select.rs:175:5 + --> $DIR/cfg_select.rs:176:5 | LL | () => {} | ^^ expressions are not allowed here error[E0539]: malformed `cfg_select` macro input - --> $DIR/cfg_select.rs:180:5 + --> $DIR/cfg_select.rs:181:5 | LL | "str" => {} | ^^^^^ expected a valid identifier here error[E0539]: malformed `cfg_select` macro input - --> $DIR/cfg_select.rs:185:5 + --> $DIR/cfg_select.rs:186:5 | LL | a::b => {} | ^^^^ expected a valid identifier here error[E0537]: invalid predicate `a` - --> $DIR/cfg_select.rs:190:5 + --> $DIR/cfg_select.rs:191:5 | LL | a() => {} | ^^^ error: expected one of `(`, `::`, `=>`, or `=`, found `+` - --> $DIR/cfg_select.rs:195:7 + --> $DIR/cfg_select.rs:196:7 | LL | a + 1 => {} | ^ expected one of `(`, `::`, `=>`, or `=` error: expected one of `(`, `::`, `=>`, or `=`, found `!` - --> $DIR/cfg_select.rs:201:8 + --> $DIR/cfg_select.rs:202:8 | LL | cfg!() => {} | ^ expected one of `(`, `::`, `=>`, or `=` warning: unreachable configuration predicate - --> $DIR/cfg_select.rs:136:5 + --> $DIR/cfg_select.rs:137:5 | LL | _ => {} | - always matches @@ -70,7 +70,7 @@ LL | #![warn(unreachable_cfg_select_predicates)] // Unused warnings are disabled | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unreachable configuration predicate - --> $DIR/cfg_select.rs:142:5 + --> $DIR/cfg_select.rs:143:5 | LL | true => {} | ---- always matches @@ -78,25 +78,25 @@ LL | _ => {} | ^ this configuration predicate is never reached warning: unreachable configuration predicate - --> $DIR/cfg_select.rs:149:5 + --> $DIR/cfg_select.rs:150:5 | LL | _ => {} | ^ this configuration predicate is never reached warning: unreachable configuration predicate - --> $DIR/cfg_select.rs:155:5 + --> $DIR/cfg_select.rs:156:5 | LL | test => {} | ^^^^ this configuration predicate is never reached warning: unreachable configuration predicate - --> $DIR/cfg_select.rs:157:5 + --> $DIR/cfg_select.rs:158:5 | LL | _ => {} | ^ this configuration predicate is never reached warning: unexpected `cfg` condition name: `a` - --> $DIR/cfg_select.rs:195:5 + --> $DIR/cfg_select.rs:196:5 | LL | a + 1 => {} | ^ help: found config with similar value: `target_feature = "a"` @@ -107,7 +107,7 @@ LL | a + 1 => {} = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `cfg` - --> $DIR/cfg_select.rs:201:5 + --> $DIR/cfg_select.rs:202:5 | LL | cfg!() => {} | ^^^ From f693a1df2b5fd345f73f78ac674c6b8c67314d61 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 8 Feb 2026 14:12:42 +0100 Subject: [PATCH 716/978] Update diagnostics documentation --- .../src/diagnostics/diagnostic-structs.md | 173 ++++++------------ 1 file changed, 53 insertions(+), 120 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md index 4e5c3413cb8a..2260b1ec4df1 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md @@ -12,7 +12,7 @@ customizing the rendering logic, or selecting messages at runtime, you will need the corresponding trait (`Diagnostic`, `LintDiagnostic`, or `Subdiagnostic`). This approach provides greater flexibility and is recommended for diagnostics that go beyond simple, static structures. -Diagnostic can be translated into different languages and each has a slug that uniquely identifies the diagnostic. +Diagnostic can be translated into different languages. ## `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` @@ -21,13 +21,13 @@ shown below: ```rust,ignore #[derive(Diagnostic)] -#[diag(hir_analysis_field_already_declared, code = E0124)] +#[diag("field `{$field_name}` is already declared", code = E0124)] pub struct FieldAlreadyDeclared { pub field_name: Ident, #[primary_span] - #[label] + #[label("field already declared")] pub span: Span, - #[label(previous_decl_label)] + #[label("`{$field_name}` first declared here")] pub prev_span: Span, } ``` @@ -42,25 +42,10 @@ the `code` sub-attribute. Specifying a `code` isn't mandatory, but if you are porting a diagnostic that uses `Diag` to use `Diagnostic` then you should keep the code if there was one. -`#[diag(..)]` must provide a slug as the first positional argument (a path to an -item in `rustc_errors::fluent::*`). A slug uniquely identifies the diagnostic -and is also how the compiler knows what error message to emit (in the default -locale of the compiler, or in the locale requested by the user). See +`#[diag(..)]` must provide a message as the first positional argument. +The message is written in English, but might be translated to the locale requested by the user. See [translation documentation](./translation.md) to learn more about how -translatable error messages are written and how slug items are generated. - -In our example, the Fluent message for the "field already declared" diagnostic -looks like this: - -```fluent -hir_analysis_field_already_declared = - field `{$field_name}` is already declared - .label = field already declared - .previous_decl_label = `{$field_name}` first declared here -``` - -`hir_analysis_field_already_declared` is the slug from our example and is followed -by the diagnostic message. +translatable error messages are written and how they are generated. Every field of the `Diagnostic` which does not have an annotation is available in Fluent messages as a variable, like `field_name` in the example @@ -76,13 +61,7 @@ specified on a `Diagnostic`. `#[label]`, `#[help]`, `#[warning]` and `#[note]` can all be applied to fields which have the type `Span`. Applying any of these attributes will create the corresponding -subdiagnostic with that `Span`. These attributes will look for their -diagnostic message in a Fluent attribute attached to the primary Fluent -message. In our example, `#[label]` will look for -`hir_analysis_field_already_declared.label` (which has the message "field already -declared"). If there is more than one subdiagnostic of the same type, then -these attributes can also take a value that is the attribute name to look for -(e.g. `previous_decl_label` in our example). +subdiagnostic with that `Span`. These attributes take a diagnostic message as an argument. Other types have special behavior when used in a `Diagnostic` derive: @@ -99,17 +78,17 @@ represent optional `#[note]`/`#[help]`/`#[warning]` subdiagnostics. Suggestions can be emitted using one of four field attributes: -- `#[suggestion(slug, code = "...", applicability = "...")]` -- `#[suggestion_hidden(slug, code = "...", applicability = "...")]` -- `#[suggestion_short(slug, code = "...", applicability = "...")]` -- `#[suggestion_verbose(slug, code = "...", applicability = "...")]` +- `#[suggestion("message", code = "...", applicability = "...")]` +- `#[suggestion_hidden("message", code = "...", applicability = "...")]` +- `#[suggestion_short("message", code = "...", applicability = "...")]` +- `#[suggestion_verbose("message", code = "...", applicability = "...")]` Suggestions must be applied on either a `Span` field or a `(Span, -MachineApplicability)` field. Similarly to other field attributes, the slug -specifies the Fluent attribute with the message and defaults to the equivalent -of `.suggestion`. `code` specifies the code that should be suggested as a +MachineApplicability)` field. Similarly to other field attributes, a message +needs to be provided which will be shown to the user. +`code` specifies the code that should be suggested as a replacement and is a format string (e.g. `{field_name}` would be replaced by -the value of the `field_name` field of the struct), not a Fluent identifier. +the value of the `field_name` field of the struct). `applicability` can be used to specify the applicability in the attribute, it cannot be used when the field's type contains an `Applicability`. @@ -119,15 +98,15 @@ In the end, the `Diagnostic` derive will generate an implementation of ```rust,ignore impl<'a, G: EmissionGuarantee> Diagnostic<'a> for FieldAlreadyDeclared { fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> { - let mut diag = Diag::new(dcx, level, fluent::hir_analysis_field_already_declared); + let mut diag = Diag::new(dcx, level, "field `{$field_name}` is already declared"); diag.set_span(self.span); diag.span_label( self.span, - fluent::hir_analysis_label + "field already declared" ); diag.span_label( self.prev_span, - fluent::hir_analysis_previous_decl_label + "`{$field_name}` first declared here" ); diag } @@ -150,60 +129,40 @@ tcx.dcx().emit_err(FieldAlreadyDeclared { `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` support the following attributes: -- `#[diag(slug, code = "...")]` +- `#[diag("message", code = "...")]` - _Applied to struct or enum variant._ - _Mandatory_ - Defines the text and error code to be associated with the diagnostic. - - Slug (_Mandatory_) - - Uniquely identifies the diagnostic and corresponds to its Fluent message, - mandatory. - - A path to an item in `rustc_errors::fluent`, e.g. - `rustc_errors::fluent::hir_analysis_field_already_declared` - (`rustc_errors::fluent` is implicit in the attribute, so just - `hir_analysis_field_already_declared`). + - Message (_Mandatory_) + - The diagnostic message which will be shown to the user. - See [translation documentation](./translation.md). - `code = "..."` (_Optional_) - Specifies the error code. -- `#[note]` or `#[note(slug)]` (_Optional_) +- `#[note("message")]` (_Optional_) - _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._ - Adds a note subdiagnostic. - - Value is a path to an item in `rustc_errors::fluent` for the note's - message. - - Defaults to equivalent of `.note`. + - Value is the note's message. - If applied to a `Span` field, creates a spanned note. -- `#[help]` or `#[help(slug)]` (_Optional_) +- `#[help("message")]` (_Optional_) - _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._ - Adds a help subdiagnostic. - - Value is a path to an item in `rustc_errors::fluent` for the note's - message. - - Defaults to equivalent of `.help`. + - Value is the help message. - If applied to a `Span` field, creates a spanned help. -- `#[label]` or `#[label(slug)]` (_Optional_) +- `#[label("message")]` (_Optional_) - _Applied to `Span` fields._ - Adds a label subdiagnostic. - - Value is a path to an item in `rustc_errors::fluent` for the note's - message. - - Defaults to equivalent of `.label`. -- `#[warning]` or `#[warning(slug)]` (_Optional_) + - Value is the label's message. +- `#[warning("message")]` (_Optional_) - _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._ - Adds a warning subdiagnostic. - - Value is a path to an item in `rustc_errors::fluent` for the note's - message. - - Defaults to equivalent of `.warn`. -- `#[suggestion{,_hidden,_short,_verbose}(slug, code = "...", applicability = "...")]` + - Value is the warning's message. +- `#[suggestion{,_hidden,_short,_verbose}("message", code = "...", applicability = "...")]` (_Optional_) - _Applied to `(Span, MachineApplicability)` or `Span` fields._ - Adds a suggestion subdiagnostic. - - Slug (_Mandatory_) - - A path to an item in `rustc_errors::fluent`, e.g. - `rustc_errors::fluent::hir_analysis_field_already_declared` - (`rustc_errors::fluent` is implicit in the attribute, so just - `hir_analysis_field_already_declared`). Fluent attributes for all messages - exist as top-level items in that module (so `hir_analysis_message.attr` is just - `attr`). + - Message (_Mandatory_) + - Value is the suggestion message that will be shown to the user. - See [translation documentation](./translation.md). - - Defaults to `rustc_errors::fluent::_subdiag::suggestion` (or - - `.suggestion` in Fluent). - `code = "..."`/`code("...", ...)` (_Mandatory_) - One or multiple format strings indicating the code to be suggested as a replacement. Multiple values signify multiple possible replacements. @@ -235,12 +194,12 @@ shown below: ```rust #[derive(Subdiagnostic)] pub enum ExpectedReturnTypeLabel<'tcx> { - #[label(hir_analysis_expected_default_return_type)] + #[label("expected `()` because of default return type")] Unit { #[primary_span] span: Span, }, - #[label(hir_analysis_expected_return_type)] + #[label("expected `{$expected}` because of return type")] Other { #[primary_span] span: Span, @@ -260,21 +219,9 @@ attribute applied to the struct or each variant, one of: - `#[warning(..)]` for defining a warning - `#[suggestion{,_hidden,_short,_verbose}(..)]` for defining a suggestion -All of the above must provide a slug as the first positional argument (a path -to an item in `rustc_errors::fluent::*`). A slug uniquely identifies the -diagnostic and is also how the compiler knows what error message to emit (in -the default locale of the compiler, or in the locale requested by the user). +All of the above must provide a diagnostic message as the first positional argument. See [translation documentation](./translation.md) to learn more about how -translatable error messages are written and how slug items are generated. - -In our example, the Fluent message for the "expected return type" label -looks like this: - -```fluent -hir_analysis_expected_default_return_type = expected `()` because of default return type - -hir_analysis_expected_return_type = expected `{$expected}` because of return type -``` +translatable error messages are generated. Using the `#[primary_span]` attribute on a field (with type `Span`) will denote the primary span of the subdiagnostic. A primary span is only necessary for a @@ -289,17 +236,15 @@ Like `Diagnostic`, `Subdiagnostic` supports `Option` and Suggestions can be emitted using one of four attributes on the type/variant: -- `#[suggestion(..., code = "...", applicability = "...")]` -- `#[suggestion_hidden(..., code = "...", applicability = "...")]` -- `#[suggestion_short(..., code = "...", applicability = "...")]` -- `#[suggestion_verbose(..., code = "...", applicability = "...")]` +- `#[suggestion("...", code = "...", applicability = "...")]` +- `#[suggestion_hidden("...", code = "...", applicability = "...")]` +- `#[suggestion_short("...", code = "...", applicability = "...")]` +- `#[suggestion_verbose("...", code = "...", applicability = "...")]` Suggestions require `#[primary_span]` be set on a field and can have the following sub-attributes: -- The first positional argument specifies the path to a item in - `rustc_errors::fluent` corresponding to the Fluent attribute with the message - and defaults to the equivalent of `.suggestion`. +- The first positional argument specifies the message which will be shown to the user. - `code` specifies the code that should be suggested as a replacement and is a format string (e.g. `{field_name}` would be replaced by the value of the `field_name` field of the struct), not a Fluent identifier. @@ -318,11 +263,11 @@ impl<'tcx> Subdiagnostic for ExpectedReturnTypeLabel<'tcx> { use rustc_errors::{Applicability, IntoDiagArg}; match self { ExpectedReturnTypeLabel::Unit { span } => { - diag.span_label(span, rustc_errors::fluent::hir_analysis_expected_default_return_type) + diag.span_label(span, "expected `()` because of default return type") } ExpectedReturnTypeLabel::Other { span, expected } => { diag.set_arg("expected", expected); - diag.span_label(span, rustc_errors::fluent::hir_analysis_expected_return_type) + diag.span_label(span, "expected `{$expected}` because of return type") } } } @@ -354,7 +299,7 @@ If a subdiagnostic sets a argument with the same name as a arguments already in it will report an error at runtime unless both have exactly the same value. It has two benefits: - preserves the flexibility that arguments in the main diagnostic are allowed to appear in the attributes of the subdiagnostic. -For example, There is an attribute `#[suggestion(code = "{new_vis}")]` in the subdiagnostic, but `new_vis` is the field in the main diagnostic struct. +For example, There is an attribute `#[suggestion("...", code = "{new_vis}")]` in the subdiagnostic, but `new_vis` is the field in the main diagnostic struct. - prevents accidental overwriting or deletion of arguments required by the main diagnostic or other subdiagnostics. These rules guarantee that arguments injected by subdiagnostics are strictly scoped to their own rendering. @@ -364,32 +309,20 @@ Additionally, subdiagnostics can access arguments from the main diagnostic with ### Reference for `#[derive(Subdiagnostic)]` `#[derive(Subdiagnostic)]` supports the following attributes: -- `#[label(slug)]`, `#[help(slug)]`, `#[warning(slug)]` or `#[note(slug)]` +- `#[label("message")]`, `#[help("message")]`, `#[warning("message")]` or `#[note("message")]` - _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._ - _Mandatory_ - Defines the type to be representing a label, help or note. - - Slug (_Mandatory_) - - Uniquely identifies the diagnostic and corresponds to its Fluent message, - mandatory. - - A path to an item in `rustc_errors::fluent`, e.g. - `rustc_errors::fluent::hir_analysis_field_already_declared` - (`rustc_errors::fluent` is implicit in the attribute, so just - `hir_analysis_field_already_declared`). + - Message (_Mandatory_) + - The diagnostic message that will be shown to the user. - See [translation documentation](./translation.md). -- `#[suggestion{,_hidden,_short,_verbose}(slug, code = "...", applicability = "...")]` +- `#[suggestion{,_hidden,_short,_verbose}("message", code = "...", applicability = "...")]` - _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._ - _Mandatory_ - Defines the type to be representing a suggestion. - - Slug (_Mandatory_) - - A path to an item in `rustc_errors::fluent`, e.g. - `rustc_errors::fluent::hir_analysis_field_already_declared` - (`rustc_errors::fluent` is implicit in the attribute, so just - `hir_analysis::field_already_declared`). Fluent attributes for all messages - exist as top-level items in that module (so `hir_analysis_message.attr` is just - `hir_analysis::attr`). + - Message (_Mandatory_) + - The diagnostic message that will be shown to the user. - See [translation documentation](./translation.md). - - Defaults to `rustc_errors::fluent::_subdiag::suggestion` (or - - `.suggestion` in Fluent). - `code = "..."`/`code("...", ...)` (_Mandatory_) - One or multiple format strings indicating the code to be suggested as a replacement. Multiple values signify multiple possible replacements. @@ -401,11 +334,11 @@ Additionally, subdiagnostics can access arguments from the main diagnostic with - `maybe-incorrect` - `has-placeholders` - `unspecified` -- `#[multipart_suggestion{,_hidden,_short,_verbose}(slug, applicability = "...")]` +- `#[multipart_suggestion{,_hidden,_short,_verbose}("message", applicability = "...")]` - _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._ - _Mandatory_ - Defines the type to be representing a multipart suggestion. - - Slug (_Mandatory_): see `#[suggestion]` + - Message (_Mandatory_): see `#[suggestion]` - `applicability = "..."` (_Optional_): see `#[suggestion]` - `#[primary_span]` (_Mandatory_ for labels and suggestions; _optional_ otherwise; not applicable to multipart suggestions) From 37a314b719af622c982c29fad4aeb992f5068035 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 8 Feb 2026 14:12:46 +0100 Subject: [PATCH 717/978] Update translation documentation --- .../src/diagnostics/translation.md | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/diagnostics/translation.md b/src/doc/rustc-dev-guide/src/diagnostics/translation.md index 58d75f54a005..fcb26fab667c 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/translation.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/translation.md @@ -13,10 +13,7 @@ active redesign proposals (as of Please see the tracking issue for status updates. -We have downgraded the internal lints `untranslatable_diagnostic` and -`diagnostic_outside_of_impl`. Those internal lints previously required new code -to use the current translation infrastructure. However, because the translation -infra is waiting for a yet-to-be-proposed redesign and thus rework, we are not +The translation infra is waiting for a yet-to-be-proposed redesign and thus rework, we are not mandating usage of current translation infra. Use the infra if you *want to* or otherwise makes the code cleaner, but otherwise sidestep the translation infra if you need more flexibility. @@ -40,11 +37,6 @@ There are two ways of writing translatable diagnostics: When adding or changing a translatable diagnostic, you don't need to worry about the translations. Only updating the original English message is required. -Currently, -each crate which defines translatable diagnostics has its own Fluent resource, -which is a file named `messages.ftl`, -located in the root of the crate -(such as`compiler/rustc_expand/messages.ftl`). ## Fluent @@ -118,11 +110,8 @@ information that needs to be provided by the code to do so. ### Compile-time validation and typed identifiers -rustc's `fluent_messages` macro performs compile-time validation of Fluent -resources and generates code to make it easier to refer to Fluent messages in -diagnostics. - -Compile-time validation of Fluent resources will emit any parsing errors +rustc's `#[derive(Diagnostic)]` macro performs compile-time validation of Fluent +messages. Compile-time validation of Fluent resources will emit any parsing errors from Fluent resources while building the compiler, preventing invalid Fluent resources from causing panics in the compiler. Compile-time validation also emits an error if multiple Fluent messages have the same identifier. From d8ff397cd69c50d735e3ff6e7e4cbfe18c1b01dc Mon Sep 17 00:00:00 2001 From: Adwin White Date: Sun, 8 Feb 2026 12:38:02 +0800 Subject: [PATCH 718/978] check stalled coroutine obligations eagerly --- compiler/rustc_borrowck/src/lib.rs | 5 +++++ compiler/rustc_interface/src/passes.rs | 18 +++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 361e98454e83..38b73a07a689 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -121,6 +121,11 @@ fn mir_borrowck( let (input_body, _) = tcx.mir_promoted(def); debug!("run query mir_borrowck: {}", tcx.def_path_str(def)); + // We should eagerly check stalled coroutine obligations from HIR typeck. + // Not doing so leads to silent normalization failures later, which will + // fail to register opaque types in the next solver. + tcx.check_coroutine_obligations(def)?; + let input_body: &Body<'_> = &input_body.borrow(); if let Some(guar) = input_body.tainted_by_errors { debug!("Skipping borrowck because of tainted body"); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 35f8c44b685d..23c59602d296 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1116,18 +1116,14 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { { tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id); } - if tcx.is_coroutine(def_id.to_def_id()) { - tcx.ensure_ok().mir_coroutine_witnesses(def_id); - let _ = tcx.ensure_ok().check_coroutine_obligations( - tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(), + if tcx.is_coroutine(def_id.to_def_id()) + && (!tcx.is_async_drop_in_place_coroutine(def_id.to_def_id())) + { + // Eagerly check the unsubstituted layout for cycles. + tcx.ensure_ok().layout_of( + ty::TypingEnv::post_analysis(tcx, def_id.to_def_id()) + .as_query_input(tcx.type_of(def_id).instantiate_identity()), ); - if !tcx.is_async_drop_in_place_coroutine(def_id.to_def_id()) { - // Eagerly check the unsubstituted layout for cycles. - tcx.ensure_ok().layout_of( - ty::TypingEnv::post_analysis(tcx, def_id.to_def_id()) - .as_query_input(tcx.type_of(def_id).instantiate_identity()), - ); - } } }); }); From 8aa0e905f4a1806a9406eb7c34e0c58157dc2856 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 8 Feb 2026 10:23:58 +0100 Subject: [PATCH 719/978] Fix suggestion on `CallToDeprecatedSafeFnRequiresUnsafe` diagnostic --- compiler/rustc_mir_build/src/errors.rs | 2 +- .../unsafe-before_exec-suggestion.fixed | 18 ++++++++++++++++ .../unsafe-before_exec-suggestion.rs | 17 +++++++++++++++ .../unsafe-before_exec-suggestion.stderr | 21 +++++++++++++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 tests/ui/rust-2024/unsafe-before_exec-suggestion.fixed create mode 100644 tests/ui/rust-2024/unsafe-before_exec-suggestion.rs create mode 100644 tests/ui/rust-2024/unsafe-before_exec-suggestion.stderr diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 13d8211999e6..2474b3c49a61 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -22,7 +22,7 @@ pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe { #[derive(Subdiagnostic)] #[multipart_suggestion( - "you can wrap the call in an `unsafe` block if you can guarantee that the environment access only happens in single-threaded code", + "you can wrap the call in an `unsafe` block if you can guarantee {$guarantee}", applicability = "machine-applicable" )] pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafeSub { diff --git a/tests/ui/rust-2024/unsafe-before_exec-suggestion.fixed b/tests/ui/rust-2024/unsafe-before_exec-suggestion.fixed new file mode 100644 index 000000000000..d850428cc1a5 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-before_exec-suggestion.fixed @@ -0,0 +1,18 @@ +//@ edition:2015 +//@ only-unix +//@ run-rustfix + +#![deny(deprecated_safe_2024)] + +use std::process::Command; +use std::os::unix::process::CommandExt; + +#[allow(deprecated)] +fn main() { + let mut cmd = Command::new("sleep"); + // TODO: Audit that the closure is async-signal-safe. + unsafe { cmd.before_exec(|| Ok(())) }; + //~^ ERROR call to deprecated safe function + //~| WARN this is accepted in the current edition + drop(cmd); +} diff --git a/tests/ui/rust-2024/unsafe-before_exec-suggestion.rs b/tests/ui/rust-2024/unsafe-before_exec-suggestion.rs new file mode 100644 index 000000000000..c6894ea631ae --- /dev/null +++ b/tests/ui/rust-2024/unsafe-before_exec-suggestion.rs @@ -0,0 +1,17 @@ +//@ edition:2015 +//@ only-unix +//@ run-rustfix + +#![deny(deprecated_safe_2024)] + +use std::process::Command; +use std::os::unix::process::CommandExt; + +#[allow(deprecated)] +fn main() { + let mut cmd = Command::new("sleep"); + cmd.before_exec(|| Ok(())); + //~^ ERROR call to deprecated safe function + //~| WARN this is accepted in the current edition + drop(cmd); +} diff --git a/tests/ui/rust-2024/unsafe-before_exec-suggestion.stderr b/tests/ui/rust-2024/unsafe-before_exec-suggestion.stderr new file mode 100644 index 000000000000..33893f30ceca --- /dev/null +++ b/tests/ui/rust-2024/unsafe-before_exec-suggestion.stderr @@ -0,0 +1,21 @@ +error: call to deprecated safe function `std::os::unix::process::CommandExt::before_exec` is unsafe and requires unsafe block + --> $DIR/unsafe-before_exec-suggestion.rs:13:5 + | +LL | cmd.before_exec(|| Ok(())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see +note: the lint level is defined here + --> $DIR/unsafe-before_exec-suggestion.rs:5:9 + | +LL | #![deny(deprecated_safe_2024)] + | ^^^^^^^^^^^^^^^^^^^^ +help: you can wrap the call in an `unsafe` block if you can guarantee that the closure is async-signal-safe + | +LL + // TODO: Audit that the closure is async-signal-safe. +LL ~ unsafe { cmd.before_exec(|| Ok(())) }; + | + +error: aborting due to 1 previous error + From d14c26f45a84eff6eabddd8c0e0580d851ade217 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 8 Feb 2026 10:24:07 +0100 Subject: [PATCH 720/978] Fix help on `AmbiguousMissingKwForItemSub` diagnostic --- compiler/rustc_parse/src/errors.rs | 4 +++- tests/ui/macros/metavar-expressions/usage-errors.rs | 2 ++ tests/ui/macros/metavar-expressions/usage-errors.stderr | 8 ++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 418d56f632bd..b54782ec592c 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2266,7 +2266,9 @@ pub(crate) enum AmbiguousMissingKwForItemSub { span: Span, snippet: String, }, - #[help("you likely meant to define an item, e.g., `{$vis} fn foo() {\"{}\"}`")] + #[help( + "if you meant to call a macro, remove the `pub` and add a trailing `!` after the identifier" + )] HelpMacro, } diff --git a/tests/ui/macros/metavar-expressions/usage-errors.rs b/tests/ui/macros/metavar-expressions/usage-errors.rs index feff02e2ce47..966ffadb32af 100644 --- a/tests/ui/macros/metavar-expressions/usage-errors.rs +++ b/tests/ui/macros/metavar-expressions/usage-errors.rs @@ -27,6 +27,7 @@ curly__rhs_dollar__no_round !(a); macro_rules! no_curly__no_rhs_dollar__round { ( $( $i:ident ),* ) => { count(i) }; //~^ ERROR missing `fn` or `struct` for function or struct definition + //~| HELP if you meant to call a macro, try } no_curly__no_rhs_dollar__round !(a, b, c); @@ -34,6 +35,7 @@ no_curly__no_rhs_dollar__round !(a, b, c); macro_rules! no_curly__no_rhs_dollar__no_round { ( $i:ident ) => { count(i) }; //~^ ERROR missing `fn` or `struct` for function or struct definition + //~| HELP if you meant to call a macro, try } no_curly__no_rhs_dollar__no_round !(a); diff --git a/tests/ui/macros/metavar-expressions/usage-errors.stderr b/tests/ui/macros/metavar-expressions/usage-errors.stderr index f66f522e23b9..3d22e3ac4b30 100644 --- a/tests/ui/macros/metavar-expressions/usage-errors.stderr +++ b/tests/ui/macros/metavar-expressions/usage-errors.stderr @@ -26,7 +26,7 @@ LL | ( $( $i:ident ),* ) => { count!(i) }; | + error: missing `fn` or `struct` for function or struct definition - --> $DIR/usage-errors.rs:35:23 + --> $DIR/usage-errors.rs:36:23 | LL | ( $i:ident ) => { count(i) }; | ^^^^^ @@ -41,13 +41,13 @@ LL | ( $i:ident ) => { count!(i) }; | + error: variable `i` is still repeating at this depth - --> $DIR/usage-errors.rs:42:36 + --> $DIR/usage-errors.rs:44:36 | LL | ( $( $i:ident ),* ) => { count($i) }; | ^^ error[E0425]: cannot find value `a` in this scope - --> $DIR/usage-errors.rs:52:49 + --> $DIR/usage-errors.rs:54:49 | LL | ( $i:ident ) => { count($i) }; | -- due to this macro variable @@ -56,7 +56,7 @@ LL | const _: u32 = no_curly__rhs_dollar__no_round! (a); | ^ not found in this scope error[E0425]: cannot find function `count` in this scope - --> $DIR/usage-errors.rs:49:23 + --> $DIR/usage-errors.rs:51:23 | LL | ( $i:ident ) => { count($i) }; | ^^^^^ not found in this scope From 4d07a8f24c42c4cb7362ea8c4db8cfca62a846b2 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 8 Feb 2026 12:29:59 -0500 Subject: [PATCH 721/978] std: Don't panic when removing a nonexistent UEFI var `std::env::remove_var` does not say that deleting a nonexistent variable is an error (and at least on Linux, it indeed does not cause an error). The UEFI Shell Protocol spec also doesn't say it's an error, but the edk2 implementation delegates to the UEFI runtime `SetVariable` function, which returns `EFI_NOT_FOUND` when trying to delete a nonexistent variable. Change the UEFI implementation to check for a `NotFound` error and treat it as success. --- library/std/src/sys/env/uefi.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/env/uefi.rs b/library/std/src/sys/env/uefi.rs index af16a02642a4..bc2aed423179 100644 --- a/library/std/src/sys/env/uefi.rs +++ b/library/std/src/sys/env/uefi.rs @@ -43,7 +43,20 @@ mod uefi_env { pub(crate) fn unset(key: &OsStr) -> io::Result<()> { let mut key_ptr = helpers::os_string_to_raw(key) .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?; - unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) } + let r = unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) }; + + // The UEFI Shell spec only lists `EFI_SUCCESS` as a possible return value for + // `SetEnv`, but the edk2 implementation can return errors. Allow most of these + // errors to bubble up to the caller, but ignore `NotFound` errors; deleting a + // nonexistent variable is not listed as an error condition of + // `std::env::remove_var`. + if let Err(err) = &r + && err.kind() == io::ErrorKind::NotFound + { + Ok(()) + } else { + r + } } pub(crate) fn get_all() -> io::Result> { From 9a30ec81498592914950d7a63253965e61d8cc05 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 7 Jan 2026 15:22:47 -0800 Subject: [PATCH 722/978] Implement MVP for opaque generic const arguments This is meant to be the interim successor to generic const expressions. Essentially, const item RHS's will be allowed to do arbitrary const operations using generics. The limitation is that these const items will be treated opaquely, like ADTs in nominal typing, such that uses of them will only be equal if the same const item is referenced. In other words, two const items with the exact same RHS will not be considered equal. I also added some logic to check feature gates that depend on others being enabled (like oGCA depending on mGCA). = Coherence = During coherence, OGCA consts should be normalized ambiguously because they are opaque but eventually resolved to a real value. We don't want two OGCAs that have the same value to be treated as distinct for coherence purposes. (Just like opaque types.) This actually doesn't work yet because there are pre-existing fundamental issues with equate relations involving consts that need to be normalized. The problem is that we normalize only one layer of the const item and don't actually process the resulting anon const. Normally the created inference variable should be handled, which in this case would cause us to hit the anon const, but that's not happening. Specifically, `visit_const` on `Generalizer` should be updated to be similar to `visit_ty`. --- compiler/rustc_ast_passes/src/errors.rs | 10 +++ compiler/rustc_ast_passes/src/feature_gate.rs | 22 +++++++ compiler/rustc_ast_passes/src/lib.rs | 1 + compiler/rustc_feature/src/lib.rs | 3 +- compiler/rustc_feature/src/unstable.rs | 8 +++ compiler/rustc_hir_analysis/src/collect.rs | 64 ++++++++++++++++++- .../src/collect/generics_of.rs | 2 + .../src/hir_ty_lowering/mod.rs | 5 ++ compiler/rustc_middle/src/ty/consts.rs | 15 +---- compiler/rustc_middle/src/ty/context.rs | 3 + compiler/rustc_middle/src/ty/mod.rs | 4 +- .../src/solve/normalizes_to/anon_const.rs | 15 ++++- compiler/rustc_parse/src/parser/item.rs | 4 +- compiler/rustc_span/src/symbol.rs | 1 + .../rustc_trait_selection/src/traits/mod.rs | 14 ++++ compiler/rustc_type_ir/src/const_kind.rs | 20 ++++++ compiler/rustc_type_ir/src/interner.rs | 1 + .../non_valtreeable_const_arg-2.rs | 2 +- .../non_valtreeable_const_arg-2.stderr | 6 +- .../associated-const-bindings/ambiguity.rs | 2 +- .../coexisting-with-type-binding.rs | 2 +- ...dyn-compat-assoc-const-ty-mentions-self.rs | 1 + ...compat-assoc-const-ty-mentions-self.stderr | 4 +- ...elf-const-projections-in-assoc-const-ty.rs | 13 +++- ...const-projections-in-assoc-const-ty.stderr | 8 +-- .../esc-bound-var-in-ty.rs | 1 + .../esc-bound-var-in-ty.stderr | 2 +- .../mgca/adt_expr_arg_simple.stderr | 2 + .../mgca/early-bound-param-lt-bad.stderr | 2 + .../mgca/explicit_anon_consts.stderr | 14 ++++ .../mgca/selftyalias-containing-param.stderr | 1 + .../ui/const-generics/mgca/selftyparam.stderr | 2 + .../size-of-generic-ptr-in-array-len.stderr | 2 + .../mgca/tuple_ctor_complex_args.stderr | 2 + .../mgca/tuple_expr_arg_complex.stderr | 2 + .../mgca/type_const-on-generic-expr.stderr | 4 ++ .../mgca/type_const-on-generic_expr-2.stderr | 6 ++ .../unbraced_const_block_const_arg_gated.rs | 1 - ...nbraced_const_block_const_arg_gated.stderr | 12 +--- tests/ui/const-generics/ogca/basic-fail.rs | 22 +++++++ .../ui/const-generics/ogca/basic-fail.stderr | 9 +++ tests/ui/const-generics/ogca/basic.rs | 22 +++++++ .../ogca/coherence-ambiguous.rs | 21 ++++++ .../const-generics/ogca/rhs-but-not-root.rs | 14 ++++ .../ogca/rhs-but-not-root.stderr | 8 +++ .../feature-gate-opaque-generic-const-args.rs | 9 +++ ...ture-gate-opaque-generic-const-args.stderr | 10 +++ .../assoc-const-no-infer-ice-115806.rs | 2 +- 48 files changed, 347 insertions(+), 53 deletions(-) create mode 100644 tests/ui/const-generics/ogca/basic-fail.rs create mode 100644 tests/ui/const-generics/ogca/basic-fail.stderr create mode 100644 tests/ui/const-generics/ogca/basic.rs create mode 100644 tests/ui/const-generics/ogca/coherence-ambiguous.rs create mode 100644 tests/ui/const-generics/ogca/rhs-but-not-root.rs create mode 100644 tests/ui/const-generics/ogca/rhs-but-not-root.stderr create mode 100644 tests/ui/feature-gates/feature-gate-opaque-generic-const-args.rs create mode 100644 tests/ui/feature-gates/feature-gate-opaque-generic-const-args.stderr diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index baf6f6beaeed..7282a5168213 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -950,6 +950,16 @@ pub(crate) struct IncompatibleFeatures { pub f2: Symbol, } +#[derive(Diagnostic)] +#[diag("`{$parent}` requires {$missing} to be enabled")] +#[help("enable all of these features")] +pub(crate) struct MissingDependentFeatures { + #[primary_span] + pub parent_span: Span, + pub parent: Symbol, + pub missing: String, +} + #[derive(Diagnostic)] #[diag("negative bounds are not supported")] pub(crate) struct NegativeBoundUnsupported { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 1b1bbb1564c4..ce9001d65931 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -441,6 +441,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { maybe_stage_features(sess, features, krate); check_incompatible_features(sess, features); + check_dependent_features(sess, features); check_new_solver_banned_features(sess, features); let mut visitor = PostExpansionVisitor { sess, features }; @@ -649,6 +650,27 @@ fn check_incompatible_features(sess: &Session, features: &Features) { } } +fn check_dependent_features(sess: &Session, features: &Features) { + for &(parent, children) in + rustc_feature::DEPENDENT_FEATURES.iter().filter(|(parent, _)| features.enabled(*parent)) + { + if children.iter().any(|f| !features.enabled(*f)) { + let parent_span = features + .enabled_features_iter_stable_order() + .find_map(|(name, span)| (name == parent).then_some(span)) + .unwrap(); + // FIXME: should probably format this in fluent instead of here + let missing = children + .iter() + .filter(|f| !features.enabled(**f)) + .map(|s| format!("`{}`", s.as_str())) + .intersperse(String::from(", ")) + .collect(); + sess.dcx().emit_err(errors::MissingDependentFeatures { parent_span, parent, missing }); + } + } +} + fn check_new_solver_banned_features(sess: &Session, features: &Features) { if !sess.opts.unstable_opts.next_solver.globally { return; diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 2630348c49c1..7793f786cefe 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -5,6 +5,7 @@ // tidy-alphabetical-start #![feature(box_patterns)] #![feature(if_let_guard)] +#![feature(iter_intersperse)] #![feature(iter_is_partitioned)] // tidy-alphabetical-end diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 4ba50d03d707..619726f0d5d8 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -136,5 +136,6 @@ pub use builtin_attrs::{ }; pub use removed::REMOVED_LANG_FEATURES; pub use unstable::{ - EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES, UNSTABLE_LANG_FEATURES, + DEPENDENT_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES, + UNSTABLE_LANG_FEATURES, }; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 2ab7714f22ca..a941eb1f459e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -605,6 +605,8 @@ declare_features! ( (unstable, offset_of_enum, "1.75.0", Some(120141)), /// Allows using fields with slice type in offset_of! (unstable, offset_of_slice, "1.81.0", Some(126151)), + /// Allows using generics in more complex const expressions, based on definitional equality. + (unstable, opaque_generic_const_args, "CURRENT_RUSTC_VERSION", Some(151972)), /// Allows using `#[optimize(X)]`. (unstable, optimize_attribute, "1.34.0", Some(54882)), /// Allows specifying nop padding on functions for dynamic patching. @@ -782,3 +784,9 @@ pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = &[ // boolean logic required to tell which typing rules to use. (sym::ref_pat_eat_one_layer_2024, sym::ref_pat_eat_one_layer_2024_structural), ]; + +/// Some features require one or more other features to be enabled. +pub const DEPENDENT_FEATURES: &[(Symbol, &[Symbol])] = &[ + (sym::opaque_generic_const_args, &[sym::min_generic_const_args]), + (sym::unsized_const_params, &[sym::adt_const_params]), +]; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index f50aff187f25..f3086266eec0 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -16,7 +16,7 @@ use std::cell::Cell; use std::iter; -use std::ops::Bound; +use std::ops::{Bound, ControlFlow}; use rustc_abi::{ExternAbi, Size}; use rustc_ast::Recovered; @@ -26,12 +26,13 @@ use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, E0228, ErrorGuaranteed, StashKey, struct_span_code_err, }; use rustc_hir::attrs::AttributeKind; -use rustc_hir::def::DefKind; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt}; +use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt}; use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind, find_attr}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause}; +use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{ @@ -1511,6 +1512,20 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin let parent_hir_node = tcx.hir_node(tcx.parent_hir_id(const_arg_id)); if tcx.features().generic_const_exprs() { ty::AnonConstKind::GCE + } else if tcx.features().opaque_generic_const_args() { + // Only anon consts that are the RHS of a const item can be OGCA. + // Note: We can't just check tcx.parent because it needs to be EXACTLY + // the RHS, not just part of the RHS. + if !is_anon_const_rhs_of_const_item(tcx, def) { + return ty::AnonConstKind::MCG; + } + + let body = tcx.hir_body_owned_by(def); + let mut visitor = OGCAParamVisitor(tcx); + match visitor.visit_body(body) { + ControlFlow::Break(UsesParam) => ty::AnonConstKind::OGCA, + ControlFlow::Continue(()) => ty::AnonConstKind::MCG, + } } else if tcx.features().min_generic_const_args() { ty::AnonConstKind::MCG } else if let hir::Node::Expr(hir::Expr { @@ -1528,6 +1543,49 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin } } +fn is_anon_const_rhs_of_const_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { + let hir_id = tcx.local_def_id_to_hir_id(def_id); + let Some((_, grandparent_node)) = tcx.hir_parent_iter(hir_id).nth(1) else { return false }; + let (Node::Item(hir::Item { kind: hir::ItemKind::Const(_, _, _, ct_rhs), .. }) + | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(_, ct_rhs), .. }) + | Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(_, Some(ct_rhs)), .. + })) = grandparent_node + else { + return false; + }; + let hir::ConstItemRhs::TypeConst(hir::ConstArg { + kind: hir::ConstArgKind::Anon(rhs_anon), .. + }) = ct_rhs + else { + return false; + }; + def_id == rhs_anon.def_id +} + +struct OGCAParamVisitor<'tcx>(TyCtxt<'tcx>); + +struct UsesParam; + +impl<'tcx> Visitor<'tcx> for OGCAParamVisitor<'tcx> { + type NestedFilter = nested_filter::OnlyBodies; + type Result = ControlFlow; + + fn maybe_tcx(&mut self) -> TyCtxt<'tcx> { + self.0 + } + + fn visit_path(&mut self, path: &hir::Path<'tcx>, _id: HirId) -> ControlFlow { + if let Res::Def(DefKind::TyParam | DefKind::ConstParam | DefKind::LifetimeParam, _) = + path.res + { + return ControlFlow::Break(UsesParam); + } + + intravisit::walk_path(self, path) + } +} + #[instrument(level = "debug", skip(tcx), ret)] fn const_of_item<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 511d513216eb..0723418d8ddf 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -92,6 +92,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { match tcx.anon_const_kind(def_id) { // Stable: anon consts are not able to use any generic parameters... ty::AnonConstKind::MCG => None, + // OGCA anon consts inherit their parent's generics. + ty::AnonConstKind::OGCA => Some(parent_did), // we provide generics to repeat expr counts as a backwards compatibility hack. #76200 ty::AnonConstKind::RepeatExprCount => Some(parent_did), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index a79170452fae..7a03d8b220c5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -404,6 +404,11 @@ impl<'tcx> ForbidMCGParamUsesFolder<'tcx> { diag.span_note(impl_.self_ty.span, "not a concrete type"); } } + if self.tcx.features().min_generic_const_args() + && !self.tcx.features().opaque_generic_const_args() + { + diag.help("add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items"); + } diag.emit() } } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 5581ad5669aa..3e17943a8857 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use rustc_data_structures::intern::Interned; use rustc_error_messages::MultiSpan; -use rustc_macros::{HashStable, TyDecodable, TyEncodable}; +use rustc_macros::HashStable; use rustc_type_ir::walk::TypeWalker; use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo}; @@ -335,16 +335,3 @@ impl<'tcx> Const<'tcx> { TypeWalker::new(self.into()) } } - -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, HashStable)] -pub enum AnonConstKind { - /// `feature(generic_const_exprs)` anon consts are allowed to use arbitrary generic parameters in scope - GCE, - /// stable `min_const_generics` anon consts are not allowed to use any generic parameters - MCG, - /// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters - /// but must not depend on the actual instantiation. See #76200 for more information - RepeatExprCount, - /// anon consts outside of the type system, e.g. enum discriminants - NonTypeSystem, -} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e43a30091f50..1bb83530487d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -238,6 +238,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> { fn const_of_item(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Const<'tcx>> { self.const_of_item(def_id) } + fn anon_const_kind(self, def_id: DefId) -> ty::AnonConstKind { + self.anon_const_kind(def_id) + } type AdtDef = ty::AdtDef<'tcx>; fn adt_def(self, adt_def_id: DefId) -> Self::AdtDef { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 0220531b09fa..37871aad4a77 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -76,8 +76,8 @@ pub use self::closure::{ place_to_string_for_capture, }; pub use self::consts::{ - AnonConstKind, AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult, Expr, - ExprKind, ScalarInt, SimdAlign, UnevaluatedConst, ValTree, ValTreeKindExt, Value, + AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult, Expr, ExprKind, ScalarInt, + SimdAlign, UnevaluatedConst, ValTree, ValTreeKindExt, Value, }; pub use self::context::{ CtxtInterners, CurrentGcx, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls, diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs index 46312be5ea9a..eb6a1b51421c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs @@ -1,4 +1,4 @@ -use rustc_type_ir::{self as ty, Interner}; +use rustc_type_ir::{self as ty, Interner, TypingMode}; use tracing::instrument; use crate::delegate::SolverDelegate; @@ -14,7 +14,18 @@ where &mut self, goal: Goal>, ) -> QueryResult { - if let Some(normalized_const) = self.evaluate_const( + if self.typing_mode() == TypingMode::Coherence + && self.cx().anon_const_kind(goal.predicate.alias.def_id) == ty::AnonConstKind::OGCA + { + // During coherence, OGCA consts should be normalized ambiguously + // because they are opaque but eventually resolved to a real value. + // We don't want two OGCAs that have the same value to be treated + // as distinct for coherence purposes. (Just like opaque types.) + // + // We can't rely on evaluate_const below because that particular wrapper + // treats too-generic consts as a successful evaluation. + self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + } else if let Some(normalized_const) = self.evaluate_const( goal.param_env, ty::UnevaluatedConst::new( goal.predicate.alias.def_id.try_into().unwrap(), diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index c35ddc4dc943..9ac9bd5c0e46 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1551,7 +1551,9 @@ impl<'a> Parser<'a> { let rhs = if self.eat(exp!(Eq)) { if attr::contains_name(attrs, sym::type_const) { - Some(ConstItemRhs::TypeConst(self.parse_const_arg()?)) + let ct = + self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?; + Some(ConstItemRhs::TypeConst(ct)) } else { Some(ConstItemRhs::Body(self.parse_expr()?)) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 1915ff0380fd..6aa2eae556e2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1628,6 +1628,7 @@ symbols! { on_const, on_unimplemented, opaque, + opaque_generic_const_args, opaque_module_name_placeholder: "", open_options_new, ops, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 4e027a301cc8..08f1d947dfb5 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -681,6 +681,20 @@ pub fn try_evaluate_const<'tcx>( (args, typing_env) } + Some(ty::AnonConstKind::OGCA) => { + if infcx.typing_mode() != TypingMode::PostAnalysis { + // OGCA anon consts should be treated as always having generics + // during anything before codegen (or maybe MIR opts too). + return Err(EvaluateConstErr::HasGenericsOrInfers); + } + + if uv.args.has_non_region_param() || uv.args.has_non_region_infer() { + return Err(EvaluateConstErr::HasGenericsOrInfers); + } + + let typing_env = ty::TypingEnv::fully_monomorphized(); + (uv.args, typing_env) + } Some(ty::AnonConstKind::MCG) | Some(ty::AnonConstKind::NonTypeSystem) | None => { // We are only dealing with "truly" generic/uninferred constants here: // - GCEConsts have been handled separately diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index b215230ea443..1c39f31469b1 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -200,3 +200,23 @@ impl ValTreeKind { } } } + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] +pub enum AnonConstKind { + /// `feature(generic_const_exprs)` anon consts are allowed to use arbitrary generic parameters in scope + GCE, + /// stable `min_const_generics` anon consts are not allowed to use any generic parameters + MCG, + /// `feature(opaque_generic_const_args)` anon consts are allowed to use arbitrary + /// generic parameters in scope, but only if they syntactically reference them. + OGCA, + /// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters + /// but must not depend on the actual instantiation. See #76200 for more information + RepeatExprCount, + /// anon consts outside of the type system, e.g. enum discriminants + NonTypeSystem, +} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 59ae6733fb84..8f446cdfba6d 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -205,6 +205,7 @@ pub trait Interner: fn type_of_opaque_hir_typeck(self, def_id: Self::LocalDefId) -> ty::EarlyBinder; fn const_of_item(self, def_id: Self::DefId) -> ty::EarlyBinder; + fn anon_const_kind(self, def_id: Self::DefId) -> ty::AnonConstKind; type AdtDef: AdtDef; fn adt_def(self, adt_def_id: Self::AdtId) -> Self::AdtDef; diff --git a/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.rs b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.rs index 6b87ad86d4bc..e364368b8a4c 100644 --- a/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.rs +++ b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.rs @@ -1,4 +1,4 @@ -#![feature(generic_const_exprs, unsized_const_params)] +#![feature(adt_const_params, generic_const_exprs, unsized_const_params)] #![allow(incomplete_features)] // Regression test for 128232 diff --git a/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr index 72dfda50ea5c..b13f76eabadb 100644 --- a/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr +++ b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr @@ -9,13 +9,11 @@ help: you might be missing a const parameter LL | impl Wrapper<{ bar() }> { | +++++++++++++++++++++++ -error: using function pointers as const generic parameters is forbidden +error[E0741]: using function pointers as const generic parameters is forbidden --> $DIR/non_valtreeable_const_arg-2.rs:8:25 | LL | struct Wrapper; | ^^^^ - | - = note: the only supported types are integers, `bool`, and `char` error[E0599]: the function or associated item `call` exists for struct `Wrapper`, but its trait bounds were not satisfied --> $DIR/non_valtreeable_const_arg-2.rs:17:26 @@ -37,5 +35,5 @@ note: the trait `Fn` must be implemented error: aborting due to 3 previous errors -Some errors have detailed explanations: E0425, E0599. +Some errors have detailed explanations: E0425, E0599, E0741. For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/const-generics/associated-const-bindings/ambiguity.rs b/tests/ui/const-generics/associated-const-bindings/ambiguity.rs index 6bc2a6d5d153..785d43e51b3d 100644 --- a/tests/ui/const-generics/associated-const-bindings/ambiguity.rs +++ b/tests/ui/const-generics/associated-const-bindings/ambiguity.rs @@ -1,7 +1,7 @@ // We used to say "ambiguous associated type" on ambiguous associated consts. // Ensure that we now use the correct label. -#![feature(min_generic_const_args, unsized_const_params)] +#![feature(adt_const_params, min_generic_const_args, unsized_const_params)] #![allow(incomplete_features)] trait Trait0: Parent0 + Parent0 {} diff --git a/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs b/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs index 004215986711..0af91bfe7da8 100644 --- a/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs +++ b/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs @@ -5,7 +5,7 @@ //@ check-pass -#![feature(min_generic_const_args, unsized_const_params)] +#![feature(adt_const_params, min_generic_const_args, unsized_const_params)] #![allow(incomplete_features)] trait Trait: SuperTrait { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs index d19e7acbaff0..bd26acce681f 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs @@ -3,6 +3,7 @@ //@ dont-require-annotations: NOTE +#![feature(adt_const_params)] #![feature(generic_const_items)] #![feature(generic_const_parameter_types)] #![feature(min_generic_const_args)] diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.stderr index dba1643d2c5c..dedbdd7f82bb 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.stderr @@ -1,12 +1,12 @@ error[E0038]: the trait `Trait` is not dyn compatible - --> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:37:16 + --> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:38:16 | LL | let _: dyn Trait; | ^^^^^ `Trait` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:17:11 + --> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:18:11 | LL | trait Trait { | ----- this trait is not dyn compatible... diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs index 936556e957ca..fc3bd1d2e753 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs @@ -4,17 +4,24 @@ // to the rest of the compiler and by extension the user via diagnostics. //@ known-bug: unknown -#![feature(min_generic_const_args, unsized_const_params, generic_const_parameter_types)] +#![feature( + adt_const_params, + min_generic_const_args, + unsized_const_params, + generic_const_parameter_types +)] #![expect(incomplete_features)] trait A { type Ty: std::marker::ConstParamTy_; - #[type_const] const CT: Self::Ty; + #[type_const] + const CT: Self::Ty; } impl A for () { type Ty = i32; - #[type_const] const CT: i32 = 0; + #[type_const] + const CT: i32 = 0; } fn main() { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr index 8ee231ec070f..0b8dae1aac43 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr @@ -1,23 +1,23 @@ error[E0277]: the trait bound `FreshTy(0): A` is not satisfied - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:27:33 + --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:34:33 | LL | let _: dyn A; | ^ the trait `A` is not implemented for `FreshTy(0)` | help: the trait `A` is implemented for `()` - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:15:1 + --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:21:1 | LL | impl A for () { | ^^^^^^^^^^^^^ error[E0277]: the trait bound `FreshTy(0): A` is not satisfied - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:29:34 + --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:36:34 | LL | let _: &dyn A = &(); | ^ the trait `A` is not implemented for `FreshTy(0)` | help: the trait `A` is implemented for `()` - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:15:1 + --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:21:1 | LL | impl A for () { | ^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs b/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs index d32737fcb62f..4d06cdc7620f 100644 --- a/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs +++ b/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs @@ -1,6 +1,7 @@ // Detect and reject escaping late-bound generic params in // the type of assoc consts used in an equality bound. #![feature( + adt_const_params, min_generic_const_args, unsized_const_params, generic_const_parameter_types, diff --git a/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.stderr b/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.stderr index 122893662933..3966483aa600 100644 --- a/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.stderr +++ b/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.stderr @@ -1,5 +1,5 @@ error: the type of the associated constant `K` cannot capture late-bound generic parameters - --> $DIR/esc-bound-var-in-ty.rs:15:35 + --> $DIR/esc-bound-var-in-ty.rs:16:35 | LL | fn take(_: impl for<'r> Trait<'r, K = const { &() }>) {} | -- ^ its type cannot capture the late-bound lifetime parameter `'r` diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr b/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr index 8b9c228c1ee5..f1d5e5c67475 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr @@ -9,6 +9,8 @@ error: generic parameters may not be used in const operations | LL | foo::<{ Some:: { 0: const { N + 1 } } }>(); | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/early-bound-param-lt-bad.stderr b/tests/ui/const-generics/mgca/early-bound-param-lt-bad.stderr index 461a26e33a3c..e0804158952d 100644 --- a/tests/ui/const-generics/mgca/early-bound-param-lt-bad.stderr +++ b/tests/ui/const-generics/mgca/early-bound-param-lt-bad.stderr @@ -3,6 +3,8 @@ error: generic parameters may not be used in const operations | LL | T: Trait | ^^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr index 551815c4c31a..1251f4415171 100644 --- a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr +++ b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr @@ -39,42 +39,56 @@ error: generic parameters may not be used in const operations | LL | const ITEM3: usize = const { N }; | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:60:31 | LL | T3: Trait, | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:69:58 | LL | struct Default3; | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:28:27 | LL | let _3 = [(); const { N }]; | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:33:26 | LL | let _6: [(); const { N }] = todo!(); | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:11:41 | LL | type Adt3 = Foo; | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:19:42 | LL | type Arr3 = [(); const { N }]; | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 13 previous errors diff --git a/tests/ui/const-generics/mgca/selftyalias-containing-param.stderr b/tests/ui/const-generics/mgca/selftyalias-containing-param.stderr index fdd3e6efdf65..1c841e39e673 100644 --- a/tests/ui/const-generics/mgca/selftyalias-containing-param.stderr +++ b/tests/ui/const-generics/mgca/selftyalias-containing-param.stderr @@ -9,6 +9,7 @@ note: not a concrete type | LL | impl S { | ^^^^ + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/selftyparam.stderr b/tests/ui/const-generics/mgca/selftyparam.stderr index 376e63da9a75..c3e0770fb978 100644 --- a/tests/ui/const-generics/mgca/selftyparam.stderr +++ b/tests/ui/const-generics/mgca/selftyparam.stderr @@ -3,6 +3,8 @@ error: generic parameters may not be used in const operations | LL | fn foo() -> [(); const { let _: Self; 1 }]; | ^^^^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr index 913d8195fe21..6d8d3b4054d3 100644 --- a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr +++ b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr @@ -9,6 +9,8 @@ error: generic parameters may not be used in const operations | LL | [0; const { size_of::<*mut T>() }]; | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr index e0ea3fd5560c..2961c714d141 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr +++ b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr @@ -9,6 +9,8 @@ error: generic parameters may not be used in const operations | LL | with_point::<{ Point(const { N + 1 }, N) }>(); | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr index b294e1032ce8..b4853d3c2e38 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr @@ -21,6 +21,8 @@ error: generic parameters may not be used in const operations | LL | takes_nested_tuple::<{ (N, (N, const { N + 1 })) }>(); | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr b/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr index f339e82beeed..8d43f2177562 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr +++ b/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr @@ -3,12 +3,16 @@ error: generic parameters may not be used in const operations | LL | const FREE1: usize = const { std::mem::size_of::() }; | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/type_const-on-generic-expr.rs:8:46 | LL | const FREE2: usize = const { I + 1 }; | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr index 9d4e99ca0aaf..1a6097752e33 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr +++ b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr @@ -3,18 +3,24 @@ error: generic parameters may not be used in const operations | LL | const N1: usize = const { std::mem::size_of::() }; | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/type_const-on-generic_expr-2.rs:20:47 | LL | const N2: usize = const { I + 1 }; | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/type_const-on-generic_expr-2.rs:23:35 | LL | const N3: usize = const { 2 & X }; | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs index 588fa2f913b6..c01fb47002b2 100644 --- a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs +++ b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs @@ -35,7 +35,6 @@ const NON_TYPE_CONST: usize = const { 1 }; #[type_const] //~^ ERROR: the `#[type_const]` attribute is an experimental feature const TYPE_CONST: usize = const { 1 }; -//~^ ERROR: unbraced const blocks as const args are experimental static STATIC: usize = const { 1 }; diff --git a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr index 00db630c27e9..bbcd9f9897a6 100644 --- a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr +++ b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr @@ -48,16 +48,6 @@ LL | generic::(); = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: unbraced const blocks as const args are experimental - --> $DIR/unbraced_const_block_const_arg_gated.rs:37:27 - | -LL | const TYPE_CONST: usize = const { 1 }; - | ^^^^^^^^^^^ - | - = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0658]: the `#[type_const]` attribute is an experimental feature --> $DIR/unbraced_const_block_const_arg_gated.rs:35:1 | @@ -68,6 +58,6 @@ LL | #[type_const] = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/ogca/basic-fail.rs b/tests/ui/const-generics/ogca/basic-fail.rs new file mode 100644 index 000000000000..87176c7b067e --- /dev/null +++ b/tests/ui/const-generics/ogca/basic-fail.rs @@ -0,0 +1,22 @@ +#![feature(generic_const_items)] +#![feature(min_generic_const_args)] +#![feature(opaque_generic_const_args)] +#![expect(incomplete_features)] + +#[type_const] +const ADD1: usize = const { N + 1 }; + +#[type_const] +const INC: usize = const { N + 1 }; + +#[type_const] +const ONE: usize = ADD1::<0>; + +#[type_const] +const OTHER_ONE: usize = INC::<0>; + +// Not definitionally equal. +const ARR: [(); ADD1::<0>] = [(); INC::<0>]; +//~^ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/const-generics/ogca/basic-fail.stderr b/tests/ui/const-generics/ogca/basic-fail.stderr new file mode 100644 index 000000000000..05de01b132c6 --- /dev/null +++ b/tests/ui/const-generics/ogca/basic-fail.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/basic-fail.rs:19:30 + | +LL | const ARR: [(); ADD1::<0>] = [(); INC::<0>]; + | ^^^^^^^^^^^^^^ expected an array with a size of const { N + 1 }, found one with a size of const { N + 1 } + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/ogca/basic.rs b/tests/ui/const-generics/ogca/basic.rs new file mode 100644 index 000000000000..c8aec9ee24ce --- /dev/null +++ b/tests/ui/const-generics/ogca/basic.rs @@ -0,0 +1,22 @@ +//@ check-pass + +#![feature(generic_const_items)] +#![feature(min_generic_const_args)] +#![feature(opaque_generic_const_args)] +#![expect(incomplete_features)] + +#[type_const] +const ADD1: usize = const { N + 1 }; + +#[type_const] +const INC: usize = ADD1::; + +#[type_const] +const ONE: usize = ADD1::<0>; + +#[type_const] +const OTHER_ONE: usize = INC::<0>; + +const ARR: [(); ADD1::<0>] = [(); INC::<0>]; + +fn main() {} diff --git a/tests/ui/const-generics/ogca/coherence-ambiguous.rs b/tests/ui/const-generics/ogca/coherence-ambiguous.rs new file mode 100644 index 000000000000..c8c088b1e8fc --- /dev/null +++ b/tests/ui/const-generics/ogca/coherence-ambiguous.rs @@ -0,0 +1,21 @@ +// FIXME(ogca): this should ERROR not pass!! +//@ check-pass + +#![feature(generic_const_items, min_generic_const_args, opaque_generic_const_args)] +#![expect(incomplete_features)] + +#[type_const] +const FOO: usize = const { N + 1 }; + +#[type_const] +const BAR: usize = const { N + 1 }; + +trait Trait {} + +impl Trait for [(); FOO::<1>] {} +impl Trait for [(); BAR::<1>] {} +// FIXME(ogca): this should ERROR! +impl Trait for [(); BAR::<2>] {} +// FIXME(ogca): this should ERROR! + +fn main() {} diff --git a/tests/ui/const-generics/ogca/rhs-but-not-root.rs b/tests/ui/const-generics/ogca/rhs-but-not-root.rs new file mode 100644 index 000000000000..4ed136f04ced --- /dev/null +++ b/tests/ui/const-generics/ogca/rhs-but-not-root.rs @@ -0,0 +1,14 @@ +#![feature(generic_const_items)] +#![feature(min_generic_const_args)] +#![feature(opaque_generic_const_args)] +#![expect(incomplete_features)] + +// Anon consts must be the root of the RHS to be OGCA. +#[type_const] +const FOO: usize = ID::; +//~^ ERROR generic parameters may not be used in const operations + +#[type_const] +const ID: usize = N; + +fn main() {} diff --git a/tests/ui/const-generics/ogca/rhs-but-not-root.stderr b/tests/ui/const-generics/ogca/rhs-but-not-root.stderr new file mode 100644 index 000000000000..f4fdf5fb981b --- /dev/null +++ b/tests/ui/const-generics/ogca/rhs-but-not-root.stderr @@ -0,0 +1,8 @@ +error: generic parameters may not be used in const operations + --> $DIR/rhs-but-not-root.rs:8:49 + | +LL | const FOO: usize = ID::; + | ^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.rs b/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.rs new file mode 100644 index 000000000000..0b78911158ba --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.rs @@ -0,0 +1,9 @@ +#![feature(generic_const_items, min_generic_const_args)] +#![expect(incomplete_features)] + +#[type_const] +const INC: usize = const { N + 1 }; +//~^ ERROR generic parameters may not be used in const operations +//~| HELP add `#![feature(opaque_generic_const_args)]` + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.stderr b/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.stderr new file mode 100644 index 000000000000..1b87443aa3cb --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.stderr @@ -0,0 +1,10 @@ +error: generic parameters may not be used in const operations + --> $DIR/feature-gate-opaque-generic-const-args.rs:5:44 + | +LL | const INC: usize = const { N + 1 }; + | ^ + | + = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + +error: aborting due to 1 previous error + diff --git a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs index fb2506daf078..518ed6452369 100644 --- a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs +++ b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs @@ -1,6 +1,6 @@ // ICE: assertion failed: !value.has_infer() // issue: rust-lang/rust#115806 -#![feature(min_generic_const_args, unsized_const_params)] +#![feature(adt_const_params, min_generic_const_args, unsized_const_params)] #![allow(incomplete_features)] pub struct NoPin; From 875c5908c747f5e97227aab367d4bcc7c161c892 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sun, 8 Feb 2026 20:39:02 +0100 Subject: [PATCH 723/978] Update examples for diagnostics changes Co-authored-by: bjorn3 --- .../examples/rustc-interface-example.rs | 15 +++++---------- .../rustc-interface-getting-diagnostics.rs | 8 +++----- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs index 360f70c8e865..b4439504650a 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-example.rs @@ -4,14 +4,12 @@ extern crate rustc_driver; extern crate rustc_error_codes; -extern crate rustc_errors; extern crate rustc_hash; extern crate rustc_hir; extern crate rustc_interface; extern crate rustc_session; extern crate rustc_span; -use rustc_errors::registry; use rustc_hash::FxHashMap; use rustc_session::config; @@ -30,12 +28,11 @@ fn main() { println!("{HELLO}"); } "# - .into(), + .into(), }, - output_dir: None, // Option - output_file: None, // Option - file_loader: None, // Option> - locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES.to_owned(), + output_dir: None, // Option + output_file: None, // Option + file_loader: None, // Option> lint_caps: FxHashMap::default(), // FxHashMap // This is a callback from the driver that is called when [`ParseSess`] is created. psess_created: None, //Option> @@ -50,8 +47,6 @@ fn main() { // // The second parameter is local providers and the third parameter is external providers. override_queries: None, // Option, &mut ty::query::Providers<'_>)> - // Registry of diagnostics codes. - registry: registry::Registry::new(rustc_errors::codes::DIAGNOSTICS), make_codegen_backend: None, expanded_args: Vec::new(), ice_file: None, @@ -77,4 +72,4 @@ fn main() { } }); }); -} +} \ No newline at end of file diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs index 2512ba3c3f92..342316ba670a 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs @@ -15,7 +15,7 @@ extern crate rustc_span; use std::sync::{Arc, Mutex}; use rustc_errors::emitter::Emitter; -use rustc_errors::registry::{self, Registry}; +use rustc_errors::registry::Registry; use rustc_errors::translation::Translate; use rustc_errors::{DiagInner, FluentBundle}; use rustc_session::config; @@ -59,14 +59,13 @@ fn main() { let x: &str = 1; } " - .into(), + .into(), }, crate_cfg: Vec::new(), crate_check_cfg: Vec::new(), output_dir: None, output_file: None, file_loader: None, - locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES.to_owned(), lint_caps: rustc_hash::FxHashMap::default(), psess_created: Some(Box::new(|parse_sess| { parse_sess.dcx().set_emitter(Box::new(DebugEmitter { @@ -76,7 +75,6 @@ fn main() { })), register_lints: None, override_queries: None, - registry: registry::Registry::new(rustc_errors::codes::DIAGNOSTICS), make_codegen_backend: None, expanded_args: Vec::new(), ice_file: None, @@ -99,4 +97,4 @@ fn main() { buffer.lock().unwrap().iter().for_each(|diagnostic| { println!("{diagnostic:#?}"); }); -} +} \ No newline at end of file From 4a979d546bc779f97e6224e8ab3d26f8bd69a6e9 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 8 Feb 2026 19:54:03 +0000 Subject: [PATCH 724/978] Stop having two different alignment constants * Stop having two different alignment constants * Update library/core/src/alloc/global.rs --- library/core/src/alloc/global.rs | 7 ++++--- library/core/src/mem/mod.rs | 5 ++++- library/core/src/ptr/alignment.rs | 3 +-- .../default_boxed_slice.main.GVN.32bit.panic-abort.diff | 2 +- .../default_boxed_slice.main.GVN.32bit.panic-unwind.diff | 2 +- .../default_boxed_slice.main.GVN.64bit.panic-abort.diff | 2 +- .../default_boxed_slice.main.GVN.64bit.panic-unwind.diff | 2 +- tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff | 2 +- 8 files changed, 14 insertions(+), 11 deletions(-) diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs index d18e1f525d10..bf3d3e0a5aca 100644 --- a/library/core/src/alloc/global.rs +++ b/library/core/src/alloc/global.rs @@ -284,9 +284,10 @@ pub unsafe trait GlobalAlloc { /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html #[stable(feature = "global_alloc", since = "1.28.0")] unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - // SAFETY: the caller must ensure that the `new_size` does not overflow. - // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid. - let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; + let alignment = layout.alignment(); + // SAFETY: the caller must ensure that the `new_size` does not overflow + // when rounded up to the next multiple of `alignment`. + let new_layout = unsafe { Layout::from_size_alignment_unchecked(new_size, alignment) }; // SAFETY: the caller must ensure that `new_layout` is greater than zero. let new_ptr = unsafe { self.alloc(new_layout) }; if !new_ptr.is_null() { diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 7c486875a826..eb6f8f975721 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1260,7 +1260,10 @@ pub trait SizedTypeProperties: Sized { #[doc(hidden)] #[unstable(feature = "ptr_alignment_type", issue = "102070")] - const ALIGNMENT: Alignment = Alignment::of::(); + const ALIGNMENT: Alignment = { + // This can't panic since type alignment is always a power of two. + Alignment::new(Self::ALIGN).unwrap() + }; /// `true` if this type requires no storage. /// `false` if its [size](size_of) is greater than zero. diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 7c34b026e14b..b27930de4e66 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -52,8 +52,7 @@ impl Alignment { #[inline] #[must_use] pub const fn of() -> Self { - // This can't actually panic since type alignment is always a power of two. - const { Alignment::new(align_of::()).unwrap() } + ::ALIGNMENT } /// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to. diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff index 7d66d3129115..308f19ea759d 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff @@ -44,7 +44,7 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); -- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute); +- _6 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as *const [bool; 0] (Transmute); - _5 = NonNull::<[bool; 0]> { pointer: copy _6 }; + _6 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff index cc00bd300a3c..819ad6054df8 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff @@ -44,7 +44,7 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); -- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute); +- _6 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as *const [bool; 0] (Transmute); - _5 = NonNull::<[bool; 0]> { pointer: copy _6 }; + _6 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff index 9380cdd6ccb4..7029e02a857a 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff @@ -44,7 +44,7 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); -- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute); +- _6 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as *const [bool; 0] (Transmute); - _5 = NonNull::<[bool; 0]> { pointer: copy _6 }; + _6 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff index bea564376274..23a134f3666b 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff @@ -44,7 +44,7 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); -- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as *const [bool; 0] (Transmute); +- _6 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as *const [bool; 0] (Transmute); - _5 = NonNull::<[bool; 0]> { pointer: copy _6 }; + _6 = const {0x1 as *const [bool; 0]}; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; diff --git a/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff b/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff index 9e543699da70..23889b266e4a 100644 --- a/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff +++ b/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff @@ -40,7 +40,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); -- _3 = const std::ptr::Alignment::of::::{constant#0}; +- _3 = const ::ALIGNMENT; - _2 = copy _3 as *mut u8 (Transmute); + _3 = const std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }}; + _2 = const {0x1 as *mut u8}; From f1b4c2a0e64ccb5c1b4b2b2391ac91f40d143302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sat, 7 Feb 2026 14:42:17 +0100 Subject: [PATCH 725/978] Port rustc_insignificant_dtor to the new attribute parser --- .../src/attributes/rustc_internal.rs | 13 +++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ compiler/rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_ty_utils/src/needs_drop.rs | 6 +++--- 6 files changed, 22 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index a8a0ee3e5e22..4740cc107353 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -739,6 +739,19 @@ impl CombineAttributeParser for RustcThenThisWouldNeedParser { } } +pub(crate) struct RustcInsignificantDtorParser; + +impl NoArgsAttributeParser for RustcInsignificantDtorParser { + const PATH: &[Symbol] = &[sym::rustc_insignificant_dtor]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Enum), + Allow(Target::Struct), + Allow(Target::ForeignTy), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInsignificantDtor; +} + pub(crate) struct RustcEffectiveVisibilityParser; impl NoArgsAttributeParser for RustcEffectiveVisibilityParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index ad39b0ec26d9..7921928ce7c5 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -270,6 +270,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 79452913c259..aaeebcc5c66d 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1120,6 +1120,9 @@ pub enum AttributeKind { /// Represents `#[rustc_if_this_changed]` RustcIfThisChanged(Span, Option), + /// Represents `#[rustc_insignificant_dtor]` + RustcInsignificantDtor, + /// Represents `#[rustc_intrinsic]` RustcIntrinsic, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index ba351d80544c..4fb20599a026 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -118,6 +118,7 @@ impl AttributeKind { RustcHasIncoherentInherentImpls => Yes, RustcHiddenTypeOfOpaques => No, RustcIfThisChanged(..) => No, + RustcInsignificantDtor => Yes, RustcIntrinsic => Yes, RustcIntrinsicConstStableIndirect => No, RustcLayout(..) => No, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 6c4b76a08ad2..2f1695f0712a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -313,6 +313,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcHasIncoherentInherentImpls | AttributeKind::RustcHiddenTypeOfOpaques | AttributeKind::RustcIfThisChanged(..) + | AttributeKind::RustcInsignificantDtor | AttributeKind::RustcIntrinsic | AttributeKind::RustcIntrinsicConstStableIndirect | AttributeKind::RustcLayout(..) @@ -386,7 +387,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::default_lib_allocator | sym::rustc_diagnostic_item | sym::rustc_no_mir_inline - | sym::rustc_insignificant_dtor | sym::rustc_nonnull_optimization_guaranteed | sym::rustc_inherit_overflow_checks | sym::rustc_trivial_field_reads diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 0ef435b1a0e2..06eef7e95145 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -1,13 +1,14 @@ //! Check whether a type has (potentially) non-trivial drop glue. use rustc_data_structures::fx::FxHashSet; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::DefId; +use rustc_hir::find_attr; use rustc_hir::limit::Limit; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::util::{AlwaysRequiresDrop, needs_drop_components}; use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt}; -use rustc_span::sym; use tracing::{debug, instrument}; use crate::errors::NeedsDropOverflow; @@ -396,8 +397,7 @@ fn adt_consider_insignificant_dtor<'tcx>( tcx: TyCtxt<'tcx>, ) -> impl Fn(ty::AdtDef<'tcx>) -> Option { move |adt_def: ty::AdtDef<'tcx>| { - let is_marked_insig = tcx.has_attr(adt_def.did(), sym::rustc_insignificant_dtor); - if is_marked_insig { + if find_attr!(tcx.get_all_attrs(adt_def.did()), AttributeKind::RustcInsignificantDtor) { // In some cases like `std::collections::HashMap` where the struct is a wrapper around // a type that is a Drop type, and the wrapped type (eg: `hashbrown::HashMap`) lies // outside stdlib, we might choose to still annotate the wrapper (std HashMap) with From 9d6e120939cad8e87c3ccd4e2f33d3591b82edf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sat, 7 Feb 2026 15:06:32 +0100 Subject: [PATCH 726/978] remove from impl block in std --- library/alloc/src/ffi/c_str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index d6dcba7107a9..fba967c04895 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -103,6 +103,7 @@ use crate::vec::Vec; /// and other memory errors. #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)] #[rustc_diagnostic_item = "cstring_type"] +#[rustc_insignificant_dtor] #[stable(feature = "alloc_c_string", since = "1.64.0")] pub struct CString { // Invariant 1: the slice ends with a zero byte and has a length of at least one. @@ -694,7 +695,6 @@ impl CString { // memory-unsafe code from working by accident. Inline // to prevent LLVM from optimizing it away in debug builds. #[stable(feature = "cstring_drop", since = "1.13.0")] -#[rustc_insignificant_dtor] impl Drop for CString { #[inline] fn drop(&mut self) { From 2dda303229b936641c29db1f277a9940473ebc70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Thu, 5 Feb 2026 15:12:05 +0100 Subject: [PATCH 727/978] Port rustc_strict_coherence to the new attribute parser --- .../src/attributes/rustc_internal.rs | 15 +++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + .../rustc_hir/src/attrs/data_structures.rs | 4 ++++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_middle/src/error.rs | 2 +- .../src/traits/specialization_graph.rs | 19 ++++++------------- compiler/rustc_passes/src/check_attr.rs | 2 +- 7 files changed, 29 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index a8a0ee3e5e22..c4c0a04c44e4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -845,3 +845,18 @@ impl NoArgsAttributeParser for RustcIntrinsicConstStableIndirectPar const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect; } + +pub(crate) struct RustcStrictCoherenceParser; + +impl NoArgsAttributeParser for RustcStrictCoherenceParser { + const PATH: &[Symbol] = &[sym::rustc_strict_coherence]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Trait), + Allow(Target::Struct), + Allow(Target::Enum), + Allow(Target::Union), + Allow(Target::ForeignTy), + ]); + const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcStrictCoherence; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index ad39b0ec26d9..16a3403b5243 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -286,6 +286,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 79452913c259..de7b2bd06546 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1230,6 +1230,9 @@ pub enum AttributeKind { /// Represents `#[rustc_std_internal_symbol]`. RustcStdInternalSymbol(Span), + /// Represents `#[rustc_strict_coherence]`. + RustcStrictCoherence(Span), + /// Represents `#[rustc_symbol_name]` RustcSymbolName(Span), @@ -1266,6 +1269,7 @@ pub enum AttributeKind { /// Span of the attribute. span: Span, }, + /// Represents `#[target_feature(enable = "...")]` and /// `#[unsafe(force_target_feature(enable = "...")]`. TargetFeature { features: ThinVec<(Symbol, Span)>, attr_span: Span, was_forced: bool }, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index ba351d80544c..954c72ca86fe 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -153,6 +153,7 @@ impl AttributeKind { RustcSkipDuringMethodDispatch { .. } => No, RustcSpecializationTrait(..) => No, RustcStdInternalSymbol(..) => No, + RustcStrictCoherence(..) => Yes, RustcSymbolName(..) => Yes, RustcThenThisWouldNeed(..) => No, RustcUnsafeSpecializationMarker(..) => No, diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index a5d5978916eb..d487caf4d3ac 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -93,7 +93,7 @@ pub(crate) struct StrictCoherenceNeedsNegativeCoherence { #[primary_span] pub span: Span, #[label("due to this attribute")] - pub attr_span: Option, + pub attr_span: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index 05c19db4caa8..84415a592a2e 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -1,8 +1,9 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::{DefId, DefIdMap}; +use rustc_hir::find_attr; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; -use rustc_span::sym; use crate::error::StrictCoherenceNeedsNegativeCoherence; use crate::ty::fast_reject::SimplifiedType; @@ -61,23 +62,15 @@ pub enum OverlapMode { impl OverlapMode { pub fn get(tcx: TyCtxt<'_>, trait_id: DefId) -> OverlapMode { let with_negative_coherence = tcx.features().with_negative_coherence(); - let strict_coherence = tcx.has_attr(trait_id, sym::rustc_strict_coherence); + let strict_coherence = find_attr!(tcx.get_all_attrs(trait_id), AttributeKind::RustcStrictCoherence(span) => *span); if with_negative_coherence { - if strict_coherence { OverlapMode::Strict } else { OverlapMode::WithNegative } + if strict_coherence.is_some() { OverlapMode::Strict } else { OverlapMode::WithNegative } } else { - if strict_coherence { - let attr_span = trait_id - .as_local() - .into_iter() - .flat_map(|local_def_id| { - tcx.hir_attrs(tcx.local_def_id_to_hir_id(local_def_id)) - }) - .find(|attr| attr.has_name(sym::rustc_strict_coherence)) - .map(|attr| attr.span()); + if let Some(span) = strict_coherence { tcx.dcx().emit_err(StrictCoherenceNeedsNegativeCoherence { span: tcx.def_span(trait_id), - attr_span, + attr_span: span, }); } OverlapMode::Stable diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 6c4b76a08ad2..c29e4b2b1afe 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -344,6 +344,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcSkipDuringMethodDispatch { .. } | AttributeKind::RustcSpecializationTrait(..) | AttributeKind::RustcStdInternalSymbol (..) + | AttributeKind::RustcStrictCoherence(..) | AttributeKind::RustcSymbolName(..) | AttributeKind::RustcThenThisWouldNeed(..) | AttributeKind::RustcUnsafeSpecializationMarker(..) @@ -402,7 +403,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_never_type_options | sym::rustc_autodiff | sym::rustc_capture_analysis - | sym::rustc_strict_coherence | sym::rustc_mir | sym::rustc_outlives | sym::rustc_evaluate_where_clauses From dfef1209b1ed4d4bb9eee0d00fe3df1154e3edf7 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 31 Jan 2026 22:33:56 +0100 Subject: [PATCH 728/978] x86: use `intrinsics::simd` for masked truncated saturating stores --- .../crates/core_arch/src/x86/avx512bw.rs | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs index 8e074fdcfa48..3ba171c0fa50 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs @@ -12476,7 +12476,14 @@ pub unsafe fn _mm512_mask_cvtsepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask32, #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmovswb))] pub unsafe fn _mm256_mask_cvtsepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask16, a: __m256i) { - vpmovswbmem256(mem_addr, a.as_i16x16(), k); + let mask = simd_select_bitmask(k, i16x16::splat(!0), i16x16::ZERO); + + let max = simd_splat(i16::from(i8::MAX)); + let min = simd_splat(i16::from(i8::MIN)); + + let v = simd_imax(simd_imin(a.as_i16x16(), max), min); + let truncated: i8x16 = simd_cast(v); + simd_masked_store!(SimdAlign::Unaligned, mask, mem_addr, truncated); } /// Convert packed signed 16-bit integers in a to packed 8-bit integers with signed saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. @@ -12487,7 +12494,14 @@ pub unsafe fn _mm256_mask_cvtsepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask16, #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmovswb))] pub unsafe fn _mm_mask_cvtsepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m128i) { - vpmovswbmem128(mem_addr, a.as_i16x8(), k); + let mask = simd_select_bitmask(k, i16x8::splat(!0), i16x8::ZERO); + + let max = simd_splat(i16::from(i8::MAX)); + let min = simd_splat(i16::from(i8::MIN)); + + let v = simd_imax(simd_imin(a.as_i16x8(), max), min); + let truncated: i8x8 = simd_cast(v); + simd_masked_store!(SimdAlign::Unaligned, mask, mem_addr, truncated); } /// Convert packed 16-bit integers in a to packed 8-bit integers with truncation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. @@ -12555,7 +12569,12 @@ pub unsafe fn _mm512_mask_cvtusepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask32 #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmovuswb))] pub unsafe fn _mm256_mask_cvtusepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask16, a: __m256i) { - vpmovuswbmem256(mem_addr, a.as_i16x16(), k); + let mask = simd_select_bitmask(k, i16x16::splat(!0), i16x16::ZERO); + let mem_addr = mem_addr.cast::(); + let max = simd_splat(u16::from(u8::MAX)); + + let truncated: u8x16 = simd_cast(simd_imin(a.as_u16x16(), max)); + simd_masked_store!(SimdAlign::Unaligned, mask, mem_addr, truncated); } /// Convert packed unsigned 16-bit integers in a to packed unsigned 8-bit integers with unsigned saturation, and store the active results (those with their respective bit set in writemask k) to unaligned memory at base_addr. @@ -12566,7 +12585,15 @@ pub unsafe fn _mm256_mask_cvtusepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask16 #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpmovuswb))] pub unsafe fn _mm_mask_cvtusepi16_storeu_epi8(mem_addr: *mut i8, k: __mmask8, a: __m128i) { - vpmovuswbmem128(mem_addr, a.as_i16x8(), k); + let mask = simd_select_bitmask(k, i16x8::splat(!0), i16x8::ZERO); + let mem_addr = mem_addr.cast::(); + let max = simd_splat(u16::from(u8::MAX)); + + let v = a.as_u16x8(); + let v = simd_imin(v, max); + + let truncated: u8x8 = simd_cast(v); + simd_masked_store!(SimdAlign::Unaligned, mask, mem_addr, truncated); } #[allow(improper_ctypes)] @@ -12632,17 +12659,9 @@ unsafe extern "C" { #[link_name = "llvm.x86.avx512.mask.pmovs.wb.mem.512"] fn vpmovswbmem(mem_addr: *mut i8, a: i16x32, mask: u32); - #[link_name = "llvm.x86.avx512.mask.pmovs.wb.mem.256"] - fn vpmovswbmem256(mem_addr: *mut i8, a: i16x16, mask: u16); - #[link_name = "llvm.x86.avx512.mask.pmovs.wb.mem.128"] - fn vpmovswbmem128(mem_addr: *mut i8, a: i16x8, mask: u8); #[link_name = "llvm.x86.avx512.mask.pmovus.wb.mem.512"] fn vpmovuswbmem(mem_addr: *mut i8, a: i16x32, mask: u32); - #[link_name = "llvm.x86.avx512.mask.pmovus.wb.mem.256"] - fn vpmovuswbmem256(mem_addr: *mut i8, a: i16x16, mask: u16); - #[link_name = "llvm.x86.avx512.mask.pmovus.wb.mem.128"] - fn vpmovuswbmem128(mem_addr: *mut i8, a: i16x8, mask: u8); } #[cfg(test)] From 2d65a33c612cf85e9a0b80e73c870520eb289008 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 7 Feb 2026 00:01:35 +0100 Subject: [PATCH 729/978] Implement indent check --- .../src/diagnostics/diagnostic_builder.rs | 7 +++- .../rustc_macros/src/diagnostics/message.rs | 39 +++++++++++++++++-- .../rustc_macros/src/diagnostics/utils.rs | 2 +- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index b386408a1918..de8ee42caf45 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -203,8 +203,11 @@ impl DiagnosticDeriveVariantBuilder { ) .emit(); } - self.message = - Some(Message { message_span: message.span(), value: message.value() }); + self.message = Some(Message { + attr_span: attr.span(), + message_span: message.span(), + value: message.value(), + }); } // Parse arguments diff --git a/compiler/rustc_macros/src/diagnostics/message.rs b/compiler/rustc_macros/src/diagnostics/message.rs index 18d4d60dde3e..3276abfce413 100644 --- a/compiler/rustc_macros/src/diagnostics/message.rs +++ b/compiler/rustc_macros/src/diagnostics/message.rs @@ -9,6 +9,7 @@ use crate::diagnostics::error::span_err; #[derive(Clone)] pub(crate) struct Message { + pub attr_span: Span, pub message_span: Span, pub value: String, } @@ -19,12 +20,18 @@ impl Message { /// For subdiagnostics, we cannot check this. pub(crate) fn diag_message(&self, variant: Option<&VariantInfo<'_>>) -> TokenStream { let message = &self.value; - verify_fluent_message(self.message_span, &message, variant); + self.verify(variant); quote! { rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed(#message)) } } + + fn verify(&self, variant: Option<&VariantInfo<'_>>) { + verify_variables_used(self.message_span, &self.value, variant); + verify_message_style(self.message_span, &self.value); + verify_message_formatting(self.attr_span, self.message_span, &self.value); + } } -fn verify_fluent_message(msg_span: Span, message_str: &str, variant: Option<&VariantInfo<'_>>) { +fn verify_variables_used(msg_span: Span, message_str: &str, variant: Option<&VariantInfo<'_>>) { // Parse the fluent message const GENERATED_MSG_ID: &str = "generated_msg"; let resource = @@ -53,8 +60,6 @@ fn verify_fluent_message(msg_span: Span, message_str: &str, variant: Option<&Var } } } - - verify_message_style(msg_span, message_str); } fn variable_references<'a>(msg: &fluent_syntax::ast::Message<&'a str>) -> Vec<&'a str> { @@ -120,3 +125,29 @@ fn verify_message_style(msg_span: Span, message: &str) { return; } } + +/// Verifies that the message is properly indented into the code +fn verify_message_formatting(attr_span: Span, msg_span: Span, message: &str) { + // Find the indent at the start of the message (`column()` is one-indexed) + let start = attr_span.unwrap().column() - 1; + + for line in message.lines().skip(1) { + if line.is_empty() { + continue; + } + let indent = line.chars().take_while(|c| *c == ' ').count(); + if indent < start { + span_err( + msg_span.unwrap(), + format!("message is not properly indented. {indent} < {start}"), + ) + .emit(); + return; + } + if indent % 4 != 0 { + span_err(msg_span.unwrap(), "message is not indented with a multiple of 4 spaces") + .emit(); + return; + } + } +} diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index c308f6126325..55a8445744cb 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -708,7 +708,7 @@ impl SubdiagnosticVariant { } if !input.is_empty() { input.parse::()?; } if is_first { - message = Some(Message { message_span: inline_message.span(), value: inline_message.value() }); + message = Some(Message { attr_span: attr.span(), message_span: inline_message.span(), value: inline_message.value() }); is_first = false; } else { span_err(inline_message.span().unwrap(), "a diagnostic message must be the first argument to the attribute").emit(); From 99c6009c45fd2c1b7f4740b96d9c634d83ad4a5a Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 7 Feb 2026 10:25:00 +0100 Subject: [PATCH 730/978] Reformat existing messages --- compiler/rustc_const_eval/src/errors.rs | 46 +++--- compiler/rustc_mir_build/src/errors.rs | 34 ++--- compiler/rustc_monomorphize/src/errors.rs | 6 +- compiler/rustc_parse/src/errors.rs | 2 +- compiler/rustc_passes/src/errors.rs | 4 +- compiler/rustc_trait_selection/src/errors.rs | 150 ++++++++++--------- 6 files changed, 122 insertions(+), 120 deletions(-) diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 3b49dbd907c8..a673e0cb1efb 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -106,9 +106,9 @@ pub(crate) struct UnstableInStableExposed { pub is_function_call2: bool, #[suggestion( "if the {$is_function_call2 -> - [true] caller - *[false] function -} is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`", + [true] caller + *[false] function + } is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`", code = "#[rustc_const_unstable(feature = \"...\", issue = \"...\")]\n", applicability = "has-placeholders" )] @@ -300,11 +300,11 @@ pub(crate) struct UnallowedHeapAllocations { #[primary_span] #[label( r#"allocation not allowed in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"# + [const] constant + [static] static + [const_fn] constant function + *[other] {""} + }s"# )] pub span: Span, pub kind: ConstContext, @@ -539,20 +539,20 @@ pub enum NonConstClosureNote { }, #[note( r#"function pointers need an RFC before allowed to be called in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"# + [const] constant + [static] static + [const_fn] constant function + *[other] {""} + }s"# )] FnPtr, #[note( r#"closures need an RFC before allowed to be called in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"# + [const] constant + [static] static + [const_fn] constant function + *[other] {""} + }s"# )] Closure, } @@ -608,11 +608,11 @@ pub struct LiveDrop<'tcx> { #[primary_span] #[label( r#"the destructor for this type cannot be evaluated in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"# + [const] constant + [static] static + [const_fn] constant function + *[other] {""} + }s"# )] pub span: Span, pub kind: ConstContext, diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 2474b3c49a61..fed0435f59a0 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -198,12 +198,12 @@ pub(crate) struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { pub(crate) missing_target_features: DiagArgValue, pub(crate) missing_target_features_count: usize, #[note("the {$build_target_features} target {$build_target_features_count -> - [1] feature - *[count] features + [1] feature + *[count] features } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> - [1] it -*[count] them -} in `#[target_feature]`")] + [1] it + *[count] them + } in `#[target_feature]`")] pub(crate) note: bool, pub(crate) build_target_features: DiagArgValue, pub(crate) build_target_features_count: usize, @@ -532,12 +532,12 @@ pub(crate) struct CallToFunctionWithRequiresUnsafe { pub(crate) missing_target_features: DiagArgValue, pub(crate) missing_target_features_count: usize, #[note("the {$build_target_features} target {$build_target_features_count -> - [1] feature - *[count] features -} being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> - [1] it - *[count] them -} in `#[target_feature]`")] + [1] feature + *[count] features + } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it + *[count] them + } in `#[target_feature]`")] pub(crate) note: bool, pub(crate) build_target_features: DiagArgValue, pub(crate) build_target_features_count: usize, @@ -1264,9 +1264,9 @@ pub(crate) struct InterpretedAsConstSugg { pub(crate) enum SuggestLet { #[multipart_suggestion( "you might want to use `if let` to ignore the {$count -> -[one] variant that isn't -*[other] variants that aren't -} matched", + [one] variant that isn't + *[other] variants that aren't + } matched", applicability = "has-placeholders" )] If { @@ -1278,9 +1278,9 @@ pub(crate) enum SuggestLet { }, #[suggestion( "you might want to use `let...else` to handle the {$count -> -[one] variant that isn't -*[other] variants that aren't -} matched", + [one] variant that isn't + *[other] variants that aren't + } matched", code = " else {{ todo!() }}", applicability = "has-placeholders" )] diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index d045ae0b92cb..62a8743873bd 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -162,9 +162,9 @@ pub(crate) struct AbiRequiredTargetFeature<'a> { #[primary_span] #[label( "function {$is_call -> -[true] called -*[false] defined -} here" + [true] called + *[false] defined + } here" )] pub span: Span, pub required_feature: &'a str, diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index b54782ec592c..fb77af1c1948 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1151,7 +1151,7 @@ pub(crate) enum MatchArmBodyWithoutBracesSugg { #[multipart_suggestion( "surround the {$num_statements -> [one] statement - *[other] statements + *[other] statements } with a body", applicability = "machine-applicable" )] diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 90b4d1b32bf7..f420bba9b4e9 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1417,8 +1417,8 @@ pub(crate) struct DuplicateEiiImpls { pub second_crate: Symbol, #[note("in addition to these two, { $num_additional_crates -> - [one] another implementation was found in crate {$additional_crate_names} - *[other] more implementations were also found in the following crates: {$additional_crate_names} + [one] another implementation was found in crate {$additional_crate_names} + *[other] more implementations were also found in the following crates: {$additional_crate_names} }")] pub additional_crates: Option<()>, diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index c904eb83896d..013e4b522fb5 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -327,18 +327,18 @@ pub struct InferenceBadError<'a> { pub enum SourceKindSubdiag<'a> { #[suggestion( "{$kind -> -[with_pattern] consider giving `{$name}` an explicit type -[closure] consider giving this closure parameter an explicit type -*[other] consider giving this pattern a type -}{$x_kind -> -[has_name] , where the {$prefix_kind -> -*[type] type for {$prefix} -[const_with_param] value of const parameter -[const] value of the constant -} `{$arg_name}` is specified -[underscore] , where the placeholders `_` are specified -*[empty] {\"\"} -}", + [with_pattern] consider giving `{$name}` an explicit type + [closure] consider giving this closure parameter an explicit type + *[other] consider giving this pattern a type + }{$x_kind -> + [has_name] , where the {$prefix_kind -> + *[type] type for {$prefix} + [const_with_param] value of const parameter + [const] value of the constant + } `{$arg_name}` is specified + [underscore] , where the placeholders `_` are specified + *[empty] {\"\"} + }", style = "verbose", code = ": {type_name}", applicability = "has-placeholders" @@ -356,15 +356,15 @@ pub enum SourceKindSubdiag<'a> { }, #[label( "cannot infer {$is_type -> -[true] type -*[false] the value -} of the {$is_type -> -[true] type -*[false] const -} {$parent_exists -> -[true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}` -*[false] parameter {$param_name} -}" + [true] type + *[false] the value + } of the {$is_type -> + [true] type + *[false] const + } {$parent_exists -> + [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}` + *[false] parameter {$param_name} + }" )] GenericLabel { #[primary_span] @@ -377,9 +377,9 @@ pub enum SourceKindSubdiag<'a> { }, #[suggestion( "consider specifying the generic {$arg_count -> -[one] argument -*[other] arguments -}", + [one] argument + *[other] arguments + }", style = "verbose", code = "::<{args}>", applicability = "has-placeholders" @@ -945,9 +945,9 @@ impl IntoDiagArg for TyOrSig<'_> { #[derive(Subdiagnostic)] pub enum ActualImplExplNotes<'tcx> { #[note("{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] + [true] ... + *[false] {\"\"} + }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedSignatureTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -956,9 +956,9 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_2: usize, }, #[note("{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...")] + [true] ... + *[false] {\"\"} + }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...")] ExpectedSignatureAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -966,9 +966,9 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, }, #[note("{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...")] + [true] ... + *[false] {\"\"} + }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...")] ExpectedSignatureSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -977,9 +977,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`" + [true] ... + *[false] {\"\"} + }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`" )] ExpectedSignatureNothing { leading_ellipsis: bool, @@ -987,9 +987,9 @@ pub enum ActualImplExplNotes<'tcx> { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, #[note("{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] + [true] ... + *[false] {\"\"} + }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedPassiveTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -998,9 +998,9 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_2: usize, }, #[note("{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...")] + [true] ... + *[false] {\"\"} + }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...")] ExpectedPassiveAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -1008,9 +1008,9 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, }, #[note("{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...")] + [true] ... + *[false] {\"\"} + }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...")] ExpectedPassiveSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -1019,9 +1019,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`" + [true] ... + *[false] {\"\"} + }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`" )] ExpectedPassiveNothing { leading_ellipsis: bool, @@ -1029,9 +1029,9 @@ pub enum ActualImplExplNotes<'tcx> { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, #[note("{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] + [true] ... + *[false] {\"\"} + }`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedOtherTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -1041,9 +1041,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`..." + [true] ... + *[false] {\"\"} + }`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`..." )] ExpectedOtherAny { leading_ellipsis: bool, @@ -1053,9 +1053,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`..." + [true] ... + *[false] {\"\"} + }`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`..." )] ExpectedOtherSome { leading_ellipsis: bool, @@ -1065,9 +1065,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$ty_or_sig}` must implement `{$trait_path}`" + [true] ... + *[false] {\"\"} + }`{$ty_or_sig}` must implement `{$trait_path}`" )] ExpectedOtherNothing { leading_ellipsis: bool, @@ -1076,9 +1076,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "...but it actually implements `{$trait_path}`{$has_lifetime -> -[true] , for some specific lifetime `'{$lifetime}` -*[false] {\"\"} -}" + [true] , for some specific lifetime `'{$lifetime}` + *[false] {\"\"} + }" )] ButActuallyImplementsTrait { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, @@ -1087,9 +1087,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime -> -[true] , for some specific lifetime `'{$lifetime}` -*[false] {\"\"} -}" + [true] , for some specific lifetime `'{$lifetime}` + *[false] {\"\"} + }" )] ButActuallyImplementedForTy { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, @@ -1099,9 +1099,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime -> -[true] , for some specific lifetime `'{$lifetime}` -*[false] {\"\"} -}" + [true] , for some specific lifetime `'{$lifetime}` + *[false] {\"\"} + }" )] ButActuallyTyImplements { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, @@ -1246,7 +1246,7 @@ pub struct TraitImplDiff { pub trait_sp: Span, #[note( "expected signature `{$expected}` - {\" \"}found signature `{$found}`" + {\" \"}found signature `{$found}`" )] pub note: (), #[subdiagnostic] @@ -1940,10 +1940,12 @@ pub enum ObligationCauseFailureCode { #[primary_span] span: Span, }, - #[diag("{$lang_item_name -> -[panic_impl] `#[panic_handler]` -*[lang_item_name] lang item `{$lang_item_name}` -} function has wrong type", code = E0308)] + #[diag( + "{$lang_item_name -> + [panic_impl] `#[panic_handler]` + *[lang_item_name] lang item `{$lang_item_name}` + } function has wrong type" + , code = E0308)] FnLangCorrectType { #[primary_span] span: Span, From d3d4fd9312da82cbb0b17a597f458b282febfea7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 9 Feb 2026 10:14:40 +1100 Subject: [PATCH 731/978] Tweak query key trait bounds. Query keys must be stably hashable. Currently this requirement is expressed as a where-clause on `impl QueryDispatcher for SemiDynamicQueryDispatcher` and a where-clause on `create_deferred_query_stack_frame`. This commit removes those where-clause bounds and adds a single bound to `QueryCache::Key`, which already has some other bounds. I.e. it consolidates the bounds. It also gives them a name (`QueryCacheKey`) to avoid repeating them. There is also a related `Key` trait in `rustc_middle`; it should probably be merged with `QueryCacheKey` in the future, but not today. This cleanup helps with the next two commits, which do bigger rearrangements, and where the where-clauses caused me some difficulties. --- compiler/rustc_query_impl/src/lib.rs | 4 ---- compiler/rustc_query_impl/src/plumbing.rs | 3 +-- compiler/rustc_query_system/src/lib.rs | 1 + compiler/rustc_query_system/src/query/caches.rs | 11 ++++++++--- compiler/rustc_query_system/src/query/mod.rs | 4 +++- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 228d0070b55b..7e12365fc2ac 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -10,7 +10,6 @@ use std::marker::ConstParamTy; -use rustc_data_structures::stable_hasher::HashStable; use rustc_data_structures::sync::AtomicU64; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::{self, DepKind, DepKindVTable, DepNodeIndex}; @@ -23,7 +22,6 @@ use rustc_middle::query::plumbing::{QuerySystem, QuerySystemFns, QueryVTable}; use rustc_middle::query::values::Value; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::SerializedDepNodeIndex; -use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ CycleError, CycleErrorHandling, HashResult, QueryCache, QueryDispatcher, QueryMap, QueryMode, QueryState, @@ -78,8 +76,6 @@ impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> Clone // This is `impl QueryDispatcher for SemiDynamicQueryDispatcher`. impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> QueryDispatcher<'tcx> for SemiDynamicQueryDispatcher<'tcx, C, FLAGS> -where - for<'a> C::Key: HashStable>, { type Qcx = QueryCtxt<'tcx>; type Key = C::Key; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 676d01be3385..dd8ea35019a4 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -27,7 +27,6 @@ use rustc_middle::ty::print::with_reduced_queries; use rustc_middle::ty::tls::{self, ImplicitCtxt}; use rustc_middle::ty::{self, TyCtxt}; use rustc_query_system::dep_graph::{DepNodeKey, FingerprintStyle, HasDepContext}; -use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ QueryCache, QueryContext, QueryDispatcher, QueryJobId, QueryMap, QuerySideEffect, QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, @@ -360,7 +359,7 @@ pub(crate) fn create_deferred_query_stack_frame<'tcx, Cache>( ) -> QueryStackFrame> where Cache: QueryCache, - Cache::Key: Key + DynSend + DynSync + for<'a> HashStable> + 'tcx, + Cache::Key: Key + DynSend + DynSync, { let kind = vtable.dep_kind; diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index 7f6426e395f9..fc63df3595c4 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -2,6 +2,7 @@ #![allow(internal_features)] #![feature(assert_matches)] #![feature(min_specialization)] +#![feature(trait_alias)] // tidy-alphabetical-end pub mod dep_graph; diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs index 67ad767d4d31..c1f5e5b67085 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_query_system/src/query/caches.rs @@ -3,12 +3,17 @@ use std::hash::Hash; use std::sync::OnceLock; use rustc_data_structures::sharded::ShardedHashMap; +use rustc_data_structures::stable_hasher::HashStable; pub use rustc_data_structures::vec_cache::VecCache; use rustc_hir::def_id::LOCAL_CRATE; use rustc_index::Idx; use rustc_span::def_id::{DefId, DefIndex}; use crate::dep_graph::DepNodeIndex; +use crate::ich::StableHashingContext; + +/// Traits that all query keys must satisfy. +pub trait QueryCacheKey = Hash + Eq + Copy + Debug + for<'a> HashStable>; /// Trait for types that serve as an in-memory cache for query results, /// for a given key (argument) type and value (return) type. @@ -16,7 +21,7 @@ use crate::dep_graph::DepNodeIndex; /// Types implementing this trait are associated with actual key/value types /// by the `Cache` associated type of the `rustc_middle::query::Key` trait. pub trait QueryCache: Sized { - type Key: Hash + Eq + Copy + Debug; + type Key: QueryCacheKey; type Value: Copy; /// Returns the cached value (and other information) associated with the @@ -48,7 +53,7 @@ impl Default for DefaultCache { impl QueryCache for DefaultCache where - K: Eq + Hash + Copy + Debug, + K: QueryCacheKey, V: Copy, { type Key = K; @@ -175,7 +180,7 @@ where impl QueryCache for VecCache where - K: Idx + Eq + Hash + Copy + Debug, + K: Idx + QueryCacheKey, V: Copy, { type Key = K; diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 29a572b726f0..01bb6ff09fa1 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -12,7 +12,9 @@ use rustc_macros::{Decodable, Encodable}; use rustc_span::Span; use rustc_span::def_id::DefId; -pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache}; +pub use self::caches::{ + DefIdCache, DefaultCache, QueryCache, QueryCacheKey, SingleCache, VecCache, +}; pub use self::dispatcher::{HashResult, QueryDispatcher}; pub use self::job::{ QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, QueryMap, break_query_cycles, From 52caa7ae6d06a43f9fb07d37ba39c233e9273455 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 9 Feb 2026 10:38:44 +1100 Subject: [PATCH 732/978] Remove `QueryDispatcherUnerased::Dispatcher` associated type. It's always `SemiDynamicQueryDispatcher`, so we can just use that type directly. (This requires adding some explicit generic params to `QueryDispatcherUnerased`.) Less indirection makes the code clearer, and this is a prerequisite for the next commit, which is a much bigger simplification. --- compiler/rustc_query_impl/src/lib.rs | 9 ++--- compiler/rustc_query_impl/src/plumbing.rs | 44 ++++++++++++++--------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 7e12365fc2ac..327a8f4bc6c4 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -207,17 +207,14 @@ impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> QueryDispatcher<'tcx> /// /// There is one macro-generated implementation of this trait for each query, /// on the type `rustc_query_impl::query_impl::$name::QueryType`. -trait QueryDispatcherUnerased<'tcx> { +trait QueryDispatcherUnerased<'tcx, C: QueryCache, const FLAGS: QueryFlags> { type UnerasedValue; - type Dispatcher: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>; const NAME: &'static &'static str; - fn query_dispatcher(tcx: TyCtxt<'tcx>) -> Self::Dispatcher; + fn query_dispatcher(tcx: TyCtxt<'tcx>) -> SemiDynamicQueryDispatcher<'tcx, C, FLAGS>; - fn restore_val( - value: >::Value, - ) -> Self::UnerasedValue; + fn restore_val(value: C::Value) -> Self::UnerasedValue; } pub fn query_system<'tcx>( diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index dd8ea35019a4..bbda716eadb0 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -34,9 +34,9 @@ use rustc_query_system::query::{ use rustc_serialize::{Decodable, Encodable}; use rustc_span::def_id::LOCAL_CRATE; -use crate::QueryDispatcherUnerased; use crate::error::{QueryOverflow, QueryOverflowNote}; use crate::execution::{all_inactive, force_query}; +use crate::{QueryDispatcherUnerased, QueryFlags, SemiDynamicQueryDispatcher}; /// Implements [`QueryContext`] for use by [`rustc_query_system`], since that /// crate does not have direct access to [`TyCtxt`]. @@ -377,13 +377,13 @@ where QueryStackFrame::new(info, kind, hash, def_id, def_id_for_ty_in_cycle) } -pub(crate) fn encode_query_results<'a, 'tcx, Q>( - query: Q::Dispatcher, +pub(crate) fn encode_query_results<'a, 'tcx, Q, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, qcx: QueryCtxt<'tcx>, encoder: &mut CacheEncoder<'a, 'tcx>, query_result_index: &mut EncodedDepNodeIndex, ) where - Q: QueryDispatcherUnerased<'tcx>, + Q: QueryDispatcherUnerased<'tcx, C, FLAGS>, Q::UnerasedValue: Encodable>, { let _timer = qcx.tcx.prof.generic_activity_with_arg("encode_query_results_for", query.name()); @@ -506,17 +506,22 @@ where } } -pub(crate) fn make_dep_kind_vtable_for_query<'tcx, Q>( +pub(crate) fn make_dep_kind_vtable_for_query< + 'tcx, + Q, + C: QueryCache + 'tcx, + const FLAGS: QueryFlags, +>( is_anon: bool, is_eval_always: bool, ) -> DepKindVTable<'tcx> where - Q: QueryDispatcherUnerased<'tcx>, + Q: QueryDispatcherUnerased<'tcx, C, FLAGS>, { let fingerprint_style = if is_anon { FingerprintStyle::Opaque } else { - ::Key::fingerprint_style() + >>::fingerprint_style() }; if is_anon || !fingerprint_style.reconstructible() { @@ -712,25 +717,26 @@ macro_rules! define_queries { is_feedable: feedable!([$($modifiers)*]), }; - impl<'tcx> QueryDispatcherUnerased<'tcx> for QueryType<'tcx> { + impl<'tcx> QueryDispatcherUnerased<'tcx, queries::$name::Storage<'tcx>, FLAGS> + for QueryType<'tcx> + { type UnerasedValue = queries::$name::Value<'tcx>; - type Dispatcher = SemiDynamicQueryDispatcher< - 'tcx, - queries::$name::Storage<'tcx>, - FLAGS, - >; const NAME: &'static &'static str = &stringify!($name); #[inline(always)] - fn query_dispatcher(tcx: TyCtxt<'tcx>) -> Self::Dispatcher { + fn query_dispatcher(tcx: TyCtxt<'tcx>) + -> SemiDynamicQueryDispatcher<'tcx, queries::$name::Storage<'tcx>, FLAGS> + { SemiDynamicQueryDispatcher { vtable: &tcx.query_system.query_vtables.$name, } } #[inline(always)] - fn restore_val(value: >::Value) -> Self::UnerasedValue { + fn restore_val(value: as QueryCache>::Value) + -> Self::UnerasedValue + { erase::restore_val::>(value) } } @@ -786,7 +792,11 @@ macro_rules! define_queries { encoder: &mut CacheEncoder<'_, 'tcx>, query_result_index: &mut EncodedDepNodeIndex ) { - $crate::plumbing::encode_query_results::>( + $crate::plumbing::encode_query_results::< + query_impl::$name::QueryType<'tcx>, + _, + _ + > ( query_impl::$name::QueryType::query_dispatcher(tcx), QueryCtxt::new(tcx), encoder, @@ -958,7 +968,7 @@ macro_rules! define_queries { $(pub(crate) fn $name<'tcx>() -> DepKindVTable<'tcx> { use $crate::query_impl::$name::QueryType; - $crate::plumbing::make_dep_kind_vtable_for_query::>( + $crate::plumbing::make_dep_kind_vtable_for_query::, _, _>( is_anon!([$($modifiers)*]), is_eval_always!([$($modifiers)*]), ) From 1fa165deeeff28e9b8b4a2de16b92c0844059f69 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 8 Feb 2026 22:01:24 -0500 Subject: [PATCH 733/978] style: remove unneeded trailing commas Make format-like macro calls look similar to what `cargo fmt` does automatically - remove trailing commas. When removing a comma, I also inlined some variables for consistency and clarity. --- .../infer/nice_region_error/find_anon_type.rs | 4 ++-- .../infer/nice_region_error/static_impl_trait.rs | 6 +++--- .../src/error_reporting/traits/ambiguity.rs | 6 +++--- .../src/error_reporting/traits/fulfillment_errors.rs | 2 +- .../src/error_reporting/traits/on_unimplemented.rs | 2 +- .../src/traits/select/candidate_assembly.rs | 8 ++++---- compiler/rustc_trait_selection/src/traits/select/mod.rs | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs index 8fe4ffebd865..7d061e65df80 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs @@ -190,8 +190,8 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { } Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)) => { - debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,); - debug!("id={:?}", id); + debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {debruijn_index:?}"); + debug!("id={id:?}"); if debruijn_index == self.current_index && id.to_def_id() == self.region_def_id { return ControlFlow::Break(()); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index 3ee6e6b739c0..3ed1f7c3481f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -239,14 +239,14 @@ pub fn suggest_new_region_bound( }; spans_suggs.push((fn_return.span.shrink_to_hi(), format!(" + {name} "))); err.multipart_suggestion_verbose( - format!("{declare} `{ty}` {captures}, {use_lt}",), + format!("{declare} `{ty}` {captures}, {use_lt}"), spans_suggs, Applicability::MaybeIncorrect, ); } else { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), - format!("{declare} `{ty}` {captures}, {explicit}",), + format!("{declare} `{ty}` {captures}, {explicit}"), &plus_lt, Applicability::MaybeIncorrect, ); @@ -257,7 +257,7 @@ pub fn suggest_new_region_bound( if let LifetimeKind::ImplicitObjectLifetimeDefault = lt.kind { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), - format!("{declare} the trait object {captures}, {explicit}",), + format!("{declare} the trait object {captures}, {explicit}"), &plus_lt, Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index eb72f71382ef..16c4ac68cdf0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -710,7 +710,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { predicate ); let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) { - format!(":\n{}", post.iter().map(|p| format!("- {p}")).collect::>().join("\n"),) + format!(":\n{}", post.iter().map(|p| format!("- {p}")).collect::>().join("\n")) } else if post.len() == 1 { format!(": `{}`", post[0]) } else { @@ -722,7 +722,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.note(format!("cannot satisfy `{predicate}`")); } (0, _, 1) => { - err.note(format!("{} in the `{}` crate{}", msg, crates[0], post,)); + err.note(format!("{msg} in the `{}` crate{post}", crates[0])); } (0, _, _) => { err.note(format!( @@ -739,7 +739,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { (_, 1, 1) => { let span: MultiSpan = spans.into(); err.span_note(span, msg); - err.note(format!("and another `impl` found in the `{}` crate{}", crates[0], post,)); + err.note(format!("and another `impl` found in the `{}` crate{post}", crates[0])); } _ => { let span: MultiSpan = spans.into(); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 3cb3224302b6..18597e001c9f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -2241,7 +2241,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.highlighted_span_help( self.tcx.def_span(def_id), vec![ - StringPart::normal(format!("the trait `{trait_}` ",)), + StringPart::normal(format!("the trait `{trait_}` ")), StringPart::highlighted("is"), StringPart::normal(desc), StringPart::highlighted(self_ty), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 5eff7bba7c63..a98f952d55a3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -888,7 +888,7 @@ impl<'tcx> OnUnimplementedFormatString { } } else { let reported = - struct_span_code_err!(tcx.dcx(), self.span, E0231, "{}", e.description,) + struct_span_code_err!(tcx.dcx(), self.span, E0231, "{}", e.description) .emit(); result = Err(reported); } 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 f5bf74a79919..935834b832f2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -312,7 +312,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // `async`/`gen` constructs get lowered to a special kind of coroutine that // should *not* `impl Coroutine`. ty::Coroutine(did, ..) if self.tcx().is_general_coroutine(*did) => { - debug!(?self_ty, ?obligation, "assemble_coroutine_candidates",); + debug!(?self_ty, ?obligation, "assemble_coroutine_candidates"); candidates.vec.push(CoroutineCandidate); } @@ -334,7 +334,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // async constructs get lowered to a special kind of coroutine that // should directly `impl Future`. if self.tcx().coroutine_is_async(*did) { - debug!(?self_ty, ?obligation, "assemble_future_candidates",); + debug!(?self_ty, ?obligation, "assemble_future_candidates"); candidates.vec.push(FutureCandidate); } @@ -352,7 +352,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let ty::Coroutine(did, ..) = self_ty.kind() && self.tcx().coroutine_is_gen(*did) { - debug!(?self_ty, ?obligation, "assemble_iterator_candidates",); + debug!(?self_ty, ?obligation, "assemble_iterator_candidates"); candidates.vec.push(IteratorCandidate); } @@ -378,7 +378,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // gen constructs get lowered to a special kind of coroutine that // should directly `impl AsyncIterator`. if self.tcx().coroutine_is_async_gen(did) { - debug!(?self_ty, ?obligation, "assemble_iterator_candidates",); + debug!(?self_ty, ?obligation, "assemble_iterator_candidates"); // Can only confirm this candidate if we have constrained // the `Yield` type to at least `Poll>`.. diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 787dd4ea6254..2233fb4f90e4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1223,7 +1223,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { && self.match_fresh_trait_preds(stack.fresh_trait_pred, prev.fresh_trait_pred) }) { - debug!("evaluate_stack --> unbound argument, recursive --> giving up",); + debug!("evaluate_stack --> unbound argument, recursive --> giving up"); return Ok(EvaluatedToAmbigStackDependent); } From 81fb703664280626c03428c384695d766be10031 Mon Sep 17 00:00:00 2001 From: Weixie Cui Date: Sun, 8 Feb 2026 11:44:50 +0800 Subject: [PATCH 734/978] Fix copy-paste bug: use sub_trace.cause instead of sup_trace.cause in report_sub_sup_conflict In `report_sub_sup_conflict`, when calling `values_str` for `sub_trace.values`, the code was incorrectly passing `sup_trace.cause` instead of `sub_trace.cause`. This is a copy-paste error from the preceding line which correctly uses `sup_trace.cause` for `sup_trace.values`. The `cause` parameter matters for `ValuePairs::PolySigs` comparisons, where `values_str` inspects `cause.code()` to extract `impl_item_def_id` and `trait_item_def_id` for richer function signature diagnostics. Using the wrong trace's cause could produce incorrect function def IDs, leading to misleading diagnostic output when the sub and sup traces originate from different obligations. Even for non-PolySigs variants where `cause` is currently unused by `values_str`, passing the semantically correct cause is the right thing to do for correctness and maintainability. --- .../rustc_trait_selection/src/error_reporting/infer/region.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index d15fb40dd1cb..81cca3dd67ac 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -1020,7 +1020,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let Some((sup_expected, sup_found)) = self.values_str(sup_trace.values, &sup_trace.cause, err.long_ty_path()) && let Some((sub_expected, sub_found)) = - self.values_str(sub_trace.values, &sup_trace.cause, err.long_ty_path()) + self.values_str(sub_trace.values, &sub_trace.cause, err.long_ty_path()) && sub_expected == sup_expected && sub_found == sup_found { From 3b705eae4fe9f16efd8193fc5dc822fc9e66e5da Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 9 Feb 2026 14:24:59 +0800 Subject: [PATCH 735/978] Add ui test insufficient-suggestion-issue-141679.rs --- .../insufficient-suggestion-issue-141679.rs | 8 ++++++++ .../insufficient-suggestion-issue-141679.stderr | 11 +++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.rs create mode 100644 tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.stderr diff --git a/tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.rs b/tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.rs new file mode 100644 index 000000000000..daf8693b5264 --- /dev/null +++ b/tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.rs @@ -0,0 +1,8 @@ +use std::rc::Rc; +pub struct Foo; + +pub type Function = Rc; + +impl Function {} +//~^ ERROR cannot define inherent `impl` for a type outside of the crate where the type is defined [E0116] +fn main(){} \ No newline at end of file diff --git a/tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.stderr b/tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.stderr new file mode 100644 index 000000000000..cbb94ea4d367 --- /dev/null +++ b/tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.stderr @@ -0,0 +1,11 @@ +error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined + --> $DIR/insufficient-suggestion-issue-141679.rs:6:1 + | +LL | impl Function {} + | ^^^^^^^^^^^^^ impl for type defined outside of crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0116`. From 91a612620822993435a49c288256c1028351a236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 9 Feb 2026 07:36:48 +0100 Subject: [PATCH 736/978] Use `scope` for `par_slice` instead of `join` --- .../src/sync/parallel.rs | 41 +++++++------------ 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs index b515c0bee8a6..552d02b8b91d 100644 --- a/compiler/rustc_data_structures/src/sync/parallel.rs +++ b/compiler/rustc_data_structures/src/sync/parallel.rs @@ -138,34 +138,21 @@ fn par_slice( guard: &ParallelGuard, for_each: impl Fn(&mut I) + DynSync + DynSend, ) { - struct State<'a, F> { - for_each: FromDyn, - guard: &'a ParallelGuard, - group: usize, - } - - fn par_rec( - items: &mut [I], - state: &State<'_, F>, - ) { - if items.len() <= state.group { - for item in items { - state.guard.run(|| (state.for_each)(item)); - } - } else { - let (left, right) = items.split_at_mut(items.len() / 2); - let mut left = state.for_each.derive(left); - let mut right = state.for_each.derive(right); - rustc_thread_pool::join(move || par_rec(*left, state), move || par_rec(*right, state)); + let for_each = FromDyn::from(for_each); + let mut items = for_each.derive(items); + rustc_thread_pool::scope(|s| { + let proof = items.derive(()); + let group_size = std::cmp::max(items.len() / 128, 1); + for group in items.chunks_exact_mut(group_size) { + let group = proof.derive(group); + s.spawn(|_| { + let mut group = group; + for i in group.iter_mut() { + guard.run(|| for_each(i)); + } + }); } - } - - let state = State { - for_each: FromDyn::from(for_each), - guard, - group: std::cmp::max(items.len() / 128, 1), - }; - par_rec(items, &state) + }); } pub fn par_for_each_in>( From f24839539428bca14becbf813d0352e1aff17c18 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Sun, 8 Feb 2026 17:00:47 +0800 Subject: [PATCH 737/978] bless tests --- tests/crashes/137916.rs | 13 ---- tests/crashes/138274.rs | 18 ------ tests/ui/async-await/issue-70818.rs | 3 +- tests/ui/async-await/issue-70818.stderr | 23 +------ .../async-await/issue-70935-complex-spans.rs | 1 - .../issue-70935-complex-spans.stderr | 47 +------------- tests/ui/coroutine/issue-105084.rs | 1 - tests/ui/coroutine/issue-105084.stderr | 29 +-------- .../stalled-coroutine-obligations.rs | 32 ++++++++++ .../stalled-coroutine-obligations.stderr | 40 ++++++++++++ .../stalled-coroutine-obligations.rs | 50 +++++++++++++++ .../stalled-coroutine-obligations.stderr | 62 +++++++++++++++++++ 12 files changed, 190 insertions(+), 129 deletions(-) delete mode 100644 tests/crashes/137916.rs delete mode 100644 tests/crashes/138274.rs create mode 100644 tests/ui/coroutine/stalled-coroutine-obligations.rs create mode 100644 tests/ui/coroutine/stalled-coroutine-obligations.stderr create mode 100644 tests/ui/traits/next-solver/stalled-coroutine-obligations.rs create mode 100644 tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr diff --git a/tests/crashes/137916.rs b/tests/crashes/137916.rs deleted file mode 100644 index b25e7b200d95..000000000000 --- a/tests/crashes/137916.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #137916 -//@ edition: 2021 -use std::ptr::null; - -async fn a() -> Box { - Box::new(async { - let non_send = null::<()>(); - &non_send; - async {}.await - }) -} - -fn main() {} diff --git a/tests/crashes/138274.rs b/tests/crashes/138274.rs deleted file mode 100644 index d657b27e46f3..000000000000 --- a/tests/crashes/138274.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ known-bug: #138274 -//@ edition: 2021 -//@ compile-flags: --crate-type=lib -trait Trait {} - -fn foo() -> Box { - todo!() -} - -fn fetch() { - async { - let fut = async { - let _x = foo(); - async {}.await; - }; - let _: Box = Box::new(fut); - }; -} diff --git a/tests/ui/async-await/issue-70818.rs b/tests/ui/async-await/issue-70818.rs index c11332fe7d84..af9f33d9050b 100644 --- a/tests/ui/async-await/issue-70818.rs +++ b/tests/ui/async-await/issue-70818.rs @@ -2,9 +2,8 @@ use std::future::Future; fn foo(ty: T, ty1: U) -> impl Future + Send { - //~^ ERROR future cannot be sent between threads safely + //~^ ERROR: future cannot be sent between threads safely async { (ty, ty1) } - //~^ ERROR future cannot be sent between threads safely } fn main() {} diff --git a/tests/ui/async-await/issue-70818.stderr b/tests/ui/async-await/issue-70818.stderr index 07fd20cdd77e..8de6a825042b 100644 --- a/tests/ui/async-await/issue-70818.stderr +++ b/tests/ui/async-await/issue-70818.stderr @@ -1,24 +1,3 @@ -error: future cannot be sent between threads safely - --> $DIR/issue-70818.rs:6:5 - | -LL | async { (ty, ty1) } - | ^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` - | -note: captured value is not `Send` - --> $DIR/issue-70818.rs:6:18 - | -LL | async { (ty, ty1) } - | ^^^ has type `U` which is not `Send` -note: required by a bound in an opaque type - --> $DIR/issue-70818.rs:4:69 - | -LL | fn foo(ty: T, ty1: U) -> impl Future + Send { - | ^^^^ -help: consider restricting type parameter `U` with trait `Send` - | -LL | fn foo(ty: T, ty1: U) -> impl Future + Send { - | +++++++++++++++++++ - error: future cannot be sent between threads safely --> $DIR/issue-70818.rs:4:38 | @@ -35,5 +14,5 @@ help: consider restricting type parameter `U` with trait `Send` LL | fn foo(ty: T, ty1: U) -> impl Future + Send { | +++++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/async-await/issue-70935-complex-spans.rs b/tests/ui/async-await/issue-70935-complex-spans.rs index 2851637ae78f..27826f79dcd9 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.rs +++ b/tests/ui/async-await/issue-70935-complex-spans.rs @@ -15,7 +15,6 @@ async fn baz(_c: impl FnMut() -> T) where T: Future { fn foo(x: NotSync) -> impl Future + Send { //~^ ERROR `*mut ()` cannot be shared between threads safely async move { - //~^ ERROR `*mut ()` cannot be shared between threads safely baz(|| async { foo(x.clone()); }).await; diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr index 31d15c459217..b9180c620b0d 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.stderr @@ -1,46 +1,3 @@ -error[E0277]: `*mut ()` cannot be shared between threads safely - --> $DIR/issue-70935-complex-spans.rs:17:5 - | -LL | / async move { -LL | | -LL | | baz(|| async { -LL | | foo(x.clone()); -LL | | }).await; -LL | | } - | |_____^ `*mut ()` cannot be shared between threads safely - | - = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()` -note: required because it appears within the type `PhantomData<*mut ()>` - --> $SRC_DIR/core/src/marker.rs:LL:COL -note: required because it appears within the type `NotSync` - --> $DIR/issue-70935-complex-spans.rs:9:8 - | -LL | struct NotSync(PhantomData<*mut ()>); - | ^^^^^^^ - = note: required for `&NotSync` to implement `Send` -note: required because it's used within this closure - --> $DIR/issue-70935-complex-spans.rs:19:13 - | -LL | baz(|| async { - | ^^ -note: required because it's used within this `async` fn body - --> $DIR/issue-70935-complex-spans.rs:12:67 - | -LL | async fn baz(_c: impl FnMut() -> T) where T: Future { - | ___________________________________________________________________^ -LL | | } - | |_^ -note: required because it's used within this `async` block - --> $DIR/issue-70935-complex-spans.rs:17:5 - | -LL | async move { - | ^^^^^^^^^^ -note: required by a bound in an opaque type - --> $DIR/issue-70935-complex-spans.rs:15:37 - | -LL | fn foo(x: NotSync) -> impl Future + Send { - | ^^^^ - error[E0277]: `*mut ()` cannot be shared between threads safely --> $DIR/issue-70935-complex-spans.rs:15:23 | @@ -57,7 +14,7 @@ LL | struct NotSync(PhantomData<*mut ()>); | ^^^^^^^ = note: required for `&NotSync` to implement `Send` note: required because it's used within this closure - --> $DIR/issue-70935-complex-spans.rs:19:13 + --> $DIR/issue-70935-complex-spans.rs:18:13 | LL | baz(|| async { | ^^ @@ -74,6 +31,6 @@ note: required because it's used within this `async` block LL | async move { | ^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coroutine/issue-105084.rs b/tests/ui/coroutine/issue-105084.rs index cddee4990175..4e9f6ee3a595 100644 --- a/tests/ui/coroutine/issue-105084.rs +++ b/tests/ui/coroutine/issue-105084.rs @@ -36,7 +36,6 @@ fn main() { // one inside `g` and one inside `h`. // Proceed and drop `t` in `g`. Pin::new(&mut g).resume(()); - //~^ ERROR borrow of moved value: `g` // Proceed and drop `t` in `h` -> double free! Pin::new(&mut h).resume(()); diff --git a/tests/ui/coroutine/issue-105084.stderr b/tests/ui/coroutine/issue-105084.stderr index 23c1fdc54592..a69d20e607a4 100644 --- a/tests/ui/coroutine/issue-105084.stderr +++ b/tests/ui/coroutine/issue-105084.stderr @@ -1,27 +1,3 @@ -error[E0382]: borrow of moved value: `g` - --> $DIR/issue-105084.rs:38:14 - | -LL | let mut g = #[coroutine] - | ----- move occurs because `g` has type `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`, which does not implement the `Copy` trait -... -LL | let mut h = copy(g); - | - value moved here -... -LL | Pin::new(&mut g).resume(()); - | ^^^^^^ value borrowed here after move - | -note: consider changing this parameter type in function `copy` to borrow instead if owning the value isn't necessary - --> $DIR/issue-105084.rs:10:21 - | -LL | fn copy(x: T) -> T { - | ---- ^ this parameter takes ownership of the value - | | - | in this function -help: consider cloning the value if the performance cost is acceptable - | -LL | let mut h = copy(g.clone()); - | ++++++++ - error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}` --> $DIR/issue-105084.rs:32:17 | @@ -45,7 +21,6 @@ note: required by a bound in `copy` LL | fn copy(x: T) -> T { | ^^^^ required by this bound in `copy` -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0382. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coroutine/stalled-coroutine-obligations.rs b/tests/ui/coroutine/stalled-coroutine-obligations.rs new file mode 100644 index 000000000000..89af3c9a583c --- /dev/null +++ b/tests/ui/coroutine/stalled-coroutine-obligations.rs @@ -0,0 +1,32 @@ +//@ edition: 2021 + +// Regression tests for #137916 and #138274 +// We now check stalled coroutine obligations eagerly at the start of `mir_borrowck`. +// So these unsatisfied bounds are caught before causing ICEs. +use std::ptr::null; + +async fn a() -> Box { + Box::new(async { + //~^ ERROR: future cannot be sent between threads safely + let non_send = null::<()>(); + &non_send; + async {}.await + }) +} + + +trait Trait {} +fn foo() -> Box { todo!() } + +fn fetch() { + async { + let fut = async { + let _x = foo(); + async {}.await; + }; + let _: Box = Box::new(fut); + //~^ ERROR: future cannot be sent between threads safely + }; +} + +fn main() {} diff --git a/tests/ui/coroutine/stalled-coroutine-obligations.stderr b/tests/ui/coroutine/stalled-coroutine-obligations.stderr new file mode 100644 index 000000000000..cbf395dd6cfb --- /dev/null +++ b/tests/ui/coroutine/stalled-coroutine-obligations.stderr @@ -0,0 +1,40 @@ +error: future cannot be sent between threads safely + --> $DIR/stalled-coroutine-obligations.rs:9:5 + | +LL | / Box::new(async { +LL | | +LL | | let non_send = null::<()>(); +LL | | &non_send; +LL | | async {}.await +LL | | }) + | |______^ future created by async block is not `Send` + | + = help: within `{async block@$DIR/stalled-coroutine-obligations.rs:9:14: 9:19}`, the trait `Send` is not implemented for `*const ()` +note: future is not `Send` as this value is used across an await + --> $DIR/stalled-coroutine-obligations.rs:13:18 + | +LL | let non_send = null::<()>(); + | -------- has type `*const ()` which is not `Send` +LL | &non_send; +LL | async {}.await + | ^^^^^ await occurs here, with `non_send` maybe used later + = note: required for the cast from `Box<{async block@$DIR/stalled-coroutine-obligations.rs:9:14: 9:19}>` to `Box` + +error: future cannot be sent between threads safely + --> $DIR/stalled-coroutine-obligations.rs:27:32 + | +LL | let _: Box = Box::new(fut); + | ^^^^^^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `Send` is not implemented for `dyn Trait` +note: future is not `Send` as this value is used across an await + --> $DIR/stalled-coroutine-obligations.rs:25:22 + | +LL | let _x = foo(); + | -- has type `Box` which is not `Send` +LL | async {}.await; + | ^^^^^ await occurs here, with `_x` maybe used later + = note: required for the cast from `Box<{async block@$DIR/stalled-coroutine-obligations.rs:23:19: 23:24}>` to `Box` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/next-solver/stalled-coroutine-obligations.rs b/tests/ui/traits/next-solver/stalled-coroutine-obligations.rs new file mode 100644 index 000000000000..7c789af9e4cc --- /dev/null +++ b/tests/ui/traits/next-solver/stalled-coroutine-obligations.rs @@ -0,0 +1,50 @@ +//@ edition: 2024 +//@ compile-flags: -Znext-solver --diagnostic-width=300 + +// Previously we check stalled coroutine obligations after borrowck pass. +// And we wrongly assume that these obligations hold in borrowck which leads to +// silent normalization failures. +// In the next solver, we register opaques types via `NormalizesTo` goals. +// So these failures also cause those opaques types not registered in storage. +// +// Regression test for #151322 and #151323. + +#![feature(type_alias_impl_trait)] +#![feature(negative_impls)] +#![feature(auto_traits)] + +fn stalled_copy_clone() { + type T = impl Copy; + let foo: T = async {}; + //~^ ERROR: the trait bound + + type U = impl Clone; + let bar: U = async {}; + //~^ ERROR: the trait bound +} + +auto trait Valid {} +struct False; +impl !Valid for False {} + +fn stalled_auto_traits() { + type T = impl Valid; + let a = False; + let foo: T = async { a }; + //~^ ERROR: the trait bound `False: Valid` is not satisfied +} + + +trait Trait { + fn stalled_send(&self, b: *mut ()) -> impl Future + Send { + //~^ ERROR: type mismatch resolving + //~| ERROR: type mismatch resolving + async move { + //~^ ERROR: type mismatch resolving + b + } + } +} + + +fn main() {} diff --git a/tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr b/tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr new file mode 100644 index 000000000000..6afa406bf367 --- /dev/null +++ b/tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr @@ -0,0 +1,62 @@ +error[E0277]: the trait bound `{async block@$DIR/stalled-coroutine-obligations.rs:18:18: 18:23}: Copy` is not satisfied + --> $DIR/stalled-coroutine-obligations.rs:18:14 + | +LL | let foo: T = async {}; + | ^ the trait `Copy` is not implemented for `{async block@$DIR/stalled-coroutine-obligations.rs:18:18: 18:23}` + +error[E0277]: the trait bound `{async block@$DIR/stalled-coroutine-obligations.rs:22:18: 22:23}: Clone` is not satisfied + --> $DIR/stalled-coroutine-obligations.rs:22:14 + | +LL | let bar: U = async {}; + | ^ the trait `Clone` is not implemented for `{async block@$DIR/stalled-coroutine-obligations.rs:22:18: 22:23}` + +error[E0277]: the trait bound `False: Valid` is not satisfied in `{async block@$DIR/stalled-coroutine-obligations.rs:33:18: 33:23}` + --> $DIR/stalled-coroutine-obligations.rs:33:14 + | +LL | let foo: T = async { a }; + | ^ ----- within this `{async block@$DIR/stalled-coroutine-obligations.rs:33:18: 33:23}` + | | + | unsatisfied trait bound + | +help: within `{async block@$DIR/stalled-coroutine-obligations.rs:33:18: 33:23}`, the trait `Valid` is not implemented for `False` + --> $DIR/stalled-coroutine-obligations.rs:27:1 + | +LL | struct False; + | ^^^^^^^^^^^^ +note: captured value does not implement `Valid` + --> $DIR/stalled-coroutine-obligations.rs:33:26 + | +LL | let foo: T = async { a }; + | ^ has type `False` which does not implement `Valid` + +error[E0271]: type mismatch resolving `impl Future + Send == {async block@$DIR/stalled-coroutine-obligations.rs:42:9: 42:19}` + --> $DIR/stalled-coroutine-obligations.rs:39:5 + | +LL | fn stalled_send(&self, b: *mut ()) -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `impl Future + Send == {async block@$DIR/stalled-coroutine-obligations.rs:42:9: 42:19}` + --> $DIR/stalled-coroutine-obligations.rs:42:9 + | +LL | / async move { +LL | | +LL | | b +LL | | } + | |_________^ types differ + +error[E0271]: type mismatch resolving `{async block@$DIR/stalled-coroutine-obligations.rs:42:9: 42:19} <: impl Future + Send` + --> $DIR/stalled-coroutine-obligations.rs:39:62 + | +LL | fn stalled_send(&self, b: *mut ()) -> impl Future + Send { + | ______________________________________________________________^ +LL | | +LL | | +LL | | async move { +... | +LL | | } + | |_____^ types differ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. From ed90b3566960797ca7afbeca6c64ff042bf52158 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 9 Feb 2026 15:06:55 +0800 Subject: [PATCH 738/978] Add note when inherent impl for a alias type defined outside of the crate --- .../src/coherence/inherent_impls.rs | 17 ++++++++++++++++- compiler/rustc_hir_analysis/src/errors.rs | 18 +++++++++++++++++- tests/ui/error-codes/E0116.stderr | 3 ++- .../insufficient-suggestion-issue-141679.rs | 2 +- ...insufficient-suggestion-issue-141679.stderr | 8 +++++++- .../no-attr-empty-impl.stderr | 12 ++++++++---- .../no-other-unrelated-errors.stderr | 3 ++- .../ui/traits/trait-or-new-type-instead.stderr | 3 ++- 8 files changed, 55 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index edaf33e493c0..588747f46d17 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -110,7 +110,22 @@ impl<'tcx> InherentCollect<'tcx> { Ok(()) } else { let impl_span = self.tcx.def_span(impl_def_id); - Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideNew { span: impl_span })) + let mut err = errors::InherentTyOutsideNew { span: impl_span, note: None }; + + if let hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)) = + self.tcx.hir_node_by_def_id(impl_def_id).expect_item().expect_impl().self_ty.kind + && let rustc_hir::def::Res::Def(DefKind::TyAlias, def_id) = path.res + { + let ty_name = self.tcx.def_path_str(def_id); + let alias_ty_name = self.tcx.type_of(def_id).skip_binder().to_string(); + err.note = Some(errors::InherentTyOutsideNewAliasNote { + span: self.tcx.def_span(def_id), + ty_name, + alias_ty_name, + }); + } + + Err(self.tcx.dcx().emit_err(err)) } } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 6a23b42ae098..fb79789df76e 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1223,11 +1223,27 @@ pub(crate) struct InherentTyOutsideRelevant { #[derive(Diagnostic)] #[diag("cannot define inherent `impl` for a type outside of the crate where the type is defined", code = E0116)] -#[note("define and implement a trait or new type instead")] +#[help( + "consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it" +)] +#[note( + "for more details about the orphan rules, see " +)] pub(crate) struct InherentTyOutsideNew { #[primary_span] #[label("impl for type defined outside of crate")] pub span: Span, + #[subdiagnostic] + pub note: Option, +} + +#[derive(Subdiagnostic)] +#[note("`{$ty_name}` does not define a new type, only an alias of `{$alias_ty_name}` defined here")] +pub(crate) struct InherentTyOutsideNewAliasNote { + #[primary_span] + pub span: Span, + pub ty_name: String, + pub alias_ty_name: String, } #[derive(Diagnostic)] diff --git a/tests/ui/error-codes/E0116.stderr b/tests/ui/error-codes/E0116.stderr index 1ea5a57f46db..20e3b196226a 100644 --- a/tests/ui/error-codes/E0116.stderr +++ b/tests/ui/error-codes/E0116.stderr @@ -4,7 +4,8 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher LL | impl Vec {} | ^^^^^^^^^^^^ impl for type defined outside of crate | - = note: define and implement a trait or new type instead + = help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it + = note: for more details about the orphan rules, see error: aborting due to 1 previous error diff --git a/tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.rs b/tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.rs index daf8693b5264..b13b6f418d42 100644 --- a/tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.rs +++ b/tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.rs @@ -5,4 +5,4 @@ pub type Function = Rc; impl Function {} //~^ ERROR cannot define inherent `impl` for a type outside of the crate where the type is defined [E0116] -fn main(){} \ No newline at end of file +fn main(){} diff --git a/tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.stderr b/tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.stderr index cbb94ea4d367..a62f7f82ba9d 100644 --- a/tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.stderr +++ b/tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.stderr @@ -4,7 +4,13 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher LL | impl Function {} | ^^^^^^^^^^^^^ impl for type defined outside of crate | - = note: define and implement a trait or new type instead + = help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it + = note: for more details about the orphan rules, see +note: `Function` does not define a new type, only an alias of `Rc` defined here + --> $DIR/insufficient-suggestion-issue-141679.rs:4:1 + | +LL | pub type Function = Rc; + | ^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr b/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr index f8491697910c..de61c3900d46 100644 --- a/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr +++ b/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr @@ -4,7 +4,8 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher LL | impl extern_crate::StructWithAttr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate | - = note: define and implement a trait or new type instead + = help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it + = note: for more details about the orphan rules, see error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined --> $DIR/no-attr-empty-impl.rs:7:1 @@ -12,7 +13,8 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher LL | impl extern_crate::StructNoAttr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate | - = note: define and implement a trait or new type instead + = help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it + = note: for more details about the orphan rules, see error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined --> $DIR/no-attr-empty-impl.rs:10:1 @@ -20,7 +22,8 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher LL | impl extern_crate::EnumWithAttr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate | - = note: define and implement a trait or new type instead + = help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it + = note: for more details about the orphan rules, see error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined --> $DIR/no-attr-empty-impl.rs:13:1 @@ -28,7 +31,8 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher LL | impl extern_crate::EnumNoAttr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate | - = note: define and implement a trait or new type instead + = help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it + = note: for more details about the orphan rules, see error[E0390]: cannot define inherent `impl` for primitive types --> $DIR/no-attr-empty-impl.rs:16:1 diff --git a/tests/ui/incoherent-inherent-impls/no-other-unrelated-errors.stderr b/tests/ui/incoherent-inherent-impls/no-other-unrelated-errors.stderr index 2a33262f8389..f01817e29443 100644 --- a/tests/ui/incoherent-inherent-impls/no-other-unrelated-errors.stderr +++ b/tests/ui/incoherent-inherent-impls/no-other-unrelated-errors.stderr @@ -4,7 +4,8 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher LL | impl Vec {} | ^^^^^^^^^^^^^^^ impl for type defined outside of crate | - = note: define and implement a trait or new type instead + = help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it + = note: for more details about the orphan rules, see error: aborting due to 1 previous error diff --git a/tests/ui/traits/trait-or-new-type-instead.stderr b/tests/ui/traits/trait-or-new-type-instead.stderr index 5f5aa3ac5698..ad12a84a4b80 100644 --- a/tests/ui/traits/trait-or-new-type-instead.stderr +++ b/tests/ui/traits/trait-or-new-type-instead.stderr @@ -4,7 +4,8 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher LL | impl Option { | ^^^^^^^^^^^^^^^^^ impl for type defined outside of crate | - = note: define and implement a trait or new type instead + = help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it + = note: for more details about the orphan rules, see error: aborting due to 1 previous error From 2b1dc3144bd38e3f655bcc991b685d824f4176f6 Mon Sep 17 00:00:00 2001 From: "Eddy (Eduard) Stefes" Date: Wed, 14 Jan 2026 13:08:10 +0100 Subject: [PATCH 739/978] add a new s390x-unknown-none-softfloat target This target is intended to be used for kernel development. Becasue on s390x float and vector registers overlap we have to disable the vector extension. The default s390x-unknown-gnu-linux target will not allow use of softfloat. Co-authored-by: Jubilee --- compiler/rustc_target/src/spec/mod.rs | 8 ++ .../targets/s390x_unknown_none_softfloat.rs | 39 ++++++++++ compiler/rustc_target/src/target_features.rs | 29 +++++-- src/bootstrap/src/core/sanity.rs | 1 + src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 1 + .../s390x-unknown-none-softfloat.md | 77 +++++++++++++++++++ tests/assembly-llvm/targets/targets-elf.rs | 3 + 8 files changed, 153 insertions(+), 6 deletions(-) create mode 100644 compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs create mode 100644 src/doc/rustc/src/platform-support/s390x-unknown-none-softfloat.md diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 9799f3e50ae2..eabfda35028d 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1007,6 +1007,8 @@ crate::target_spec_enum! { X86Sse2 = "x86-sse2", /// On x86-32/64 only: do not use any FPU or SIMD registers for the ABI. X86Softfloat = "x86-softfloat", + // On S390x only: do not use any FPU or Vector registers for the ABI. + S390xSoftFloat = "s390x-softfloat", } parse_error_type = "rustc abi"; @@ -1460,6 +1462,7 @@ supported_targets! { ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu), ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl), ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu), + ("s390x-unknown-none-softfloat", s390x_unknown_none_softfloat), ("s390x-unknown-linux-musl", s390x_unknown_linux_musl), ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu), ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu), @@ -3209,6 +3212,11 @@ impl Target { Arch::X86 | Arch::X86_64, "`x86-softfloat` ABI is only valid for x86 targets" ), + RustcAbi::S390xSoftFloat => check_matches!( + self.arch, + Arch::S390x, + "`s390x-softfloat` ABI is only valid for s390x targets" + ), } } diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs new file mode 100644 index 000000000000..1453a3d6c9b3 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs @@ -0,0 +1,39 @@ +use rustc_abi::{Align, Endian}; + +use crate::spec::{ + Abi, Arch, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, RustcAbi, SanitizerSet, + StackProbeType, Target, TargetMetadata, TargetOptions, +}; + +pub(crate) fn target() -> Target { + let opts = TargetOptions { + abi: Abi::SoftFloat, + cpu: "z10".into(), + endian: Endian::Big, + features: "+soft-float,-vector".into(), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + max_atomic_width: Some(128), + min_global_align: Some(Align::from_bits(16).unwrap()), + panic_strategy: PanicStrategy::Abort, + relocation_model: RelocModel::Static, + rustc_abi: Some(RustcAbi::S390xSoftFloat), + stack_probes: StackProbeType::Inline, + supported_sanitizers: SanitizerSet::KERNELADDRESS, + ..Default::default() + }; + + Target { + llvm_target: "s390x-unknown-linux-gnu".into(), + metadata: TargetMetadata { + description: Some("S390x Linux".into()), + host_tools: Some(false), + std: Some(false), + tier: Some(2), + }, + arch: Arch::S390x, + data_layout: "E-S64-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64".into(), + options: opts, + pointer_width: 64, + } +} diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index bc12e1eb9737..671761a4edd4 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -863,7 +863,7 @@ const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("miscellaneous-extensions-3", Stable, &[]), ("miscellaneous-extensions-4", Stable, &[]), ("nnp-assist", Stable, &["vector"]), - ("soft-float", Forbidden { reason: "currently unsupported ABI-configuration feature" }, &[]), + ("soft-float", Forbidden { reason: "unsupported ABI-configuration feature" }, &[]), ("transactional-execution", Unstable(sym::s390x_target_feature), &[]), ("vector", Stable, &[]), ("vector-enhancements-1", Stable, &["vector"]), @@ -1105,6 +1105,7 @@ impl Target { // LLVM handles the rest. FeatureConstraints { required: &["soft-float"], incompatible: &[] } } + Some(r) => panic!("invalid Rust ABI for x86: {r:?}"), } } Arch::X86_64 => { @@ -1218,11 +1219,27 @@ impl Target { } } Arch::S390x => { - // We don't currently support a softfloat target on this architecture. - // As usual, we have to reject swapping the `soft-float` target feature. - // The "vector" target feature does not affect the ABI for floats - // because the vector and float registers overlap. - FeatureConstraints { required: &[], incompatible: &["soft-float"] } + // Same as x86, We use our own ABI indicator here; + // LLVM does not have anything native and will switch ABI based + // on the soft-float target feature. + // Every case should require or forbid `soft-float`! + // The "vector" target feature may only be used without soft-float + // because the float and vector registers overlap and the + // standard s390x C ABI may pass vectors via these registers. + match self.rustc_abi { + None => { + // Default hardfloat ABI. + FeatureConstraints { required: &[], incompatible: &["soft-float"] } + } + Some(RustcAbi::S390xSoftFloat) => { + // Softfloat ABI, requires corresponding target feature. + // llvm will switch to soft-float ABI just based on this feature. + FeatureConstraints { required: &["soft-float"], incompatible: &["vector"] } + } + Some(r) => { + panic!("invalid Rust ABI for s390x: {r:?}"); + } + } } _ => NOTHING, } diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 8b6405afa892..e5327ab79ee2 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -48,6 +48,7 @@ const STAGE0_MISSING_TARGETS: &[&str] = &[ "thumbv6-none-eabi", "aarch64v8r-unknown-none", "aarch64v8r-unknown-none-softfloat", + "s390x-unknown-none-softfloat", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 2ec0c3648bdf..9049828c8b12 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -120,6 +120,7 @@ - [riscv64a23-unknown-linux-gnu](platform-support/riscv64a23-unknown-linux-gnu.md) - [s390x-unknown-linux-gnu](platform-support/s390x-unknown-linux-gnu.md) - [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md) + - [s390x-unknown-none-softfloat](platform-support/s390x-unknown-none-softfloat.md) - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - [solaris](platform-support/solaris.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 114f66282afd..29553f9c2a00 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -188,6 +188,7 @@ target | std | notes [`riscv64im-unknown-none-elf`](platform-support/riscv64im-unknown-none-elf.md) | * | Bare RISC-V (RV64IM ISA) `riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA) `sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4+, glibc 2.23) +[`s390x-unknown-none-softfloat`](platform-support/s390x-unknown-none-softfloat.md) | * | Bare S390x (softfloat ABI) [`thumbv6m-none-eabi`](platform-support/thumbv6m-none-eabi.md) | * | Bare Armv6-M [`thumbv7em-none-eabi`](platform-support/thumbv7em-none-eabi.md) | * | Bare Armv7E-M [`thumbv7em-none-eabihf`](platform-support/thumbv7em-none-eabi.md) | * | Bare Armv7E-M, hardfloat diff --git a/src/doc/rustc/src/platform-support/s390x-unknown-none-softfloat.md b/src/doc/rustc/src/platform-support/s390x-unknown-none-softfloat.md new file mode 100644 index 000000000000..39a1a7c52c39 --- /dev/null +++ b/src/doc/rustc/src/platform-support/s390x-unknown-none-softfloat.md @@ -0,0 +1,77 @@ +# `s390x-unknown-none-softfloat` + +**Tier: 2** + +IBM z/Architecture (s390x) code in ELF format for kernels, etc. + +## Target maintainers + +[@uweigand](https://github.com/uweigand) +[@cuviper](https://github.com/cuviper) + +## Requirements + +This target is intended for kernel development on s390x only. This target is +cross-compiled. There is no support for `std`.There is no default allocator, +but it's possible to use `alloc` by supplying an allocator. + +The target does not assume existence of a FPU and does not make use of any +non-GPR register. This allows the generated code to run in environments, such +as kernels, which may need to avoid the use of such registers or which may have +special considerations about the use of such registers (e.g. saving and +restoring them to avoid breaking userspace code using the same registers). You +can change code generation to use additional CPU features via the +`-C target-feature=` codegen options to rustc, or via the `#[target_feature]` +mechanism within Rust code. + +By default, code generated with the soft-float target should run on any Z System +starting at [Z10][s390x-isa]. Enabling additional target features or changing the +`-Ctarget-cpu` may raise the ISA required from the `z10` baseline. + +`extern "C"` does not use a stable ABI and is subject to change between compiler +or codegen backend versions. + +The target only generates object files in the ELF format. Any alternate formats +or special considerations for binary layout will require linker options or linker +scripts. + +* [z/Architecture Principles of Operation][s390x-isa] + +[s390x-isa]: https://publibfp.dhe.ibm.com/epubs/pdf/a227832d.pdf +[s390x-abi]: https://github.com/IBM/s390x-abi + +## Building the target + +You can build Rust with support for the target by adding it to the `target` +list in `bootstrap.toml`: + +```toml +[build] +target = ["s390x-unknown-none-softfloat"] +``` + +## Building Rust programs + +This target is not intended to build stand-alone binaries. You should only use +it in conjunction with the kernel build toolchain. + +## Testing + +As code generated by this target is intended to always be part of the kernel, +there are no additional requirements for testing. + +If you want to do native testing but do not have your own s390x +machine, there are several options how to get access to one: + +* The [IBM LinuxONE Community Cloud][cloud-community] provides a + self-service portal where you can create s390x virtual machine + instances. These are intended for temporary use (limited to 120 days). + +* The [IBM LinuxONE Open Source Cloud][cloud-opensource] provides + permanent access to s390x machines. This requires approval by IBM, + which will normally be granted if you're planning to use the machine + to work on an open-source project that is relevant to the IBM Z + ecosystem - the Rust compiler would certainly qualify. + +[cloud-community]: https://linuxone.cloud.marist.edu/ +[cloud-opensource]: https://community.ibm.com/zsystems/form/l1cc-oss-vm-request/ diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index c38e86315b27..b7deb6686cfe 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -544,6 +544,9 @@ //@ revisions: s390x_unknown_linux_musl //@ [s390x_unknown_linux_musl] compile-flags: --target s390x-unknown-linux-musl //@ [s390x_unknown_linux_musl] needs-llvm-components: systemz +//@ revisions: s390x_unknown_none_softfloat +//@ [s390x_unknown_none_softfloat] compile-flags: --target s390x-unknown-none-softfloat +//@ [s390x_unknown_none_softfloat] needs-llvm-components: systemz //@ revisions: sparc64_unknown_helenos //@ [sparc64_unknown_helenos] compile-flags: --target sparc64-unknown-helenos //@ [sparc64_unknown_helenos] needs-llvm-components: sparc From 51affa03942074a84ccce448ea6b7b9e02a4f4a6 Mon Sep 17 00:00:00 2001 From: "Eddy (Eduard) Stefes" Date: Thu, 22 Jan 2026 13:50:54 +0100 Subject: [PATCH 740/978] add tests for s390x-unknown-none-softfloat tests will check: - correct emit of assembly for softfloat target - incompatible set features will emit warnings/errors - incompatible target tripples in crates will not link --- tests/assembly-llvm/s390x-softfloat-abi.rs | 64 +++++++++++++++++++ ...0x-softfloat-gate.disable-softfloat.stderr | 12 ++++ ...90x-softfloat-gate.enable-softfloat.stderr | 7 ++ tests/ui/abi/s390x-softfloat-gate.rs | 38 +++++++++++ ...imd-abi-checks-s390x.z13_soft_float.stderr | 2 +- .../auxiliary/disabled_softfloat.rs | 8 +++ .../auxiliary/enabled_softfloat.rs | 8 +++ ...softfloat_targets.disable-softfloat.stderr | 12 ++++ ..._softfloat_targets.enable-softfloat.stderr | 12 ++++ .../incompatible_softfloat_targets.rs | 20 ++++++ 10 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 tests/assembly-llvm/s390x-softfloat-abi.rs create mode 100644 tests/ui/abi/s390x-softfloat-gate.disable-softfloat.stderr create mode 100644 tests/ui/abi/s390x-softfloat-gate.enable-softfloat.stderr create mode 100644 tests/ui/abi/s390x-softfloat-gate.rs create mode 100644 tests/ui/target_modifiers/auxiliary/disabled_softfloat.rs create mode 100644 tests/ui/target_modifiers/auxiliary/enabled_softfloat.rs create mode 100644 tests/ui/target_modifiers/incompatible_softfloat_targets.disable-softfloat.stderr create mode 100644 tests/ui/target_modifiers/incompatible_softfloat_targets.enable-softfloat.stderr create mode 100644 tests/ui/target_modifiers/incompatible_softfloat_targets.rs diff --git a/tests/assembly-llvm/s390x-softfloat-abi.rs b/tests/assembly-llvm/s390x-softfloat-abi.rs new file mode 100644 index 000000000000..e2d9d013d201 --- /dev/null +++ b/tests/assembly-llvm/s390x-softfloat-abi.rs @@ -0,0 +1,64 @@ +//@ add-minicore +//@ revisions: enable-softfloat disable-softfloat +//@ assembly-output: emit-asm +//@ compile-flags: -Copt-level=3 --crate-type=lib +//@[enable-softfloat] compile-flags: --target=s390x-unknown-none-softfloat +//@[enable-softfloat] needs-llvm-components: systemz +//@[disable-softfloat] compile-flags: --target=s390x-unknown-linux-gnu +//@[disable-softfloat] needs-llvm-components: systemz +//@ ignore-backends: gcc + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +extern crate minicore; +use minicore::*; + +extern "C" { + fn extern_func(value: f64) -> f64; +} + +// CHECK-LABEL: test_softfloat +#[no_mangle] +extern "C" fn test_softfloat() -> f64 { + let value = 3.141_f64; + + // without softfloat we load the value direct to the first float register + // we do NOT construct a softfloat in r2 (first non-float arg register) + // disable-softfloat: ld %f{{.*}}, 0(%r{{.*}}) + // disable-softfloat-NOT: llihf %r{{.*}}, 1074340036 + // disable-softfloat-NOT: oilf %r{{.*}}, 2611340116 + + // with softfloat we construct the softfloat arg in r2 + // we do NOT pass anything by f0 (first float arg register) + // float registers can not be accessed + // enable-softfloat: llihf %r{{.*}}, 1074340036 + // enable-softfloat-NEXT: oilf %r{{.*}}, 2611340116 + // enable-softfloat-NOT: ld %f{{.*}}, 0(%r{{.*}}) + + unsafe { extern_func(value) }; + // disable-softfloat-NEXT: brasl %r{{.*}}, extern_func@PLT + // enable-softfloat-NEXT: brasl %r{{.*}}, extern_func@PLT + + // for return we check that without softfloat we write to float register + // disable-softfloat: ld %f{{.*}}, 0(%r{{.*}}) + // disable-softfloat-NOT: llihf %r{{.*}}, 1072841097 + // disable-softfloat-NOT: oilf %r{{.*}}, 927712936 + + #[cfg(not(target_feature = "soft-float"))] + { + 1.141_f64 + } + + // for return we check that WITH softfloat we write to genral purpose register + // enable-softfloat: llihf %r{{.*}}, 1072841097 + // enable-softfloat-NEXT: oilf %r{{.*}}, 927712936 + // enable-softfloat-NOT: ld %f{{.*}}, 0(%r{{.*}}) + #[cfg(target_feature = "soft-float")] + { + 2.718_f64 + } + // enable-softfloat: br %r{{.*}} + // disable-softfloat: br %r{{.*}} +} diff --git a/tests/ui/abi/s390x-softfloat-gate.disable-softfloat.stderr b/tests/ui/abi/s390x-softfloat-gate.disable-softfloat.stderr new file mode 100644 index 000000000000..e82d5b744a26 --- /dev/null +++ b/tests/ui/abi/s390x-softfloat-gate.disable-softfloat.stderr @@ -0,0 +1,12 @@ +warning: target feature `soft-float` cannot be enabled with `-Ctarget-feature`: unsupported ABI-configuration feature + | + = note: 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 #116344 + +warning: target feature `soft-float` must be disabled to ensure that the ABI of the current target can be implemented correctly + | + = note: 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 #116344 + +warning: 2 warnings emitted + diff --git a/tests/ui/abi/s390x-softfloat-gate.enable-softfloat.stderr b/tests/ui/abi/s390x-softfloat-gate.enable-softfloat.stderr new file mode 100644 index 000000000000..ecc96e448dcf --- /dev/null +++ b/tests/ui/abi/s390x-softfloat-gate.enable-softfloat.stderr @@ -0,0 +1,7 @@ +warning: target feature `vector` must be disabled to ensure that the ABI of the current target can be implemented correctly + | + = note: 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 #116344 + +warning: 1 warning emitted + diff --git a/tests/ui/abi/s390x-softfloat-gate.rs b/tests/ui/abi/s390x-softfloat-gate.rs new file mode 100644 index 000000000000..496929eb0955 --- /dev/null +++ b/tests/ui/abi/s390x-softfloat-gate.rs @@ -0,0 +1,38 @@ +//@ add-minicore +//@ revisions: disable-softfloat enable-softfloat +//@ assembly-output: emit-asm +//@ compile-flags: -Copt-level=3 --crate-type=lib + +// we expect the build to fail in the feature +//@ build-pass +//@ [enable-softfloat] compile-flags: --target=s390x-unknown-none-softfloat +//@ [enable-softfloat] compile-flags: -C target-feature=+vector +//@ [enable-softfloat] needs-llvm-components: systemz +//@ [disable-softfloat] compile-flags: --target=s390x-unknown-linux-gnu +//@ [disable-softfloat] compile-flags: -C target-feature=+soft-float +//@ [disable-softfloat] needs-llvm-components: systemz +//@ ignore-backends: gcc + +//[disable-softfloat]~? WARN target feature `soft-float` must be disabled to ensure that the ABI of the current target can be implemented correctly +//[disable-softfloat]~? WARN target feature `soft-float` cannot be enabled with `-Ctarget-feature` +//[enable-softfloat]~? WARN target feature `vector` must be disabled to ensure that the ABI of the current target can be implemented correctly + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +extern crate minicore; +use minicore::*; + +extern "C" { + fn extern_func(value: f64) -> f64; +} + +#[no_mangle] +extern "C" fn test_softfloat() -> f64 { + let value = 3.141_f64; + + unsafe { extern_func(value) } ; + + 2.718_f64 +} diff --git a/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr b/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr index 0e8e6637507d..cda51a211324 100644 --- a/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr +++ b/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr @@ -1,4 +1,4 @@ -warning: target feature `soft-float` cannot be enabled with `-Ctarget-feature`: currently unsupported ABI-configuration feature +warning: target feature `soft-float` cannot be enabled with `-Ctarget-feature`: unsupported ABI-configuration feature | = note: 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 #116344 diff --git a/tests/ui/target_modifiers/auxiliary/disabled_softfloat.rs b/tests/ui/target_modifiers/auxiliary/disabled_softfloat.rs new file mode 100644 index 000000000000..0063d925deca --- /dev/null +++ b/tests/ui/target_modifiers/auxiliary/disabled_softfloat.rs @@ -0,0 +1,8 @@ +//@ add-minicore +//@ no-prefer-dynamic +//@ compile-flags: --target=s390x-unknown-linux-gnu +//@ needs-llvm-components: systemz + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] diff --git a/tests/ui/target_modifiers/auxiliary/enabled_softfloat.rs b/tests/ui/target_modifiers/auxiliary/enabled_softfloat.rs new file mode 100644 index 000000000000..7439a1eb69b5 --- /dev/null +++ b/tests/ui/target_modifiers/auxiliary/enabled_softfloat.rs @@ -0,0 +1,8 @@ +//@ add-minicore +//@ no-prefer-dynamic +//@ compile-flags: --target=s390x-unknown-none-softfloat +//@ needs-llvm-components: systemz + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] diff --git a/tests/ui/target_modifiers/incompatible_softfloat_targets.disable-softfloat.stderr b/tests/ui/target_modifiers/incompatible_softfloat_targets.disable-softfloat.stderr new file mode 100644 index 000000000000..090ebe6ca14c --- /dev/null +++ b/tests/ui/target_modifiers/incompatible_softfloat_targets.disable-softfloat.stderr @@ -0,0 +1,12 @@ +error[E0461]: couldn't find crate `enabled_softfloat` with expected target triple s390x-unknown-linux-gnu + --> $DIR/incompatible_softfloat_targets.rs:17:1 + | +LL | extern crate enabled_softfloat; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the following crate versions were found: + crate `enabled_softfloat`, target triple s390x-unknown-none-softfloat: $TEST_BUILD_DIR/auxiliary/libenabled_softfloat.rlib + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0461`. diff --git a/tests/ui/target_modifiers/incompatible_softfloat_targets.enable-softfloat.stderr b/tests/ui/target_modifiers/incompatible_softfloat_targets.enable-softfloat.stderr new file mode 100644 index 000000000000..9adb6d265651 --- /dev/null +++ b/tests/ui/target_modifiers/incompatible_softfloat_targets.enable-softfloat.stderr @@ -0,0 +1,12 @@ +error[E0461]: couldn't find crate `disabled_softfloat` with expected target triple s390x-unknown-none-softfloat + --> $DIR/incompatible_softfloat_targets.rs:19:1 + | +LL | extern crate disabled_softfloat; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the following crate versions were found: + crate `disabled_softfloat`, target triple s390x-unknown-linux-gnu: $TEST_BUILD_DIR/auxiliary/libdisabled_softfloat.rlib + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0461`. diff --git a/tests/ui/target_modifiers/incompatible_softfloat_targets.rs b/tests/ui/target_modifiers/incompatible_softfloat_targets.rs new file mode 100644 index 000000000000..3d253c5f0c78 --- /dev/null +++ b/tests/ui/target_modifiers/incompatible_softfloat_targets.rs @@ -0,0 +1,20 @@ +//@ add-minicore +//@ aux-build: disabled_softfloat.rs +//@ aux-build: enabled_softfloat.rs +//@ revisions: disable-softfloat enable-softfloat +//@ check-fail +//@ [enable-softfloat] compile-flags: --target=s390x-unknown-none-softfloat +//@ [enable-softfloat] needs-llvm-components: systemz +//@ [disable-softfloat] compile-flags: --target=s390x-unknown-linux-gnu +//@ [disable-softfloat] needs-llvm-components: systemz +//@ ignore-backends: gcc + + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] + +extern crate enabled_softfloat; +//[disable-softfloat]~^ ERROR couldn't find crate `enabled_softfloat` with expected target triple s390x-unknown-linux-gnu +extern crate disabled_softfloat; +//[enable-softfloat]~^ ERROR couldn't find crate `disabled_softfloat` with expected target triple s390x-unknown-none-softfloat From 7c3d096b0dcb39ad23b42394d889ec8177f7ce26 Mon Sep 17 00:00:00 2001 From: "Eddy (Eduard) Stefes" Date: Fri, 6 Feb 2026 10:53:59 +0100 Subject: [PATCH 741/978] allow for variant aliases in target_spec_enum! --- compiler/rustc_target/src/lib.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index dfa1b2320718..1dc62cb3659c 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -76,7 +76,7 @@ macro_rules! target_spec_enum { pub enum $Name:ident { $( $( #[$variant_attr:meta] )* - $Variant:ident = $string:literal, + $Variant:ident = $string:literal $(,$alias:literal)* , )* } parse_error_type = $parse_error_type:literal; @@ -88,6 +88,7 @@ macro_rules! target_spec_enum { $( $( #[$variant_attr] )* #[serde(rename = $string)] // for JSON schema generation only + $( #[serde(alias = $alias)] )* $Variant, )* } @@ -97,7 +98,10 @@ macro_rules! target_spec_enum { fn from_str(s: &str) -> Result { Ok(match s { - $( $string => Self::$Variant, )* + $( + $string => Self::$Variant, + $($alias => Self::$Variant,)* + )* _ => { let all = [$( concat!("'", $string, "'") ),*].join(", "); return Err(format!("invalid {}: '{s}'. allowed values: {all}", $parse_error_type)); @@ -123,7 +127,7 @@ macro_rules! target_spec_enum { pub enum $Name:ident { $( $( #[$variant_attr:meta] )* - $Variant:ident = $string:literal, + $Variant:ident = $string:literal $(,$alias:literal)* , )* } $( #[$other_variant_attr:meta] )* @@ -134,6 +138,7 @@ macro_rules! target_spec_enum { pub enum $Name { $( $( #[$variant_attr:meta] )* + $( #[serde(alias = $alias)] )* $Variant, )* /// The vast majority of the time, the compiler deals with a fixed @@ -165,7 +170,10 @@ macro_rules! target_spec_enum { fn from_str(s: &str) -> Result { Ok(match s { - $( $string => Self::$Variant, )* + $( + $string => Self::$Variant, + $($alias => Self::$Variant,)* + )* _ => Self::$OtherVariant(s.to_owned().into()), }) } From 83dba5b430160bee94e5cc9514993fea4bfa0d96 Mon Sep 17 00:00:00 2001 From: "Eddy (Eduard) Stefes" Date: Thu, 22 Jan 2026 13:20:52 +0100 Subject: [PATCH 742/978] renamed RustcAbi::X86Softfloat to Softfloat an made an alias to the old string --- compiler/rustc_target/src/callconv/x86_win64.rs | 2 +- compiler/rustc_target/src/spec/mod.rs | 17 +++++------------ .../src/spec/targets/i686_unknown_uefi.rs | 2 +- .../targets/s390x_unknown_none_softfloat.rs | 2 +- .../src/spec/targets/x86_64_unknown_none.rs | 2 +- .../src/spec/targets/x86_64_unknown_uefi.rs | 2 +- compiler/rustc_target/src/target_features.rs | 7 +++---- 7 files changed, 13 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_target/src/callconv/x86_win64.rs b/compiler/rustc_target/src/callconv/x86_win64.rs index 48f7700a86d5..4026c4f471a7 100644 --- a/compiler/rustc_target/src/callconv/x86_win64.rs +++ b/compiler/rustc_target/src/callconv/x86_win64.rs @@ -28,7 +28,7 @@ where BackendRepr::ScalableVector { .. } => panic!("scalable vectors are unsupported"), BackendRepr::Scalar(scalar) => { if is_ret && matches!(scalar.primitive(), Primitive::Int(Integer::I128, _)) { - if cx.target_spec().rustc_abi == Some(RustcAbi::X86Softfloat) { + if cx.target_spec().rustc_abi == Some(RustcAbi::Softfloat) { // Use the native `i128` LLVM type for the softfloat ABI -- in other words, adjust nothing. } else { // `i128` is returned in xmm0 by Clang and GCC diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index eabfda35028d..537185f536ab 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1005,10 +1005,8 @@ crate::target_spec_enum! { pub enum RustcAbi { /// On x86-32 only: make use of SSE and SSE2 for ABI purposes. X86Sse2 = "x86-sse2", - /// On x86-32/64 only: do not use any FPU or SIMD registers for the ABI. - X86Softfloat = "x86-softfloat", - // On S390x only: do not use any FPU or Vector registers for the ABI. - S390xSoftFloat = "s390x-softfloat", + /// On x86-32/64 and S390x: do not use any FPU or SIMD registers for the ABI. + Softfloat = "softfloat", "x86-softfloat", } parse_error_type = "rustc abi"; @@ -3207,15 +3205,10 @@ impl Target { Arch::X86, "`x86-sse2` ABI is only valid for x86-32 targets" ), - RustcAbi::X86Softfloat => check_matches!( + RustcAbi::Softfloat => check_matches!( self.arch, - Arch::X86 | Arch::X86_64, - "`x86-softfloat` ABI is only valid for x86 targets" - ), - RustcAbi::S390xSoftFloat => check_matches!( - self.arch, - Arch::S390x, - "`s390x-softfloat` ABI is only valid for s390x targets" + Arch::X86 | Arch::X86_64 | Arch::S390x, + "`softfloat` ABI is only valid for x86 and s390x targets" ), } } diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs index 37b202097b46..7696edd5ba71 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs @@ -22,7 +22,7 @@ pub(crate) fn target() -> Target { // If you initialize FP units yourself, you can override these flags with custom linker // arguments, thus giving you access to full MMX/SSE acceleration. base.features = "-mmx,-sse,+soft-float".into(); - base.rustc_abi = Some(RustcAbi::X86Softfloat); + base.rustc_abi = Some(RustcAbi::Softfloat); // Turn off DWARF. This fixes an lld warning, "section name .debug_frame is longer than 8 // characters and will use a non-standard string table". That section will not be created if diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs index 1453a3d6c9b3..7d42c1fd9244 100644 --- a/compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_none_softfloat.rs @@ -17,7 +17,7 @@ pub(crate) fn target() -> Target { min_global_align: Some(Align::from_bits(16).unwrap()), panic_strategy: PanicStrategy::Abort, relocation_model: RelocModel::Static, - rustc_abi: Some(RustcAbi::S390xSoftFloat), + rustc_abi: Some(RustcAbi::Softfloat), stack_probes: StackProbeType::Inline, supported_sanitizers: SanitizerSet::KERNELADDRESS, ..Default::default() diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs index 520a59d6a6f6..0afe7a0b68b0 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs @@ -20,7 +20,7 @@ pub(crate) fn target() -> Target { relro_level: RelroLevel::Full, linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), - rustc_abi: Some(RustcAbi::X86Softfloat), + rustc_abi: Some(RustcAbi::Softfloat), features: "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2,+soft-float".into(), supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, disable_redzone: true, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs index 8a494d0e56dd..333e20bd0ac1 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs @@ -27,7 +27,7 @@ pub(crate) fn target() -> Target { // If you initialize FP units yourself, you can override these flags with custom linker // arguments, thus giving you access to full MMX/SSE acceleration. base.features = "-mmx,-sse,+soft-float".into(); - base.rustc_abi = Some(RustcAbi::X86Softfloat); + base.rustc_abi = Some(RustcAbi::Softfloat); Target { llvm_target: "x86_64-unknown-windows".into(), diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 671761a4edd4..dfa2b839a4c0 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -1098,14 +1098,13 @@ impl Target { incompatible: &["soft-float"], } } - Some(RustcAbi::X86Softfloat) => { + Some(RustcAbi::Softfloat) => { // Softfloat ABI, requires corresponding target feature. That feature trumps // `x87` and all other FPU features so those do not matter. // Note that this one requirement is the entire implementation of the ABI! // LLVM handles the rest. FeatureConstraints { required: &["soft-float"], incompatible: &[] } } - Some(r) => panic!("invalid Rust ABI for x86: {r:?}"), } } Arch::X86_64 => { @@ -1119,7 +1118,7 @@ impl Target { incompatible: &["soft-float"], } } - Some(RustcAbi::X86Softfloat) => { + Some(RustcAbi::Softfloat) => { // Softfloat ABI, requires corresponding target feature. That feature trumps // `x87` and all other FPU features so those do not matter. // Note that this one requirement is the entire implementation of the ABI! @@ -1231,7 +1230,7 @@ impl Target { // Default hardfloat ABI. FeatureConstraints { required: &[], incompatible: &["soft-float"] } } - Some(RustcAbi::S390xSoftFloat) => { + Some(RustcAbi::Softfloat) => { // Softfloat ABI, requires corresponding target feature. // llvm will switch to soft-float ABI just based on this feature. FeatureConstraints { required: &["soft-float"], incompatible: &["vector"] } From f91c8083d8a90d6a275584389e853cccb0b45b08 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 9 Feb 2026 11:01:03 +1100 Subject: [PATCH 743/978] Adjust `make_dep_kind_vtable_for_query`. It takes an `is_anon` argument, but it's now generic over `QueryFlags`, which contains the same `is_anon` field. So the argument is no longer necessary. --- compiler/rustc_query_impl/src/plumbing.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index bbda716eadb0..aefd4418e192 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -512,12 +512,12 @@ pub(crate) fn make_dep_kind_vtable_for_query< C: QueryCache + 'tcx, const FLAGS: QueryFlags, >( - is_anon: bool, is_eval_always: bool, ) -> DepKindVTable<'tcx> where Q: QueryDispatcherUnerased<'tcx, C, FLAGS>, { + let is_anon = FLAGS.is_anon; let fingerprint_style = if is_anon { FingerprintStyle::Opaque } else { @@ -969,7 +969,6 @@ macro_rules! define_queries { $(pub(crate) fn $name<'tcx>() -> DepKindVTable<'tcx> { use $crate::query_impl::$name::QueryType; $crate::plumbing::make_dep_kind_vtable_for_query::, _, _>( - is_anon!([$($modifiers)*]), is_eval_always!([$($modifiers)*]), ) })* From 541d7fc19d14c64a1490c065a73986f9e018b3d6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 9 Feb 2026 13:02:06 +1100 Subject: [PATCH 744/978] Remove `trait QueryDispatcher`. It existed only to bridge the divide between `rustc_query_system` and `rustc_query_impl`. But enough pieces have been moved from the former to the latter that the trait is no longer needed. Less indirection and abstraction makes the code easier to understand. --- compiler/rustc_query_impl/src/execution.rs | 157 +++++++----------- compiler/rustc_query_impl/src/lib.rs | 55 +++--- compiler/rustc_query_impl/src/plumbing.rs | 30 ++-- .../rustc_query_system/src/query/caches.rs | 3 + .../src/query/dispatcher.rs | 87 ---------- compiler/rustc_query_system/src/query/mod.rs | 2 +- 6 files changed, 111 insertions(+), 223 deletions(-) diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index e58e626a7dfa..ba442d8a0081 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -9,14 +9,14 @@ use rustc_middle::dep_graph::DepsType; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::{DepGraphData, DepNodeKey, HasDepContext}; use rustc_query_system::query::{ - ActiveKeyStatus, CycleError, CycleErrorHandling, QueryCache, QueryContext, QueryDispatcher, - QueryJob, QueryJobId, QueryJobInfo, QueryLatch, QueryMap, QueryMode, QueryStackDeferred, - QueryStackFrame, QueryState, incremental_verify_ich, report_cycle, + ActiveKeyStatus, CycleError, CycleErrorHandling, QueryCache, QueryContext, QueryJob, + QueryJobId, QueryJobInfo, QueryLatch, QueryMap, QueryMode, QueryStackDeferred, QueryStackFrame, + QueryState, incremental_verify_ich, report_cycle, }; use rustc_span::{DUMMY_SP, Span}; use crate::dep_graph::{DepContext, DepNode, DepNodeIndex}; -use crate::plumbing::QueryCtxt; +use crate::{QueryCtxt, QueryFlags, SemiDynamicQueryDispatcher}; #[inline] fn equivalent_key(k: &K) -> impl Fn(&(K, V)) -> bool + '_ { @@ -95,23 +95,21 @@ where #[cold] #[inline(never)] -fn mk_cycle<'tcx, Q>(query: Q, qcx: QueryCtxt<'tcx>, cycle_error: CycleError) -> Q::Value -where - Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, -{ +fn mk_cycle<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + qcx: QueryCtxt<'tcx>, + cycle_error: CycleError, +) -> C::Value { let error = report_cycle(qcx.tcx.sess, &cycle_error); handle_cycle_error(query, qcx, &cycle_error, error) } -fn handle_cycle_error<'tcx, Q>( - query: Q, +fn handle_cycle_error<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, qcx: QueryCtxt<'tcx>, cycle_error: &CycleError, error: Diag<'_>, -) -> Q::Value -where - Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, -{ +) -> C::Value { match query.cycle_error_handling() { CycleErrorHandling::Error => { let guar = error.emit(); @@ -205,15 +203,12 @@ where #[cold] #[inline(never)] -fn cycle_error<'tcx, Q>( - query: Q, +fn cycle_error<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, qcx: QueryCtxt<'tcx>, try_execute: QueryJobId, span: Span, -) -> (Q::Value, Option) -where - Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, -{ +) -> (C::Value, Option) { // Ensure there was no errors collecting all active jobs. // We need the complete map to ensure we find a cycle to break. let query_map = qcx @@ -226,17 +221,14 @@ where } #[inline(always)] -fn wait_for_query<'tcx, Q>( - query: Q, +fn wait_for_query<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, qcx: QueryCtxt<'tcx>, span: Span, - key: Q::Key, + key: C::Key, latch: QueryLatch<'tcx>, current: Option, -) -> (Q::Value, Option) -where - Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, -{ +) -> (C::Value, Option) { // For parallel queries, we'll block and wait until the query running // in another thread has completed. Record how long we wait in the // self-profiler. @@ -275,16 +267,13 @@ where } #[inline(never)] -fn try_execute_query<'tcx, Q, const INCR: bool>( - query: Q, +fn try_execute_query<'tcx, C: QueryCache, const FLAGS: QueryFlags, const INCR: bool>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, qcx: QueryCtxt<'tcx>, span: Span, - key: Q::Key, + key: C::Key, dep_node: Option, -) -> (Q::Value, Option) -where - Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, -{ +) -> (C::Value, Option) { let state = query.query_state(qcx); let key_hash = sharded::make_hash(&key); let mut state_lock = state.active.lock_shard_by_hash(key_hash); @@ -315,7 +304,7 @@ where // Drop the lock before we start executing the query drop(state_lock); - execute_job::(query, qcx, state, key, key_hash, id, dep_node) + execute_job::(query, qcx, state, key, key_hash, id, dep_node) } Entry::Occupied(mut entry) => { match &mut entry.get_mut().1 { @@ -344,18 +333,15 @@ where } #[inline(always)] -fn execute_job<'tcx, Q, const INCR: bool>( - query: Q, +fn execute_job<'tcx, C: QueryCache, const FLAGS: QueryFlags, const INCR: bool>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, qcx: QueryCtxt<'tcx>, - state: &'tcx QueryState<'tcx, Q::Key>, - key: Q::Key, + state: &'tcx QueryState<'tcx, C::Key>, + key: C::Key, key_hash: u64, id: QueryJobId, dep_node: Option, -) -> (Q::Value, Option) -where - Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, -{ +) -> (C::Value, Option) { // Use `JobOwner` so the query will be poisoned if executing it panics. let job_owner = JobOwner { state, key }; @@ -409,15 +395,12 @@ where // Fast path for when incr. comp. is off. #[inline(always)] -fn execute_job_non_incr<'tcx, Q>( - query: Q, +fn execute_job_non_incr<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, qcx: QueryCtxt<'tcx>, - key: Q::Key, + key: C::Key, job_id: QueryJobId, -) -> (Q::Value, DepNodeIndex) -where - Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, -{ +) -> (C::Value, DepNodeIndex) { debug_assert!(!qcx.tcx.dep_graph.is_fully_enabled()); // Fingerprint the key, just to assert that it doesn't @@ -445,17 +428,14 @@ where } #[inline(always)] -fn execute_job_incr<'tcx, Q>( - query: Q, +fn execute_job_incr<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, qcx: QueryCtxt<'tcx>, dep_graph_data: &DepGraphData, - key: Q::Key, + key: C::Key, mut dep_node_opt: Option, job_id: QueryJobId, -) -> (Q::Value, DepNodeIndex) -where - Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, -{ +) -> (C::Value, DepNodeIndex) { if !query.anon() && !query.eval_always() { // `to_dep_node` is expensive for some `DepKind`s. let dep_node = dep_node_opt.get_or_insert_with(|| query.construct_dep_node(qcx.tcx, &key)); @@ -495,16 +475,13 @@ where } #[inline(always)] -fn try_load_from_disk_and_cache_in_memory<'tcx, Q>( - query: Q, +fn try_load_from_disk_and_cache_in_memory<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, dep_graph_data: &DepGraphData, qcx: QueryCtxt<'tcx>, - key: &Q::Key, + key: &C::Key, dep_node: &DepNode, -) -> Option<(Q::Value, DepNodeIndex)> -where - Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, -{ +) -> Option<(C::Value, DepNodeIndex)> { // Note this function can be called concurrently from the same query // We must ensure that this is handled correctly. @@ -598,15 +575,12 @@ where /// /// Note: The optimization is only available during incr. comp. #[inline(never)] -fn ensure_must_run<'tcx, Q>( - query: Q, +fn ensure_must_run<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, qcx: QueryCtxt<'tcx>, - key: &Q::Key, + key: &C::Key, check_cache: bool, -) -> (bool, Option) -where - Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, -{ +) -> (bool, Option) { if query.eval_always() { return (true, None); } @@ -644,31 +618,25 @@ where } #[inline(always)] -pub(super) fn get_query_non_incr<'tcx, Q>( - query: Q, +pub(super) fn get_query_non_incr<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, qcx: QueryCtxt<'tcx>, span: Span, - key: Q::Key, -) -> Q::Value -where - Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, -{ + key: C::Key, +) -> C::Value { debug_assert!(!qcx.tcx.dep_graph.is_fully_enabled()); - ensure_sufficient_stack(|| try_execute_query::(query, qcx, span, key, None).0) + ensure_sufficient_stack(|| try_execute_query::(query, qcx, span, key, None).0) } #[inline(always)] -pub(super) fn get_query_incr<'tcx, Q>( - query: Q, +pub(super) fn get_query_incr<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, qcx: QueryCtxt<'tcx>, span: Span, - key: Q::Key, + key: C::Key, mode: QueryMode, -) -> Option -where - Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, -{ +) -> Option { debug_assert!(qcx.tcx.dep_graph.is_fully_enabled()); let dep_node = if let QueryMode::Ensure { check_cache } = mode { @@ -681,18 +649,21 @@ where None }; - let (result, dep_node_index) = - ensure_sufficient_stack(|| try_execute_query::(query, qcx, span, key, dep_node)); + let (result, dep_node_index) = ensure_sufficient_stack(|| { + try_execute_query::(query, qcx, span, key, dep_node) + }); if let Some(dep_node_index) = dep_node_index { qcx.tcx.dep_graph.read_index(dep_node_index) } Some(result) } -pub(super) fn force_query<'tcx, Q>(query: Q, qcx: QueryCtxt<'tcx>, key: Q::Key, dep_node: DepNode) -where - Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, -{ +pub(crate) fn force_query<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + qcx: QueryCtxt<'tcx>, + key: C::Key, + dep_node: DepNode, +) { // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. if let Some((_, index)) = query.query_cache(qcx).lookup(&key) { @@ -703,6 +674,6 @@ where debug_assert!(!query.anon()); ensure_sufficient_stack(|| { - try_execute_query::(query, qcx, DUMMY_SP, key, Some(dep_node)) + try_execute_query::(query, qcx, DUMMY_SP, key, Some(dep_node)) }); } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 327a8f4bc6c4..7ca4a1300fe6 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -12,7 +12,7 @@ use std::marker::ConstParamTy; use rustc_data_structures::sync::AtomicU64; use rustc_middle::arena::Arena; -use rustc_middle::dep_graph::{self, DepKind, DepKindVTable, DepNodeIndex}; +use rustc_middle::dep_graph::{self, DepKind, DepKindVTable, DepNode, DepNodeIndex}; use rustc_middle::queries::{ self, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates, }; @@ -23,8 +23,7 @@ use rustc_middle::query::values::Value; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::SerializedDepNodeIndex; use rustc_query_system::query::{ - CycleError, CycleErrorHandling, HashResult, QueryCache, QueryDispatcher, QueryMap, QueryMode, - QueryState, + CycleError, CycleErrorHandling, HashResult, QueryCache, QueryMap, QueryMode, QueryState, }; use rustc_span::{ErrorGuaranteed, Span}; @@ -50,8 +49,8 @@ struct QueryFlags { is_feedable: bool, } -/// Combines a [`QueryVTable`] with some additional compile-time booleans -/// to implement [`QueryDispatcher`], for use by code in [`rustc_query_system`]. +/// Combines a [`QueryVTable`] with some additional compile-time booleans. +/// "Dispatcher" should be understood as a near-synonym of "vtable". /// /// Baking these boolean flags into the type gives a modest but measurable /// improvement to compiler perf and compiler code size; see @@ -73,54 +72,49 @@ impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> Clone } } -// This is `impl QueryDispatcher for SemiDynamicQueryDispatcher`. -impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> QueryDispatcher<'tcx> - for SemiDynamicQueryDispatcher<'tcx, C, FLAGS> -{ - type Qcx = QueryCtxt<'tcx>; - type Key = C::Key; - type Value = C::Value; - type Cache = C; - +impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> SemiDynamicQueryDispatcher<'tcx, C, FLAGS> { #[inline(always)] fn name(self) -> &'static str { self.vtable.name } #[inline(always)] - fn will_cache_on_disk_for_key(self, tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool { + fn will_cache_on_disk_for_key(self, tcx: TyCtxt<'tcx>, key: &C::Key) -> bool { self.vtable.will_cache_on_disk_for_key_fn.map_or(false, |f| f(tcx, key)) } + // Don't use this method to access query results, instead use the methods on TyCtxt. #[inline(always)] - fn query_state(self, qcx: QueryCtxt<'tcx>) -> &'tcx QueryState<'tcx, Self::Key> { + fn query_state(self, qcx: QueryCtxt<'tcx>) -> &'tcx QueryState<'tcx, C::Key> { // Safety: // This is just manually doing the subfield referencing through pointer math. unsafe { &*(&qcx.tcx.query_system.states as *const QueryStates<'tcx>) .byte_add(self.vtable.query_state) - .cast::>() + .cast::>() } } + // Don't use this method to access query results, instead use the methods on TyCtxt. #[inline(always)] - fn query_cache(self, qcx: QueryCtxt<'tcx>) -> &'tcx Self::Cache { + fn query_cache(self, qcx: QueryCtxt<'tcx>) -> &'tcx C { // Safety: // This is just manually doing the subfield referencing through pointer math. unsafe { &*(&qcx.tcx.query_system.caches as *const QueryCaches<'tcx>) .byte_add(self.vtable.query_cache) - .cast::() + .cast::() } } + // Don't use this method to compute query results, instead use the methods on TyCtxt. #[inline(always)] - fn execute_query(self, tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value { + fn execute_query(self, tcx: TyCtxt<'tcx>, key: C::Key) -> C::Value { (self.vtable.execute_query)(tcx, key) } #[inline(always)] - fn compute(self, qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value { + fn compute(self, qcx: QueryCtxt<'tcx>, key: C::Key) -> C::Value { (self.vtable.compute_fn)(qcx.tcx, key) } @@ -128,10 +122,10 @@ impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> QueryDispatcher<'tcx> fn try_load_from_disk( self, qcx: QueryCtxt<'tcx>, - key: &Self::Key, + key: &C::Key, prev_index: SerializedDepNodeIndex, index: DepNodeIndex, - ) -> Option { + ) -> Option { // `?` will return None immediately for queries that never cache to disk. self.vtable.try_load_from_disk_fn?(qcx.tcx, key, prev_index, index) } @@ -140,23 +134,24 @@ impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> QueryDispatcher<'tcx> fn is_loadable_from_disk( self, qcx: QueryCtxt<'tcx>, - key: &Self::Key, + key: &C::Key, index: SerializedDepNodeIndex, ) -> bool { self.vtable.is_loadable_from_disk_fn.map_or(false, |f| f(qcx.tcx, key, index)) } + /// Synthesize an error value to let compilation continue after a cycle. fn value_from_cycle_error( self, tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed, - ) -> Self::Value { + ) -> C::Value { (self.vtable.value_from_cycle_error)(tcx, cycle_error, guar) } #[inline(always)] - fn format_value(self) -> fn(&Self::Value) -> String { + fn format_value(self) -> fn(&C::Value) -> String { self.vtable.format_value } @@ -191,13 +186,17 @@ impl<'tcx, C: QueryCache, const FLAGS: QueryFlags> QueryDispatcher<'tcx> } #[inline(always)] - fn hash_result(self) -> HashResult { + fn hash_result(self) -> HashResult { self.vtable.hash_result } + + fn construct_dep_node(self, tcx: TyCtxt<'tcx>, key: &C::Key) -> DepNode { + DepNode::construct(tcx, self.dep_kind(), key) + } } /// Provides access to vtable-like operations for a query -/// (by creating a [`QueryDispatcher`]), +/// (by creating a [`SemiDynamicQueryDispatcher`]), /// but also keeps track of the "unerased" value type of the query /// (i.e. the actual result type in the query declaration). /// diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index aefd4418e192..776d720f500b 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -28,8 +28,8 @@ use rustc_middle::ty::tls::{self, ImplicitCtxt}; use rustc_middle::ty::{self, TyCtxt}; use rustc_query_system::dep_graph::{DepNodeKey, FingerprintStyle, HasDepContext}; use rustc_query_system::query::{ - QueryCache, QueryContext, QueryDispatcher, QueryJobId, QueryMap, QuerySideEffect, - QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, + QueryCache, QueryContext, QueryJobId, QueryMap, QuerySideEffect, QueryStackDeferred, + QueryStackFrame, QueryStackFrameExtra, }; use rustc_serialize::{Decodable, Encodable}; use rustc_span::def_id::LOCAL_CRATE; @@ -404,8 +404,8 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q, C: QueryCache, const FLAGS: Quer }); } -pub(crate) fn query_key_hash_verify<'tcx>( - query: impl QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, +pub(crate) fn query_key_hash_verify<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, qcx: QueryCtxt<'tcx>, ) { let _timer = qcx.tcx.prof.generic_activity_with_arg("query_key_hash_verify_for", query.name()); @@ -430,13 +430,14 @@ pub(crate) fn query_key_hash_verify<'tcx>( }); } -fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -where - Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, -{ +fn try_load_from_on_disk_cache<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + tcx: TyCtxt<'tcx>, + dep_node: DepNode, +) { debug_assert!(tcx.dep_graph.is_green(&dep_node)); - let key = Q::Key::recover(tcx, &dep_node).unwrap_or_else(|| { + let key = C::Key::recover(tcx, &dep_node).unwrap_or_else(|| { panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash) }); if query.will_cache_on_disk_for_key(tcx, &key) { @@ -476,10 +477,11 @@ where value } -fn force_from_dep_node<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool -where - Q: QueryDispatcher<'tcx, Qcx = QueryCtxt<'tcx>>, -{ +fn force_from_dep_node<'tcx, C: QueryCache, const FLAGS: QueryFlags>( + query: SemiDynamicQueryDispatcher<'tcx, C, FLAGS>, + tcx: TyCtxt<'tcx>, + dep_node: DepNode, +) -> bool { // We must avoid ever having to call `force_from_dep_node()` for a // `DepNode::codegen_unit`: // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we @@ -498,7 +500,7 @@ where "calling force_from_dep_node() on dep_kinds::codegen_unit" ); - if let Some(key) = Q::Key::recover(tcx, &dep_node) { + if let Some(key) = C::Key::recover(tcx, &dep_node) { force_query(query, QueryCtxt::new(tcx), key, dep_node); true } else { diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs index c1f5e5b67085..eea1c5872290 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_query_system/src/query/caches.rs @@ -21,6 +21,9 @@ pub trait QueryCacheKey = Hash + Eq + Copy + Debug + for<'a> HashStable = Option, &V) -> Fingerprint>; - -/// Unambiguous shorthand for `::DepContext`. -#[expect(type_alias_bounds)] -type DepContextOf<'tcx, This: QueryDispatcher<'tcx>> = - <>::Qcx as HasDepContext>::DepContext; - -/// Trait that can be used as a vtable for a single query, providing operations -/// and metadata for that query. -/// -/// Implemented by `rustc_query_impl::SemiDynamicQueryDispatcher`, which -/// mostly delegates to `rustc_middle::query::plumbing::QueryVTable`. -/// Those types are not visible from this `rustc_query_system` crate. -/// -/// "Dispatcher" should be understood as a near-synonym of "vtable". -pub trait QueryDispatcher<'tcx>: Copy + 'tcx { - fn name(self) -> &'static str; - - /// Query context used by this dispatcher, i.e. `rustc_query_impl::QueryCtxt`. - type Qcx: QueryContext<'tcx>; - - // `Key` and `Value` are `Copy` instead of `Clone` to ensure copying them stays cheap, - // but it isn't necessary. - type Key: DepNodeKey> + Eq + Hash + Copy + Debug; - type Value: Copy; - - type Cache: QueryCache; - - fn format_value(self) -> fn(&Self::Value) -> String; - - // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_state(self, tcx: Self::Qcx) -> &'tcx QueryState<'tcx, Self::Key>; - - // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_cache(self, tcx: Self::Qcx) -> &'tcx Self::Cache; - - fn will_cache_on_disk_for_key(self, tcx: DepContextOf<'tcx, Self>, key: &Self::Key) -> bool; - - // Don't use this method to compute query results, instead use the methods on TyCtxt - fn execute_query(self, tcx: DepContextOf<'tcx, Self>, k: Self::Key) -> Self::Value; - - fn compute(self, tcx: Self::Qcx, key: Self::Key) -> Self::Value; - - fn try_load_from_disk( - self, - tcx: Self::Qcx, - key: &Self::Key, - prev_index: SerializedDepNodeIndex, - index: DepNodeIndex, - ) -> Option; - - fn is_loadable_from_disk( - self, - qcx: Self::Qcx, - key: &Self::Key, - idx: SerializedDepNodeIndex, - ) -> bool; - - /// Synthesize an error value to let compilation continue after a cycle. - fn value_from_cycle_error( - self, - tcx: DepContextOf<'tcx, Self>, - cycle_error: &CycleError, - guar: ErrorGuaranteed, - ) -> Self::Value; - - fn anon(self) -> bool; - fn eval_always(self) -> bool; - fn depth_limit(self) -> bool; - fn feedable(self) -> bool; - - fn dep_kind(self) -> DepKind; - fn cycle_error_handling(self) -> CycleErrorHandling; - fn hash_result(self) -> HashResult; - - // Just here for convenience and checking that the key matches the kind, don't override this. - fn construct_dep_node(self, tcx: DepContextOf<'tcx, Self>, key: &Self::Key) -> DepNode { - DepNode::construct(tcx, self.dep_kind(), key) - } -} diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 01bb6ff09fa1..828502b47d4c 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -15,7 +15,7 @@ use rustc_span::def_id::DefId; pub use self::caches::{ DefIdCache, DefaultCache, QueryCache, QueryCacheKey, SingleCache, VecCache, }; -pub use self::dispatcher::{HashResult, QueryDispatcher}; +pub use self::dispatcher::HashResult; pub use self::job::{ QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, QueryMap, break_query_cycles, print_query_stack, report_cycle, From f9958048e0e9a969848dfd24a9432a40de054429 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 9 Feb 2026 13:28:44 +1100 Subject: [PATCH 745/978] Move `HashResult`. It's the only thing left in `rustc_query_system::query::dispatcher`. --- compiler/rustc_middle/src/query/plumbing.rs | 6 +++++- compiler/rustc_query_impl/src/lib.rs | 4 ++-- compiler/rustc_query_system/src/query/dispatcher.rs | 5 ----- compiler/rustc_query_system/src/query/mod.rs | 2 -- 4 files changed, 7 insertions(+), 10 deletions(-) delete mode 100644 compiler/rustc_query_system/src/query/dispatcher.rs diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index abb02caef25d..04a3ceb0918a 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -1,12 +1,14 @@ use std::ops::Deref; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::sync::{AtomicU64, WorkerLocal}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::hir_id::OwnerId; use rustc_macros::HashStable; use rustc_query_system::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; +use rustc_query_system::ich::StableHashingContext; pub(crate) use rustc_query_system::query::QueryJobId; -use rustc_query_system::query::{CycleError, CycleErrorHandling, HashResult, QueryCache}; +use rustc_query_system::query::{CycleError, CycleErrorHandling, QueryCache}; use rustc_span::{ErrorGuaranteed, Span}; pub use sealed::IntoQueryParam; @@ -30,6 +32,8 @@ pub type TryLoadFromDiskFn<'tcx, Key, Value> = fn( pub type IsLoadableFromDiskFn<'tcx, Key> = fn(tcx: TyCtxt<'tcx>, key: &Key, index: SerializedDepNodeIndex) -> bool; +pub type HashResult = Option, &V) -> Fingerprint>; + /// Stores function pointers and other metadata for a particular query. /// /// Used indirectly by query plumbing in `rustc_query_system` via a trait, diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 7ca4a1300fe6..a33bdd22a797 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -18,12 +18,12 @@ use rustc_middle::queries::{ }; use rustc_middle::query::AsLocalKey; use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; -use rustc_middle::query::plumbing::{QuerySystem, QuerySystemFns, QueryVTable}; +use rustc_middle::query::plumbing::{HashResult, QuerySystem, QuerySystemFns, QueryVTable}; use rustc_middle::query::values::Value; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::SerializedDepNodeIndex; use rustc_query_system::query::{ - CycleError, CycleErrorHandling, HashResult, QueryCache, QueryMap, QueryMode, QueryState, + CycleError, CycleErrorHandling, QueryCache, QueryMap, QueryMode, QueryState, }; use rustc_span::{ErrorGuaranteed, Span}; diff --git a/compiler/rustc_query_system/src/query/dispatcher.rs b/compiler/rustc_query_system/src/query/dispatcher.rs deleted file mode 100644 index 3ef8295a07c3..000000000000 --- a/compiler/rustc_query_system/src/query/dispatcher.rs +++ /dev/null @@ -1,5 +0,0 @@ -use rustc_data_structures::fingerprint::Fingerprint; - -use crate::ich::StableHashingContext; - -pub type HashResult = Option, &V) -> Fingerprint>; diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 828502b47d4c..f4a3fda7e372 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -15,7 +15,6 @@ use rustc_span::def_id::DefId; pub use self::caches::{ DefIdCache, DefaultCache, QueryCache, QueryCacheKey, SingleCache, VecCache, }; -pub use self::dispatcher::HashResult; pub use self::job::{ QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, QueryMap, break_query_cycles, print_query_stack, report_cycle, @@ -24,7 +23,6 @@ pub use self::plumbing::*; use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; mod caches; -mod dispatcher; mod job; mod plumbing; From eb2ba7d6b9429297c582fed42fd5da5e5a51cd8f Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Mon, 9 Feb 2026 18:18:24 +0900 Subject: [PATCH 746/978] fix ICE in supertrait_vtable_slot when supertrait has missing generics --- .../src/traits/vtable.rs | 11 +++- .../vtable/missing-generics-issue-151330.rs | 23 ++++++++ .../missing-generics-issue-151330.stderr | 53 +++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 tests/ui/traits/vtable/missing-generics-issue-151330.rs create mode 100644 tests/ui/traits/vtable/missing-generics-issue-151330.stderr diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 584c8e2a27c8..539c1d3a35ba 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -434,7 +434,16 @@ pub(crate) fn supertrait_vtable_slot<'tcx>( } }; - prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap() + prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap_or_else(|| { + // This can happen if the trait hierarchy is malformed (e.g., due to + // missing generics on a supertrait bound). There should already be an error + // emitted for this, so we just delay the ICE. + tcx.dcx().delayed_bug(format!( + "could not find the supertrait vtable slot for `{}` -> `{}`", + source, target + )); + None + }) } pub(super) fn provide(providers: &mut Providers) { diff --git a/tests/ui/traits/vtable/missing-generics-issue-151330.rs b/tests/ui/traits/vtable/missing-generics-issue-151330.rs new file mode 100644 index 000000000000..352ad7be3d3a --- /dev/null +++ b/tests/ui/traits/vtable/missing-generics-issue-151330.rs @@ -0,0 +1,23 @@ +//@ compile-flags: -Znext-solver=globally +// Regression test for issue https://github.com/rust-lang/rust/issues/151330 + +trait Supertrait {} + +trait Trait

: Supertrait {} +//~^ ERROR missing generics for trait `Supertrait` +//~| ERROR missing generics for trait `Supertrait` +//~| ERROR missing generics for trait `Supertrait` + +impl

Trait

for () {} + +const fn upcast

(x: &dyn Trait

) -> &dyn Trait

{ + x +} + +const fn foo() -> &'static dyn Supertrait<()> { + upcast::<()>(&()) +} + +const _: &'static dyn Supertrait<()> = foo(); + +fn main() {} diff --git a/tests/ui/traits/vtable/missing-generics-issue-151330.stderr b/tests/ui/traits/vtable/missing-generics-issue-151330.stderr new file mode 100644 index 000000000000..65ef08cad32a --- /dev/null +++ b/tests/ui/traits/vtable/missing-generics-issue-151330.stderr @@ -0,0 +1,53 @@ +error[E0107]: missing generics for trait `Supertrait` + --> $DIR/missing-generics-issue-151330.rs:6:17 + | +LL | trait Trait

: Supertrait {} + | ^^^^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `T` + --> $DIR/missing-generics-issue-151330.rs:4:7 + | +LL | trait Supertrait {} + | ^^^^^^^^^^ - +help: add missing generic argument + | +LL | trait Trait

: Supertrait {} + | +++ + +error[E0107]: missing generics for trait `Supertrait` + --> $DIR/missing-generics-issue-151330.rs:6:17 + | +LL | trait Trait

: Supertrait {} + | ^^^^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `T` + --> $DIR/missing-generics-issue-151330.rs:4:7 + | +LL | trait Supertrait {} + | ^^^^^^^^^^ - + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: add missing generic argument + | +LL | trait Trait

: Supertrait {} + | +++ + +error[E0107]: missing generics for trait `Supertrait` + --> $DIR/missing-generics-issue-151330.rs:6:17 + | +LL | trait Trait

: Supertrait {} + | ^^^^^^^^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `T` + --> $DIR/missing-generics-issue-151330.rs:4:7 + | +LL | trait Supertrait {} + | ^^^^^^^^^^ - + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: add missing generic argument + | +LL | trait Trait

: Supertrait {} + | +++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0107`. From 3339b061af6a9c37ae326f60895048ddbbf3cd6d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sat, 7 Feb 2026 19:24:59 +0000 Subject: [PATCH 747/978] Do not require `'static` for obtaining reflection information. --- library/core/src/intrinsics/mod.rs | 2 +- library/core/src/mem/type_info.rs | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 051dda731881..094def9796db 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2887,7 +2887,7 @@ pub const fn type_name() -> &'static str; #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] -pub const fn type_id() -> crate::any::TypeId; +pub const fn type_id() -> crate::any::TypeId; /// Tests (at compile-time) if two [`crate::any::TypeId`] instances identify the /// same type. This is necessary because at const-eval time the actual discriminating diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index 8b30803c97c9..d3a7421ff2ee 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -2,7 +2,7 @@ //! runtime or const-eval processable way. use crate::any::TypeId; -use crate::intrinsics::type_of; +use crate::intrinsics::{type_id, type_of}; /// Compile-time type information. #[derive(Debug)] @@ -28,11 +28,17 @@ impl TypeId { impl Type { /// Returns the type information of the generic type parameter. + /// + /// Note: Unlike `TypeId`s obtained via `TypeId::of`, the `Type` + /// struct and its fields contain `TypeId`s that are not necessarily + /// derived from types that outlive `'static`. This means that using + /// the `TypeId`s (transitively) obtained from this function will + /// be able to break invariants that other `TypeId` consuming crates + /// may have assumed to hold. #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - // FIXME(reflection): don't require the 'static bound - pub const fn of() -> Self { - const { TypeId::of::().info() } + pub const fn of() -> Self { + const { type_id::().info() } } } From 6babe687a50440ae6a1d60a748f6a1f809b56d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Thu, 5 Feb 2026 15:57:14 +0100 Subject: [PATCH 748/978] Port rustc_reservation_impl to the new attribute parser --- .../src/attributes/rustc_internal.rs | 26 +++++++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + .../rustc_hir/src/attrs/data_structures.rs | 3 +++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_hir_analysis/src/collect.rs | 3 ++- compiler/rustc_passes/src/check_attr.rs | 2 +- .../src/traits/coherence.rs | 9 +++---- .../src/traits/select/mod.rs | 9 +++---- 8 files changed, 42 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index cbf4af8ce4f4..0fd8c8a04a57 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -873,3 +873,29 @@ impl NoArgsAttributeParser for RustcStrictCoherenceParser { ]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcStrictCoherence; } + +pub(crate) struct RustcReservationImplParser; + +impl SingleAttributeParser for RustcReservationImplParser { + const PATH: &[Symbol] = &[sym::rustc_reservation_impl]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowList(&[Allow(Target::Impl { of_trait: true })]); + + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "reservation message"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(nv) = args.name_value() else { + cx.expected_name_value(args.span().unwrap_or(cx.attr_span), None); + return None; + }; + + let Some(value_str) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + return None; + }; + + Some(AttributeKind::RustcReservationImpl(cx.attr_span, value_str)) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index afbb70654f4d..ddb5ae33bc98 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -209,6 +209,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index ef790fe76b74..d9c4179cca83 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1219,6 +1219,9 @@ pub enum AttributeKind { /// Represents `#[rustc_regions]` RustcRegions, + /// Represents `#[rustc_reservation_impl]` + RustcReservationImpl(Span, Symbol), + /// Represents `#[rustc_scalable_vector(N)]` RustcScalableVector { /// The base multiple of lanes that are in a scalable vector, if provided. `element_count` diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index cba7679d2df3..d55cb1d6f66a 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -151,6 +151,7 @@ impl AttributeKind { RustcPubTransparent(..) => Yes, RustcReallocator => No, RustcRegions => No, + RustcReservationImpl(..) => Yes, RustcScalableVector { .. } => Yes, RustcShouldNotBeCalledOnConstItems(..) => Yes, RustcSimdMonomorphizeLaneLimit(..) => Yes, // Affects layout computation, which needs to work cross-crate diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index f3086266eec0..219e44cd2e27 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1275,7 +1275,8 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplTraitHeader .of_trait .unwrap_or_else(|| panic!("expected impl trait, found inherent impl on {def_id:?}")); let selfty = tcx.type_of(def_id).instantiate_identity(); - let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); + let is_rustc_reservation = + find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcReservationImpl(..)); check_impl_constness(tcx, impl_.constness, &of_trait.trait_ref); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index dd0de90d575b..3f89ff577d59 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -342,6 +342,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcPreserveUbChecks | AttributeKind::RustcReallocator | AttributeKind::RustcRegions + | AttributeKind::RustcReservationImpl(..) | AttributeKind::RustcScalableVector { .. } | AttributeKind::RustcShouldNotBeCalledOnConstItems(..) | AttributeKind::RustcSimdMonomorphizeLaneLimit(..) @@ -396,7 +397,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_trivial_field_reads | sym::rustc_on_unimplemented | sym::rustc_do_not_const_check - | sym::rustc_reservation_impl | sym::rustc_doc_primitive | sym::rustc_conversion_suggestion | sym::rustc_deprecated_safe_2024 diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 9f59f6c59250..fc628e78a3e2 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -8,8 +8,10 @@ use std::fmt::Debug; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::{Diag, EmissionGuarantee}; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; +use rustc_hir::find_attr; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::PredicateObligations; use rustc_macros::{TypeFoldable, TypeVisitable}; @@ -23,7 +25,7 @@ use rustc_middle::ty::{ }; pub use rustc_next_trait_solver::coherence::*; use rustc_next_trait_solver::solve::SolverDelegateEvalExt; -use rustc_span::{DUMMY_SP, Span, sym}; +use rustc_span::{DUMMY_SP, Span}; use tracing::{debug, instrument, warn}; use super::ObligationCtxt; @@ -758,10 +760,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { } = cand.kind() && let ty::ImplPolarity::Reservation = infcx.tcx.impl_polarity(def_id) { - let message = infcx - .tcx - .get_attr(def_id, sym::rustc_reservation_impl) - .and_then(|a| a.value_str()); + let message = find_attr!(infcx.tcx.get_all_attrs(def_id), AttributeKind::RustcReservationImpl(_, message) => *message); if let Some(message) = message { self.causes.insert(IntercrateAmbiguityCause::ReservationImpl { message }); } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 787dd4ea6254..4469afc3a4eb 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -12,9 +12,9 @@ use rustc_data_structures::assert_matches; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Diag, EmissionGuarantee}; -use rustc_hir as hir; -use rustc_hir::LangItem; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::DefId; +use rustc_hir::{self as hir, LangItem, find_attr}; use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::at::ToTrace; @@ -33,7 +33,7 @@ use rustc_middle::ty::{ may_use_unstable_feature, }; use rustc_next_trait_solver::solve::AliasBoundKind; -use rustc_span::{Symbol, sym}; +use rustc_span::Symbol; use tracing::{debug, instrument, trace}; use self::EvaluationResult::*; @@ -1445,8 +1445,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { && let ty::ImplPolarity::Reservation = tcx.impl_polarity(def_id) { if let Some(intercrate_ambiguity_clauses) = &mut self.intercrate_ambiguity_causes { - let message = - tcx.get_attr(def_id, sym::rustc_reservation_impl).and_then(|a| a.value_str()); + let message = find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcReservationImpl(_, message) => *message); if let Some(message) = message { debug!( "filter_reservation_impls: \ From 88c296a19fb205e08edd9636a7ccf94b0346720c Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 9 Feb 2026 18:24:11 +0800 Subject: [PATCH 749/978] std: introduce path normalize methods at top of std::path --- library/std/src/path.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 25bd7005b994..14b41a427f1e 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -19,6 +19,20 @@ //! matter the platform or filesystem. An exception to this is made for Windows //! drive letters. //! +//! ## Path normalization +//! +//! Several methods in this module perform basic path normalization by disregarding +//! repeated separators, non-leading `.` components, and trailing separators. These include: +//! - Methods for iteration, such as [`Path::components`] and [`Path::iter`] +//! - Methods for inspection, such as [`Path::has_root`] +//! - Comparisons using [`PartialEq`], [`PartialOrd`], and [`Ord`] +//! +//! [`Path::join`] and [`PathBuf::push`] also disregard trailing slashes. +//! +// FIXME(normalize_lexically): mention normalize_lexically once stable +//! These methods **do not** resolve `..` components or symlinks. For full normalization +//! including `..` resolution, use [`Path::canonicalize`] (which does access the filesystem). +//! //! ## Simple usage //! //! Path manipulation includes both parsing components from slices and building From 8cd47adab253c6ec0eea949563215fa7fdbc7241 Mon Sep 17 00:00:00 2001 From: Juho Kahala <57393910+quaternic@users.noreply.github.com> Date: Mon, 9 Feb 2026 12:32:04 +0200 Subject: [PATCH 750/978] libm: Fix tests for lgamma The tests were using `rug::ln_gamma` as a reference for `libm::lgamma`, which actually computes the natural logarithm *of the absolute value* of the Gamma function. This changes the range of inputs used for the icount-benchmarks of these functions, which causes false regressions in [1]. [1]: https://github.com/rust-lang/compiler-builtins/actions/runs/21788698368/job/62864230903?pr=1075#step:7:2710. Fixes: a1a066611dc2 ("Create interfaces for testing against MPFR") --- .../compiler-builtins/libm-test/src/domain.rs | 2 +- .../libm-test/src/mpfloat.rs | 27 +++++++++++++- .../libm-test/src/precision.rs | 36 +++++++++---------- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/library/compiler-builtins/libm-test/src/domain.rs b/library/compiler-builtins/libm-test/src/domain.rs index 94641be9b548..eb009bfa093f 100644 --- a/library/compiler-builtins/libm-test/src/domain.rs +++ b/library/compiler-builtins/libm-test/src/domain.rs @@ -207,7 +207,7 @@ impl EitherPrim, Domain> { .into_prim_float()]; /// Domain for `loggamma` - const LGAMMA: [Self; 1] = Self::STRICTLY_POSITIVE; + const LGAMMA: [Self; 1] = Self::UNBOUNDED1; /// Domain for `jn` and `yn`. // FIXME: the domain should provide some sort of "reasonable range" so we don't actually test diff --git a/library/compiler-builtins/libm-test/src/mpfloat.rs b/library/compiler-builtins/libm-test/src/mpfloat.rs index 9b51dc6051d0..85f0a4da4a6e 100644 --- a/library/compiler-builtins/libm-test/src/mpfloat.rs +++ b/library/compiler-builtins/libm-test/src/mpfloat.rs @@ -170,7 +170,9 @@ libm_macros::for_each_function! { ldexpf, ldexpf128, ldexpf16, + lgamma, lgamma_r, + lgammaf, lgammaf_r, modf, modff, @@ -213,7 +215,6 @@ libm_macros::for_each_function! { fmaximum_num | fmaximum_numf | fmaximum_numf16 | fmaximum_numf128 => max, fmin | fminf | fminf16 | fminf128 | fminimum_num | fminimum_numf | fminimum_numf16 | fminimum_numf128 => min, - lgamma | lgammaf => ln_gamma, log | logf => ln, log1p | log1pf => ln_1p, tgamma | tgammaf => gamma, @@ -576,6 +577,30 @@ impl MpOp for crate::op::lgammaf_r::Routine { } } +impl MpOp for crate::op::lgamma::Routine { + type MpTy = MpFloat; + + fn new_mp() -> Self::MpTy { + new_mpfloat::() + } + + fn run(this: &mut Self::MpTy, input: Self::RustArgs) -> Self::RustRet { + ::run(this, input).0 + } +} + +impl MpOp for crate::op::lgammaf::Routine { + type MpTy = MpFloat; + + fn new_mp() -> Self::MpTy { + new_mpfloat::() + } + + fn run(this: &mut Self::MpTy, input: Self::RustArgs) -> Self::RustRet { + ::run(this, input).0 + } +} + /* stub implementations so we don't need to special case them */ impl MpOp for crate::op::nextafter::Routine { diff --git a/library/compiler-builtins/libm-test/src/precision.rs b/library/compiler-builtins/libm-test/src/precision.rs index a94fe429f5f3..5d52da168fe7 100644 --- a/library/compiler-builtins/libm-test/src/precision.rs +++ b/library/compiler-builtins/libm-test/src/precision.rs @@ -67,7 +67,7 @@ pub fn default_ulp(ctx: &CheckCtx) -> u32 { Bn::Exp2 => 1, Bn::Expm1 => 1, Bn::Hypot => 1, - Bn::Lgamma | Bn::LgammaR => 16, + Bn::Lgamma | Bn::LgammaR => 4, Bn::Log => 1, Bn::Log10 => 1, Bn::Log1p => 1, @@ -102,7 +102,6 @@ pub fn default_ulp(ctx: &CheckCtx) -> u32 { match ctx.base_name { Bn::Cosh => ulp = 2, Bn::Exp10 if usize::BITS < 64 => ulp = 4, - Bn::Lgamma | Bn::LgammaR => ulp = 400, Bn::Tanh => ulp = 4, _ => (), } @@ -218,17 +217,17 @@ impl MaybeOverride<(f16,)> for SpecialCase {} impl MaybeOverride<(f32,)> for SpecialCase { fn check_float(input: (f32,), actual: F, expected: F, ctx: &CheckCtx) -> CheckAction { - if (ctx.base_name == BaseName::Lgamma || ctx.base_name == BaseName::LgammaR) - && input.0 > 4e36 - && expected.is_infinite() - && !actual.is_infinite() - { - // This result should saturate but we return a finite value. + if ctx.base_name == BaseName::J0 && input.0 < -1e34 { + // Errors get huge close to -inf return XFAIL_NOCHECK; } - if ctx.base_name == BaseName::J0 && input.0 < -1e34 { - // Errors get huge close to -inf + // FIXME(correctness): lgammaf has high relative inaccuracy near its zeroes + if matches!(ctx.base_name, BaseName::Lgamma | BaseName::LgammaR) + && input.0 > -13.0625 + && input.0 < -2.0 + && (expected.abs() < F::ONE || (input.0 - input.0.round()).abs() < 0.02) + { return XFAIL_NOCHECK; } @@ -275,6 +274,15 @@ impl MaybeOverride<(f64,)> for SpecialCase { return XFAIL_NOCHECK; } + // FIXME(correctness): lgamma has high relative inaccuracy near its zeroes + if matches!(ctx.base_name, BaseName::Lgamma | BaseName::LgammaR) + && input.0 > -32.0 + && input.0 < -2.0 + && (expected.abs() < F::ONE || (input.0 - input.0.round()).abs() < 0.02) + { + return XFAIL_NOCHECK; + } + // maybe_check_nan_bits(actual, expected, ctx) unop_common(input, actual, expected, ctx) } @@ -304,14 +312,6 @@ fn unop_common( expected: F2, ctx: &CheckCtx, ) -> CheckAction { - if (ctx.base_name == BaseName::Lgamma || ctx.base_name == BaseName::LgammaR) - && input.0 < F1::ZERO - && !input.0.is_infinite() - { - // loggamma should not be defined for x < 0, yet we both return results - return XFAIL_NOCHECK; - } - // fabs and copysign must leave NaNs untouched. if ctx.base_name == BaseName::Fabs && input.0.is_nan() { // LLVM currently uses x87 instructions which quieten signalling NaNs to handle the i686 From 8c0a493e358a27f1dea9888f85680c613e41903f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Feb 2026 12:03:29 +0100 Subject: [PATCH 751/978] BikeshedGuaranteedNoDrop trait: add comments indicating that it can be observed on stable --- compiler/rustc_next_trait_solver/src/solve/trait_goals.rs | 3 +++ .../rustc_trait_selection/src/traits/select/confirmation.rs | 2 ++ 2 files changed, 5 insertions(+) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 003841f3af3f..dd012a5146e6 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -687,6 +687,9 @@ where /// /// because these impls overlap, and I'd rather not build a coherence hack for /// this harmless overlap. + /// + /// This trait is indirectly exposed on stable, so do *not* extend the set of types that + /// implement the trait without FCP! fn consider_builtin_bikeshed_guaranteed_no_drop_candidate( ecx: &mut EvalCtxt<'_, D>, goal: Goal, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 4f65b30775ed..b0e045274d0d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1246,6 +1246,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) } + /// This trait is indirectly exposed on stable, so do *not* extend the set of types that + /// implement the trait without FCP! fn confirm_bikeshed_guaranteed_no_drop_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, From 0cf7b94bf52f45996776d8b27708516928b12e0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Thu, 13 Nov 2025 15:44:20 +0100 Subject: [PATCH 752/978] fix Nix setup description --- src/doc/rustc-dev-guide/src/building/suggested.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index 3ed4f129d144..ac8f15db7751 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -426,7 +426,7 @@ You can then use that rust2 folder as a separate workspace for modifying and bui Several nix configurations are defined in `src/tools/nix-dev-shell`. -If you're using direnv, you can create a symbol link to `src/tools/nix-dev-shell/envrc-flake` or `src/tools/nix-dev-shell/envrc-shell` +If you're using direnv, you can create a symbolic link to `src/tools/nix-dev-shell/envrc-flake` or `src/tools/nix-dev-shell/envrc-shell` ```bash ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc # Use flake @@ -436,6 +436,12 @@ or ln -s ./src/tools/nix-dev-shell/envrc-shell ./.envrc # Use nix-shell ``` +If you're using the flake, make sure to also update it with the following command: + +``` +nix flake update --flake ./src/tools/nix-dev-shell +``` + ### Note Note that when using nix on a not-NixOS distribution, it may be necessary to set From 389294dcde4f50e9c910e5da6aca0582ced13796 Mon Sep 17 00:00:00 2001 From: Nora Breitmoser-Widdecke <23097564+puzzlewolf@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:35:09 +0100 Subject: [PATCH 753/978] Fix documentation for `indexing_slicing` Replace typo'd name with link to the lint. --- clippy_lints/src/indexing_slicing.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index a2fcdb4a54b4..e9ddd3ca8ede 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -44,7 +44,7 @@ declare_clippy_lint! { /// Checks for usage of indexing or slicing that may panic at runtime. /// /// This lint does not report on indexing or slicing operations - /// that always panic, clippy's `out_of_bound_indexing` already + /// that always panic, [out_of_bounds_indexing](#out_of_bounds_indexing) already /// handles those cases. /// /// ### Why restrict this? From e04ae80c5ac7fab7d01aee9ad97ef109fe7f024d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 9 Feb 2026 17:32:48 +1100 Subject: [PATCH 754/978] Rename `JobOwner` to `ActiveJobGuard` This commit also adds and updates some relevant comments. --- compiler/rustc_middle/src/ty/context/tls.rs | 3 +-- compiler/rustc_query_impl/src/execution.rs | 25 +++++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs index fa9995898ac2..a06f92792820 100644 --- a/compiler/rustc_middle/src/ty/context/tls.rs +++ b/compiler/rustc_middle/src/ty/context/tls.rs @@ -16,8 +16,7 @@ pub struct ImplicitCtxt<'a, 'tcx> { /// The current `TyCtxt`. pub tcx: TyCtxt<'tcx>, - /// The current query job, if any. This is updated by `JobOwner::start` in - /// `ty::query::plumbing` when executing a query. + /// The current query job, if any. pub query: Option, /// Used to prevent queries from calling too deeply. diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index ba442d8a0081..7bed6ee937db 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -83,9 +83,12 @@ pub(crate) fn gather_active_jobs_inner<'tcx, K: Copy>( Some(()) } -/// A type representing the responsibility to execute the job in the `job` field. -/// This will poison the relevant query if dropped. -struct JobOwner<'tcx, K> +/// Guard object representing the responsibility to execute a query job and +/// mark it as completed. +/// +/// This will poison the relevant query key if it is dropped without calling +/// [`Self::complete`]. +struct ActiveJobGuard<'tcx, K> where K: Eq + Hash + Copy, { @@ -137,12 +140,12 @@ fn handle_cycle_error<'tcx, C: QueryCache, const FLAGS: QueryFlags>( } } -impl<'tcx, K> JobOwner<'tcx, K> +impl<'tcx, K> ActiveJobGuard<'tcx, K> where K: Eq + Hash + Copy, { /// Completes the query by updating the query cache with the `result`, - /// signals the waiter and forgets the JobOwner, so it won't poison the query + /// signals the waiter, and forgets the guard so it won't poison the query. fn complete(self, cache: &C, key_hash: u64, result: C::Value, dep_node_index: DepNodeIndex) where C: QueryCache, @@ -174,7 +177,7 @@ where } } -impl<'tcx, K> Drop for JobOwner<'tcx, K> +impl<'tcx, K> Drop for ActiveJobGuard<'tcx, K> where K: Eq + Hash + Copy, { @@ -342,11 +345,13 @@ fn execute_job<'tcx, C: QueryCache, const FLAGS: QueryFlags, const INCR: bool>( id: QueryJobId, dep_node: Option, ) -> (C::Value, Option) { - // Use `JobOwner` so the query will be poisoned if executing it panics. - let job_owner = JobOwner { state, key }; + // Set up a guard object that will automatically poison the query if a + // panic occurs while executing the query (or any intermediate plumbing). + let job_guard = ActiveJobGuard { state, key }; debug_assert_eq!(qcx.tcx.dep_graph.is_fully_enabled(), INCR); + // Delegate to another function to actually execute the query job. let (result, dep_node_index) = if INCR { execute_job_incr(query, qcx, qcx.tcx.dep_graph.data().unwrap(), key, dep_node, id) } else { @@ -388,7 +393,9 @@ fn execute_job<'tcx, C: QueryCache, const FLAGS: QueryFlags, const INCR: bool>( } } } - job_owner.complete(cache, key_hash, result, dep_node_index); + + // Tell the guard to perform completion bookkeeping, and also to not poison the query. + job_guard.complete(cache, key_hash, result, dep_node_index); (result, Some(dep_node_index)) } From c475bdaa53441f52977ce79ac2e16b807dcb006d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 9 Feb 2026 17:36:29 +1100 Subject: [PATCH 755/978] Include `key_hash` in `ActiveJobGuard` This value is a previously-computed hash of the key, so it makes sense to bundle it with the key inside the guard, since the guard will need it on completion anyway. --- compiler/rustc_query_impl/src/execution.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 7bed6ee937db..88604c91d025 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -94,6 +94,7 @@ where { state: &'tcx QueryState<'tcx, K>, key: K, + key_hash: u64, } #[cold] @@ -146,14 +147,13 @@ where { /// Completes the query by updating the query cache with the `result`, /// signals the waiter, and forgets the guard so it won't poison the query. - fn complete(self, cache: &C, key_hash: u64, result: C::Value, dep_node_index: DepNodeIndex) + fn complete(self, cache: &C, result: C::Value, dep_node_index: DepNodeIndex) where C: QueryCache, { - let key = self.key; - let state = self.state; - - // Forget ourself so our destructor won't poison the query + // Forget ourself so our destructor won't poison the query. + // (Extract fields by value first to make sure we don't leak anything.) + let Self { state, key, key_hash }: Self = self; mem::forget(self); // Mark as complete before we remove the job from the active state @@ -185,11 +185,10 @@ where #[cold] fn drop(&mut self) { // Poison the query so jobs waiting on it panic. - let state = self.state; + let Self { state, key, key_hash } = *self; let job = { - let key_hash = sharded::make_hash(&self.key); let mut shard = state.active.lock_shard_by_hash(key_hash); - match shard.find_entry(key_hash, equivalent_key(&self.key)) { + match shard.find_entry(key_hash, equivalent_key(&key)) { Err(_) => panic!(), Ok(occupied) => { let ((key, value), vacant) = occupied.remove(); @@ -347,7 +346,7 @@ fn execute_job<'tcx, C: QueryCache, const FLAGS: QueryFlags, const INCR: bool>( ) -> (C::Value, Option) { // Set up a guard object that will automatically poison the query if a // panic occurs while executing the query (or any intermediate plumbing). - let job_guard = ActiveJobGuard { state, key }; + let job_guard = ActiveJobGuard { state, key, key_hash }; debug_assert_eq!(qcx.tcx.dep_graph.is_fully_enabled(), INCR); @@ -395,7 +394,7 @@ fn execute_job<'tcx, C: QueryCache, const FLAGS: QueryFlags, const INCR: bool>( } // Tell the guard to perform completion bookkeeping, and also to not poison the query. - job_guard.complete(cache, key_hash, result, dep_node_index); + job_guard.complete(cache, result, dep_node_index); (result, Some(dep_node_index)) } From 2b22150c1802bd5833492e263745a9037f1a190a Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Wed, 4 Feb 2026 18:37:10 +0000 Subject: [PATCH 756/978] Port rustc_no_implicit_bounds attribute to parser. --- .../rustc_attr_parsing/src/attributes/crate_level.rs | 9 +++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ compiler/rustc_hir/src/attrs/encode_cross_crate.rs | 1 + .../rustc_hir_analysis/src/hir_ty_lowering/bounds.rs | 10 ++++++---- compiler/rustc_passes/src/check_attr.rs | 2 +- 6 files changed, 21 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index 557dfe09853b..bdfe7bfb8f1f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -283,3 +283,12 @@ impl NoArgsAttributeParser for RustcPreserveUbChecksParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks; } + +pub(crate) struct RustcNoImplicitBoundsParser; + +impl NoArgsAttributeParser for RustcNoImplicitBoundsParser { + const PATH: &[Symbol] = &[sym::rustc_no_implicit_bounds]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitBounds; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index afbb70654f4d..573e14786abf 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -281,6 +281,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index ef790fe76b74..869e3f43ea71 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1177,6 +1177,9 @@ pub enum AttributeKind { /// Represents `#[rustc_no_implicit_autorefs]` RustcNoImplicitAutorefs, + /// Represents `#[rustc_no_implicit_bounds]` + RustcNoImplicitBounds, + /// Represents `#[rustc_non_const_trait_method]`. RustcNonConstTraitMethod, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index cba7679d2df3..001448b3e72e 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -137,6 +137,7 @@ impl AttributeKind { RustcMustImplementOneOf { .. } => No, RustcNeverReturnsNullPointer => Yes, RustcNoImplicitAutorefs => Yes, + RustcNoImplicitBounds => No, RustcNonConstTraitMethod => No, // should be reported via other queries like `constness` RustcNounwind => No, RustcObjcClass { .. } => No, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index a1c3af5f999d..85e96e200c2e 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -4,15 +4,16 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; -use rustc_hir::PolyTraitRef; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; +use rustc_hir::{PolyTraitRef, find_attr}; use rustc_middle::bug; use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast, }; -use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; +use rustc_span::{ErrorGuaranteed, Ident, Span, kw}; use rustc_trait_selection::traits; use smallvec::SmallVec; use tracing::{debug, instrument}; @@ -170,7 +171,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let tcx = self.tcx(); // Skip adding any default bounds if `#![rustc_no_implicit_bounds]` - if tcx.has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) { + if find_attr!(tcx.get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcNoImplicitBounds) { return; } @@ -284,7 +285,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { context: ImpliedBoundsContext<'tcx>, ) -> bool { let collected = collect_bounds(hir_bounds, context, trait_def_id); - !self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any() + !find_attr!(self.tcx().get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcNoImplicitBounds) + && !collected.any() } fn reject_duplicate_relaxed_bounds(&self, relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>) { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index dd0de90d575b..2dcfbaaef579 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -330,6 +330,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcMir(_) | AttributeKind::RustcNeverReturnsNullPointer | AttributeKind::RustcNoImplicitAutorefs + | AttributeKind::RustcNoImplicitBounds | AttributeKind::RustcNonConstTraitMethod | AttributeKind::RustcNounwind | AttributeKind::RustcObjcClass { .. } @@ -413,7 +414,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // crate-level attrs, are checked below | sym::feature | sym::register_tool - | sym::rustc_no_implicit_bounds | sym::test_runner, .. ] => {} From 43e5203a8cc1d10f12895475069c216db4d2dd95 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 6 Feb 2026 16:16:17 +0000 Subject: [PATCH 757/978] compiletest: `-Zunstable-options` for json targets --- src/tools/compiletest/src/common.rs | 4 +++- src/tools/compiletest/src/runtest.rs | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index c71a350ffd30..54c0f2ec7430 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -949,7 +949,9 @@ impl TargetCfgs { // actually be changed with `-C` flags. for config in query_rustc_output( config, - &["--print=cfg", "--target", &config.target], + // `-Zunstable-options` is necessary when compiletest is running with custom targets + // (such as synthetic targets used to bless mir-opt tests). + &["-Zunstable-options", "--print=cfg", "--target", &config.target], Default::default(), ) .trim() diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 1804490a5f12..742790a50fce 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1670,6 +1670,11 @@ impl<'test> TestCx<'test> { if self.props.force_host { &*self.config.host } else { &*self.config.target }; compiler.arg(&format!("--target={}", target)); + if target.ends_with(".json") { + // `-Zunstable-options` is necessary when compiletest is running with custom targets + // (such as synthetic targets used to bless mir-opt tests). + compiler.arg("-Zunstable-options"); + } } self.set_revision_flags(&mut compiler); From 40a264cd454e791f478dae1488bb67ed7d7d058d Mon Sep 17 00:00:00 2001 From: Weixie Cui Date: Mon, 9 Feb 2026 22:16:36 +0800 Subject: [PATCH 758/978] fix: rhs_span to rhs_span_new --- compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 4fb739403ced..853ecd3c91f7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1695,7 +1695,7 @@ fn suggest_ampmut<'tcx>( && let Either::Left(rhs_stmt_new) = body.stmt_at(*assign) && let StatementKind::Assign(box (_, rvalue_new)) = &rhs_stmt_new.kind && let rhs_span_new = rhs_stmt_new.source_info.span - && let Ok(rhs_str_new) = tcx.sess.source_map().span_to_snippet(rhs_span) + && let Ok(rhs_str_new) = tcx.sess.source_map().span_to_snippet(rhs_span_new) { (rvalue, rhs_span, rhs_str) = (rvalue_new, rhs_span_new, rhs_str_new); } From 00432c0b85ecd3a099fbe4b0f867f3929b099366 Mon Sep 17 00:00:00 2001 From: mikhailofff Date: Mon, 9 Feb 2026 18:54:17 +0400 Subject: [PATCH 759/978] fix dead links in type checking section of the doc --- book/src/development/type_checking.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/book/src/development/type_checking.md b/book/src/development/type_checking.md index 578836ecc568..55adb0aceadd 100644 --- a/book/src/development/type_checking.md +++ b/book/src/development/type_checking.md @@ -146,7 +146,7 @@ in this chapter: - [Stages of compilation](https://rustc-dev-guide.rust-lang.org/compiler-src.html#the-main-stages-of-compilation) - [Diagnostic items](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html) -- [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html) +- [Type checking](https://rustc-dev-guide.rust-lang.org/hir-typeck/summary.html) - [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html) [Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/ty_kind/enum.TyKind.html#variant.Adt @@ -163,5 +163,5 @@ in this chapter: [TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/ty_kind/enum.TyKind.html [TypeckResults]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html [middle_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html -[hir_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/struct.Ty.html +[hir_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Ty.html [lower_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/fn.lower_ty.html From 73a991fb9d7f68f497f047d4e948bde463f2f6eb Mon Sep 17 00:00:00 2001 From: Keith-Cancel Date: Thu, 5 Feb 2026 22:01:57 -0800 Subject: [PATCH 760/978] Allow provisional mgca syntax of type const = to be reconized. Revert, but without type const. Update symbol for feature err, then update suggestion output, and lastly update tests that change because of those. Update these new tests with the correct syntax, and few existing tests with the new outputs the merge with main added. Fix for tidyfmt and some errors when manually resolving a merge conflicts. Update these tests to use update error messages and type const syntax. Update comments and error message to use new syntax instead of old type_const attribute. Remove the type_const attribute update some more tests to use the new syntax. Update these test cases. update feature gate test Change gate logic for `mgca_type_const_syntax` to work also if `min_generic_const_args` is enabled. Create a new feature gate that checks for the feature before expansion. Make rustfmt handle the `type const` syntax correctly. Add a convience method to check if a RhsKind is type const. Rename `Const` discriminant to `Body` for `ConstItemRhsKind` Give the `TraitItemKind` flag an enum instead of a simple bool to better describe what the flag is for. Update formatting for these match statements. Update clippy test to use type const syntax. Update test to use type const syntax. update rustfmt to match ast items. Update clippy to match ast and hir items. Few more test cases that used old attribute, instead of 'type const' Update to match the output from the feature gate checks. tidyfmt adjustments. Update the is_type_const, so I can constrain record!(..) in encoder.rs Update conditional compilation test. Move the feature gate to after expansion to allow for cfg(...) to work. Update some more tests to use the new syntax. Update type const tests in associated-const-bindings to use new syntax. Don't check based off the attribute, but the item here. Update some tests outside of the const_generics folder that were using #[type_const] update the tests in associated consts that use #[type_const] to use type const Update these mgca tests with the type const syntax. Add a flag to TraitItemKind for detecting type const for now. Maybe later change ItemConstRhs to have optional consts but that touches a lot more lines of code. Don't need into for these now that it's a query. Add is_type_const query to handle foreign def ids. update this test to use type const syntax. Fix logic here, we only want to lower if there is expression in this case. Update built-in macros to use ConstItemRhsKind Update more instance of the old ConstItemRhs. Rename ConstItemKind to ConstItemRhsKind, I noticed there is a typed called ConstantItemKind, so add the Rhs to the name to avoid confusion. Update lower to use ConstItemKind Add an other helper method to check if the rhs kinda has an expr. Update item parse to use ConstItemKind enum. Felt the field name could a be little clear when editing a few other things. Change the ConstItem struct see know if we have a type const or regular const. Make sure this syntax is properly feature gated. --- compiler/rustc_ast/src/ast.rs | 37 ++++++--- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/item.rs | 35 +++++--- compiler/rustc_ast_lowering/src/lib.rs | 19 ++--- .../rustc_ast_passes/src/ast_validation.rs | 16 ++-- compiler/rustc_ast_passes/src/feature_gate.rs | 43 ++++++++++ .../rustc_ast_pretty/src/pprust/state/item.rs | 8 +- .../src/attributes/traits.rs | 9 --- compiler/rustc_attr_parsing/src/context.rs | 1 - .../src/alloc_error_handler.rs | 2 +- compiler/rustc_builtin_macros/src/eii.rs | 2 +- .../src/global_allocator.rs | 2 +- .../src/proc_macro_harness.rs | 2 +- compiler/rustc_builtin_macros/src/test.rs | 4 +- .../src/check_consts/qualifs.rs | 2 +- .../src/const_eval/eval_queries.rs | 2 +- compiler/rustc_expand/src/build.rs | 4 +- compiler/rustc_feature/src/builtin_attrs.rs | 7 -- compiler/rustc_feature/src/unstable.rs | 2 + .../rustc_hir/src/attrs/data_structures.rs | 3 - .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 - compiler/rustc_hir/src/hir.rs | 31 +++++-- compiler/rustc_hir/src/intravisit.rs | 2 +- .../rustc_hir_analysis/src/check/check.rs | 2 +- .../src/check/compare_impl_item.rs | 4 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 25 +++++- .../src/collect/resolve_bound_vars.rs | 2 +- .../rustc_hir_analysis/src/collect/type_of.rs | 8 +- .../src/hir_ty_lowering/bounds.rs | 6 +- .../src/hir_ty_lowering/mod.rs | 13 +-- .../rustc_hir_analysis/src/hir_wf_check.rs | 2 +- compiler/rustc_hir_analysis/src/lib.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_lint/src/unused.rs | 4 +- .../src/rmeta/decoder/cstore_impl.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 3 + compiler/rustc_metadata/src/rmeta/mod.rs | 1 + compiler/rustc_middle/src/queries.rs | 10 ++- compiler/rustc_middle/src/traits/mod.rs | 4 +- compiler/rustc_middle/src/ty/context.rs | 22 +++-- compiler/rustc_mir_build/src/builder/mod.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 80 ++++++++++++------- compiler/rustc_passes/src/check_attr.rs | 1 - compiler/rustc_passes/src/reachable.rs | 8 +- compiler/rustc_resolve/src/late.rs | 63 +++++++-------- compiler/rustc_span/src/symbol.rs | 2 +- .../src/traits/normalize.rs | 2 +- src/librustdoc/clean/mod.rs | 4 +- .../clippy/clippy_lints/src/non_copy_const.rs | 4 +- .../clippy/clippy_lints/src/types/mod.rs | 2 +- .../clippy/clippy_utils/src/ast_utils/mod.rs | 28 ++++--- ...duplication_in_bounds_assoc_const_eq.fixed | 4 +- ...it_duplication_in_bounds_assoc_const_eq.rs | 4 +- src/tools/rustfmt/src/items.rs | 56 ++++++++----- tests/crashes/149809.rs | 3 +- tests/debuginfo/associated-const-bindings.rs | 6 +- .../ice-associated-const-equality-105952.rs | 3 +- .../auxiliary/assoc-const-equality.rs | 3 +- .../associated-constant-not-allowed-102467.rs | 3 +- tests/ui/associated-consts/issue-110933.rs | 3 +- .../type-const-in-array-len-wrong-type.rs | 3 +- .../type-const-in-array-len-wrong-type.stderr | 2 +- .../type-const-in-array-len.rs | 9 +-- .../duplicate-bound-err.rs | 12 +-- .../duplicate-bound-err.stderr | 42 +++++----- .../associated-type-bounds/duplicate-bound.rs | 6 +- .../type-const-inherent-impl-normalize.rs | 6 +- .../type-const-inherent-impl-normalize.stderr | 18 ++++- tests/ui/attributes/malformed-attrs.rs | 2 - tests/ui/attributes/malformed-attrs.stderr | 61 ++++++-------- .../associated-const-bindings/ambiguity.rs | 9 +-- .../ambiguity.stderr | 16 ++-- .../associated-const-bindings/assoc-const.rs | 6 +- .../bound-var-in-ty-not-wf.rs | 3 +- .../bound-var-in-ty-not-wf.stderr | 4 +- .../bound-var-in-ty.rs | 3 +- .../coexisting-with-type-binding.rs | 6 +- .../associated-const-bindings/coherence.rs | 6 +- .../coherence.stderr | 2 +- .../const-projection-err.rs | 3 +- .../const-projection-err.stderr | 4 +- .../const_evaluatable_unchecked.rs | 3 +- ...dyn-compat-assoc-const-ty-mentions-self.rs | 6 +- ...compat-assoc-const-ty-mentions-self.stderr | 12 +-- .../dyn-compat-basic.rs | 15 ++-- .../dyn-compat-const-mismatch.rs | 6 +- .../dyn-compat-const-mismatch.stderr | 2 +- ...ompat-const-param-default-mentions-self.rs | 6 +- ...t-const-param-default-mentions-self.stderr | 2 +- ...ection-behind-trait-alias-mentions-self.rs | 3 +- ...on-behind-trait-alias-mentions-self.stderr | 2 +- ...rojection-from-supertrait-mentions-self.rs | 6 +- ...ction-from-supertrait-mentions-self.stderr | 6 +- .../dyn-compat-non-type-assoc-const.rs | 4 +- .../dyn-compat-non-type-assoc-const.stderr | 8 +- ...und-on-assoc-const-allowed-and-enforced.rs | 6 +- ...on-assoc-const-allowed-and-enforced.stderr | 10 +-- ...elf-const-projections-in-assoc-const-ty.rs | 6 +- ...const-projections-in-assoc-const-ty.stderr | 8 +- ...ompat-self-const-projections-in-methods.rs | 9 +-- ...-const-projections-in-supertrait-bounds.rs | 3 +- ...st-projections-in-supertrait-bounds.stderr | 2 +- .../dyn-compat-symbol-mangling.rs | 3 +- .../dyn-compat-symbol-mangling.v0.stderr | 6 +- .../dyn-compat-unspecified-assoc-consts.rs | 3 +- ...dyn-compat-unspecified-assoc-consts.stderr | 18 ++--- .../equality-unused-issue-126729.rs | 24 ++---- .../equality_bound_with_infer.rs | 6 +- .../esc-bound-var-in-ty.rs | 3 +- .../esc-bound-var-in-ty.stderr | 2 +- .../issue-102335-const.rs | 3 +- .../mismatched-types-with-generic-in-ace.rs | 6 +- ...ismatched-types-with-generic-in-ace.stderr | 16 ++-- .../normalization-via-param-env.rs | 3 +- .../associated-const-bindings/param-in-ty.rs | 6 +- .../param-in-ty.stderr | 22 ++--- .../projection-unspecified-but-bounded.rs | 3 +- .../projection-unspecified-but-bounded.stderr | 4 +- .../associated-const-bindings/supertraits.rs | 3 +- .../using-fnptr-as-type_const.rs | 3 +- .../using-fnptr-as-type_const.stderr | 6 +- .../auxiliary/non_local_type_const.rs | 3 +- .../mgca/adt_expr_arg_simple.rs | 4 +- .../mgca/adt_expr_arg_tuple_expr_fail.rs | 4 +- .../mgca/adt_expr_infers_from_value.rs | 3 +- .../mgca/array-expr-with-assoc-const.rs | 3 +- .../mgca/assoc-const-projection-in-bound.rs | 6 +- .../mgca/assoc-const-without-type_const.rs | 4 +- .../assoc-const-without-type_const.stderr | 22 ++--- tests/ui/const-generics/mgca/assoc-const.rs | 3 +- .../mgca/bad-type_const-syntax.rs | 14 ++-- .../mgca/bad-type_const-syntax.stderr | 40 ++++++---- .../concrete-expr-with-generics-in-env.rs | 18 ++--- ...const-arg-coherence-conflicting-methods.rs | 4 +- .../mgca/cyclic-type-const-151251.rs | 3 +- .../mgca/cyclic-type-const-151251.stderr | 6 +- .../mgca/explicit_anon_consts.rs | 24 +++--- .../mgca/explicit_anon_consts.stderr | 12 +-- .../explicit_anon_consts_literals_hack.rs | 3 +- .../mgca/multi_braced_direct_const_args.rs | 3 +- .../non-local-const-without-type_const.rs | 2 +- .../non-local-const-without-type_const.stderr | 4 +- .../printing_valtrees_supports_non_values.rs | 4 +- .../const-generics/mgca/projection-error.rs | 4 +- .../mgca/projection-error.stderr | 4 +- .../mgca/tuple_ctor_arg_simple.rs | 3 +- .../mgca/tuple_ctor_erroneous.rs | 4 +- .../mgca/tuple_expr_arg_complex.rs | 4 +- .../mgca/tuple_expr_arg_simple.rs | 3 +- .../type-const-assoc-const-without-body.rs | 6 +- ...type-const-assoc-const-without-body.stderr | 10 +-- ...const-inherent-assoc-const-without-body.rs | 3 +- ...t-inherent-assoc-const-without-body.stderr | 10 +-- .../mgca/type-const-used-in-trait.rs | 3 +- .../mgca/type_const-array-return.rs | 6 +- ...pe_const-generic-param-in-type.gate.stderr | 36 ++++----- ..._const-generic-param-in-type.nogate.stderr | 54 ++++++------- .../mgca/type_const-generic-param-in-type.rs | 27 +++---- .../mgca/type_const-incemental-compile.rs | 3 +- .../type_const-inherent-const-omitted-type.rs | 3 +- ...e_const-inherent-const-omitted-type.stderr | 10 +-- .../mgca/type_const-mismatched-types.rs | 12 +-- .../mgca/type_const-mismatched-types.stderr | 22 ++--- .../mgca/type_const-not-constparamty.rs | 9 +-- .../mgca/type_const-not-constparamty.stderr | 18 ++--- .../mgca/type_const-on-generic-expr.rs | 8 +- .../mgca/type_const-on-generic-expr.stderr | 12 +-- .../mgca/type_const-on-generic_expr-2.rs | 18 ++--- .../mgca/type_const-on-generic_expr-2.stderr | 18 ++--- .../type_const-only-in-impl-omitted-type.rs | 5 +- ...ype_const-only-in-impl-omitted-type.stderr | 12 +-- .../mgca/type_const-only-in-impl.rs | 5 +- .../mgca/type_const-only-in-impl.stderr | 6 +- .../mgca/type_const-only-in-trait.rs | 5 +- .../mgca/type_const-only-in-trait.stderr | 12 ++- .../ui/const-generics/mgca/type_const-pub.rs | 3 +- .../mgca/type_const-recursive.rs | 4 +- .../mgca/type_const-recursive.stderr | 4 +- .../ui/const-generics/mgca/type_const-use.rs | 3 +- .../unbraced_const_block_const_arg_gated.rs | 7 +- ...nbraced_const_block_const_arg_gated.stderr | 20 +++-- .../mgca/unmarked-free-const.rs | 2 +- .../mgca/unmarked-free-const.stderr | 11 +-- .../mgca/wrong_type_const_arr_diag_trait.rs | 4 +- tests/ui/const-generics/ogca/basic-fail.rs | 12 +-- .../ui/const-generics/ogca/basic-fail.stderr | 2 +- tests/ui/const-generics/ogca/basic.rs | 12 +-- .../ogca/coherence-ambiguous.rs | 6 +- .../const-generics/ogca/rhs-but-not-root.rs | 6 +- .../ogca/rhs-but-not-root.stderr | 6 +- .../type-relative-path-144547.rs | 14 ++-- .../feature-gate-mgca-type-const-syntax.rs | 17 ++++ ...feature-gate-mgca-type-const-syntax.stderr | 63 +++++++++++++++ .../feature-gate-min-generic-const-args.rs | 6 +- ...feature-gate-min-generic-const-args.stderr | 18 ++++- .../feature-gate-opaque-generic-const-args.rs | 3 +- ...ture-gate-opaque-generic-const-args.stderr | 6 +- .../assoc-const-bindings.rs | 12 +-- .../assoc-const-no-infer-ice-115806.rs | 3 +- .../assoc-const-no-infer-ice-115806.stderr | 2 +- .../assoc-const-projection-issue-151878.rs | 3 +- .../overlap-due-to-unsatisfied-const-bound.rs | 7 +- ...rlap-due-to-unsatisfied-const-bound.stderr | 2 +- 204 files changed, 1014 insertions(+), 906 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.rs create mode 100644 tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index fea87c2360f1..fa323b7cf581 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3869,27 +3869,44 @@ pub struct ConstItem { pub ident: Ident, pub generics: Generics, pub ty: Box, - pub rhs: Option, + pub rhs_kind: ConstItemRhsKind, pub define_opaque: Option>, } #[derive(Clone, Encodable, Decodable, Debug, Walkable)] -pub enum ConstItemRhs { - TypeConst(AnonConst), - Body(Box), +pub enum ConstItemRhsKind { + Body { rhs: Option> }, + TypeConst { rhs: Option }, } -impl ConstItemRhs { - pub fn span(&self) -> Span { - self.expr().span +impl ConstItemRhsKind { + pub fn new_body(rhs: Box) -> Self { + Self::Body { rhs: Some(rhs) } } - pub fn expr(&self) -> &Expr { + pub fn span(&self) -> Option { + Some(self.expr()?.span) + } + + pub fn expr(&self) -> Option<&Expr> { match self { - ConstItemRhs::TypeConst(anon_const) => &anon_const.value, - ConstItemRhs::Body(expr) => expr, + Self::Body { rhs: Some(body) } => Some(&body), + Self::TypeConst { rhs: Some(anon) } => Some(&anon.value), + _ => None, } } + + pub fn has_expr(&self) -> bool { + match self { + Self::Body { rhs: Some(_) } => true, + Self::TypeConst { rhs: Some(_) } => true, + _ => false, + } + } + + pub fn is_type_const(&self) -> bool { + matches!(self, &Self::TypeConst { .. }) + } } #[derive(Clone, Encodable, Decodable, Debug, Walkable)] diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 51614460d3c4..8556e8288670 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -427,7 +427,7 @@ macro_rules! common_visitor_and_walkers { Const, ConstBlockItem, ConstItem, - ConstItemRhs, + ConstItemRhsKind, Defaultness, Delegation, DelegationMac, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 12eaa99143e9..9922ed8a5c58 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -288,7 +288,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ident, generics, ty, - rhs, + rhs_kind, define_opaque, }) => { let ident = self.lower_ident(*ident); @@ -301,7 +301,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy), ); - let rhs = this.lower_const_item_rhs(attrs, rhs.as_ref(), span); + let rhs = this.lower_const_item_rhs(rhs_kind, span); (ty, rhs) }, ); @@ -941,7 +941,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let (ident, generics, kind, has_default) = match &i.kind { AssocItemKind::Const(box ConstItem { - ident, generics, ty, rhs, define_opaque, .. + ident, + generics, + ty, + rhs_kind, + define_opaque, + .. }) => { let (generics, kind) = self.lower_generics( generics, @@ -952,15 +957,18 @@ impl<'hir> LoweringContext<'_, 'hir> { ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy), ); - let rhs = rhs - .as_ref() - .map(|rhs| this.lower_const_item_rhs(attrs, Some(rhs), i.span)); - hir::TraitItemKind::Const(ty, rhs) + // Trait associated consts don't need an expression/body. + let rhs = if rhs_kind.has_expr() { + Some(this.lower_const_item_rhs(rhs_kind, i.span)) + } else { + None + }; + hir::TraitItemKind::Const(ty, rhs, rhs_kind.is_type_const().into()) }, ); if define_opaque.is_some() { - if rhs.is_some() { + if rhs_kind.has_expr() { self.lower_define_opaque(hir_id, &define_opaque); } else { self.dcx().span_err( @@ -970,7 +978,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - (*ident, generics, kind, rhs.is_some()) + (*ident, generics, kind, rhs_kind.has_expr()) } AssocItemKind::Fn(box Fn { sig, ident, generics, body: None, define_opaque, .. @@ -1154,7 +1162,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let (ident, (generics, kind)) = match &i.kind { AssocItemKind::Const(box ConstItem { - ident, generics, ty, rhs, define_opaque, .. + ident, + generics, + ty, + rhs_kind, + define_opaque, + .. }) => ( *ident, self.lower_generics( @@ -1167,7 +1180,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy), ); this.lower_define_opaque(hir_id, &define_opaque); - let rhs = this.lower_const_item_rhs(attrs, rhs.as_ref(), i.span); + let rhs = this.lower_const_item_rhs(rhs_kind, i.span); hir::ImplItemKind::Const(ty, rhs) }, ), diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 6dded9936fba..ff5edfc79943 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2374,15 +2374,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_const_item_rhs( &mut self, - attrs: &[hir::Attribute], - rhs: Option<&ConstItemRhs>, + rhs_kind: &ConstItemRhsKind, span: Span, ) -> hir::ConstItemRhs<'hir> { - match rhs { - Some(ConstItemRhs::TypeConst(anon)) => { + match rhs_kind { + ConstItemRhsKind::Body { rhs: Some(body) } => { + hir::ConstItemRhs::Body(self.lower_const_body(span, Some(body))) + } + ConstItemRhsKind::Body { rhs: None } => { + hir::ConstItemRhs::Body(self.lower_const_body(span, None)) + } + ConstItemRhsKind::TypeConst { rhs: Some(anon) } => { hir::ConstItemRhs::TypeConst(self.lower_anon_const_to_const_arg_and_alloc(anon)) } - None if find_attr!(attrs, AttributeKind::TypeConst(_)) => { + ConstItemRhsKind::TypeConst { rhs: None } => { let const_arg = ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Error( @@ -2392,10 +2397,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; hir::ConstItemRhs::TypeConst(self.arena.alloc(const_arg)) } - Some(ConstItemRhs::Body(body)) => { - hir::ConstItemRhs::Body(self.lower_const_body(span, Some(body))) - } - None => hir::ConstItemRhs::Body(self.lower_const_body(span, None)), } } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 2457e0a777e4..b9fb20b68971 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1361,9 +1361,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } }); } - ItemKind::Const(box ConstItem { defaultness, ident, rhs, .. }) => { + ItemKind::Const(box ConstItem { defaultness, ident, rhs_kind, .. }) => { self.check_defaultness(item.span, *defaultness); - if rhs.is_none() { + if !rhs_kind.has_expr() { self.dcx().emit_err(errors::ConstWithoutBody { span: item.span, replace_span: self.ending_semi_or_hi(item.span), @@ -1715,11 +1715,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let AssocCtxt::Impl { .. } = ctxt { match &item.kind { - AssocItemKind::Const(box ConstItem { rhs: None, .. }) => { - self.dcx().emit_err(errors::AssocConstWithoutBody { - span: item.span, - replace_span: self.ending_semi_or_hi(item.span), - }); + AssocItemKind::Const(box ConstItem { rhs_kind, .. }) => { + if !rhs_kind.has_expr() { + self.dcx().emit_err(errors::AssocConstWithoutBody { + span: item.span, + replace_span: self.ending_semi_or_hi(item.span), + }); + } } AssocItemKind::Fn(box Fn { body, .. }) => { if body.is_none() && !self.is_sdylib_interface { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index ce9001d65931..eac7f03d8450 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -249,6 +249,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => { self.check_impl_trait(ty, false) } + ast::ItemKind::Const(box ast::ConstItem { + rhs_kind: ast::ConstItemRhsKind::TypeConst { .. }, + .. + }) => { + // Make sure this is only allowed if the feature gate is enabled. + // #![feature(min_generic_const_args)] + gate!(&self, min_generic_const_args, i.span, "top-level `type const` are unstable"); + } _ => {} } @@ -422,6 +430,20 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } false } + ast::AssocItemKind::Const(box ast::ConstItem { + rhs_kind: ast::ConstItemRhsKind::TypeConst { .. }, + .. + }) => { + // Make sure this is only allowed if the feature gate is enabled. + // #![feature(min_generic_const_args)] + gate!( + &self, + min_generic_const_args, + i.span, + "associated `type const` are unstable" + ); + false + } _ => false, }; if let ast::Defaultness::Default(_) = i.kind.defaultness() { @@ -528,6 +550,27 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { } } } + // `mgca_type_const_syntax` is part of `min_generic_const_args` so either + // or both are enabled we don't need to emit a feature error. + if let Some(spans) = spans.get(&sym::mgca_type_const_syntax) { + for span in spans { + if visitor.features.min_generic_const_args() + || visitor.features.mgca_type_const_syntax() + || span.allows_unstable(sym::min_generic_const_args) + || span.allows_unstable(sym::mgca_type_const_syntax) + { + continue; + } + feature_err( + &visitor.sess, + sym::min_generic_const_args, + *span, + "`type const` syntax is experimental", + ) + .emit(); + } + } + gate_all!(global_registration, "global registration is experimental"); gate_all!(return_type_notation, "return type notation is experimental"); gate_all!(pin_ergonomics, "pinned reference syntax is experimental"); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 68054b06e39f..c7f110a2e003 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -221,7 +221,7 @@ impl<'a> State<'a> { ident, generics, ty, - rhs, + rhs_kind, define_opaque, }) => { self.print_item_const( @@ -229,7 +229,7 @@ impl<'a> State<'a> { None, generics, ty, - rhs.as_ref().map(|ct| ct.expr()), + rhs_kind.expr(), &item.vis, ast::Safety::Default, *defaultness, @@ -573,7 +573,7 @@ impl<'a> State<'a> { ident, generics, ty, - rhs, + rhs_kind, define_opaque, }) => { self.print_item_const( @@ -581,7 +581,7 @@ impl<'a> State<'a> { None, generics, ty, - rhs.as_ref().map(|ct| ct.expr()), + rhs_kind.expr(), vis, ast::Safety::Default, *defaultness, diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs index bfea02e789a0..ceaa43948d67 100644 --- a/compiler/rustc_attr_parsing/src/attributes/traits.rs +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -66,15 +66,6 @@ impl NoArgsAttributeParser for ParenSugarParser { const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcParenSugar; } -pub(crate) struct TypeConstParser; -impl NoArgsAttributeParser for TypeConstParser { - const PATH: &[Symbol] = &[sym::type_const]; - const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowList(&[Allow(Target::Const), Allow(Target::AssocConst)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::TypeConst; -} - // Markers pub(crate) struct MarkerParser; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index afbb70654f4d..5c3368e4c930 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -297,7 +297,6 @@ attribute_parsers!( Single>, Single>, Single>, - Single>, Single>, // tidy-alphabetical-end ]; diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index 12ccc4a6de04..c87f1e41043d 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -43,7 +43,7 @@ pub(crate) fn expand( // Generate anonymous constant serving as container for the allocator methods. let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new())); - let const_body = ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts))); + let const_body = ast::ConstItemRhsKind::new_body(ecx.expr_block(ecx.block(span, stmts))); let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body); let const_item = if is_stmt { Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item))) diff --git a/compiler/rustc_builtin_macros/src/eii.rs b/compiler/rustc_builtin_macros/src/eii.rs index 538f5afae5fc..7b651ed84828 100644 --- a/compiler/rustc_builtin_macros/src/eii.rs +++ b/compiler/rustc_builtin_macros/src/eii.rs @@ -232,7 +232,7 @@ fn generate_default_impl( span, underscore, unit, - ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts))), + ast::ConstItemRhsKind::new_body(ecx.expr_block(ecx.block(span, stmts))), ) }; diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index bb031dafdcfd..9e22d408c125 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -47,7 +47,7 @@ pub(crate) fn expand( // Generate anonymous constant serving as container for the allocator methods. let const_ty = ecx.ty(ty_span, TyKind::Tup(ThinVec::new())); - let const_body = ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts))); + let const_body = ast::ConstItemRhsKind::new_body(ecx.expr_block(ecx.block(span, stmts))); let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body); let const_item = if is_stmt { Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item))) diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index e30d506a31b9..24a5d79958c6 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -385,7 +385,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> Box { cx.attr_nested_word(sym::allow, sym::deprecated, span), ]); - let block = ast::ConstItemRhs::Body(cx.expr_block( + let block = ast::ConstItemRhsKind::new_body(cx.expr_block( cx.block(span, thin_vec![cx.stmt_item(span, krate), cx.stmt_item(span, decls_static)]), )); diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index d5f774865a9e..a9718d53ac49 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -289,7 +289,7 @@ pub(crate) fn expand_test_or_bench( ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))), define_opaque: None, // test::TestDescAndFn { - rhs: Some(ast::ConstItemRhs::Body( + rhs_kind: ast::ConstItemRhsKind::new_body( cx.expr_struct( sp, test_path("TestDescAndFn"), @@ -371,7 +371,7 @@ pub(crate) fn expand_test_or_bench( field("testfn", test_fn), // } ], ), // } - )), + ), } .into(), ), diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index fe3891d0dd7e..462254f064cf 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -345,7 +345,7 @@ where let uneval = match constant.const_ { Const::Ty(_, ct) => match ct.kind() { ty::ConstKind::Param(_) | ty::ConstKind::Error(_) => None, - // Unevaluated consts in MIR bodies don't have associated MIR (e.g. `#[type_const]`). + // Unevaluated consts in MIR bodies don't have associated MIR (e.g. `type const`). ty::ConstKind::Unevaluated(_) => None, // FIXME(mgca): Investigate whether using `None` for `ConstKind::Value` is overly // strict, and if instead we should be doing some kind of value-based analysis. diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 25da90298791..9f39750d8125 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -394,7 +394,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>( typing_env: ty::TypingEnv<'tcx>, ) -> Result { let def = cid.instance.def.def_id(); - // #[type_const] don't have bodys + // `type const` don't have bodys debug_assert!(!tcx.is_type_const(def), "CTFE tried to evaluate type-const: {:?}", def); let is_static = tcx.is_static(def); diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index e5c06889f3e0..7320ee12abe3 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -727,7 +727,7 @@ impl<'a> ExtCtxt<'a> { span: Span, ident: Ident, ty: Box, - rhs: ast::ConstItemRhs, + rhs_kind: ast::ConstItemRhsKind, ) -> Box { let defaultness = ast::Defaultness::Final; self.item( @@ -740,7 +740,7 @@ impl<'a> ExtCtxt<'a> { // FIXME(generic_const_items): Pass the generics as a parameter. generics: ast::Generics::default(), ty, - rhs: Some(rhs), + rhs_kind, define_opaque: None, } .into(), diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 182ef6816337..d74e8442545b 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -888,13 +888,6 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::Yes, experimental!(patchable_function_entry) ), - // Probably temporary component of min_generic_const_args. - // `#[type_const] const ASSOC: usize;` - gated!( - type_const, Normal, template!(Word), ErrorFollowing, - EncodeCrossCrate::Yes, min_generic_const_args, experimental!(type_const), - ), - // The `#[loop_match]` and `#[const_continue]` attributes are part of the // lang experiment for RFC 3720 tracked in: // diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index a941eb1f459e..add09c3ea58b 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -561,6 +561,8 @@ declare_features! ( (unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)), /// Allows `#[marker]` on certain traits allowing overlapping implementations. (unstable, marker_trait_attr, "1.30.0", Some(29864)), + /// Enable mgca `type const` syntax before expansion. + (incomplete, mgca_type_const_syntax, "CURRENT_RUSTC_VERSION", Some(132980)), /// Enables the generic const args MVP (only bare paths, not arbitrary computation). (incomplete, min_generic_const_args, "1.84.0", Some(132980)), /// A minimal, sound subset of specialization intended to be used by the diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index ef790fe76b74..58a748b9568a 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1292,9 +1292,6 @@ pub enum AttributeKind { /// Represents `#[track_caller]` TrackCaller(Span), - /// Represents `#[type_const]`. - TypeConst(Span), - /// Represents `#[type_length_limit]` TypeLengthLimit { attr_span: Span, limit_span: Span, limit: Limit }, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index cba7679d2df3..7d8ac6df9e3a 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -169,7 +169,6 @@ impl AttributeKind { TargetFeature { .. } => No, ThreadLocal => No, TrackCaller(..) => Yes, - TypeConst(..) => Yes, TypeLengthLimit { .. } => No, UnstableFeatureBound(..) => No, Used { .. } => No, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index cf96f33e9891..68fc7653b636 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3199,7 +3199,7 @@ impl<'hir> TraitItem<'hir> { expect_methods_self_kind! { expect_const, (&'hir Ty<'hir>, Option>), - TraitItemKind::Const(ty, rhs), (ty, *rhs); + TraitItemKind::Const(ty, rhs, _), (ty, *rhs); expect_fn, (&FnSig<'hir>, &TraitFn<'hir>), TraitItemKind::Fn(ty, trfn), (ty, trfn); @@ -3219,11 +3219,32 @@ pub enum TraitFn<'hir> { Provided(BodyId), } +#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)] +pub enum IsTypeConst { + No, + Yes, +} + +impl From for IsTypeConst { + fn from(value: bool) -> Self { + if value { Self::Yes } else { Self::No } + } +} + +impl From for bool { + fn from(value: IsTypeConst) -> Self { + matches!(value, IsTypeConst::Yes) + } +} + /// Represents a trait method or associated constant or type #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum TraitItemKind<'hir> { + // FIXME(mgca) eventually want to move the option that is around `ConstItemRhs<'hir>` + // into `ConstItemRhs`, much like `ast::ConstItemRhsKind`, but for now mark whether + // this node is a TypeConst with a flag. /// An associated constant with an optional value (otherwise `impl`s must contain a value). - Const(&'hir Ty<'hir>, Option>), + Const(&'hir Ty<'hir>, Option>, IsTypeConst), /// An associated function with an optional body. Fn(FnSig<'hir>, TraitFn<'hir>), /// An associated type with (possibly empty) bounds and optional concrete @@ -4686,7 +4707,7 @@ impl<'hir> OwnerNode<'hir> { | OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(_, TraitFn::Provided(body)) - | TraitItemKind::Const(_, Some(ConstItemRhs::Body(body))), + | TraitItemKind::Const(_, Some(ConstItemRhs::Body(body)), _), .. }) | OwnerNode::ImplItem(ImplItem { @@ -4913,7 +4934,7 @@ impl<'hir> Node<'hir> { _ => None, }, Node::TraitItem(it) => match it.kind { - TraitItemKind::Const(ty, _) => Some(ty), + TraitItemKind::Const(ty, _, _) => Some(ty), TraitItemKind::Type(_, ty) => ty, _ => None, }, @@ -4956,7 +4977,7 @@ impl<'hir> Node<'hir> { | Node::TraitItem(TraitItem { owner_id, kind: - TraitItemKind::Const(.., Some(ConstItemRhs::Body(body))) + TraitItemKind::Const(_, Some(ConstItemRhs::Body(body)), _) | TraitItemKind::Fn(_, TraitFn::Provided(body)), .. }) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index bd863abaceb4..21bcf53b5619 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1271,7 +1271,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>( try_visit!(visitor.visit_defaultness(&defaultness)); try_visit!(visitor.visit_id(hir_id)); match *kind { - TraitItemKind::Const(ref ty, default) => { + TraitItemKind::Const(ref ty, default, _) => { try_visit!(visitor.visit_ty_unambig(ty)); visit_opt!(visitor, visit_const_item_rhs, default); } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index e0bfae9617ff..1bee7a72229a 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -923,7 +923,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ); check_where_clauses(wfcx, def_id); - if tcx.is_type_const(def_id.into()) { + if tcx.is_type_const(def_id) { wfcheck::check_type_const(wfcx, def_id, ty, true)?; } Ok(()) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index cd9fdcb59fb5..c29ebe67a158 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2060,14 +2060,14 @@ fn compare_type_const<'tcx>( .dcx() .struct_span_err( tcx.def_span(impl_const_item.def_id), - "implementation of `#[type_const]` const must be marked with `#[type_const]`", + "implementation of a `type const` must also be marked as `type const`", ) .with_span_note( MultiSpan::from_spans(vec![ tcx.def_span(trait_const_item.def_id), trait_type_const_span, ]), - "trait declaration of const is marked with `#[type_const]`", + "trait declaration of const is marked as `type const`", ) .emit()); } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index f917c799ef5a..ceb0e138a0da 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -955,7 +955,7 @@ pub(crate) fn check_associated_item( wfcx.register_wf_obligation(span, loc, ty.into()); let has_value = item.defaultness(tcx).has_value(); - if tcx.is_type_const(def_id.into()) { + if tcx.is_type_const(def_id) { check_type_const(wfcx, def_id, ty, has_value)?; } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index f3086266eec0..e72fde9f0568 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -95,6 +95,7 @@ pub(crate) fn provide(providers: &mut Providers) { const_param_default, anon_const_kind, const_of_item, + is_rhs_type_const, ..*providers }; } @@ -1549,7 +1550,8 @@ fn is_anon_const_rhs_of_const_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) let (Node::Item(hir::Item { kind: hir::ItemKind::Const(_, _, _, ct_rhs), .. }) | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(_, ct_rhs), .. }) | Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Const(_, Some(ct_rhs)), .. + kind: hir::TraitItemKind::Const(_, Some(ct_rhs), _), + .. })) = grandparent_node else { return false; @@ -1594,7 +1596,7 @@ fn const_of_item<'tcx>( let ct_rhs = match tcx.hir_node_by_def_id(def_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => *ct, hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Const(.., ct), .. + kind: hir::TraitItemKind::Const(_, ct, _), .. }) => ct.expect("no default value for trait assoc const"), hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => *ct, _ => { @@ -1624,3 +1626,22 @@ fn const_of_item<'tcx>( ty::EarlyBinder::bind(ct) } } + +/// Check if a Const or AssocConst is a type const (mgca) +fn is_rhs_type_const<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> bool { + match tcx.hir_node_by_def_id(def) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Const(_, _, _, hir::ConstItemRhs::TypeConst(_)), + .. + }) + | hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Const(_, hir::ConstItemRhs::TypeConst(_)), + .. + }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(_, _, hir::IsTypeConst::Yes), + .. + }) => return true, + _ => return false, + } +} 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 d4a01d26a1fc..3e687700f11c 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -859,7 +859,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } }) } - Const(_, _) => self.visit_early(trait_item.hir_id(), trait_item.generics, |this| { + Const(_, _, _) => self.visit_early(trait_item.hir_id(), trait_item.generics, |this| { intravisit::walk_trait_item(this, trait_item) }), } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 910176a0689c..23df419d06a7 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -63,7 +63,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ let args = ty::GenericArgs::identity_for_item(tcx, def_id); Ty::new_fn_def(tcx, def_id.to_def_id(), args) } - TraitItemKind::Const(ty, rhs) => rhs + TraitItemKind::Const(ty, rhs, _) => rhs .and_then(|rhs| { ty.is_suggestable_infer_ty().then(|| { infer_placeholder_type( @@ -420,9 +420,9 @@ fn infer_placeholder_type<'tcx>( kind: &'static str, ) -> Ty<'tcx> { let tcx = cx.tcx(); - // If the type is omitted on a #[type_const] we can't run + // If the type is omitted on a `type const` we can't run // type check on since that requires the const have a body - // which type_consts don't. + // which `type const`s don't. let ty = if tcx.is_type_const(def_id.to_def_id()) { if let Some(trait_item_def_id) = tcx.trait_item_of(def_id.to_def_id()) { tcx.type_of(trait_item_def_id).instantiate_identity() @@ -430,7 +430,7 @@ fn infer_placeholder_type<'tcx>( Ty::new_error_with_message( tcx, ty_span, - "constant with #[type_const] requires an explicit type", + "constant with `type const` requires an explicit type", ) } } else { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index a1c3af5f999d..4a03b290c33d 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -607,14 +607,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if tcx.features().min_generic_const_args() { let mut err = self.dcx().struct_span_err( constraint.span, - "use of trait associated const without `#[type_const]`", + "use of trait associated const not defined as `type const`", ); - err.note("the declaration in the trait must be marked with `#[type_const]`"); + err.note("the declaration in the trait must begin with `type const` not just `const` alone"); return Err(err.emit()); } else { let err = self.dcx().span_delayed_bug( constraint.span, - "use of trait associated const without `#[type_const]`", + "use of trait associated const defined as `type const`", ); return Err(err); } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 7a03d8b220c5..f58461e5d0e1 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2849,19 +2849,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if tcx.is_type_const(def_id) { Ok(()) } else { - let mut err = self - .dcx() - .struct_span_err(span, "use of `const` in the type system without `#[type_const]`"); + let mut err = self.dcx().struct_span_err( + span, + "use of `const` in the type system not defined as `type const`", + ); if def_id.is_local() { let name = tcx.def_path_str(def_id); err.span_suggestion( tcx.def_span(def_id).shrink_to_lo(), - format!("add `#[type_const]` attribute to `{name}`"), - format!("#[type_const]\n"), + format!("add `type` before `const` for `{name}`"), + format!("type "), Applicability::MaybeIncorrect, ); } else { - err.note("only consts marked with `#[type_const]` may be used in types"); + err.note("only consts marked defined as `type const` may be used in types"); } Err(err.emit()) } diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index d414f4dbcc24..08da8d19344d 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -139,7 +139,7 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>( }, hir::Node::TraitItem(item) => match item.kind { hir::TraitItemKind::Type(_, ty) => ty.into_iter().collect(), - hir::TraitItemKind::Const(ty, _) => vec![ty], + hir::TraitItemKind::Const(ty, _, _) => vec![ty], ref item => bug!("Unexpected TraitItem {:?}", item), }, hir::Node::Item(item) => match item.kind { diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 28130383e94c..6214106d422b 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -233,7 +233,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } DefKind::Const if !tcx.generics_of(item_def_id).own_requires_monomorphization() - && !tcx.is_type_const(item_def_id.into()) => + && !tcx.is_type_const(item_def_id) => { // FIXME(generic_const_items): Passing empty instead of identity args is fishy but // seems to be fine for now. Revisit this! diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index d045ec0eb6c7..fc6cc4e67251 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -937,7 +937,7 @@ impl<'a> State<'a> { self.maybe_print_comment(ti.span.lo()); self.print_attrs(self.attrs(ti.hir_id())); match ti.kind { - hir::TraitItemKind::Const(ty, default) => { + hir::TraitItemKind::Const(ty, default, _) => { self.print_associated_const(ti.ident, ti.generics, ty, default); } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_idents)) => { diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 51d9a4641cd5..8b2a6d1d2ab5 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1058,8 +1058,8 @@ trait UnusedDelimLint { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { use ast::ItemKind::*; - let expr = if let Const(box ast::ConstItem { rhs: Some(rhs), .. }) = &item.kind { - rhs.expr() + let expr = if let Const(box ast::ConstItem { rhs_kind, .. }) = &item.kind { + if let Some(e) = rhs_kind.expr() { e } else { return } } else if let Static(box ast::StaticItem { expr: Some(expr), .. }) = &item.kind { expr } else { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index c6c87534851c..6ea9a2852804 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -418,6 +418,7 @@ provide! { tcx, def_id, other, cdata, } anon_const_kind => { table } const_of_item => { table } + is_rhs_type_const => { table } } pub(in crate::rmeta) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index d8652539d0c5..4988cafdd363 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1630,6 +1630,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let table = tcx.associated_types_for_impl_traits_in_trait_or_impl(def_id); record!(self.tables.associated_types_for_impl_traits_in_trait_or_impl[def_id] <- table); } + if let DefKind::AssocConst | DefKind::Const = def_kind { + record!(self.tables.is_rhs_type_const[def_id] <- self.tcx.is_rhs_type_const(def_id)); + } } for (def_id, impls) in &tcx.crate_inherent_impls(()).0.inherent_impls { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index af6df0cd6eb6..408b50ae48df 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -476,6 +476,7 @@ define_tables! { anon_const_kind: Table>, const_of_item: Table>>>, associated_types_for_impl_traits_in_trait_or_impl: Table>>>, + is_rhs_type_const: Table>, } #[derive(TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index de2298914438..771c300989f2 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -293,13 +293,13 @@ rustc_queries! { separate_provide_extern } - /// Returns the const of the RHS of a (free or assoc) const item, if it is a `#[type_const]`. + /// Returns the const of the RHS of a (free or assoc) const item, if it is a `type const`. /// /// When a const item is used in a type-level expression, like in equality for an assoc const /// projection, this allows us to retrieve the typesystem-appropriate representation of the /// const value. /// - /// This query will ICE if given a const that is not marked with `#[type_const]`. + /// This query will ICE if given a const that is not marked with `type const`. query const_of_item(def_id: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { desc { |tcx| "computing the type-level value for `{}`", tcx.def_path_str(def_id) } cache_on_disk_if { def_id.is_local() } @@ -2764,6 +2764,12 @@ rustc_queries! { cache_on_disk_if { *cnum == LOCAL_CRATE } separate_provide_extern } + + query is_rhs_type_const(def_id: DefId) -> bool { + desc { |tcx| "checking whether `{}` is a rhs type const", tcx.def_path_str(def_id) } + cache_on_disk_if { def_id.is_local() } + separate_provide_extern + } } rustc_with_all_queries! { define_callbacks! } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 75323bf5c8cc..2fca85c9f2f1 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -845,7 +845,7 @@ impl DynCompatibilityViolation { format!("it contains generic associated const `{name}`").into() } Self::AssocConst(name, AssocConstViolation::NonType, _) => { - format!("it contains associated const `{name}` that's not marked `#[type_const]`") + format!("it contains associated const `{name}` that's not defined as `type const`") .into() } Self::AssocConst(name, AssocConstViolation::TypeReferencesSelf, _) => format!( @@ -999,7 +999,7 @@ pub enum AssocConstViolation { /// Has own generic parameters (GAC). Generic, - /// Isn't marked `#[type_const]`. + /// Isn't defined as `type const`. NonType, /// Its type mentions the `Self` type parameter. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1bb83530487d..45bb584bf595 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1890,14 +1890,22 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn type_const_span(self, def_id: DefId) -> Option { - matches!(self.def_kind(def_id), DefKind::Const | DefKind::AssocConst) - .then(|| find_attr!(self.get_all_attrs(def_id), AttributeKind::TypeConst(sp) => *sp)) - .flatten() + if !self.is_type_const(def_id) { + return None; + } + Some(self.def_span(def_id)) } - /// Check if the given `def_id` is a const with the `#[type_const]` attribute. - pub fn is_type_const(self, def_id: DefId) -> bool { - self.type_const_span(def_id).is_some() + /// Check if the given `def_id` is a `type const` (mgca) + pub fn is_type_const>(self, def_id: I) -> bool { + // No need to call the query directly in this case always false. + if !(matches!( + self.def_kind(def_id.into_query_param()), + DefKind::Const | DefKind::AssocConst + )) { + return false; + } + self.is_rhs_type_const(def_id) } /// Returns the movability of the coroutine of `def_id`, or panics @@ -2923,7 +2931,7 @@ impl<'tcx> TyCtxt<'tcx> { ) -> bool { let generics = self.generics_of(def_id); - // IATs and IACs (inherent associated types/consts with #[type_const]) themselves have a + // IATs and IACs (inherent associated types/consts with `type const`) themselves have a // weird arg setup (self + own args), but nested items *in* IATs (namely: opaques, i.e. // ATPITs) do not. let is_inherent_assoc_ty = matches!(self.def_kind(def_id), DefKind::AssocTy) diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 317df4e64fdb..fbd7aa90f49c 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -578,7 +578,7 @@ fn construct_const<'a, 'tcx>( }) | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(ty, _), span, .. }) | Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Const(ty, Some(_)), + kind: hir::TraitItemKind::Const(ty, Some(_), _), span, .. }) => (*span, ty.span), diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 9ac9bd5c0e46..5b81acb0f91f 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -6,9 +6,7 @@ use rustc_ast::ast::*; use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::util::case::Case; -use rustc_ast::{ - attr, {self as ast}, -}; +use rustc_ast::{self as ast}; use rustc_ast_pretty::pprust; use rustc_errors::codes::*; use rustc_errors::{Applicability, PResult, StashKey, inline_fluent, struct_span_code_err}; @@ -286,13 +284,13 @@ impl<'a> Parser<'a> { // CONST ITEM self.recover_const_mut(const_span); self.recover_missing_kw_before_item()?; - let (ident, generics, ty, rhs) = self.parse_const_item(attrs)?; + let (ident, generics, ty, rhs_kind) = self.parse_const_item(false)?; ItemKind::Const(Box::new(ConstItem { defaultness: def_(), ident, generics, ty, - rhs, + rhs_kind, define_opaque: None, })) } else if let Some(kind) = self.is_reuse_item() { @@ -303,8 +301,26 @@ impl<'a> Parser<'a> { // MODULE ITEM self.parse_item_mod(attrs)? } else if self.eat_keyword_case(exp!(Type), case) { - // TYPE ITEM - self.parse_type_alias(def_())? + if let Const::Yes(const_span) = self.parse_constness(case) { + // TYPE CONST (mgca) + self.recover_const_mut(const_span); + self.recover_missing_kw_before_item()?; + let (ident, generics, ty, rhs_kind) = self.parse_const_item(true)?; + // Make sure this is only allowed if the feature gate is enabled. + // #![feature(mgca_type_const_syntax)] + self.psess.gated_spans.gate(sym::mgca_type_const_syntax, lo.to(const_span)); + ItemKind::Const(Box::new(ConstItem { + defaultness: def_(), + ident, + generics, + ty, + rhs_kind, + define_opaque: None, + })) + } else { + // TYPE ITEM + self.parse_type_alias(def_())? + } } else if self.eat_keyword_case(exp!(Enum), case) { // ENUM ITEM self.parse_item_enum()? @@ -1113,13 +1129,12 @@ impl<'a> Parser<'a> { define_opaque, }) => { self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span }); - let rhs = expr.map(ConstItemRhs::Body); AssocItemKind::Const(Box::new(ConstItem { defaultness: Defaultness::Final, ident, generics: Generics::default(), ty, - rhs, + rhs_kind: ConstItemRhsKind::Body { rhs: expr }, define_opaque, })) } @@ -1360,7 +1375,7 @@ impl<'a> Parser<'a> { let kind = match ForeignItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { - ItemKind::Const(box ConstItem { ident, ty, rhs, .. }) => { + ItemKind::Const(box ConstItem { ident, ty, rhs_kind, .. }) => { let const_span = Some(span.with_hi(ident.span.lo())) .filter(|span| span.can_be_used_for_suggestions()); self.dcx().emit_err(errors::ExternItemCannotBeConst { @@ -1371,10 +1386,13 @@ impl<'a> Parser<'a> { ident, ty, mutability: Mutability::Not, - expr: rhs.map(|b| match b { - ConstItemRhs::TypeConst(anon_const) => anon_const.value, - ConstItemRhs::Body(expr) => expr, - }), + expr: match rhs_kind { + ConstItemRhsKind::Body { rhs } => rhs, + ConstItemRhsKind::TypeConst { rhs: Some(anon) } => { + Some(anon.value) + } + ConstItemRhsKind::TypeConst { rhs: None } => None, + }, safety: Safety::Default, define_opaque: None, })) @@ -1516,13 +1534,16 @@ impl<'a> Parser<'a> { /// Parse a constant item with the prefix `"const"` already parsed. /// + /// If `const_arg` is true, any expression assigned to the const will be parsed + /// as a const_arg instead of a body expression. + /// /// ```ebnf /// Const = "const" ($ident | "_") Generics ":" $ty (= $expr)? WhereClause ";" ; /// ``` fn parse_const_item( &mut self, - attrs: &[Attribute], - ) -> PResult<'a, (Ident, Generics, Box, Option)> { + const_arg: bool, + ) -> PResult<'a, (Ident, Generics, Box, ConstItemRhsKind)> { let ident = self.parse_ident_or_underscore()?; let mut generics = self.parse_generics()?; @@ -1549,16 +1570,15 @@ impl<'a> Parser<'a> { let before_where_clause = if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() }; - let rhs = if self.eat(exp!(Eq)) { - if attr::contains_name(attrs, sym::type_const) { - let ct = - self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?; - Some(ConstItemRhs::TypeConst(ct)) - } else { - Some(ConstItemRhs::Body(self.parse_expr()?)) - } - } else { - None + let rhs = match (self.eat(exp!(Eq)), const_arg) { + (true, true) => ConstItemRhsKind::TypeConst { + rhs: Some( + self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?, + ), + }, + (true, false) => ConstItemRhsKind::Body { rhs: Some(self.parse_expr()?) }, + (false, true) => ConstItemRhsKind::TypeConst { rhs: None }, + (false, false) => ConstItemRhsKind::Body { rhs: None }, }; let after_where_clause = self.parse_where_clause()?; @@ -1567,18 +1587,18 @@ impl<'a> Parser<'a> { // Users may be tempted to write such code if they are still used to the deprecated // where-clause location on type aliases and associated types. See also #89122. if before_where_clause.has_where_token - && let Some(rhs) = &rhs + && let Some(rhs_span) = rhs.span() { self.dcx().emit_err(errors::WhereClauseBeforeConstBody { span: before_where_clause.span, name: ident.span, - body: rhs.span(), + body: rhs_span, sugg: if !after_where_clause.has_where_token { - self.psess.source_map().span_to_snippet(rhs.span()).ok().map(|body_s| { + self.psess.source_map().span_to_snippet(rhs_span).ok().map(|body_s| { errors::WhereClauseBeforeConstBodySugg { left: before_where_clause.span.shrink_to_lo(), snippet: body_s, - right: before_where_clause.span.shrink_to_hi().to(rhs.span()), + right: before_where_clause.span.shrink_to_hi().to(rhs_span), } }) } else { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index dd0de90d575b..e53922e3734b 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -356,7 +356,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcVarianceOfOpaques | AttributeKind::ShouldPanic { .. } | AttributeKind::ThreadLocal - | AttributeKind::TypeConst{..} | AttributeKind::TypeLengthLimit { .. } | AttributeKind::UnstableFeatureBound(..) | AttributeKind::Used { .. } diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index d9565e2dae0e..225487cc989f 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -145,7 +145,7 @@ impl<'tcx> ReachableContext<'tcx> { _ => false, }, Node::TraitItem(trait_method) => match trait_method.kind { - hir::TraitItemKind::Const(_, ref default) => default.is_some(), + hir::TraitItemKind::Const(_, ref default, _) => default.is_some(), hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true, hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) | hir::TraitItemKind::Type(..) => false, @@ -209,7 +209,7 @@ impl<'tcx> ReachableContext<'tcx> { self.visit_nested_body(body); } } - // For #[type_const] we want to evaluate the RHS. + // For `type const` we want to evaluate the RHS. hir::ItemKind::Const(_, _, _, init @ hir::ConstItemRhs::TypeConst(_)) => { self.visit_const_item_rhs(init); } @@ -258,11 +258,11 @@ impl<'tcx> ReachableContext<'tcx> { } Node::TraitItem(trait_method) => { match trait_method.kind { - hir::TraitItemKind::Const(_, None) + hir::TraitItemKind::Const(_, None, _) | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => { // Keep going, nothing to get exported } - hir::TraitItemKind::Const(_, Some(rhs)) => self.visit_const_item_rhs(rhs), + hir::TraitItemKind::Const(_, Some(rhs), _) => self.visit_const_item_rhs(rhs), hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => { self.visit_nested_body(body_id); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 4faf7715de6e..fe6346f6c6e9 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2847,11 +2847,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ident, generics, ty, - rhs, + rhs_kind, define_opaque, defaultness: _, }) => { - let is_type_const = attr::contains_name(&item.attrs, sym::type_const); self.with_generic_param_rib( &generics.params, RibKind::Item( @@ -2871,7 +2870,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { this.with_lifetime_rib( LifetimeRibKind::Elided(LifetimeRes::Static), |this| { - if is_type_const + if rhs_kind.is_type_const() && !this.r.tcx.features().generic_const_parameter_types() { this.with_rib(TypeNS, RibKind::ConstParamTy, |this| { @@ -2888,12 +2887,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }, ); - if let Some(rhs) = rhs { - this.resolve_const_item_rhs( - rhs, - Some((*ident, ConstantItemKind::Const)), - ); - } + this.resolve_const_item_rhs( + rhs_kind, + Some((*ident, ConstantItemKind::Const)), + ); }, ); self.resolve_define_opaques(define_opaque); @@ -3242,11 +3239,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { AssocItemKind::Const(box ast::ConstItem { generics, ty, - rhs, + rhs_kind, define_opaque, .. }) => { - let is_type_const = attr::contains_name(&item.attrs, sym::type_const); self.with_generic_param_rib( &generics.params, RibKind::AssocItem, @@ -3261,7 +3257,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }, |this| { this.visit_generics(generics); - if is_type_const + if rhs_kind.is_type_const() && !this.r.tcx.features().generic_const_parameter_types() { this.with_rib(TypeNS, RibKind::ConstParamTy, |this| { @@ -3278,14 +3274,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // Only impose the restrictions of `ConstRibKind` for an // actual constant expression in a provided default. - if let Some(rhs) = rhs { - // We allow arbitrary const expressions inside of associated consts, - // even if they are potentially not const evaluatable. - // - // Type parameters can already be used and as associated consts are - // not used as part of the type system, this is far less surprising. - this.resolve_const_item_rhs(rhs, None); - } + // + // We allow arbitrary const expressions inside of associated consts, + // even if they are potentially not const evaluatable. + // + // Type parameters can already be used and as associated consts are + // not used as part of the type system, this is far less surprising. + this.resolve_const_item_rhs(rhs_kind, None); }, ) }, @@ -3463,12 +3458,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ident, generics, ty, - rhs, + rhs_kind, define_opaque, .. }) => { debug!("resolve_implementation AssocItemKind::Const"); - let is_type_const = attr::contains_name(&item.attrs, sym::type_const); self.with_generic_param_rib( &generics.params, RibKind::AssocItem, @@ -3505,7 +3499,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); this.visit_generics(generics); - if is_type_const + if rhs_kind.is_type_const() && !this .r .tcx @@ -3527,14 +3521,12 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } else { this.visit_ty(ty); } - if let Some(rhs) = rhs { - // We allow arbitrary const expressions inside of associated consts, - // even if they are potentially not const evaluatable. - // - // Type parameters can already be used and as associated consts are - // not used as part of the type system, this is far less surprising. - this.resolve_const_item_rhs(rhs, None); - } + // We allow arbitrary const expressions inside of associated consts, + // even if they are potentially not const evaluatable. + // + // Type parameters can already be used and as associated consts are + // not used as part of the type system, this is far less surprising. + this.resolve_const_item_rhs(rhs_kind, None); }, ) }, @@ -3756,18 +3748,19 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { fn resolve_const_item_rhs( &mut self, - rhs: &'ast ConstItemRhs, + rhs_kind: &'ast ConstItemRhsKind, item: Option<(Ident, ConstantItemKind)>, ) { - self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| match rhs { - ConstItemRhs::TypeConst(anon_const) => { + self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| match rhs_kind { + ConstItemRhsKind::TypeConst { rhs: Some(anon_const) } => { this.resolve_anon_const(anon_const, AnonConstKind::ConstArg(IsRepeatExpr::No)); } - ConstItemRhs::Body(expr) => { + ConstItemRhsKind::Body { rhs: Some(expr) } => { this.with_constant_rib(IsRepeatExpr::No, ConstantHasGenerics::Yes, item, |this| { this.visit_expr(expr) }); } + _ => (), }) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6aa2eae556e2..2c34c99b0539 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1453,6 +1453,7 @@ symbols! { meta, meta_sized, metadata_type, + mgca_type_const_syntax, min_const_fn, min_const_generics, min_const_unsafe_fn, @@ -2339,7 +2340,6 @@ symbols! { type_ascribe, type_ascription, type_changing_struct_update, - type_const, type_id, type_id_eq, type_info, diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 46d95fdfabfe..3f4c75a5b133 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -453,7 +453,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx // been emitted earlier in compilation. // // That's because we can only end up with an Unevaluated ty::Const for a const item - // if it was marked with `#[type_const]`. Using this attribute without the mgca + // if it was marked with `type const`. Using this attribute without the mgca // feature gate causes a parse error. let ct = match tcx.def_kind(uv.def) { DefKind::AssocConst => match tcx.def_kind(tcx.parent(uv.def)) { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 753fba3ed482..c09e17d3787e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1209,14 +1209,14 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext let local_did = trait_item.owner_id.to_def_id(); cx.with_param_env(local_did, |cx| { let inner = match trait_item.kind { - hir::TraitItemKind::Const(ty, Some(default)) => { + hir::TraitItemKind::Const(ty, Some(default), _) => { ProvidedAssocConstItem(Box::new(Constant { generics: enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)), kind: clean_const_item_rhs(default, local_did), type_: clean_ty(ty, cx), })) } - hir::TraitItemKind::Const(ty, None) => { + hir::TraitItemKind::Const(ty, None, _) => { let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); RequiredAssocConstItem(generics, Box::new(clean_ty(ty, cx))) } diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index f99748127a8f..e09fc0a76366 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -739,7 +739,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { - if let TraitItemKind::Const(_, ct_rhs_opt) = item.kind + if let TraitItemKind::Const(_, ct_rhs_opt, _) = item.kind && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && match self.is_ty_freeze(cx.tcx, cx.typing_env(), ty) { IsFreeze::No => true, @@ -931,7 +931,7 @@ fn get_const_hir_value<'tcx>( { match tcx.hir_node(tcx.local_def_id_to_hir_id(did)) { Node::ImplItem(item) if let ImplItemKind::Const(.., ct_rhs) = item.kind => (did, ct_rhs), - Node::TraitItem(item) if let TraitItemKind::Const(.., Some(ct_rhs)) = item.kind => (did, ct_rhs), + Node::TraitItem(item) if let TraitItemKind::Const(_, Some(ct_rhs), _) = item.kind => (did, ct_rhs), _ => return None, } }, diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 7018146f184b..7d97ce97f487 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -514,7 +514,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { }; match item.kind { - TraitItemKind::Const(ty, _) | TraitItemKind::Type(_, Some(ty)) => { + TraitItemKind::Const(ty, _, _) | TraitItemKind::Type(_, Some(ty)) => { self.check_ty(cx, ty, context); }, TraitItemKind::Fn(ref sig, trait_method) => { diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index cf8716398efb..3b043f7565ef 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -355,7 +355,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { ident: li, generics: lg, ty: lt, - rhs: lb, + rhs_kind: lb, define_opaque: _, }), Const(box ConstItem { @@ -363,7 +363,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { ident: ri, generics: rg, ty: rt, - rhs: rb, + rhs_kind: rb, define_opaque: _, }), ) => { @@ -371,7 +371,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { && eq_id(*li, *ri) && eq_generics(lg, rg) && eq_ty(lt, rt) - && both(lb.as_ref(), rb.as_ref(), eq_const_item_rhs) + && both(Some(lb), Some(rb), eq_const_item_rhs) }, ( Fn(box ast::Fn { @@ -615,7 +615,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { ident: li, generics: lg, ty: lt, - rhs: lb, + rhs_kind: lb, define_opaque: _, }), Const(box ConstItem { @@ -623,7 +623,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { ident: ri, generics: rg, ty: rt, - rhs: rb, + rhs_kind: rb, define_opaque: _, }), ) => { @@ -631,7 +631,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { && eq_id(*li, *ri) && eq_generics(lg, rg) && eq_ty(lt, rt) - && both(lb.as_ref(), rb.as_ref(), eq_const_item_rhs) + && both(Some(lb), Some(rb), eq_const_item_rhs) }, ( Fn(box ast::Fn { @@ -791,12 +791,18 @@ pub fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool { eq_expr(&l.value, &r.value) } -pub fn eq_const_item_rhs(l: &ConstItemRhs, r: &ConstItemRhs) -> bool { - use ConstItemRhs::*; +pub fn eq_const_item_rhs(l: &ConstItemRhsKind, r: &ConstItemRhsKind) -> bool { + use ConstItemRhsKind::*; match (l, r) { - (TypeConst(l), TypeConst(r)) => eq_anon_const(l, r), - (Body(l), Body(r)) => eq_expr(l, r), - (TypeConst(..), Body(..)) | (Body(..), TypeConst(..)) => false, + (TypeConst { rhs: Some(l) }, TypeConst { rhs: Some(r) }) => eq_anon_const(l, r), + (TypeConst { rhs: None }, TypeConst { rhs: None }) => true, + (TypeConst { rhs: Some(..) }, TypeConst { rhs: None }) => false, + (TypeConst { rhs: None }, TypeConst { rhs: Some(..) }) => false, + (Body { rhs: Some(l) }, Body { rhs: Some(r) }) => eq_expr(l, r), + (Body { rhs: None }, Body { rhs: None }) => true, + (Body { rhs: None }, Body { rhs: Some(..) }) => false, + (Body { rhs: Some(..) }, Body { rhs: None }) => false, + (TypeConst {..}, Body { .. }) | ( Body { .. }, TypeConst { .. }) => false, } } diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed b/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed index f8be3331317c..8d63fc44e7f8 100644 --- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed +++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed @@ -3,8 +3,8 @@ #![feature(min_generic_const_args)] trait AssocConstTrait { - #[type_const] - const ASSOC: usize; + + type const ASSOC: usize; } fn assoc_const_args() where diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs b/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs index a0d7a653993f..36a83619c0f9 100644 --- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs +++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs @@ -3,8 +3,8 @@ #![feature(min_generic_const_args)] trait AssocConstTrait { - #[type_const] - const ASSOC: usize; + + type const ASSOC: usize; } fn assoc_const_args() where diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index c9e32492c50b..1aa85ce2ce55 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -2028,12 +2028,16 @@ impl<'a> StaticParts<'a> { ), ast::ItemKind::Const(c) => ( Some(c.defaultness), - "const", + if c.rhs_kind.is_type_const() { + "type const" + } else { + "const" + }, ast::Safety::Default, c.ident, &c.ty, ast::Mutability::Not, - c.rhs.as_ref().map(|rhs| rhs.expr()), + c.rhs_kind.expr(), Some(&c.generics), ), _ => unreachable!(), @@ -2053,17 +2057,25 @@ impl<'a> StaticParts<'a> { } pub(crate) fn from_trait_item(ti: &'a ast::AssocItem, ident: Ident) -> Self { - let (defaultness, ty, expr_opt, generics) = match &ti.kind { - ast::AssocItemKind::Const(c) => ( - c.defaultness, - &c.ty, - c.rhs.as_ref().map(|rhs| rhs.expr()), - Some(&c.generics), - ), + let (defaultness, ty, expr_opt, generics, prefix) = match &ti.kind { + ast::AssocItemKind::Const(c) => { + let prefix = if c.rhs_kind.is_type_const() { + "type const" + } else { + "const" + }; + ( + c.defaultness, + &c.ty, + c.rhs_kind.expr(), + Some(&c.generics), + prefix, + ) + } _ => unreachable!(), }; StaticParts { - prefix: "const", + prefix, safety: ast::Safety::Default, vis: &ti.vis, ident, @@ -2077,17 +2089,25 @@ impl<'a> StaticParts<'a> { } pub(crate) fn from_impl_item(ii: &'a ast::AssocItem, ident: Ident) -> Self { - let (defaultness, ty, expr_opt, generics) = match &ii.kind { - ast::AssocItemKind::Const(c) => ( - c.defaultness, - &c.ty, - c.rhs.as_ref().map(|rhs| rhs.expr()), - Some(&c.generics), - ), + let (defaultness, ty, expr_opt, generics, prefix) = match &ii.kind { + ast::AssocItemKind::Const(c) => { + let prefix = if c.rhs_kind.is_type_const() { + "type const" + } else { + "const" + }; + ( + c.defaultness, + &c.ty, + c.rhs_kind.expr(), + Some(&c.generics), + prefix, + ) + } _ => unreachable!(), }; StaticParts { - prefix: "const", + prefix, safety: ast::Safety::Default, vis: &ii.vis, ident, diff --git a/tests/crashes/149809.rs b/tests/crashes/149809.rs index 2b948e9079c3..f70498f11c87 100644 --- a/tests/crashes/149809.rs +++ b/tests/crashes/149809.rs @@ -5,8 +5,7 @@ struct Qux<'a> { x: &'a (), } impl<'a> Qux<'a> { - #[type_const] - const LEN: usize = 4; + type const LEN: usize = 4; fn foo(_: [u8; Qux::LEN]) {} } diff --git a/tests/debuginfo/associated-const-bindings.rs b/tests/debuginfo/associated-const-bindings.rs index b60fd66235af..88c17cee8025 100644 --- a/tests/debuginfo/associated-const-bindings.rs +++ b/tests/debuginfo/associated-const-bindings.rs @@ -14,12 +14,10 @@ #![expect(unused_variables, incomplete_features)] trait Trait { - #[type_const] - const N: usize; + type const N: usize; } impl Trait for () { - #[type_const] - const N: usize = 101; + type const N: usize = 101; } fn main() { diff --git a/tests/rustdoc-html/constant/ice-associated-const-equality-105952.rs b/tests/rustdoc-html/constant/ice-associated-const-equality-105952.rs index 310e56b917fc..bdb82b91ec27 100644 --- a/tests/rustdoc-html/constant/ice-associated-const-equality-105952.rs +++ b/tests/rustdoc-html/constant/ice-associated-const-equality-105952.rs @@ -10,8 +10,7 @@ pub enum ParseMode { Raw, } pub trait Parse { - #[type_const] - const PARSE_MODE: ParseMode; + type const PARSE_MODE: ParseMode; } pub trait RenderRaw {} diff --git a/tests/rustdoc-html/inline_cross/auxiliary/assoc-const-equality.rs b/tests/rustdoc-html/inline_cross/auxiliary/assoc-const-equality.rs index 598d2b5bf29d..939740d8f918 100644 --- a/tests/rustdoc-html/inline_cross/auxiliary/assoc-const-equality.rs +++ b/tests/rustdoc-html/inline_cross/auxiliary/assoc-const-equality.rs @@ -4,6 +4,5 @@ pub fn accept(_: impl Trait) {} pub trait Trait { - #[type_const] - const K: i32; + type const K: i32; } diff --git a/tests/rustdoc-ui/associated-constant-not-allowed-102467.rs b/tests/rustdoc-ui/associated-constant-not-allowed-102467.rs index 5b8a90d64121..4168a5653dd5 100644 --- a/tests/rustdoc-ui/associated-constant-not-allowed-102467.rs +++ b/tests/rustdoc-ui/associated-constant-not-allowed-102467.rs @@ -11,8 +11,7 @@ trait T { } trait S { - #[type_const] - const C: i32; + type const C: i32; } fn main() {} diff --git a/tests/ui/associated-consts/issue-110933.rs b/tests/ui/associated-consts/issue-110933.rs index 9a013ee71274..0115fb7d6e65 100644 --- a/tests/ui/associated-consts/issue-110933.rs +++ b/tests/ui/associated-consts/issue-110933.rs @@ -4,8 +4,7 @@ #![allow(incomplete_features)] pub trait Trait { - #[type_const] - const ASSOC: usize; + type const ASSOC: usize; } pub fn foo< diff --git a/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs b/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs index 1a37f5957f25..cb0b8a102eb4 100644 --- a/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs +++ b/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs @@ -8,8 +8,7 @@ struct OnDiskDirEntry<'a>(&'a ()); impl<'a> OnDiskDirEntry<'a> { - #[type_const] - const LFN_FRAGMENT_LEN: i64 = 2; + type const LFN_FRAGMENT_LEN: i64 = 2; fn lfn_contents() -> [char; Self::LFN_FRAGMENT_LEN] { //~^ ERROR the constant `2` is not of type `usize` diff --git a/tests/ui/associated-consts/type-const-in-array-len-wrong-type.stderr b/tests/ui/associated-consts/type-const-in-array-len-wrong-type.stderr index 607b7789ae67..b69a1b7fd7de 100644 --- a/tests/ui/associated-consts/type-const-in-array-len-wrong-type.stderr +++ b/tests/ui/associated-consts/type-const-in-array-len-wrong-type.stderr @@ -24,7 +24,7 @@ LL | #![feature(inherent_associated_types)] = note: see issue #8995 for more information error: the constant `2` is not of type `usize` - --> $DIR/type-const-in-array-len-wrong-type.rs:14:26 + --> $DIR/type-const-in-array-len-wrong-type.rs:13:26 | LL | fn lfn_contents() -> [char; Self::LFN_FRAGMENT_LEN] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `i64` diff --git a/tests/ui/associated-consts/type-const-in-array-len.rs b/tests/ui/associated-consts/type-const-in-array-len.rs index 69dd3f443b87..d33eacaade2d 100644 --- a/tests/ui/associated-consts/type-const-in-array-len.rs +++ b/tests/ui/associated-consts/type-const-in-array-len.rs @@ -8,8 +8,7 @@ // Test case from #138226: generic impl with multiple type parameters struct Foo(A, B); impl Foo { - #[type_const] - const LEN: usize = 4; + type const LEN: usize = 4; fn foo() { let _ = [5; Self::LEN]; @@ -19,8 +18,7 @@ impl Foo { // Test case from #138226: generic impl with const parameter struct Bar; impl Bar { - #[type_const] - const LEN: usize = 4; + type const LEN: usize = 4; fn bar() { let _ = [0; Self::LEN]; @@ -30,8 +28,7 @@ impl Bar { // Test case from #150960: non-generic impl with const block struct Baz; impl Baz { - #[type_const] - const LEN: usize = 4; + type const LEN: usize = 4; fn baz() { let _ = [0; { Self::LEN }]; diff --git a/tests/ui/associated-type-bounds/duplicate-bound-err.rs b/tests/ui/associated-type-bounds/duplicate-bound-err.rs index 07eb86108bff..56403fdf6630 100644 --- a/tests/ui/associated-type-bounds/duplicate-bound-err.rs +++ b/tests/ui/associated-type-bounds/duplicate-bound-err.rs @@ -50,8 +50,7 @@ fn mismatch_2() -> impl Iterator { trait Trait { type Gat; - #[type_const] - const ASSOC: i32; + type const ASSOC: i32; fn foo() -> impl Sized; } @@ -59,8 +58,7 @@ trait Trait { impl Trait for () { type Gat = (); - #[type_const] - const ASSOC: i32 = 3; + type const ASSOC: i32 = 3; fn foo() {} } @@ -68,8 +66,7 @@ impl Trait for () { impl Trait for u32 { type Gat = (); - #[type_const] - const ASSOC: i32 = 4; + type const ASSOC: i32 = 4; fn foo() -> u32 { 42 @@ -89,8 +86,7 @@ type MustFail = dyn Iterator; //~| ERROR conflicting associated type bindings trait Trait2 { - #[type_const] - const ASSOC: u32; + type const ASSOC: u32; } type MustFail2 = dyn Trait2; diff --git a/tests/ui/associated-type-bounds/duplicate-bound-err.stderr b/tests/ui/associated-type-bounds/duplicate-bound-err.stderr index 695bb8ad6066..e6bf93970d0a 100644 --- a/tests/ui/associated-type-bounds/duplicate-bound-err.stderr +++ b/tests/ui/associated-type-bounds/duplicate-bound-err.stderr @@ -100,7 +100,7 @@ LL | iter::empty::() | ----------------------- return type was inferred to be `std::iter::Empty` here error[E0271]: expected `IntoIter` to be an iterator that yields `i32`, but it yields `u32` - --> $DIR/duplicate-bound-err.rs:111:17 + --> $DIR/duplicate-bound-err.rs:107:17 | LL | fn foo() -> impl Iterator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` @@ -109,19 +109,19 @@ LL | [2u32].into_iter() | ------------------ return type was inferred to be `std::array::IntoIter` here error[E0271]: expected `impl Iterator` to be an iterator that yields `i32`, but it yields `u32` - --> $DIR/duplicate-bound-err.rs:111:17 + --> $DIR/duplicate-bound-err.rs:107:17 | LL | fn foo() -> impl Iterator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` | note: required by a bound in `Trait3::foo::{anon_assoc#0}` - --> $DIR/duplicate-bound-err.rs:107:31 + --> $DIR/duplicate-bound-err.rs:103:31 | LL | fn foo() -> impl Iterator; | ^^^^^^^^^^ required by this bound in `Trait3::foo::{anon_assoc#0}` error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate-bound-err.rs:87:42 + --> $DIR/duplicate-bound-err.rs:84:42 | LL | type MustFail = dyn Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -129,7 +129,7 @@ LL | type MustFail = dyn Iterator; | `Item` bound here first error: conflicting associated type bindings for `Item` - --> $DIR/duplicate-bound-err.rs:87:17 + --> $DIR/duplicate-bound-err.rs:84:17 | LL | type MustFail = dyn Iterator; | ^^^^^^^^^^^^^----------^^----------^ @@ -138,7 +138,7 @@ LL | type MustFail = dyn Iterator; | `Item` is specified to be `i32` here error[E0719]: the value of the associated type `ASSOC` in trait `Trait2` is already specified - --> $DIR/duplicate-bound-err.rs:96:43 + --> $DIR/duplicate-bound-err.rs:92:43 | LL | type MustFail2 = dyn Trait2; | ------------ ^^^^^^^^^^^^ re-bound here @@ -146,7 +146,7 @@ LL | type MustFail2 = dyn Trait2; | `ASSOC` bound here first error: conflicting associated constant bindings for `ASSOC` - --> $DIR/duplicate-bound-err.rs:96:18 + --> $DIR/duplicate-bound-err.rs:92:18 | LL | type MustFail2 = dyn Trait2; | ^^^^^^^^^^^------------^^------------^ @@ -155,7 +155,7 @@ LL | type MustFail2 = dyn Trait2; | `ASSOC` is specified to be `3` here error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate-bound-err.rs:100:43 + --> $DIR/duplicate-bound-err.rs:96:43 | LL | type MustFail3 = dyn Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -163,7 +163,7 @@ LL | type MustFail3 = dyn Iterator; | `Item` bound here first error[E0719]: the value of the associated type `ASSOC` in trait `Trait2` is already specified - --> $DIR/duplicate-bound-err.rs:103:43 + --> $DIR/duplicate-bound-err.rs:99:43 | LL | type MustFail4 = dyn Trait2; | ------------ ^^^^^^^^^^^^ re-bound here @@ -171,7 +171,7 @@ LL | type MustFail4 = dyn Trait2; | `ASSOC` bound here first error[E0271]: expected `Empty` to be an iterator that yields `i32`, but it yields `u32` - --> $DIR/duplicate-bound-err.rs:119:16 + --> $DIR/duplicate-bound-err.rs:115:16 | LL | uncallable(iter::empty::()); | ---------- ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` @@ -179,13 +179,13 @@ LL | uncallable(iter::empty::()); | required by a bound introduced by this call | note: required by a bound in `uncallable` - --> $DIR/duplicate-bound-err.rs:79:32 + --> $DIR/duplicate-bound-err.rs:76:32 | LL | fn uncallable(_: impl Iterator) {} | ^^^^^^^^^^ required by this bound in `uncallable` error[E0271]: expected `Empty` to be an iterator that yields `u32`, but it yields `i32` - --> $DIR/duplicate-bound-err.rs:120:16 + --> $DIR/duplicate-bound-err.rs:116:16 | LL | uncallable(iter::empty::()); | ---------- ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `i32` @@ -193,13 +193,13 @@ LL | uncallable(iter::empty::()); | required by a bound introduced by this call | note: required by a bound in `uncallable` - --> $DIR/duplicate-bound-err.rs:79:44 + --> $DIR/duplicate-bound-err.rs:76:44 | LL | fn uncallable(_: impl Iterator) {} | ^^^^^^^^^^ required by this bound in `uncallable` error[E0271]: type mismatch resolving `<() as Trait>::ASSOC == 4` - --> $DIR/duplicate-bound-err.rs:121:22 + --> $DIR/duplicate-bound-err.rs:117:22 | LL | uncallable_const(()); | ---------------- ^^ expected `4`, found `3` @@ -209,13 +209,13 @@ LL | uncallable_const(()); = note: expected constant `4` found constant `3` note: required by a bound in `uncallable_const` - --> $DIR/duplicate-bound-err.rs:81:46 + --> $DIR/duplicate-bound-err.rs:78:46 | LL | fn uncallable_const(_: impl Trait) {} | ^^^^^^^^^ required by this bound in `uncallable_const` error[E0271]: type mismatch resolving `::ASSOC == 3` - --> $DIR/duplicate-bound-err.rs:122:22 + --> $DIR/duplicate-bound-err.rs:118:22 | LL | uncallable_const(4u32); | ---------------- ^^^^ expected `3`, found `4` @@ -225,13 +225,13 @@ LL | uncallable_const(4u32); = note: expected constant `3` found constant `4` note: required by a bound in `uncallable_const` - --> $DIR/duplicate-bound-err.rs:81:35 + --> $DIR/duplicate-bound-err.rs:78:35 | LL | fn uncallable_const(_: impl Trait) {} | ^^^^^^^^^ required by this bound in `uncallable_const` error[E0271]: type mismatch resolving `<() as Trait>::ASSOC == 4` - --> $DIR/duplicate-bound-err.rs:123:20 + --> $DIR/duplicate-bound-err.rs:119:20 | LL | uncallable_rtn(()); | -------------- ^^ expected `4`, found `3` @@ -241,7 +241,7 @@ LL | uncallable_rtn(()); = note: expected constant `4` found constant `3` note: required by a bound in `uncallable_rtn` - --> $DIR/duplicate-bound-err.rs:84:61 + --> $DIR/duplicate-bound-err.rs:81:61 | LL | fn uncallable_rtn( | -------------- required by a bound in this function @@ -249,7 +249,7 @@ LL | _: impl Trait, foo(..): Trait> | ^^^^^^^^^ required by this bound in `uncallable_rtn` error[E0271]: type mismatch resolving `::ASSOC == 3` - --> $DIR/duplicate-bound-err.rs:124:20 + --> $DIR/duplicate-bound-err.rs:120:20 | LL | uncallable_rtn(17u32); | -------------- ^^^^^ expected `3`, found `4` @@ -259,7 +259,7 @@ LL | uncallable_rtn(17u32); = note: expected constant `3` found constant `4` note: required by a bound in `uncallable_rtn` - --> $DIR/duplicate-bound-err.rs:84:34 + --> $DIR/duplicate-bound-err.rs:81:34 | LL | fn uncallable_rtn( | -------------- required by a bound in this function diff --git a/tests/ui/associated-type-bounds/duplicate-bound.rs b/tests/ui/associated-type-bounds/duplicate-bound.rs index 1aeb0022a04f..39cfa9db072c 100644 --- a/tests/ui/associated-type-bounds/duplicate-bound.rs +++ b/tests/ui/associated-type-bounds/duplicate-bound.rs @@ -189,8 +189,7 @@ trait Tra3 { trait Trait { type Gat; - #[type_const] - const ASSOC: i32; + type const ASSOC: i32; fn foo() -> impl Sized; } @@ -198,8 +197,7 @@ trait Trait { impl Trait for () { type Gat = (); - #[type_const] - const ASSOC: i32 = 3; + type const ASSOC: i32 = 3; fn foo() {} } diff --git a/tests/ui/associated-types/type-const-inherent-impl-normalize.rs b/tests/ui/associated-types/type-const-inherent-impl-normalize.rs index 70eea70db4c6..a9c7373b4f44 100644 --- a/tests/ui/associated-types/type-const-inherent-impl-normalize.rs +++ b/tests/ui/associated-types/type-const-inherent-impl-normalize.rs @@ -1,8 +1,8 @@ struct S; impl S { - #[type_const] - //~^ ERROR: the `#[type_const]` attribute is an experimental feature - const LEN: usize = 1; + type const LEN: usize = 1; + //~^ ERROR: associated `type const` are unstable [E0658] + //~| ERROR: `type const` syntax is experimental [E0658] fn arr() { [8; Self::LEN] //~^ WARN: cannot use constants which depend on generic parameters in types diff --git a/tests/ui/associated-types/type-const-inherent-impl-normalize.stderr b/tests/ui/associated-types/type-const-inherent-impl-normalize.stderr index 958d38e855ea..b86859f4a993 100644 --- a/tests/ui/associated-types/type-const-inherent-impl-normalize.stderr +++ b/tests/ui/associated-types/type-const-inherent-impl-normalize.stderr @@ -1,8 +1,18 @@ -error[E0658]: the `#[type_const]` attribute is an experimental feature +error[E0658]: `type const` syntax is experimental --> $DIR/type-const-inherent-impl-normalize.rs:3:5 | -LL | #[type_const] - | ^^^^^^^^^^^^^ +LL | type const LEN: usize = 1; + | ^^^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: associated `type const` are unstable + --> $DIR/type-const-inherent-impl-normalize.rs:3:5 + | +LL | type const LEN: usize = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #132980 for more information = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable @@ -36,7 +46,7 @@ LL | fn arr() { LL | [8; Self::LEN] | ^^^^^^^^^^^^^^ expected `()`, found `[{integer}; 1]` -error: aborting due to 2 previous errors; 2 warnings emitted +error: aborting due to 3 previous errors; 2 warnings emitted Some errors have detailed explanations: E0308, E0658. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs index 6dc3086b63e1..489c8bf9f495 100644 --- a/tests/ui/attributes/malformed-attrs.rs +++ b/tests/ui/attributes/malformed-attrs.rs @@ -145,8 +145,6 @@ struct Test; #[diagnostic::on_unimplemented = 1] //~^ WARN malformed trait Hey { - #[type_const = 1] - //~^ ERROR malformed const HEY: usize = 5; } diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 22e222efa435..009da1d12a16 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -21,13 +21,13 @@ LL | #[cfg_attr] = note: for more information, visit error[E0463]: can't find crate for `wloop` - --> $DIR/malformed-attrs.rs:217:1 + --> $DIR/malformed-attrs.rs:215:1 | LL | extern crate wloop; | ^^^^^^^^^^^^^^^^^^^ can't find crate error: malformed `allow` attribute input - --> $DIR/malformed-attrs.rs:183:1 + --> $DIR/malformed-attrs.rs:181:1 | LL | #[allow] | ^^^^^^^^ @@ -43,7 +43,7 @@ LL | #[allow(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `expect` attribute input - --> $DIR/malformed-attrs.rs:185:1 + --> $DIR/malformed-attrs.rs:183:1 | LL | #[expect] | ^^^^^^^^^ @@ -59,7 +59,7 @@ LL | #[expect(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `warn` attribute input - --> $DIR/malformed-attrs.rs:187:1 + --> $DIR/malformed-attrs.rs:185:1 | LL | #[warn] | ^^^^^^^ @@ -75,7 +75,7 @@ LL | #[warn(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `deny` attribute input - --> $DIR/malformed-attrs.rs:189:1 + --> $DIR/malformed-attrs.rs:187:1 | LL | #[deny] | ^^^^^^^ @@ -91,7 +91,7 @@ LL | #[deny(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `forbid` attribute input - --> $DIR/malformed-attrs.rs:191:1 + --> $DIR/malformed-attrs.rs:189:1 | LL | #[forbid] | ^^^^^^^^^ @@ -125,7 +125,7 @@ LL | #[proc_macro_derive] | ^^^^^^^^^^^^^^^^^^^^ error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint - --> $DIR/malformed-attrs.rs:222:1 + --> $DIR/malformed-attrs.rs:220:1 | LL | #[allow_internal_unsafe = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -541,7 +541,7 @@ LL | #[cfi_encoding = ""] | help: must be of the form: `#[cfi_encoding = "encoding"]` error[E0565]: malformed `marker` attribute input - --> $DIR/malformed-attrs.rs:160:1 + --> $DIR/malformed-attrs.rs:158:1 | LL | #[marker = 3] | ^^^^^^^^^---^ @@ -550,7 +550,7 @@ LL | #[marker = 3] | help: must be of the form: `#[marker]` error[E0565]: malformed `fundamental` attribute input - --> $DIR/malformed-attrs.rs:162:1 + --> $DIR/malformed-attrs.rs:160:1 | LL | #[fundamental()] | ^^^^^^^^^^^^^--^ @@ -559,7 +559,7 @@ LL | #[fundamental()] | help: must be of the form: `#[fundamental]` error[E0565]: malformed `ffi_pure` attribute input - --> $DIR/malformed-attrs.rs:170:5 + --> $DIR/malformed-attrs.rs:168:5 | LL | #[unsafe(ffi_pure = 1)] | ^^^^^^^^^^^^^^^^^^---^^ @@ -568,7 +568,7 @@ LL | #[unsafe(ffi_pure = 1)] | help: must be of the form: `#[ffi_pure]` error[E0539]: malformed `link_ordinal` attribute input - --> $DIR/malformed-attrs.rs:172:5 + --> $DIR/malformed-attrs.rs:170:5 | LL | #[link_ordinal] | ^^^^^^^^^^^^^^^ @@ -579,7 +579,7 @@ LL | #[link_ordinal] = note: for more information, visit error[E0565]: malformed `ffi_const` attribute input - --> $DIR/malformed-attrs.rs:176:5 + --> $DIR/malformed-attrs.rs:174:5 | LL | #[unsafe(ffi_const = 1)] | ^^^^^^^^^^^^^^^^^^^---^^ @@ -588,13 +588,13 @@ LL | #[unsafe(ffi_const = 1)] | help: must be of the form: `#[ffi_const]` error[E0539]: malformed `linkage` attribute input - --> $DIR/malformed-attrs.rs:178:5 + --> $DIR/malformed-attrs.rs:176:5 | LL | #[linkage] | ^^^^^^^^^^ expected this to be of the form `linkage = "..."` error[E0539]: malformed `debugger_visualizer` attribute input - --> $DIR/malformed-attrs.rs:193:1 + --> $DIR/malformed-attrs.rs:191:1 | LL | #[debugger_visualizer] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -605,7 +605,7 @@ LL | #[debugger_visualizer] = note: for more information, visit error[E0565]: malformed `automatically_derived` attribute input - --> $DIR/malformed-attrs.rs:195:1 + --> $DIR/malformed-attrs.rs:193:1 | LL | #[automatically_derived = 18] | ^^^^^^^^^^^^^^^^^^^^^^^^----^ @@ -614,7 +614,7 @@ LL | #[automatically_derived = 18] | help: must be of the form: `#[automatically_derived]` error[E0565]: malformed `non_exhaustive` attribute input - --> $DIR/malformed-attrs.rs:203:1 + --> $DIR/malformed-attrs.rs:201:1 | LL | #[non_exhaustive = 1] | ^^^^^^^^^^^^^^^^^---^ @@ -623,7 +623,7 @@ LL | #[non_exhaustive = 1] | help: must be of the form: `#[non_exhaustive]` error[E0565]: malformed `thread_local` attribute input - --> $DIR/malformed-attrs.rs:209:1 + --> $DIR/malformed-attrs.rs:207:1 | LL | #[thread_local()] | ^^^^^^^^^^^^^^--^ @@ -632,7 +632,7 @@ LL | #[thread_local()] | help: must be of the form: `#[thread_local]` error[E0565]: malformed `no_link` attribute input - --> $DIR/malformed-attrs.rs:213:1 + --> $DIR/malformed-attrs.rs:211:1 | LL | #[no_link()] | ^^^^^^^^^--^ @@ -641,7 +641,7 @@ LL | #[no_link()] | help: must be of the form: `#[no_link]` error[E0539]: malformed `macro_use` attribute input - --> $DIR/malformed-attrs.rs:215:1 + --> $DIR/malformed-attrs.rs:213:1 | LL | #[macro_use = 1] | ^^^^^^^^^^^^---^ @@ -659,7 +659,7 @@ LL + #[macro_use] | error[E0539]: malformed `macro_export` attribute input - --> $DIR/malformed-attrs.rs:220:1 + --> $DIR/malformed-attrs.rs:218:1 | LL | #[macro_export = 18] | ^^^^^^^^^^^^^^^----^ @@ -676,7 +676,7 @@ LL + #[macro_export] | error[E0565]: malformed `allow_internal_unsafe` attribute input - --> $DIR/malformed-attrs.rs:222:1 + --> $DIR/malformed-attrs.rs:220:1 | LL | #[allow_internal_unsafe = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^---^ @@ -684,15 +684,6 @@ LL | #[allow_internal_unsafe = 1] | | didn't expect any arguments here | help: must be of the form: `#[allow_internal_unsafe]` -error[E0565]: malformed `type_const` attribute input - --> $DIR/malformed-attrs.rs:148:5 - | -LL | #[type_const = 1] - | ^^^^^^^^^^^^^---^ - | | | - | | didn't expect any arguments here - | help: must be of the form: `#[type_const]` - error: attribute should be applied to `const fn` --> $DIR/malformed-attrs.rs:32:1 | @@ -820,13 +811,13 @@ LL | #[no_implicit_prelude = 23] = help: `#[no_implicit_prelude]` can be applied to crates and modules warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/malformed-attrs.rs:154:1 + --> $DIR/malformed-attrs.rs:152:1 | LL | #[diagnostic::do_not_recommend()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` attribute cannot be used on modules - --> $DIR/malformed-attrs.rs:195:1 + --> $DIR/malformed-attrs.rs:193:1 | LL | #[automatically_derived = 18] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -835,7 +826,7 @@ LL | #[automatically_derived = 18] = help: `#[automatically_derived]` can only be applied to trait impl blocks error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:229:1 + --> $DIR/malformed-attrs.rs:227:1 | LL | #[ignore = 1] | ^^^^^^^^^^^^^ @@ -854,7 +845,7 @@ LL | #[coroutine = 63] || {} = note: expected unit type `()` found coroutine `{coroutine@$DIR/malformed-attrs.rs:116:23: 116:25}` -error: aborting due to 76 previous errors; 8 warnings emitted +error: aborting due to 75 previous errors; 8 warnings emitted Some errors have detailed explanations: E0308, E0463, E0539, E0565, E0658, E0805. For more information about an error, try `rustc --explain E0308`. @@ -882,7 +873,7 @@ LL | #[ignore()] Future breakage diagnostic: error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:229:1 + --> $DIR/malformed-attrs.rs:227:1 | LL | #[ignore = 1] | ^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/associated-const-bindings/ambiguity.rs b/tests/ui/const-generics/associated-const-bindings/ambiguity.rs index 785d43e51b3d..6871a028de5f 100644 --- a/tests/ui/const-generics/associated-const-bindings/ambiguity.rs +++ b/tests/ui/const-generics/associated-const-bindings/ambiguity.rs @@ -6,8 +6,7 @@ trait Trait0: Parent0 + Parent0 {} trait Parent0 { - #[type_const] - const K: (); + type const K: (); } fn take0(_: impl Trait0) {} @@ -15,12 +14,10 @@ fn take0(_: impl Trait0) {} trait Trait1: Parent1 + Parent2 {} trait Parent1 { - #[type_const] - const C: i32; + type const C: i32; } trait Parent2 { - #[type_const] - const C: &'static str; + type const C: &'static str; } fn take1(_: impl Trait1) {} diff --git a/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr b/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr index 806708f18d65..9dcb30d6b737 100644 --- a/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr +++ b/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr @@ -1,8 +1,8 @@ error[E0222]: ambiguous associated constant `K` in bounds of `Trait0` - --> $DIR/ambiguity.rs:13:25 + --> $DIR/ambiguity.rs:12:25 | -LL | const K: (); - | ----------- +LL | type const K: (); + | ---------------- | | | ambiguous `K` from `Parent0` | ambiguous `K` from `Parent0` @@ -17,13 +17,13 @@ LL | fn take0(_: impl Trait0) {} T: Parent0::K = const { } error[E0222]: ambiguous associated constant `C` in bounds of `Trait1` - --> $DIR/ambiguity.rs:26:25 + --> $DIR/ambiguity.rs:23:25 | -LL | const C: i32; - | ------------ ambiguous `C` from `Parent1` +LL | type const C: i32; + | ----------------- ambiguous `C` from `Parent1` ... -LL | const C: &'static str; - | --------------------- ambiguous `C` from `Parent2` +LL | type const C: &'static str; + | -------------------------- ambiguous `C` from `Parent2` ... LL | fn take1(_: impl Trait1) {} | ^^^^^^^ ambiguous associated constant `C` diff --git a/tests/ui/const-generics/associated-const-bindings/assoc-const.rs b/tests/ui/const-generics/associated-const-bindings/assoc-const.rs index ac9f7e53b3cb..3f8353b6914d 100644 --- a/tests/ui/const-generics/associated-const-bindings/assoc-const.rs +++ b/tests/ui/const-generics/associated-const-bindings/assoc-const.rs @@ -3,15 +3,13 @@ #![allow(unused, incomplete_features)] pub trait Foo { - #[type_const] - const N: usize; + type const N: usize; } pub struct Bar; impl Foo for Bar { - #[type_const] - const N: usize = 3; + type const N: usize = 3; } const TEST: usize = 3; diff --git a/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty-not-wf.rs b/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty-not-wf.rs index 803cc59cc93d..53f65319db9d 100644 --- a/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty-not-wf.rs +++ b/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty-not-wf.rs @@ -11,8 +11,7 @@ use std::marker::ConstParamTy_; trait Trait { - #[type_const] - const K: T; + type const K: T; } fn take( diff --git a/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty-not-wf.stderr b/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty-not-wf.stderr index a4f97525b515..f2f69aad4ee6 100644 --- a/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty-not-wf.stderr +++ b/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty-not-wf.stderr @@ -1,11 +1,11 @@ error: higher-ranked subtype error - --> $DIR/bound-var-in-ty-not-wf.rs:21:13 + --> $DIR/bound-var-in-ty-not-wf.rs:20:13 | LL | K = const { () } | ^^^^^^^^^^^^ error: higher-ranked subtype error - --> $DIR/bound-var-in-ty-not-wf.rs:21:13 + --> $DIR/bound-var-in-ty-not-wf.rs:20:13 | LL | K = const { () } | ^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty.rs b/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty.rs index e6fd5bdad002..a509fe0d52e3 100644 --- a/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty.rs +++ b/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty.rs @@ -14,8 +14,7 @@ use std::marker::ConstParamTy_; trait Trait { - #[type_const] - const K: T; + type const K: T; } fn take( diff --git a/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs b/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs index 0af91bfe7da8..149755bad4ca 100644 --- a/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs +++ b/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs @@ -12,13 +12,11 @@ trait Trait: SuperTrait { type N; type Q; - #[type_const] - const N: usize; + type const N: usize; } trait SuperTrait { - #[type_const] - const Q: &'static str; + type const Q: &'static str; } fn take0(_: impl Trait) {} diff --git a/tests/ui/const-generics/associated-const-bindings/coherence.rs b/tests/ui/const-generics/associated-const-bindings/coherence.rs index f4081fae6144..e9296f3a8df0 100644 --- a/tests/ui/const-generics/associated-const-bindings/coherence.rs +++ b/tests/ui/const-generics/associated-const-bindings/coherence.rs @@ -2,12 +2,10 @@ #![expect(incomplete_features)] pub trait IsVoid { - #[type_const] - const IS_VOID: bool; + type const IS_VOID: bool; } impl IsVoid for () { - #[type_const] - const IS_VOID: bool = true; + type const IS_VOID: bool = true; } pub trait Maybe {} diff --git a/tests/ui/const-generics/associated-const-bindings/coherence.stderr b/tests/ui/const-generics/associated-const-bindings/coherence.stderr index 23d6495a16a4..df6781f2f9a2 100644 --- a/tests/ui/const-generics/associated-const-bindings/coherence.stderr +++ b/tests/ui/const-generics/associated-const-bindings/coherence.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Maybe` for type `()` - --> $DIR/coherence.rs:15:1 + --> $DIR/coherence.rs:13:1 | LL | impl Maybe for () {} | ----------------- first implementation here diff --git a/tests/ui/const-generics/associated-const-bindings/const-projection-err.rs b/tests/ui/const-generics/associated-const-bindings/const-projection-err.rs index d485316ce371..8e871ddf90ce 100644 --- a/tests/ui/const-generics/associated-const-bindings/const-projection-err.rs +++ b/tests/ui/const-generics/associated-const-bindings/const-projection-err.rs @@ -2,8 +2,7 @@ #![allow(incomplete_features)] trait TraitWAssocConst { - #[type_const] - const A: usize; + type const A: usize; } fn foo>() {} diff --git a/tests/ui/const-generics/associated-const-bindings/const-projection-err.stderr b/tests/ui/const-generics/associated-const-bindings/const-projection-err.stderr index 552b1579e618..c533a7d65b90 100644 --- a/tests/ui/const-generics/associated-const-bindings/const-projection-err.stderr +++ b/tests/ui/const-generics/associated-const-bindings/const-projection-err.stderr @@ -1,5 +1,5 @@ error[E0271]: type mismatch resolving `::A == 1` - --> $DIR/const-projection-err.rs:12:11 + --> $DIR/const-projection-err.rs:11:11 | LL | foo::(); | ^ expected `1`, found `0` @@ -7,7 +7,7 @@ LL | foo::(); = note: expected constant `1` found constant `0` note: required by a bound in `foo` - --> $DIR/const-projection-err.rs:9:28 + --> $DIR/const-projection-err.rs:8:28 | LL | fn foo>() {} | ^^^^^ required by this bound in `foo` diff --git a/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs b/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs index 161eef63d36f..578904ea1891 100644 --- a/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs +++ b/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs @@ -8,8 +8,7 @@ #![allow(incomplete_features)] pub trait TraitA { - #[type_const] - const K: u8 = 0; + type const K: u8 = 0; } pub trait TraitB {} diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs index bd26acce681f..771f48cba068 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs @@ -14,14 +14,12 @@ trait Trait { // NOTE: The `ConstParamTy_` bound is intentionally on the assoc const and not on the trait as // doing the latter would already render the trait dyn incompatible due to it being // bounded by `PartialEq` and supertrait bounds cannot mention `Self` like this. - #[type_const] - const K: Self where Self: std::marker::ConstParamTy_; + type const K: Self where Self: std::marker::ConstParamTy_; //~^ NOTE it contains associated const `K` whose type references the `Self` type // This is not a "`Self` projection" in our sense (which would be allowed) // since the trait is not the principal trait or a supertrait thereof. - #[type_const] - const Q: ::Output; + type const Q: ::Output; //~^ NOTE it contains associated const `Q` whose type references the `Self` type } diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.stderr index dedbdd7f82bb..19cd8bf5af99 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.stderr @@ -1,21 +1,21 @@ error[E0038]: the trait `Trait` is not dyn compatible - --> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:38:16 + --> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:36:16 | LL | let _: dyn Trait; | ^^^^^ `Trait` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:18:11 + --> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:17:16 | LL | trait Trait { | ----- this trait is not dyn compatible... ... -LL | const K: Self where Self: std::marker::ConstParamTy_; - | ^ ...because it contains associated const `K` whose type references the `Self` type +LL | type const K: Self where Self: std::marker::ConstParamTy_; + | ^ ...because it contains associated const `K` whose type references the `Self` type ... -LL | const Q: ::Output; - | ^ ...because it contains associated const `Q` whose type references the `Self` type +LL | type const Q: ::Output; + | ^ ...because it contains associated const `Q` whose type references the `Self` type = help: consider moving `K` to another trait = help: consider moving `Q` to another trait diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-basic.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-basic.rs index 6e35d56dc6e7..8de8cb1a60db 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-basic.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-basic.rs @@ -7,25 +7,20 @@ #![expect(incomplete_features)] trait Trait: SuperTrait { - #[type_const] - const K: usize; + type const K: usize; } trait SuperTrait { - #[type_const] - const Q: usize; - #[type_const] - const C: usize; + type const Q: usize; + type const C: usize; } trait Bound { - #[type_const] - const N: usize; + type const N: usize; } impl Bound for () { - #[type_const] - const N: usize = 10; + type const N: usize = 10; } fn main() { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.rs index be41906a4f2f..ad5c4b679117 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.rs @@ -4,13 +4,11 @@ #![expect(incomplete_features)] trait Trait { - #[type_const] - const N: usize; + type const N: usize; } impl Trait for () { - #[type_const] - const N: usize = 1; + type const N: usize = 1; } fn main() { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.stderr index 2ab02068eb34..282504e3bc35 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.stderr @@ -1,5 +1,5 @@ error[E0271]: type mismatch resolving `<() as Trait>::N == 0` - --> $DIR/dyn-compat-const-mismatch.rs:17:32 + --> $DIR/dyn-compat-const-mismatch.rs:15:32 | LL | let _: &dyn Trait = &(); | ^^^ expected `0`, found `1` diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.rs index 30e7a78c2a85..8130960195d9 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.rs @@ -7,13 +7,11 @@ trait X::N }> {} trait Y { - #[type_const] - const N: usize; + type const N: usize; } impl Y for T { - #[type_const] - const N: usize = 1; + type const N: usize = 1; } fn main() { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.stderr index d92fd620f0ea..a22545fcd8d2 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.stderr @@ -1,5 +1,5 @@ error[E0393]: the const parameter `N` must be explicitly specified - --> $DIR/dyn-compat-const-param-default-mentions-self.rs:20:16 + --> $DIR/dyn-compat-const-param-default-mentions-self.rs:18:16 | LL | trait X::N }> {} | -------------------------------------------- const parameter `N` must be specified for this diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs index 93036fbc01a8..415d7bda347b 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs @@ -9,8 +9,7 @@ #![expect(incomplete_features)] trait Trait { - #[type_const] - const Y: i32; + type const Y: i32; } struct Hold(T); diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.stderr index 109cb7602dcd..576d4c3230ee 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.stderr @@ -1,5 +1,5 @@ error: associated constant binding in trait object type mentions `Self` - --> $DIR/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs:21:12 + --> $DIR/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs:20:12 | LL | trait Bound = Trait }>; | -------------------- this binding mentions `Self` diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-from-supertrait-mentions-self.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-from-supertrait-mentions-self.rs index aa93edd02531..560a1b7f3f7a 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-from-supertrait-mentions-self.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-from-supertrait-mentions-self.rs @@ -5,13 +5,11 @@ #![expect(incomplete_features)] trait X: Y { - #[type_const] - const Q: usize; + type const Q: usize; } trait Y { - #[type_const] - const K: usize; + type const K: usize; } fn main() { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-from-supertrait-mentions-self.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-from-supertrait-mentions-self.stderr index 373c4f0e6611..dae9e3d8c22b 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-from-supertrait-mentions-self.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-from-supertrait-mentions-self.stderr @@ -1,8 +1,8 @@ error[E0191]: the value of the associated constant `K` in `Y` must be specified - --> $DIR/dyn-compat-const-projection-from-supertrait-mentions-self.rs:18:16 + --> $DIR/dyn-compat-const-projection-from-supertrait-mentions-self.rs:16:16 | -LL | const K: usize; - | -------------- `K` defined here +LL | type const K: usize; + | ------------------- `K` defined here ... LL | let _: dyn X; | ^^^^^^^^^ help: specify the associated constant: `X` diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-non-type-assoc-const.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-non-type-assoc-const.rs index 67650bce8c89..38d593984724 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-non-type-assoc-const.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-non-type-assoc-const.rs @@ -7,7 +7,7 @@ trait Trait { const K: usize; - //~^ NOTE it contains associated const `K` that's not marked `#[type_const]` + //~^ NOTE it contains associated const `K` that's not defined as `type const` } fn main() { @@ -16,5 +16,5 @@ fn main() { // Check that specifying the non-type assoc const doesn't "magically make it work". let _: dyn Trait; //~^ ERROR the trait `Trait` is not dyn compatible - //~| ERROR use of trait associated const without `#[type_const]` + //~| ERROR use of trait associated const not defined as `type const` } diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-non-type-assoc-const.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-non-type-assoc-const.stderr index c579cd312f1f..5bc072e98c0f 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-non-type-assoc-const.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-non-type-assoc-const.stderr @@ -11,16 +11,16 @@ note: for a trait to be dyn compatible it needs to allow building a vtable LL | trait Trait { | ----- this trait is not dyn compatible... LL | const K: usize; - | ^ ...because it contains associated const `K` that's not marked `#[type_const]` + | ^ ...because it contains associated const `K` that's not defined as `type const` = help: consider moving `K` to another trait -error: use of trait associated const without `#[type_const]` +error: use of trait associated const not defined as `type const` --> $DIR/dyn-compat-non-type-assoc-const.rs:17:22 | LL | let _: dyn Trait; | ^^^^^ | - = note: the declaration in the trait must be marked with `#[type_const]` + = note: the declaration in the trait must begin with `type const` not just `const` alone error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/dyn-compat-non-type-assoc-const.rs:17:16 @@ -35,7 +35,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable LL | trait Trait { | ----- this trait is not dyn compatible... LL | const K: usize; - | ^ ...because it contains associated const `K` that's not marked `#[type_const]` + | ^ ...because it contains associated const `K` that's not defined as `type const` = help: consider moving `K` to another trait error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs index 07ce629ab7be..03f1a526b73a 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs @@ -6,13 +6,11 @@ #![expect(incomplete_features)] trait Trait { - #[type_const] - const N: i32 where Self: Bound; + type const N: i32 where Self: Bound; } impl Trait for () { - #[type_const] - const N: i32 = 0; + type const N: i32 = 0; } trait Bound {} diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.stderr index 8eeb60d55c38..21e407f8a861 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.stderr @@ -1,19 +1,19 @@ error[E0277]: the trait bound `(): Bound` is not satisfied - --> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:23:32 + --> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:21:32 | LL | let _: &dyn Trait = &(); | ^^^ the trait `Bound` is not implemented for `()` | help: this trait has no implementations, consider adding one - --> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:18:1 + --> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:16:1 | LL | trait Bound {} | ^^^^^^^^^^^ note: required by a bound in `Trait::N` - --> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:10:30 + --> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:9:35 | -LL | const N: i32 where Self: Bound; - | ^^^^^ required by this bound in `Trait::N` +LL | type const N: i32 where Self: Bound; + | ^^^^^ required by this bound in `Trait::N` error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs index fc3bd1d2e753..623769f5d12f 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs @@ -14,14 +14,12 @@ trait A { type Ty: std::marker::ConstParamTy_; - #[type_const] - const CT: Self::Ty; + type const CT: Self::Ty; } impl A for () { type Ty = i32; - #[type_const] - const CT: i32 = 0; + type const CT: i32 = 0; } fn main() { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr index 0b8dae1aac43..cc08c25906b6 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr @@ -1,23 +1,23 @@ error[E0277]: the trait bound `FreshTy(0): A` is not satisfied - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:34:33 + --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:32:33 | LL | let _: dyn A; | ^ the trait `A` is not implemented for `FreshTy(0)` | help: the trait `A` is implemented for `()` - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:21:1 + --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:20:1 | LL | impl A for () { | ^^^^^^^^^^^^^ error[E0277]: the trait bound `FreshTy(0): A` is not satisfied - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:36:34 + --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:34:34 | LL | let _: &dyn A = &(); | ^ the trait `A` is not implemented for `FreshTy(0)` | help: the trait `A` is implemented for `()` - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:21:1 + --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:20:1 | LL | impl A for () { | ^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-methods.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-methods.rs index f5a5fbc8188c..9886213743c8 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-methods.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-methods.rs @@ -15,15 +15,13 @@ #![expect(incomplete_features)] trait Trait { - #[type_const] - const N: usize; + type const N: usize; fn process(&self, _: [u8; Self::N]) -> [u8; Self::N]; } impl Trait for u8 { - #[type_const] - const N: usize = 2; + type const N: usize = 2; fn process(&self, [x, y]: [u8; Self::N]) -> [u8; Self::N] { [self * x, self + y] @@ -31,8 +29,7 @@ impl Trait for u8 { } impl Trait for [u8; N] { - #[type_const] - const N: usize = N; + type const N: usize = N; fn process(&self, other: [u8; Self::N]) -> [u8; Self::N] { let mut result = [0; _]; diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-supertrait-bounds.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-supertrait-bounds.rs index c8929750f61c..f2ae98accda5 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-supertrait-bounds.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-supertrait-bounds.rs @@ -9,8 +9,7 @@ trait Trait: SuperTrait<{ Self::N }> { //~^ NOTE it uses `Self` as a type parameter - #[type_const] - const N: usize; + type const N: usize; } trait SuperTrait {} diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-supertrait-bounds.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-supertrait-bounds.stderr index 33edc96117d5..38c928fd58d7 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-supertrait-bounds.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-supertrait-bounds.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Trait` is not dyn compatible - --> $DIR/dyn-compat-self-const-projections-in-supertrait-bounds.rs:19:16 + --> $DIR/dyn-compat-self-const-projections-in-supertrait-bounds.rs:18:16 | LL | let _: dyn Trait; | ^^^^^ `Trait` is not dyn compatible diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.rs index 18be0fccc051..52ecd42b191d 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.rs @@ -15,8 +15,7 @@ #![crate_name = "sym"] trait Trait { - #[type_const] - const N: usize; + type const N: usize; } #[rustc_symbol_name] diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.v0.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.v0.stderr index 424251acc3e9..8ca0f73494d3 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.v0.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.v0.stderr @@ -1,17 +1,17 @@ error: symbol-name(_RMCsCRATE_HASH_3symDNtB_5Traitp1NKj0_EL_) - --> $DIR/dyn-compat-symbol-mangling.rs:22:1 + --> $DIR/dyn-compat-symbol-mangling.rs:21:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling(>) - --> $DIR/dyn-compat-symbol-mangling.rs:22:1 + --> $DIR/dyn-compat-symbol-mangling.rs:21:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: demangling-alt(>) - --> $DIR/dyn-compat-symbol-mangling.rs:22:1 + --> $DIR/dyn-compat-symbol-mangling.rs:21:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.rs index 3525cbceb87b..5bd8aa609420 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.rs @@ -6,8 +6,7 @@ #![expect(incomplete_features)] trait Trait { - #[type_const] - const K: usize; + type const K: usize; } // fn ctxt / body diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.stderr index 68658a5711cb..35fdd7f2751e 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.stderr @@ -1,26 +1,26 @@ error[E0191]: the value of the associated constant `K` in `Trait` must be specified - --> $DIR/dyn-compat-unspecified-assoc-consts.rs:20:18 + --> $DIR/dyn-compat-unspecified-assoc-consts.rs:19:18 | -LL | const K: usize; - | -------------- `K` defined here +LL | type const K: usize; + | ------------------- `K` defined here ... LL | struct Store(dyn Trait); | ^^^^^ help: specify the associated constant: `Trait` error[E0191]: the value of the associated constant `K` in `Trait` must be specified - --> $DIR/dyn-compat-unspecified-assoc-consts.rs:24:21 + --> $DIR/dyn-compat-unspecified-assoc-consts.rs:23:21 | -LL | const K: usize; - | -------------- `K` defined here +LL | type const K: usize; + | ------------------- `K` defined here ... LL | type DynTrait = dyn Trait; | ^^^^^ help: specify the associated constant: `Trait` error[E0191]: the value of the associated constant `K` in `Trait` must be specified - --> $DIR/dyn-compat-unspecified-assoc-consts.rs:15:16 + --> $DIR/dyn-compat-unspecified-assoc-consts.rs:14:16 | -LL | const K: usize; - | -------------- `K` defined here +LL | type const K: usize; + | ------------------- `K` defined here ... LL | let _: dyn Trait; | ^^^^^ help: specify the associated constant: `Trait` diff --git a/tests/ui/const-generics/associated-const-bindings/equality-unused-issue-126729.rs b/tests/ui/const-generics/associated-const-bindings/equality-unused-issue-126729.rs index 614ed8c803d4..f42589f91d15 100644 --- a/tests/ui/const-generics/associated-const-bindings/equality-unused-issue-126729.rs +++ b/tests/ui/const-generics/associated-const-bindings/equality-unused-issue-126729.rs @@ -5,42 +5,34 @@ #![deny(dead_code)] trait Tr { - #[type_const] - const I: i32; + type const I: i32; } impl Tr for () { - #[type_const] - const I: i32 = 1; + type const I: i32 = 1; } fn foo() -> impl Tr {} trait Tr2 { - #[type_const] - const J: i32; - #[type_const] - const K: i32; + type const J: i32; + type const K: i32; } impl Tr2 for () { - #[type_const] - const J: i32 = 1; - #[type_const] - const K: i32 = 1; + type const J: i32 = 1; + type const K: i32 = 1; } fn foo2() -> impl Tr2 {} mod t { pub trait Tr3 { - #[type_const] - const L: i32; + type const L: i32; } impl Tr3 for () { - #[type_const] - const L: i32 = 1; + type const L: i32 = 1; } } diff --git a/tests/ui/const-generics/associated-const-bindings/equality_bound_with_infer.rs b/tests/ui/const-generics/associated-const-bindings/equality_bound_with_infer.rs index b7ed8ee39f87..e50c13b5d3b5 100644 --- a/tests/ui/const-generics/associated-const-bindings/equality_bound_with_infer.rs +++ b/tests/ui/const-generics/associated-const-bindings/equality_bound_with_infer.rs @@ -7,13 +7,11 @@ // though it contained inference variables, which would cause ICEs. trait Foo { - #[type_const] - const ASSOC: u32; + type const ASSOC: u32; } impl Foo for () { - #[type_const] - const ASSOC: u32 = N; + type const ASSOC: u32 = N; } fn bar = 10>>() {} diff --git a/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs b/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs index 4d06cdc7620f..de888c5a7939 100644 --- a/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs +++ b/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs @@ -9,8 +9,7 @@ #![allow(incomplete_features)] trait Trait<'a> { - #[type_const] - const K: &'a (); + type const K: &'a (); } fn take(_: impl for<'r> Trait<'r, K = const { &() }>) {} diff --git a/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.stderr b/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.stderr index 3966483aa600..122893662933 100644 --- a/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.stderr +++ b/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.stderr @@ -1,5 +1,5 @@ error: the type of the associated constant `K` cannot capture late-bound generic parameters - --> $DIR/esc-bound-var-in-ty.rs:16:35 + --> $DIR/esc-bound-var-in-ty.rs:15:35 | LL | fn take(_: impl for<'r> Trait<'r, K = const { &() }>) {} | -- ^ its type cannot capture the late-bound lifetime parameter `'r` diff --git a/tests/ui/const-generics/associated-const-bindings/issue-102335-const.rs b/tests/ui/const-generics/associated-const-bindings/issue-102335-const.rs index a88a3abf0a12..1663cad13c7c 100644 --- a/tests/ui/const-generics/associated-const-bindings/issue-102335-const.rs +++ b/tests/ui/const-generics/associated-const-bindings/issue-102335-const.rs @@ -8,8 +8,7 @@ trait T { } trait S { - #[type_const] - const C: i32; + type const C: i32; } fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.rs b/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.rs index 77f0f06f8040..1c6e873b98c3 100644 --- a/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.rs +++ b/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.rs @@ -2,13 +2,11 @@ #![expect(incomplete_features)] trait Foo { - #[type_const] - const ASSOC: u32; + type const ASSOC: u32; } impl Foo for () { - #[type_const] - const ASSOC: u32 = N; + type const ASSOC: u32 = N; } fn bar = { N }>>() {} diff --git a/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.stderr b/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.stderr index c2fb7faa3a3a..b447cd08a214 100644 --- a/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.stderr +++ b/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.stderr @@ -1,26 +1,26 @@ error: the constant `N` is not of type `u32` - --> $DIR/mismatched-types-with-generic-in-ace.rs:14:29 + --> $DIR/mismatched-types-with-generic-in-ace.rs:12:29 | LL | fn bar = { N }>>() {} | ^^^^^^^^^^^^^^^^ expected `u32`, found `u64` | note: required by a const generic parameter in `Foo::ASSOC` - --> $DIR/mismatched-types-with-generic-in-ace.rs:6:17 + --> $DIR/mismatched-types-with-generic-in-ace.rs:5:22 | -LL | const ASSOC: u32; - | ^^^^^^^^^^^^ required by this const generic parameter in `Foo::ASSOC` +LL | type const ASSOC: u32; + | ^^^^^^^^^^^^ required by this const generic parameter in `Foo::ASSOC` error: the constant `10` is not of type `u32` - --> $DIR/mismatched-types-with-generic-in-ace.rs:18:5 + --> $DIR/mismatched-types-with-generic-in-ace.rs:16:5 | LL | bar::<10_u64, ()>(); | ^^^^^^^^^^^^^^^^^^^ expected `u32`, found `u64` | note: required by a const generic parameter in `Foo::ASSOC` - --> $DIR/mismatched-types-with-generic-in-ace.rs:6:17 + --> $DIR/mismatched-types-with-generic-in-ace.rs:5:22 | -LL | const ASSOC: u32; - | ^^^^^^^^^^^^ required by this const generic parameter in `Foo::ASSOC` +LL | type const ASSOC: u32; + | ^^^^^^^^^^^^ required by this const generic parameter in `Foo::ASSOC` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/associated-const-bindings/normalization-via-param-env.rs b/tests/ui/const-generics/associated-const-bindings/normalization-via-param-env.rs index c7bb5bccedb3..a1efa74090bb 100644 --- a/tests/ui/const-generics/associated-const-bindings/normalization-via-param-env.rs +++ b/tests/ui/const-generics/associated-const-bindings/normalization-via-param-env.rs @@ -6,8 +6,7 @@ // with associated const equality bounds. trait Trait { - #[type_const] - const C: usize; + type const C: usize; } fn f>() { diff --git a/tests/ui/const-generics/associated-const-bindings/param-in-ty.rs b/tests/ui/const-generics/associated-const-bindings/param-in-ty.rs index 44e7e3f19ef2..4d67186f71f9 100644 --- a/tests/ui/const-generics/associated-const-bindings/param-in-ty.rs +++ b/tests/ui/const-generics/associated-const-bindings/param-in-ty.rs @@ -11,8 +11,7 @@ use std::marker::ConstParamTy_; trait Trait<'a, T: 'a + ConstParamTy_, const N: usize> { - #[type_const] - const K: &'a [T; N]; + type const K: &'a [T; N]; } fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>( @@ -32,8 +31,7 @@ fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>( ) {} trait Project: ConstParamTy_ { - #[type_const] - const SELF: Self; + type const SELF: Self; } fn take1(_: impl Project) {} diff --git a/tests/ui/const-generics/associated-const-bindings/param-in-ty.stderr b/tests/ui/const-generics/associated-const-bindings/param-in-ty.stderr index 719dad816a6f..2ef3fab7e5ff 100644 --- a/tests/ui/const-generics/associated-const-bindings/param-in-ty.stderr +++ b/tests/ui/const-generics/associated-const-bindings/param-in-ty.stderr @@ -1,5 +1,5 @@ error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/param-in-ty.rs:22:29 + --> $DIR/param-in-ty.rs:21:29 | LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>( | -- the lifetime parameter `'r` is defined here @@ -10,7 +10,7 @@ LL | _: impl Trait<'r, A, Q, K = const { loop {} }> = note: `K` has type `&'r [A; Q]` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/param-in-ty.rs:22:29 + --> $DIR/param-in-ty.rs:21:29 | LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>( | - the type parameter `A` is defined here @@ -21,7 +21,7 @@ LL | _: impl Trait<'r, A, Q, K = const { loop {} }> = note: `K` has type `&'r [A; Q]` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/param-in-ty.rs:22:29 + --> $DIR/param-in-ty.rs:21:29 | LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>( | - the const parameter `Q` is defined here @@ -32,7 +32,7 @@ LL | _: impl Trait<'r, A, Q, K = const { loop {} }> = note: `K` has type `&'r [A; Q]` error: the type of the associated constant `SELF` must not depend on `impl Trait` - --> $DIR/param-in-ty.rs:39:26 + --> $DIR/param-in-ty.rs:37:26 | LL | fn take1(_: impl Project) {} | -------------^^^^------------ @@ -41,7 +41,7 @@ LL | fn take1(_: impl Project) {} | the `impl Trait` is specified here error: the type of the associated constant `SELF` must not depend on generic parameters - --> $DIR/param-in-ty.rs:44:21 + --> $DIR/param-in-ty.rs:42:21 | LL | fn take2>(_: P) {} | - ^^^^ its type must not depend on the type parameter `P` @@ -51,7 +51,7 @@ LL | fn take2>(_: P) {} = note: `SELF` has type `P` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/param-in-ty.rs:53:52 + --> $DIR/param-in-ty.rs:51:52 | LL | trait Iface<'r>: ConstParamTy_ { | -- the lifetime parameter `'r` is defined here @@ -62,7 +62,7 @@ LL | type Assoc: Trait<'r, Self, Q, K = const { loop {} }> = note: `K` has type `&'r [Self; Q]` error: the type of the associated constant `K` must not depend on `Self` - --> $DIR/param-in-ty.rs:53:52 + --> $DIR/param-in-ty.rs:51:52 | LL | type Assoc: Trait<'r, Self, Q, K = const { loop {} }> | ^ its type must not depend on `Self` @@ -70,7 +70,7 @@ LL | type Assoc: Trait<'r, Self, Q, K = const { loop {} }> = note: `K` has type `&'r [Self; Q]` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/param-in-ty.rs:53:52 + --> $DIR/param-in-ty.rs:51:52 | LL | type Assoc: Trait<'r, Self, Q, K = const { loop {} }> | - ^ its type must not depend on the const parameter `Q` @@ -80,7 +80,7 @@ LL | type Assoc: Trait<'r, Self, Q, K = const { loop {} }> = note: `K` has type `&'r [Self; Q]` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/param-in-ty.rs:53:52 + --> $DIR/param-in-ty.rs:51:52 | LL | trait Iface<'r>: ConstParamTy_ { | -- the lifetime parameter `'r` is defined here @@ -92,7 +92,7 @@ LL | type Assoc: Trait<'r, Self, Q, K = const { loop {} }> = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: the type of the associated constant `K` must not depend on `Self` - --> $DIR/param-in-ty.rs:53:52 + --> $DIR/param-in-ty.rs:51:52 | LL | type Assoc: Trait<'r, Self, Q, K = const { loop {} }> | ^ its type must not depend on `Self` @@ -101,7 +101,7 @@ LL | type Assoc: Trait<'r, Self, Q, K = const { loop {} }> = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/param-in-ty.rs:53:52 + --> $DIR/param-in-ty.rs:51:52 | LL | type Assoc: Trait<'r, Self, Q, K = const { loop {} }> | - ^ its type must not depend on the const parameter `Q` diff --git a/tests/ui/const-generics/associated-const-bindings/projection-unspecified-but-bounded.rs b/tests/ui/const-generics/associated-const-bindings/projection-unspecified-but-bounded.rs index 8a78b26dbc5d..dbfbba9b7cbd 100644 --- a/tests/ui/const-generics/associated-const-bindings/projection-unspecified-but-bounded.rs +++ b/tests/ui/const-generics/associated-const-bindings/projection-unspecified-but-bounded.rs @@ -4,8 +4,7 @@ // Issue 110549 pub trait TraitWAssocConst { - #[type_const] - const A: usize; + type const A: usize; } fn foo>() {} diff --git a/tests/ui/const-generics/associated-const-bindings/projection-unspecified-but-bounded.stderr b/tests/ui/const-generics/associated-const-bindings/projection-unspecified-but-bounded.stderr index 232b15b7e981..11490a044091 100644 --- a/tests/ui/const-generics/associated-const-bindings/projection-unspecified-but-bounded.stderr +++ b/tests/ui/const-generics/associated-const-bindings/projection-unspecified-but-bounded.stderr @@ -1,5 +1,5 @@ error[E0271]: type mismatch resolving `::A == 32` - --> $DIR/projection-unspecified-but-bounded.rs:14:11 + --> $DIR/projection-unspecified-but-bounded.rs:13:11 | LL | foo::(); | ^ expected `32`, found `::A` @@ -7,7 +7,7 @@ LL | foo::(); = note: expected constant `32` found constant `::A` note: required by a bound in `foo` - --> $DIR/projection-unspecified-but-bounded.rs:11:28 + --> $DIR/projection-unspecified-but-bounded.rs:10:28 | LL | fn foo>() {} | ^^^^^^ required by this bound in `foo` diff --git a/tests/ui/const-generics/associated-const-bindings/supertraits.rs b/tests/ui/const-generics/associated-const-bindings/supertraits.rs index a5f8859c92bd..cdceb682a854 100644 --- a/tests/ui/const-generics/associated-const-bindings/supertraits.rs +++ b/tests/ui/const-generics/associated-const-bindings/supertraits.rs @@ -16,8 +16,7 @@ use std::marker::ConstParamTy_; trait Trait: SuperTrait {} trait SuperTrait: SuperSuperTrait {} trait SuperSuperTrait { - #[type_const] - const K: T; + type const K: T; } fn take(_: impl Trait) {} diff --git a/tests/ui/const-generics/associated-const-bindings/using-fnptr-as-type_const.rs b/tests/ui/const-generics/associated-const-bindings/using-fnptr-as-type_const.rs index 5c494031d4fa..95f81323acf4 100644 --- a/tests/ui/const-generics/associated-const-bindings/using-fnptr-as-type_const.rs +++ b/tests/ui/const-generics/associated-const-bindings/using-fnptr-as-type_const.rs @@ -4,8 +4,7 @@ #![feature(min_generic_const_args)] trait Trait { - #[type_const] - const F: fn(); + type const F: fn(); //~^ ERROR using function pointers as const generic parameters is forbidden } diff --git a/tests/ui/const-generics/associated-const-bindings/using-fnptr-as-type_const.stderr b/tests/ui/const-generics/associated-const-bindings/using-fnptr-as-type_const.stderr index 09d1063081fe..333dd1b89e9b 100644 --- a/tests/ui/const-generics/associated-const-bindings/using-fnptr-as-type_const.stderr +++ b/tests/ui/const-generics/associated-const-bindings/using-fnptr-as-type_const.stderr @@ -1,8 +1,8 @@ error[E0741]: using function pointers as const generic parameters is forbidden - --> $DIR/using-fnptr-as-type_const.rs:8:14 + --> $DIR/using-fnptr-as-type_const.rs:7:19 | -LL | const F: fn(); - | ^^^^ +LL | type const F: fn(); + | ^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs index 6ec1071461c5..8cd46783d4fd 100644 --- a/tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs @@ -1,5 +1,4 @@ #![feature(min_generic_const_args)] #![allow(incomplete_features)] -#[type_const] -pub const NON_LOCAL_CONST: char = 'a'; +pub type const NON_LOCAL_CONST: char = 'a'; diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs b/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs index 16479ba3f64f..8470b933cadd 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs +++ b/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs @@ -10,9 +10,9 @@ use Option::Some; fn foo>() {} + trait Trait { - #[type_const] - const ASSOC: u32; + type const ASSOC: u32; } fn bar() { diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs index 5f0d6c924bd1..68f999fb76fa 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs +++ b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs @@ -1,9 +1,9 @@ #![feature(min_generic_const_args, adt_const_params, unsized_const_params)] #![expect(incomplete_features)] + trait Trait { - #[type_const] - const ASSOC: usize; + type const ASSOC: usize; } fn takes_tuple() {} diff --git a/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs b/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs index d3c9b655a9e5..5def3cbb829b 100644 --- a/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs +++ b/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs @@ -16,8 +16,7 @@ struct Foo { field: T, } -#[type_const] -const WRAP: Foo = { Foo:: { +type const WRAP: Foo = { Foo:: { field: N, } }; diff --git a/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs b/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs index 47ecbfa6b7e1..7401181962bb 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs @@ -6,8 +6,7 @@ fn takes_array() {} trait Trait { - #[type_const] - const ASSOC: u32; + type const ASSOC: u32; } fn generic_caller() { diff --git a/tests/ui/const-generics/mgca/assoc-const-projection-in-bound.rs b/tests/ui/const-generics/mgca/assoc-const-projection-in-bound.rs index 460e14359483..13b2e031b118 100644 --- a/tests/ui/const-generics/mgca/assoc-const-projection-in-bound.rs +++ b/tests/ui/const-generics/mgca/assoc-const-projection-in-bound.rs @@ -7,13 +7,11 @@ trait Abc {} trait A { - #[type_const] - const VALUE: usize; + type const VALUE: usize; } impl A for T { - #[type_const] - const VALUE: usize = 0; + type const VALUE: usize = 0; } trait S {} diff --git a/tests/ui/const-generics/mgca/assoc-const-without-type_const.rs b/tests/ui/const-generics/mgca/assoc-const-without-type_const.rs index a11314c11aae..ca7299e7690b 100644 --- a/tests/ui/const-generics/mgca/assoc-const-without-type_const.rs +++ b/tests/ui/const-generics/mgca/assoc-const-without-type_const.rs @@ -6,9 +6,9 @@ pub trait Tr { } fn mk_array(_x: T) -> [(); T::SIZE] { - //~^ ERROR type_const + //~^ ERROR: use of `const` in the type system not defined as `type const` [(); T::SIZE] - //~^ ERROR type_const + //~^ ERROR: use of `const` in the type system not defined as `type const` } fn main() {} diff --git a/tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr b/tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr index e06850747ff3..759a40cc0675 100644 --- a/tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr +++ b/tests/ui/const-generics/mgca/assoc-const-without-type_const.stderr @@ -1,26 +1,20 @@ -error: use of `const` in the type system without `#[type_const]` +error: use of `const` in the type system not defined as `type const` --> $DIR/assoc-const-without-type_const.rs:8:35 | +LL | const SIZE: usize; + | - help: add `type` before `const` for `Tr::SIZE`: `type` +... LL | fn mk_array(_x: T) -> [(); T::SIZE] { | ^^^^^^^ - | -help: add `#[type_const]` attribute to `Tr::SIZE` - | -LL + #[type_const] -LL | const SIZE: usize; - | -error: use of `const` in the type system without `#[type_const]` +error: use of `const` in the type system not defined as `type const` --> $DIR/assoc-const-without-type_const.rs:10:10 | +LL | const SIZE: usize; + | - help: add `type` before `const` for `Tr::SIZE`: `type` +... LL | [(); T::SIZE] | ^^^^^^^ - | -help: add `#[type_const]` attribute to `Tr::SIZE` - | -LL + #[type_const] -LL | const SIZE: usize; - | error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/assoc-const.rs b/tests/ui/const-generics/mgca/assoc-const.rs index fb5b4308a7f8..c49b84edba10 100644 --- a/tests/ui/const-generics/mgca/assoc-const.rs +++ b/tests/ui/const-generics/mgca/assoc-const.rs @@ -4,8 +4,7 @@ #![allow(incomplete_features)] pub trait Tr { - #[type_const] - const SIZE: usize; + type const SIZE: usize; } fn mk_array>(_x: T) -> [(); >::SIZE] { diff --git a/tests/ui/const-generics/mgca/bad-type_const-syntax.rs b/tests/ui/const-generics/mgca/bad-type_const-syntax.rs index bb5bdb8d7c4c..81be1ca4eb88 100644 --- a/tests/ui/const-generics/mgca/bad-type_const-syntax.rs +++ b/tests/ui/const-generics/mgca/bad-type_const-syntax.rs @@ -1,16 +1,16 @@ trait Tr { - #[type_const()] - //~^ ERROR malformed - //~| ERROR experimental - const N: usize; + type const N: usize; + //~^ ERROR: `type const` syntax is experimental [E0658] + //~| ERROR: associated `type const` are unstable [E0658] } struct S; impl Tr for S { - #[type_const] - //~^ ERROR experimental - const N: usize = 0; + + type const N: usize = 0; + //~^ ERROR: `type const` syntax is experimental [E0658] + //~| ERROR: associated `type const` are unstable [E0658] } fn main() {} diff --git a/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr b/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr index df442c22241b..7bb2adf27199 100644 --- a/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr +++ b/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr @@ -1,33 +1,43 @@ -error[E0658]: the `#[type_const]` attribute is an experimental feature +error[E0658]: `type const` syntax is experimental --> $DIR/bad-type_const-syntax.rs:2:5 | -LL | #[type_const()] - | ^^^^^^^^^^^^^^^ +LL | type const N: usize; + | ^^^^^^^^^^ | = note: see issue #132980 for more information = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: the `#[type_const]` attribute is an experimental feature +error[E0658]: `type const` syntax is experimental --> $DIR/bad-type_const-syntax.rs:11:5 | -LL | #[type_const] - | ^^^^^^^^^^^^^ +LL | type const N: usize = 0; + | ^^^^^^^^^^ | = note: see issue #132980 for more information = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0565]: malformed `type_const` attribute input +error[E0658]: associated `type const` are unstable --> $DIR/bad-type_const-syntax.rs:2:5 | -LL | #[type_const()] - | ^^^^^^^^^^^^--^ - | | | - | | didn't expect any arguments here - | help: must be of the form: `#[type_const]` +LL | type const N: usize; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 3 previous errors +error[E0658]: associated `type const` are unstable + --> $DIR/bad-type_const-syntax.rs:11:5 + | +LL | type const N: usize = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -Some errors have detailed explanations: E0565, E0658. -For more information about an error, try `rustc --explain E0565`. +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs b/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs index 37f9c31feaa5..69d16993a7e0 100644 --- a/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs +++ b/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs @@ -4,23 +4,17 @@ #![feature(min_generic_const_args, generic_const_items)] pub trait Tr { - #[type_const] - const N1: usize; - #[type_const] - const N2: usize; - #[type_const] - const N3: usize; + type const N1: usize; + type const N2: usize; + type const N3: usize; } pub struct S; impl Tr for S { - #[type_const] - const N1: usize = 0; - #[type_const] - const N2: usize = 1; - #[type_const] - const N3: usize = 2; + type const N1: usize = 0; + type const N2: usize = 1; + type const N3: usize = 2; } fn main() {} diff --git a/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs index efab01489404..9d475f8224fa 100644 --- a/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs +++ b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs @@ -3,8 +3,8 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] -#[type_const] -const C: usize = 0; + +type const C: usize = 0; pub struct A {} impl A { fn fun1() {} diff --git a/tests/ui/const-generics/mgca/cyclic-type-const-151251.rs b/tests/ui/const-generics/mgca/cyclic-type-const-151251.rs index 823a6d58bf47..a7e46ad877e7 100644 --- a/tests/ui/const-generics/mgca/cyclic-type-const-151251.rs +++ b/tests/ui/const-generics/mgca/cyclic-type-const-151251.rs @@ -4,8 +4,7 @@ #![feature(generic_const_exprs)] #![expect(incomplete_features)] -#[type_const] -const A: u8 = A; +type const A: u8 = A; //~^ ERROR overflow normalizing the unevaluated constant `A` fn main() {} diff --git a/tests/ui/const-generics/mgca/cyclic-type-const-151251.stderr b/tests/ui/const-generics/mgca/cyclic-type-const-151251.stderr index 1ce2af817277..47653dd1896f 100644 --- a/tests/ui/const-generics/mgca/cyclic-type-const-151251.stderr +++ b/tests/ui/const-generics/mgca/cyclic-type-const-151251.stderr @@ -1,8 +1,8 @@ error[E0275]: overflow normalizing the unevaluated constant `A` - --> $DIR/cyclic-type-const-151251.rs:8:1 + --> $DIR/cyclic-type-const-151251.rs:7:1 | -LL | const A: u8 = A; - | ^^^^^^^^^^^ +LL | type const A: u8 = A; + | ^^^^^^^^^^^^^^^^ | = note: in case this is a recursive type alias, consider using a struct, enum, or union instead diff --git a/tests/ui/const-generics/mgca/explicit_anon_consts.rs b/tests/ui/const-generics/mgca/explicit_anon_consts.rs index bf825a44b1c0..2b9909b43dfb 100644 --- a/tests/ui/const-generics/mgca/explicit_anon_consts.rs +++ b/tests/ui/const-generics/mgca/explicit_anon_consts.rs @@ -34,22 +34,22 @@ fn repeats() -> [(); N] { //~^ ERROR: generic parameters may not be used in const operations } -#[type_const] -const ITEM1: usize = N; -#[type_const] -const ITEM2: usize = { N }; -#[type_const] -const ITEM3: usize = const { N }; + +type const ITEM1: usize = N; + +type const ITEM2: usize = { N }; + +type const ITEM3: usize = const { N }; //~^ ERROR: generic parameters may not be used in const operations -#[type_const] -const ITEM4: usize = { 1 + 1 }; + +type const ITEM4: usize = { 1 + 1 }; //~^ ERROR: complex const arguments must be placed inside of a `const` block -#[type_const] -const ITEM5: usize = const { 1 + 1}; + +type const ITEM5: usize = const { 1 + 1}; trait Trait { - #[type_const] - const ASSOC: usize; + + type const ASSOC: usize; } fn ace_bounds< diff --git a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr index 1251f4415171..714d7a804d11 100644 --- a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr +++ b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr @@ -17,10 +17,10 @@ LL | let _4 = [(); 1 + 1]; | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/explicit_anon_consts.rs:45:38 + --> $DIR/explicit_anon_consts.rs:45:43 | -LL | const ITEM4: usize = { 1 + 1 }; - | ^^^^^^^^^ +LL | type const ITEM4: usize = { 1 + 1 }; + | ^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block --> $DIR/explicit_anon_consts.rs:62:23 @@ -35,10 +35,10 @@ LL | struct Default4; | ^^^^^^^^^ error: generic parameters may not be used in const operations - --> $DIR/explicit_anon_consts.rs:42:46 + --> $DIR/explicit_anon_consts.rs:42:51 | -LL | const ITEM3: usize = const { N }; - | ^ +LL | type const ITEM3: usize = const { N }; + | ^ | = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items diff --git a/tests/ui/const-generics/mgca/explicit_anon_consts_literals_hack.rs b/tests/ui/const-generics/mgca/explicit_anon_consts_literals_hack.rs index 8131a5b72343..be853bb87a37 100644 --- a/tests/ui/const-generics/mgca/explicit_anon_consts_literals_hack.rs +++ b/tests/ui/const-generics/mgca/explicit_anon_consts_literals_hack.rs @@ -4,8 +4,7 @@ #![expect(incomplete_features)] trait Trait { - #[type_const] - const ASSOC: isize; + type const ASSOC: isize; } fn ace>() {} diff --git a/tests/ui/const-generics/mgca/multi_braced_direct_const_args.rs b/tests/ui/const-generics/mgca/multi_braced_direct_const_args.rs index 31f54abf31ef..bbe624269672 100644 --- a/tests/ui/const-generics/mgca/multi_braced_direct_const_args.rs +++ b/tests/ui/const-generics/mgca/multi_braced_direct_const_args.rs @@ -6,8 +6,7 @@ struct Foo; trait Trait { - #[type_const] - const ASSOC: usize; + type const ASSOC: usize; } type Arr = [(); {{{ N }}}]; diff --git a/tests/ui/const-generics/mgca/non-local-const-without-type_const.rs b/tests/ui/const-generics/mgca/non-local-const-without-type_const.rs index e98cbdf8e617..6f1235269dfc 100644 --- a/tests/ui/const-generics/mgca/non-local-const-without-type_const.rs +++ b/tests/ui/const-generics/mgca/non-local-const-without-type_const.rs @@ -5,5 +5,5 @@ extern crate non_local_const; fn main() { let x = [(); non_local_const::N]; - //~^ ERROR use of `const` in the type system without `#[type_const]` + //~^ ERROR: use of `const` in the type system not defined as `type const` } diff --git a/tests/ui/const-generics/mgca/non-local-const-without-type_const.stderr b/tests/ui/const-generics/mgca/non-local-const-without-type_const.stderr index 671dfa5fbb9e..3c10b78eb3e1 100644 --- a/tests/ui/const-generics/mgca/non-local-const-without-type_const.stderr +++ b/tests/ui/const-generics/mgca/non-local-const-without-type_const.stderr @@ -1,10 +1,10 @@ -error: use of `const` in the type system without `#[type_const]` +error: use of `const` in the type system not defined as `type const` --> $DIR/non-local-const-without-type_const.rs:7:18 | LL | let x = [(); non_local_const::N]; | ^^^^^^^^^^^^^^^^^^ | - = note: only consts marked with `#[type_const]` may be used in types + = note: only consts marked defined as `type const` may be used in types error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs index 819323d9cbec..16ed24a7b287 100644 --- a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs +++ b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs @@ -8,8 +8,8 @@ struct Foo; trait Trait { - #[type_const] - const ASSOC: u32; + + type const ASSOC: u32; } fn foo() {} diff --git a/tests/ui/const-generics/mgca/projection-error.rs b/tests/ui/const-generics/mgca/projection-error.rs index edb6db098084..d3bd520297e1 100644 --- a/tests/ui/const-generics/mgca/projection-error.rs +++ b/tests/ui/const-generics/mgca/projection-error.rs @@ -5,10 +5,8 @@ // containing erroneous types normalizes to a const error instead of // a type error. - pub trait Tr { - #[type_const] - const SIZE: usize; + type const SIZE: usize; } fn mk_array(_x: T) -> [(); >::SIZE] {} diff --git a/tests/ui/const-generics/mgca/projection-error.stderr b/tests/ui/const-generics/mgca/projection-error.stderr index 9357600a5e11..94e6bbcdd87f 100644 --- a/tests/ui/const-generics/mgca/projection-error.stderr +++ b/tests/ui/const-generics/mgca/projection-error.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find type `T` in this scope - --> $DIR/projection-error.rs:14:17 + --> $DIR/projection-error.rs:12:17 | LL | pub trait Tr { | --------------- similarly named trait `Tr` defined here @@ -17,7 +17,7 @@ LL | fn mk_array(_x: T) -> [(); >::SIZE] {} | +++ error[E0425]: cannot find type `T` in this scope - --> $DIR/projection-error.rs:14:29 + --> $DIR/projection-error.rs:12:29 | LL | pub trait Tr { | --------------- similarly named trait `Tr` defined here diff --git a/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs b/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs index a5b3d3d0d5b6..e946441453d8 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs @@ -15,8 +15,7 @@ enum MyEnum { } trait Trait { - #[type_const] - const ASSOC: u32; + type const ASSOC: u32; } fn with_point() -> Point { diff --git a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs index ebbe097c226e..95ee42d93d73 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs @@ -12,8 +12,8 @@ enum MyEnum { Unit, } -#[type_const] -const CONST_ITEM: u32 = 42; + +type const CONST_ITEM: u32 = 42; fn accepts_point() {} fn accepts_enum>() {} diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs index e47052523fa3..5a40c1b14c2d 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs @@ -2,8 +2,8 @@ #![expect(incomplete_features)] trait Trait { - #[type_const] - const ASSOC: usize; + + type const ASSOC: usize; } fn takes_tuple() {} diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs index 3fde431e27e2..4c040bcaa945 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs @@ -4,8 +4,7 @@ #![expect(incomplete_features)] trait Trait { - #[type_const] - const ASSOC: u32; + type const ASSOC: u32; } fn takes_tuple() {} diff --git a/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.rs b/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.rs index 158a7addd10d..e98b1ad4fe37 100644 --- a/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.rs +++ b/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.rs @@ -4,15 +4,13 @@ #![expect(incomplete_features)] trait Tr { - #[type_const] - const SIZE: usize; + type const SIZE: usize; } struct T; impl Tr for T { - #[type_const] - const SIZE: usize; + type const SIZE: usize; //~^ ERROR associated constant in `impl` without body } diff --git a/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.stderr b/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.stderr index 2db677aa0ca6..ba01456ee040 100644 --- a/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.stderr +++ b/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.stderr @@ -1,10 +1,10 @@ error: associated constant in `impl` without body - --> $DIR/type-const-assoc-const-without-body.rs:15:5 + --> $DIR/type-const-assoc-const-without-body.rs:13:5 | -LL | const SIZE: usize; - | ^^^^^^^^^^^^^^^^^- - | | - | help: provide a definition for the constant: `= ;` +LL | type const SIZE: usize; + | ^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/type-const-inherent-assoc-const-without-body.rs b/tests/ui/const-generics/mgca/type-const-inherent-assoc-const-without-body.rs index 85b2327d3351..9fa417637295 100644 --- a/tests/ui/const-generics/mgca/type-const-inherent-assoc-const-without-body.rs +++ b/tests/ui/const-generics/mgca/type-const-inherent-assoc-const-without-body.rs @@ -4,8 +4,7 @@ #![expect(incomplete_features)] impl S { //~ ERROR cannot find type `S` in this scope - #[type_const] - const SIZE: usize; + type const SIZE: usize; //~^ ERROR associated constant in `impl` without body } diff --git a/tests/ui/const-generics/mgca/type-const-inherent-assoc-const-without-body.stderr b/tests/ui/const-generics/mgca/type-const-inherent-assoc-const-without-body.stderr index ac520a4e6946..b1e1edfa70d6 100644 --- a/tests/ui/const-generics/mgca/type-const-inherent-assoc-const-without-body.stderr +++ b/tests/ui/const-generics/mgca/type-const-inherent-assoc-const-without-body.stderr @@ -1,10 +1,10 @@ error: associated constant in `impl` without body - --> $DIR/type-const-inherent-assoc-const-without-body.rs:8:5 + --> $DIR/type-const-inherent-assoc-const-without-body.rs:7:5 | -LL | const SIZE: usize; - | ^^^^^^^^^^^^^^^^^- - | | - | help: provide a definition for the constant: `= ;` +LL | type const SIZE: usize; + | ^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` error[E0425]: cannot find type `S` in this scope --> $DIR/type-const-inherent-assoc-const-without-body.rs:6:6 diff --git a/tests/ui/const-generics/mgca/type-const-used-in-trait.rs b/tests/ui/const-generics/mgca/type-const-used-in-trait.rs index c98c14775a0f..1efc65bd7018 100644 --- a/tests/ui/const-generics/mgca/type-const-used-in-trait.rs +++ b/tests/ui/const-generics/mgca/type-const-used-in-trait.rs @@ -3,8 +3,7 @@ #![feature(min_generic_const_args)] #![expect(incomplete_features)] -#[type_const] -const N: usize = 2; +type const N: usize = 2; trait CollectArray { fn inner_array(&mut self) -> [A; N]; diff --git a/tests/ui/const-generics/mgca/type_const-array-return.rs b/tests/ui/const-generics/mgca/type_const-array-return.rs index 5375e4fded6d..43db35966a45 100644 --- a/tests/ui/const-generics/mgca/type_const-array-return.rs +++ b/tests/ui/const-generics/mgca/type_const-array-return.rs @@ -6,14 +6,12 @@ pub struct A; pub trait Array { - #[type_const] - const LEN: usize; + type const LEN: usize; fn arr() -> [u8; Self::LEN]; } impl Array for A { - #[type_const] - const LEN: usize = 4; + type const LEN: usize = 4; #[allow(unused_braces)] fn arr() -> [u8; const { Self::LEN }] { diff --git a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.gate.stderr b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.gate.stderr index 8a64af285da5..095f42355c77 100644 --- a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.gate.stderr +++ b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.gate.stderr @@ -1,38 +1,38 @@ error: anonymous constants referencing generics are not yet supported - --> $DIR/type_const-generic-param-in-type.rs:9:53 + --> $DIR/type_const-generic-param-in-type.rs:8:58 | -LL | const FOO: [T; 0] = const { [] }; - | ^^^^^^^^^^^^ +LL | type const FOO: [T; 0] = const { [] }; + | ^^^^^^^^^^^^ error: anonymous constants referencing generics are not yet supported - --> $DIR/type_const-generic-param-in-type.rs:14:38 + --> $DIR/type_const-generic-param-in-type.rs:12:43 | -LL | const BAR: [(); N] = const { [] }; - | ^^^^^^^^^^^^ +LL | type const BAR: [(); N] = const { [] }; + | ^^^^^^^^^^^^ error: anonymous constants with lifetimes in their type are not yet supported - --> $DIR/type_const-generic-param-in-type.rs:19:30 + --> $DIR/type_const-generic-param-in-type.rs:16:35 | -LL | const BAZ<'a>: [&'a (); 0] = const { [] }; - | ^^^^^^^^^^^^ +LL | type const BAZ<'a>: [&'a (); 0] = const { [] }; + | ^^^^^^^^^^^^ error: anonymous constants referencing generics are not yet supported - --> $DIR/type_const-generic-param-in-type.rs:39:59 + --> $DIR/type_const-generic-param-in-type.rs:32:64 | -LL | const ASSOC: [T; 0] = const { [] }; - | ^^^^^^^^^^^^ +LL | type const ASSOC: [T; 0] = const { [] }; + | ^^^^^^^^^^^^ error: anonymous constants referencing generics are not yet supported - --> $DIR/type_const-generic-param-in-type.rs:44:50 + --> $DIR/type_const-generic-param-in-type.rs:36:55 | -LL | const ASSOC_CONST: [(); N] = const { [] }; - | ^^^^^^^^^^^^ +LL | type const ASSOC_CONST: [(); N] = const { [] }; + | ^^^^^^^^^^^^ error: anonymous constants with lifetimes in their type are not yet supported - --> $DIR/type_const-generic-param-in-type.rs:49:39 + --> $DIR/type_const-generic-param-in-type.rs:40:44 | -LL | const ASSOC_LT<'a>: [&'a (); 0] = const { [] }; - | ^^^^^^^^^^^^ +LL | type const ASSOC_LT<'a>: [&'a (); 0] = const { [] }; + | ^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr index 14ae276324ad..b18bd678973a 100644 --- a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr +++ b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr @@ -1,56 +1,56 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:9:45 + --> $DIR/type_const-generic-param-in-type.rs:8:50 | -LL | const FOO: [T; 0] = const { [] }; - | ^ the type must not depend on the parameter `T` +LL | type const FOO: [T; 0] = const { [] }; + | ^ the type must not depend on the parameter `T` error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:14:33 + --> $DIR/type_const-generic-param-in-type.rs:12:38 | -LL | const BAR: [(); N] = const { [] }; - | ^ the type must not depend on the parameter `N` +LL | type const BAR: [(); N] = const { [] }; + | ^ the type must not depend on the parameter `N` error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:19:18 + --> $DIR/type_const-generic-param-in-type.rs:16:23 | -LL | const BAZ<'a>: [&'a (); 0] = const { [] }; - | ^^ the type must not depend on the parameter `'a` +LL | type const BAZ<'a>: [&'a (); 0] = const { [] }; + | ^^ the type must not depend on the parameter `'a` error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:25:51 + --> $DIR/type_const-generic-param-in-type.rs:21:56 | -LL | const ASSOC: [T; 0]; - | ^ the type must not depend on the parameter `T` +LL | type const ASSOC: [T; 0]; + | ^ the type must not depend on the parameter `T` error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:29:45 + --> $DIR/type_const-generic-param-in-type.rs:24:50 | -LL | const ASSOC_CONST: [(); N]; - | ^ the type must not depend on the parameter `N` +LL | type const ASSOC_CONST: [(); N]; + | ^ the type must not depend on the parameter `N` error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:33:27 + --> $DIR/type_const-generic-param-in-type.rs:27:32 | -LL | const ASSOC_LT<'a>: [&'a (); 0]; - | ^^ the type must not depend on the parameter `'a` +LL | type const ASSOC_LT<'a>: [&'a (); 0]; + | ^^ the type must not depend on the parameter `'a` error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:39:51 + --> $DIR/type_const-generic-param-in-type.rs:32:56 | -LL | const ASSOC: [T; 0] = const { [] }; - | ^ the type must not depend on the parameter `T` +LL | type const ASSOC: [T; 0] = const { [] }; + | ^ the type must not depend on the parameter `T` error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:44:45 + --> $DIR/type_const-generic-param-in-type.rs:36:50 | -LL | const ASSOC_CONST: [(); N] = const { [] }; - | ^ the type must not depend on the parameter `N` +LL | type const ASSOC_CONST: [(); N] = const { [] }; + | ^ the type must not depend on the parameter `N` error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:49:27 + --> $DIR/type_const-generic-param-in-type.rs:40:32 | -LL | const ASSOC_LT<'a>: [&'a (); 0] = const { [] }; - | ^^ the type must not depend on the parameter `'a` +LL | type const ASSOC_LT<'a>: [&'a (); 0] = const { [] }; + | ^^ the type must not depend on the parameter `'a` error: aborting due to 9 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs index f1a4aba9bcee..72ae464822e4 100644 --- a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs +++ b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs @@ -5,48 +5,39 @@ #![feature(adt_const_params, unsized_const_params, min_generic_const_args, generic_const_items)] #![cfg_attr(gate, feature(generic_const_parameter_types))] -#[type_const] -const FOO: [T; 0] = const { [] }; +type const FOO: [T; 0] = const { [] }; //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters //[gate]~^^ ERROR anonymous constants referencing generics are not yet supported -#[type_const] -const BAR: [(); N] = const { [] }; +type const BAR: [(); N] = const { [] }; //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters //[gate]~^^ ERROR anonymous constants referencing generics are not yet supported -#[type_const] -const BAZ<'a>: [&'a (); 0] = const { [] }; +type const BAZ<'a>: [&'a (); 0] = const { [] }; //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters //[gate]~^^ ERROR anonymous constants with lifetimes in their type are not yet supported trait Tr { - #[type_const] - const ASSOC: [T; 0]; + type const ASSOC: [T; 0]; //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters - #[type_const] - const ASSOC_CONST: [(); N]; + type const ASSOC_CONST: [(); N]; //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters - #[type_const] - const ASSOC_LT<'a>: [&'a (); 0]; + type const ASSOC_LT<'a>: [&'a (); 0]; //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters } impl Tr for () { - #[type_const] - const ASSOC: [T; 0] = const { [] }; + type const ASSOC: [T; 0] = const { [] }; //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters //[gate]~^^ ERROR anonymous constants referencing generics are not yet supported - #[type_const] - const ASSOC_CONST: [(); N] = const { [] }; + type const ASSOC_CONST: [(); N] = const { [] }; //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters //[gate]~^^ ERROR anonymous constants referencing generics are not yet supported - #[type_const] - const ASSOC_LT<'a>: [&'a (); 0] = const { [] }; + type const ASSOC_LT<'a>: [&'a (); 0] = const { [] }; //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters //[gate]~^^ ERROR anonymous constants with lifetimes in their type are not yet supported } diff --git a/tests/ui/const-generics/mgca/type_const-incemental-compile.rs b/tests/ui/const-generics/mgca/type_const-incemental-compile.rs index 60e6968363db..7094d89d5062 100644 --- a/tests/ui/const-generics/mgca/type_const-incemental-compile.rs +++ b/tests/ui/const-generics/mgca/type_const-incemental-compile.rs @@ -6,6 +6,5 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] -#[type_const] -const TYPE_CONST: usize = 0; +type const TYPE_CONST: usize = 0; fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs index b2c734098009..3262e79478bd 100644 --- a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs +++ b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs @@ -4,8 +4,7 @@ struct A; impl A { - #[type_const] - const B = 4; + type const B = 4; //~^ ERROR: missing type for `const` item } diff --git a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr index b44e47cd7e61..77e54ab2f2e9 100644 --- a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr +++ b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr @@ -1,13 +1,13 @@ error: missing type for `const` item - --> $DIR/type_const-inherent-const-omitted-type.rs:8:12 + --> $DIR/type_const-inherent-const-omitted-type.rs:7:17 | -LL | const B = 4; - | ^ +LL | type const B = 4; + | ^ | help: provide a type for the item | -LL | const B: = 4; - | ++++++++ +LL | type const B: = 4; + | ++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs index 8d2eae71d330..460c5d7b2199 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs @@ -1,22 +1,18 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] -#[type_const] -const FREE: u32 = 5_usize; +type const FREE: u32 = 5_usize; //~^ ERROR mismatched types -#[type_const] -const FREE2: isize = FREE; +type const FREE2: isize = FREE; //~^ ERROR the constant `5` is not of type `isize` trait Tr { - #[type_const] - const N: usize; + type const N: usize; } impl Tr for () { - #[type_const] - const N: usize = false; + type const N: usize = false; //~^ ERROR mismatched types } diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr index 4029bb7b6bff..152dd9ec0cca 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr @@ -1,26 +1,26 @@ error: the constant `5` is not of type `isize` - --> $DIR/type_const-mismatched-types.rs:9:1 + --> $DIR/type_const-mismatched-types.rs:7:1 | -LL | const FREE2: isize = FREE; - | ^^^^^^^^^^^^^^^^^^ expected `isize`, found `u32` +LL | type const FREE2: isize = FREE; + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `u32` error[E0308]: mismatched types - --> $DIR/type_const-mismatched-types.rs:5:19 + --> $DIR/type_const-mismatched-types.rs:4:24 | -LL | const FREE: u32 = 5_usize; - | ^^^^^^^ expected `u32`, found `usize` +LL | type const FREE: u32 = 5_usize; + | ^^^^^^^ expected `u32`, found `usize` | help: change the type of the numeric literal from `usize` to `u32` | -LL - const FREE: u32 = 5_usize; -LL + const FREE: u32 = 5_u32; +LL - type const FREE: u32 = 5_usize; +LL + type const FREE: u32 = 5_u32; | error[E0308]: mismatched types - --> $DIR/type_const-mismatched-types.rs:19:22 + --> $DIR/type_const-mismatched-types.rs:15:27 | -LL | const N: usize = false; - | ^^^^^ expected `usize`, found `bool` +LL | type const N: usize = false; + | ^^^^^ expected `usize`, found `bool` error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-not-constparamty.rs b/tests/ui/const-generics/mgca/type_const-not-constparamty.rs index 11db82187b84..b78bb4ca599d 100644 --- a/tests/ui/const-generics/mgca/type_const-not-constparamty.rs +++ b/tests/ui/const-generics/mgca/type_const-not-constparamty.rs @@ -5,21 +5,18 @@ struct S; // FIXME(mgca): need support for ctors without anon const // (we use a const-block to trigger an anon const here) -#[type_const] -const FREE: S = const { S }; +type const FREE: S = const { S }; //~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter trait Tr { - #[type_const] - const N: S; + type const N: S; //~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter } impl Tr for S { // FIXME(mgca): need support for ctors without anon const // (we use a const-block to trigger an anon const here) - #[type_const] - const N: S = const { S }; + type const N: S = const { S }; //~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter } diff --git a/tests/ui/const-generics/mgca/type_const-not-constparamty.stderr b/tests/ui/const-generics/mgca/type_const-not-constparamty.stderr index d07bbde1e62e..2cbb644f2c71 100644 --- a/tests/ui/const-generics/mgca/type_const-not-constparamty.stderr +++ b/tests/ui/const-generics/mgca/type_const-not-constparamty.stderr @@ -1,8 +1,8 @@ error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter - --> $DIR/type_const-not-constparamty.rs:9:13 + --> $DIR/type_const-not-constparamty.rs:8:18 | -LL | const FREE: S = const { S }; - | ^ +LL | type const FREE: S = const { S }; + | ^ | help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct | @@ -11,10 +11,10 @@ LL | struct S; | error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter - --> $DIR/type_const-not-constparamty.rs:22:14 + --> $DIR/type_const-not-constparamty.rs:19:19 | -LL | const N: S = const { S }; - | ^ +LL | type const N: S = const { S }; + | ^ | help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct | @@ -23,10 +23,10 @@ LL | struct S; | error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter - --> $DIR/type_const-not-constparamty.rs:14:14 + --> $DIR/type_const-not-constparamty.rs:12:19 | -LL | const N: S; - | ^ +LL | type const N: S; + | ^ | help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct | diff --git a/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs b/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs index ac4c4fb59419..f4cf3a4c5ce9 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs +++ b/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs @@ -1,11 +1,11 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args, generic_const_items)] -#[type_const] -const FREE1: usize = const { std::mem::size_of::() }; + +type const FREE1: usize = const { std::mem::size_of::() }; //~^ ERROR generic parameters may not be used in const operations -#[type_const] -const FREE2: usize = const { I + 1 }; + +type const FREE2: usize = const { I + 1 }; //~^ ERROR generic parameters may not be used in const operations fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr b/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr index 8d43f2177562..475d2cf312d6 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr +++ b/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr @@ -1,16 +1,16 @@ error: generic parameters may not be used in const operations - --> $DIR/type_const-on-generic-expr.rs:5:53 + --> $DIR/type_const-on-generic-expr.rs:5:58 | -LL | const FREE1: usize = const { std::mem::size_of::() }; - | ^ +LL | type const FREE1: usize = const { std::mem::size_of::() }; + | ^ | = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations - --> $DIR/type_const-on-generic-expr.rs:8:46 + --> $DIR/type_const-on-generic-expr.rs:8:51 | -LL | const FREE2: usize = const { I + 1 }; - | ^ +LL | type const FREE2: usize = const { I + 1 }; + | ^ | = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items diff --git a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.rs b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.rs index 37de4d4a4abb..2a26138d373f 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.rs +++ b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.rs @@ -2,25 +2,19 @@ #![feature(min_generic_const_args, generic_const_items)] pub trait Tr { - #[type_const] - const N1: usize; - #[type_const] - const N2: usize; - #[type_const] - const N3: usize; + type const N1: usize; + type const N2: usize; + type const N3: usize; } pub struct S; impl Tr for S { - #[type_const] - const N1: usize = const { std::mem::size_of::() }; + type const N1: usize = const { std::mem::size_of::() }; //~^ ERROR generic parameters may not be used in const operations - #[type_const] - const N2: usize = const { I + 1 }; + type const N2: usize = const { I + 1 }; //~^ ERROR generic parameters may not be used in const operations - #[type_const] - const N3: usize = const { 2 & X }; + type const N3: usize = const { 2 & X }; //~^ ERROR generic parameters may not be used in const operations } diff --git a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr index 1a6097752e33..e13d6fbcdd82 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr +++ b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr @@ -1,24 +1,24 @@ error: generic parameters may not be used in const operations - --> $DIR/type_const-on-generic_expr-2.rs:17:54 + --> $DIR/type_const-on-generic_expr-2.rs:13:59 | -LL | const N1: usize = const { std::mem::size_of::() }; - | ^ +LL | type const N1: usize = const { std::mem::size_of::() }; + | ^ | = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations - --> $DIR/type_const-on-generic_expr-2.rs:20:47 + --> $DIR/type_const-on-generic_expr-2.rs:15:52 | -LL | const N2: usize = const { I + 1 }; - | ^ +LL | type const N2: usize = const { I + 1 }; + | ^ | = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations - --> $DIR/type_const-on-generic_expr-2.rs:23:35 + --> $DIR/type_const-on-generic_expr-2.rs:17:40 | -LL | const N3: usize = const { 2 & X }; - | ^ +LL | type const N3: usize = const { 2 & X }; + | ^ | = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items diff --git a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs index ab613859aa5c..a7ff9f0ce03f 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs +++ b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs @@ -8,14 +8,13 @@ trait BadTr { struct GoodS; impl BadTr for GoodS { - #[type_const] - const NUM: = 84; + type const NUM: = 84; //~^ ERROR: missing type for `const` item } fn accept_bad_tr>(_x: &T) {} -//~^ ERROR use of trait associated const without `#[type_const]` +//~^ ERROR use of trait associated const not defined as `type const` fn main() { accept_bad_tr::<84, _>(&GoodS); diff --git a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr index 16f312454ed2..11a60246f6a6 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr +++ b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr @@ -1,16 +1,16 @@ error: missing type for `const` item - --> $DIR/type_const-only-in-impl-omitted-type.rs:12:15 + --> $DIR/type_const-only-in-impl-omitted-type.rs:11:20 | -LL | const NUM: = 84; - | ^ help: provide a type for the associated constant: `usize` +LL | type const NUM: = 84; + | ^ help: provide a type for the associated constant: `usize` -error: use of trait associated const without `#[type_const]` - --> $DIR/type_const-only-in-impl-omitted-type.rs:17:43 +error: use of trait associated const not defined as `type const` + --> $DIR/type_const-only-in-impl-omitted-type.rs:16:43 | LL | fn accept_bad_tr>(_x: &T) {} | ^^^^^^^^^^^ | - = note: the declaration in the trait must be marked with `#[type_const]` + = note: the declaration in the trait must begin with `type const` not just `const` alone error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-only-in-impl.rs b/tests/ui/const-generics/mgca/type_const-only-in-impl.rs index 1887f511bd62..e016908b3cc3 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-impl.rs +++ b/tests/ui/const-generics/mgca/type_const-only-in-impl.rs @@ -8,12 +8,11 @@ trait BadTr { struct GoodS; impl BadTr for GoodS { - #[type_const] - const NUM: usize = 84; + type const NUM: usize = 84; } fn accept_bad_tr>(_x: &T) {} -//~^ ERROR use of trait associated const without `#[type_const]` +//~^ ERROR use of trait associated const not defined as `type const` fn main() { accept_bad_tr::<84, _>(&GoodS); diff --git a/tests/ui/const-generics/mgca/type_const-only-in-impl.stderr b/tests/ui/const-generics/mgca/type_const-only-in-impl.stderr index 44632e46fb07..55d5cca6ba69 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-impl.stderr +++ b/tests/ui/const-generics/mgca/type_const-only-in-impl.stderr @@ -1,10 +1,10 @@ -error: use of trait associated const without `#[type_const]` - --> $DIR/type_const-only-in-impl.rs:15:43 +error: use of trait associated const not defined as `type const` + --> $DIR/type_const-only-in-impl.rs:14:43 | LL | fn accept_bad_tr>(_x: &T) {} | ^^^^^^^^^^^ | - = note: the declaration in the trait must be marked with `#[type_const]` + = note: the declaration in the trait must begin with `type const` not just `const` alone error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/type_const-only-in-trait.rs b/tests/ui/const-generics/mgca/type_const-only-in-trait.rs index 2ff38648206a..1def66a1ba68 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-trait.rs +++ b/tests/ui/const-generics/mgca/type_const-only-in-trait.rs @@ -2,15 +2,14 @@ #![feature(min_generic_const_args)] trait GoodTr { - #[type_const] - const NUM: usize; + type const NUM: usize; } struct BadS; impl GoodTr for BadS { const NUM: usize = 42; - //~^ ERROR implementation of `#[type_const]` const must be marked with `#[type_const]` + //~^ ERROR implementation of a `type const` must also be marked as `type const` } fn accept_good_tr>(_x: &T) {} diff --git a/tests/ui/const-generics/mgca/type_const-only-in-trait.stderr b/tests/ui/const-generics/mgca/type_const-only-in-trait.stderr index 29f1b724960a..f98b4d9cbbfd 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-trait.stderr +++ b/tests/ui/const-generics/mgca/type_const-only-in-trait.stderr @@ -1,16 +1,14 @@ -error: implementation of `#[type_const]` const must be marked with `#[type_const]` - --> $DIR/type_const-only-in-trait.rs:12:5 +error: implementation of a `type const` must also be marked as `type const` + --> $DIR/type_const-only-in-trait.rs:11:5 | LL | const NUM: usize = 42; | ^^^^^^^^^^^^^^^^ | -note: trait declaration of const is marked with `#[type_const]` +note: trait declaration of const is marked as `type const` --> $DIR/type_const-only-in-trait.rs:5:5 | -LL | #[type_const] - | ^^^^^^^^^^^^^ -LL | const NUM: usize; - | ^^^^^^^^^^^^^^^^ +LL | type const NUM: usize; + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/type_const-pub.rs b/tests/ui/const-generics/mgca/type_const-pub.rs index f443562394df..70fab75901b9 100644 --- a/tests/ui/const-generics/mgca/type_const-pub.rs +++ b/tests/ui/const-generics/mgca/type_const-pub.rs @@ -5,8 +5,7 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] -#[type_const] -pub const TYPE_CONST : usize = 1; +pub type const TYPE_CONST : usize = 1; fn main() { print!("{}", TYPE_CONST) } diff --git a/tests/ui/const-generics/mgca/type_const-recursive.rs b/tests/ui/const-generics/mgca/type_const-recursive.rs index 15e49f747ed6..ebaab51bbc3b 100644 --- a/tests/ui/const-generics/mgca/type_const-recursive.rs +++ b/tests/ui/const-generics/mgca/type_const-recursive.rs @@ -1,8 +1,8 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] -#[type_const] -const A: u8 = A; + +type const A: u8 = A; //~^ ERROR: overflow normalizing the unevaluated constant `A` [E0275] fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-recursive.stderr b/tests/ui/const-generics/mgca/type_const-recursive.stderr index 947319ec7eda..d21ccb22bc90 100644 --- a/tests/ui/const-generics/mgca/type_const-recursive.stderr +++ b/tests/ui/const-generics/mgca/type_const-recursive.stderr @@ -1,8 +1,8 @@ error[E0275]: overflow normalizing the unevaluated constant `A` --> $DIR/type_const-recursive.rs:5:1 | -LL | const A: u8 = A; - | ^^^^^^^^^^^ +LL | type const A: u8 = A; + | ^^^^^^^^^^^^^^^^ | = note: in case this is a recursive type alias, consider using a struct, enum, or union instead diff --git a/tests/ui/const-generics/mgca/type_const-use.rs b/tests/ui/const-generics/mgca/type_const-use.rs index 04362cd28538..f295bf465e30 100644 --- a/tests/ui/const-generics/mgca/type_const-use.rs +++ b/tests/ui/const-generics/mgca/type_const-use.rs @@ -3,8 +3,7 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] -#[type_const] -const CONST: usize = 1; +type const CONST: usize = 1; fn uses_const() { CONST; diff --git a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs index c01fb47002b2..cf75b45b9ff0 100644 --- a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs +++ b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs @@ -32,9 +32,10 @@ fn generic() { const NON_TYPE_CONST: usize = const { 1 }; -#[type_const] -//~^ ERROR: the `#[type_const]` attribute is an experimental feature -const TYPE_CONST: usize = const { 1 }; + +type const TYPE_CONST: usize = const { 1 }; +//~^ ERROR: `type const` syntax is experimental [E0658] +//~| ERROR: top-level `type const` are unstable [E0658] static STATIC: usize = const { 1 }; diff --git a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr index bbcd9f9897a6..dbcb8c56ac5b 100644 --- a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr +++ b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr @@ -48,16 +48,26 @@ LL | generic::(); = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: the `#[type_const]` attribute is an experimental feature - --> $DIR/unbraced_const_block_const_arg_gated.rs:35:1 +error[E0658]: `type const` syntax is experimental + --> $DIR/unbraced_const_block_const_arg_gated.rs:36:1 | -LL | #[type_const] - | ^^^^^^^^^^^^^ +LL | type const TYPE_CONST: usize = const { 1 }; + | ^^^^^^^^^^ | = note: see issue #132980 for more information = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 6 previous errors +error[E0658]: top-level `type const` are unstable + --> $DIR/unbraced_const_block_const_arg_gated.rs:36:1 + | +LL | type const TYPE_CONST: usize = const { 1 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/mgca/unmarked-free-const.rs b/tests/ui/const-generics/mgca/unmarked-free-const.rs index a517231facb7..d6d9b936d95b 100644 --- a/tests/ui/const-generics/mgca/unmarked-free-const.rs +++ b/tests/ui/const-generics/mgca/unmarked-free-const.rs @@ -7,5 +7,5 @@ const N: usize = 4; fn main() { let x = [(); N]; - //~^ ERROR use of `const` in the type system without `#[type_const]` + //~^ ERROR use of `const` in the type system not defined as `type const` } diff --git a/tests/ui/const-generics/mgca/unmarked-free-const.stderr b/tests/ui/const-generics/mgca/unmarked-free-const.stderr index 052ae39fdf67..76875d8db0ef 100644 --- a/tests/ui/const-generics/mgca/unmarked-free-const.stderr +++ b/tests/ui/const-generics/mgca/unmarked-free-const.stderr @@ -1,14 +1,11 @@ -error: use of `const` in the type system without `#[type_const]` +error: use of `const` in the type system not defined as `type const` --> $DIR/unmarked-free-const.rs:9:18 | +LL | const N: usize = 4; + | - help: add `type` before `const` for `N`: `type` +... LL | let x = [(); N]; | ^ - | -help: add `#[type_const]` attribute to `N` - | -LL + #[type_const] -LL | const N: usize = 4; - | error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs index d290619a04ff..909189ae4875 100644 --- a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs +++ b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs @@ -4,8 +4,8 @@ #![allow(incomplete_features)] trait Trait { - #[type_const] - const ASSOC: u8; + + type const ASSOC: u8; } struct TakesArr; diff --git a/tests/ui/const-generics/ogca/basic-fail.rs b/tests/ui/const-generics/ogca/basic-fail.rs index 87176c7b067e..e3db3dea3735 100644 --- a/tests/ui/const-generics/ogca/basic-fail.rs +++ b/tests/ui/const-generics/ogca/basic-fail.rs @@ -3,17 +3,13 @@ #![feature(opaque_generic_const_args)] #![expect(incomplete_features)] -#[type_const] -const ADD1: usize = const { N + 1 }; +type const ADD1: usize = const { N + 1 }; -#[type_const] -const INC: usize = const { N + 1 }; +type const INC: usize = const { N + 1 }; -#[type_const] -const ONE: usize = ADD1::<0>; +type const ONE: usize = ADD1::<0>; -#[type_const] -const OTHER_ONE: usize = INC::<0>; +type const OTHER_ONE: usize = INC::<0>; // Not definitionally equal. const ARR: [(); ADD1::<0>] = [(); INC::<0>]; diff --git a/tests/ui/const-generics/ogca/basic-fail.stderr b/tests/ui/const-generics/ogca/basic-fail.stderr index 05de01b132c6..ce4e8eb1471c 100644 --- a/tests/ui/const-generics/ogca/basic-fail.stderr +++ b/tests/ui/const-generics/ogca/basic-fail.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/basic-fail.rs:19:30 + --> $DIR/basic-fail.rs:15:30 | LL | const ARR: [(); ADD1::<0>] = [(); INC::<0>]; | ^^^^^^^^^^^^^^ expected an array with a size of const { N + 1 }, found one with a size of const { N + 1 } diff --git a/tests/ui/const-generics/ogca/basic.rs b/tests/ui/const-generics/ogca/basic.rs index c8aec9ee24ce..e736484b5c3c 100644 --- a/tests/ui/const-generics/ogca/basic.rs +++ b/tests/ui/const-generics/ogca/basic.rs @@ -5,17 +5,13 @@ #![feature(opaque_generic_const_args)] #![expect(incomplete_features)] -#[type_const] -const ADD1: usize = const { N + 1 }; +type const ADD1: usize = const { N + 1 }; -#[type_const] -const INC: usize = ADD1::; +type const INC: usize = ADD1::; -#[type_const] -const ONE: usize = ADD1::<0>; +type const ONE: usize = ADD1::<0>; -#[type_const] -const OTHER_ONE: usize = INC::<0>; +type const OTHER_ONE: usize = INC::<0>; const ARR: [(); ADD1::<0>] = [(); INC::<0>]; diff --git a/tests/ui/const-generics/ogca/coherence-ambiguous.rs b/tests/ui/const-generics/ogca/coherence-ambiguous.rs index c8c088b1e8fc..21efe4cfe981 100644 --- a/tests/ui/const-generics/ogca/coherence-ambiguous.rs +++ b/tests/ui/const-generics/ogca/coherence-ambiguous.rs @@ -4,11 +4,9 @@ #![feature(generic_const_items, min_generic_const_args, opaque_generic_const_args)] #![expect(incomplete_features)] -#[type_const] -const FOO: usize = const { N + 1 }; +type const FOO: usize = const { N + 1 }; -#[type_const] -const BAR: usize = const { N + 1 }; +type const BAR: usize = const { N + 1 }; trait Trait {} diff --git a/tests/ui/const-generics/ogca/rhs-but-not-root.rs b/tests/ui/const-generics/ogca/rhs-but-not-root.rs index 4ed136f04ced..2897b16d493f 100644 --- a/tests/ui/const-generics/ogca/rhs-but-not-root.rs +++ b/tests/ui/const-generics/ogca/rhs-but-not-root.rs @@ -4,11 +4,9 @@ #![expect(incomplete_features)] // Anon consts must be the root of the RHS to be OGCA. -#[type_const] -const FOO: usize = ID::; +type const FOO: usize = ID::; //~^ ERROR generic parameters may not be used in const operations -#[type_const] -const ID: usize = N; +type const ID: usize = N; fn main() {} diff --git a/tests/ui/const-generics/ogca/rhs-but-not-root.stderr b/tests/ui/const-generics/ogca/rhs-but-not-root.stderr index f4fdf5fb981b..c720b58b9bde 100644 --- a/tests/ui/const-generics/ogca/rhs-but-not-root.stderr +++ b/tests/ui/const-generics/ogca/rhs-but-not-root.stderr @@ -1,8 +1,8 @@ error: generic parameters may not be used in const operations - --> $DIR/rhs-but-not-root.rs:8:49 + --> $DIR/rhs-but-not-root.rs:7:54 | -LL | const FOO: usize = ID::; - | ^ +LL | type const FOO: usize = ID::; + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/type-relative-path-144547.rs b/tests/ui/const-generics/type-relative-path-144547.rs index b268055e1f7d..e3532fe635c2 100644 --- a/tests/ui/const-generics/type-relative-path-144547.rs +++ b/tests/ui/const-generics/type-relative-path-144547.rs @@ -2,20 +2,21 @@ //@ revisions: min mgca //@[mgca] check-pass - +#![allow(incomplete_features)] +#![feature(mgca_type_const_syntax)] #![cfg_attr(mgca, feature(min_generic_const_args))] -#![cfg_attr(mgca, expect(incomplete_features))] +// FIXME(mgca) syntax is it's own feature flag before +// expansion and is also an incomplete feature. +//#![cfg_attr(mgca, expect(incomplete_features))] trait UnderlyingImpl { type InfoType: LevelInfo; type SupportedArray; } -// FIXME: cfg_attr(..., type_const) is broken (search for sym::type_const in compiler/) trait LevelInfo { #[cfg(mgca)] - #[type_const] - const SUPPORTED_SLOTS: usize; + type const SUPPORTED_SLOTS: usize; #[cfg(not(mgca))] const SUPPORTED_SLOTS: usize; @@ -25,8 +26,7 @@ struct Info; impl LevelInfo for Info { #[cfg(mgca)] - #[type_const] - const SUPPORTED_SLOTS: usize = 1; + type const SUPPORTED_SLOTS: usize = 1; #[cfg(not(mgca))] const SUPPORTED_SLOTS: usize = 1; diff --git a/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.rs b/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.rs new file mode 100644 index 000000000000..eea1c798fd20 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.rs @@ -0,0 +1,17 @@ +type const FOO: u8 = 10; +//~^ ERROR `type const` syntax is experimental [E0658] +//~| ERROR top-level `type const` are unstable [E0658] + +trait Bar { + type const BAR: bool; + //~^ ERROR `type const` syntax is experimental [E0658] + //~| ERROR associated `type const` are unstable [E0658] +} + +impl Bar for bool { + type const BAR: bool = false; + //~^ ERROR `type const` syntax is experimental [E0658] + //~| ERROR associated `type const` are unstable [E0658] +} + +fn main() { } diff --git a/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.stderr b/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.stderr new file mode 100644 index 000000000000..15db8b87d661 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.stderr @@ -0,0 +1,63 @@ +error[E0658]: `type const` syntax is experimental + --> $DIR/feature-gate-mgca-type-const-syntax.rs:1:1 + | +LL | type const FOO: u8 = 10; + | ^^^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `type const` syntax is experimental + --> $DIR/feature-gate-mgca-type-const-syntax.rs:6:5 + | +LL | type const BAR: bool; + | ^^^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `type const` syntax is experimental + --> $DIR/feature-gate-mgca-type-const-syntax.rs:12:5 + | +LL | type const BAR: bool = false; + | ^^^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: top-level `type const` are unstable + --> $DIR/feature-gate-mgca-type-const-syntax.rs:1:1 + | +LL | type const FOO: u8 = 10; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: associated `type const` are unstable + --> $DIR/feature-gate-mgca-type-const-syntax.rs:6:5 + | +LL | type const BAR: bool; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: associated `type const` are unstable + --> $DIR/feature-gate-mgca-type-const-syntax.rs:12:5 + | +LL | type const BAR: bool = false; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs b/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs index 1cf755b2c565..49916736d46e 100644 --- a/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs +++ b/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs @@ -1,7 +1,7 @@ trait Trait { - #[type_const] - //~^ ERROR experimental - const ASSOC: usize; + type const ASSOC: usize; + //~^ ERROR: associated `type const` are unstable [E0658] + //~| ERROR: `type const` syntax is experimental [E0658] } // FIXME(mgca): add suggestion for mgca to this error diff --git a/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr b/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr index af528a3c1b79..05166b4857fb 100644 --- a/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr +++ b/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr @@ -7,16 +7,26 @@ LL | fn foo() -> [u8; ::ASSOC] { = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error[E0658]: the `#[type_const]` attribute is an experimental feature +error[E0658]: `type const` syntax is experimental --> $DIR/feature-gate-min-generic-const-args.rs:2:5 | -LL | #[type_const] - | ^^^^^^^^^^^^^ +LL | type const ASSOC: usize; + | ^^^^^^^^^^ | = note: see issue #132980 for more information = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 2 previous errors +error[E0658]: associated `type const` are unstable + --> $DIR/feature-gate-min-generic-const-args.rs:2:5 + | +LL | type const ASSOC: usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.rs b/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.rs index 0b78911158ba..f18f59cf60bd 100644 --- a/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.rs +++ b/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.rs @@ -1,8 +1,7 @@ #![feature(generic_const_items, min_generic_const_args)] #![expect(incomplete_features)] -#[type_const] -const INC: usize = const { N + 1 }; +type const INC: usize = const { N + 1 }; //~^ ERROR generic parameters may not be used in const operations //~| HELP add `#![feature(opaque_generic_const_args)]` diff --git a/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.stderr b/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.stderr index 1b87443aa3cb..ef771e77f692 100644 --- a/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.stderr +++ b/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.stderr @@ -1,8 +1,8 @@ error: generic parameters may not be used in const operations - --> $DIR/feature-gate-opaque-generic-const-args.rs:5:44 + --> $DIR/feature-gate-opaque-generic-const-args.rs:4:49 | -LL | const INC: usize = const { N + 1 }; - | ^ +LL | type const INC: usize = const { N + 1 }; + | ^ | = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items diff --git a/tests/ui/generic-const-items/assoc-const-bindings.rs b/tests/ui/generic-const-items/assoc-const-bindings.rs index d0301b920e27..2bf4bea16deb 100644 --- a/tests/ui/generic-const-items/assoc-const-bindings.rs +++ b/tests/ui/generic-const-items/assoc-const-bindings.rs @@ -5,19 +5,15 @@ #![allow(incomplete_features)] trait Owner { - #[type_const] - const C: u32; - #[type_const] - const K: u32; + type const C: u32; + type const K: u32; // #[type_const] // const Q: Maybe; } impl Owner for () { - #[type_const] - const C: u32 = N; - #[type_const] - const K: u32 = const { 99 + 1 }; + type const C: u32 = N; + type const K: u32 = const { 99 + 1 }; // FIXME(mgca): re-enable once we properly support ctors and generics on paths // #[type_const] // const Q: Maybe = Maybe::Nothing; diff --git a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs index 518ed6452369..df680f30fed9 100644 --- a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs +++ b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs @@ -8,8 +8,7 @@ pub struct NoPin; impl Pins for NoPin {} pub trait PinA { - #[type_const] - const A: &'static () = const { &() }; + type const A: &'static () = const { &() }; } pub trait Pins {} diff --git a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr index f57fd74ad99d..b719ebe0664f 100644 --- a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr +++ b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Pins<_>` for type `NoPin` - --> $DIR/assoc-const-no-infer-ice-115806.rs:17:1 + --> $DIR/assoc-const-no-infer-ice-115806.rs:16:1 | LL | impl Pins for NoPin {} | --------------------------- first implementation here diff --git a/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs b/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs index 50530e4f0db0..6bd995449fc6 100644 --- a/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs +++ b/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs @@ -8,8 +8,7 @@ #![expect(incomplete_features)] trait Trait { - #[type_const] - const N: usize = 0; + type const N: usize = 0; fn process(&self, _: [u8; Self::N]) {} } diff --git a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs index 538b0c2b1d46..578a46c67400 100644 --- a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs +++ b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs @@ -5,12 +5,11 @@ //~| WARN the feature `min_generic_const_args` is incomplete pub trait IsVoid { - #[type_const] - const IS_VOID: bool; + + type const IS_VOID: bool; } impl IsVoid for T { - #[type_const] - default const IS_VOID: bool = false; + default type const IS_VOID: bool = false; } pub trait NotVoid {} diff --git a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr index 6159c2ed331a..9361f7d6222f 100644 --- a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr +++ b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr @@ -17,7 +17,7 @@ LL | #![feature(min_generic_const_args, specialization)] = help: consider using `min_specialization` instead, which is more stable and complete error[E0119]: conflicting implementations of trait `Maybe<()>` for type `()` - --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:21:1 + --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:20:1 | LL | impl Maybe for T {} | ---------------------- first implementation here From 9bf9a12381bfab41c5d7c7a1d3f5c1457064575d Mon Sep 17 00:00:00 2001 From: Keith-Cancel Date: Thu, 5 Feb 2026 22:01:57 -0800 Subject: [PATCH 761/978] Allow provisional mgca syntax of type const = to be reconized. Revert, but without type const. Update symbol for feature err, then update suggestion output, and lastly update tests that change because of those. Update these new tests with the correct syntax, and few existing tests with the new outputs the merge with main added. Fix for tidyfmt and some errors when manually resolving a merge conflicts. Update these tests to use update error messages and type const syntax. Update comments and error message to use new syntax instead of old type_const attribute. Remove the type_const attribute update some more tests to use the new syntax. Update these test cases. update feature gate test Change gate logic for `mgca_type_const_syntax` to work also if `min_generic_const_args` is enabled. Create a new feature gate that checks for the feature before expansion. Make rustfmt handle the `type const` syntax correctly. Add a convience method to check if a RhsKind is type const. Rename `Const` discriminant to `Body` for `ConstItemRhsKind` Give the `TraitItemKind` flag an enum instead of a simple bool to better describe what the flag is for. Update formatting for these match statements. Update clippy test to use type const syntax. Update test to use type const syntax. update rustfmt to match ast items. Update clippy to match ast and hir items. Few more test cases that used old attribute, instead of 'type const' Update to match the output from the feature gate checks. tidyfmt adjustments. Update the is_type_const, so I can constrain record!(..) in encoder.rs Update conditional compilation test. Move the feature gate to after expansion to allow for cfg(...) to work. Update some more tests to use the new syntax. Update type const tests in associated-const-bindings to use new syntax. Don't check based off the attribute, but the item here. Update some tests outside of the const_generics folder that were using #[type_const] update the tests in associated consts that use #[type_const] to use type const Update these mgca tests with the type const syntax. Add a flag to TraitItemKind for detecting type const for now. Maybe later change ItemConstRhs to have optional consts but that touches a lot more lines of code. Don't need into for these now that it's a query. Add is_type_const query to handle foreign def ids. update this test to use type const syntax. Fix logic here, we only want to lower if there is expression in this case. Update built-in macros to use ConstItemRhsKind Update more instance of the old ConstItemRhs. Rename ConstItemKind to ConstItemRhsKind, I noticed there is a typed called ConstantItemKind, so add the Rhs to the name to avoid confusion. Update lower to use ConstItemKind Add an other helper method to check if the rhs kinda has an expr. Update item parse to use ConstItemKind enum. Felt the field name could a be little clear when editing a few other things. Change the ConstItem struct see know if we have a type const or regular const. Make sure this syntax is properly feature gated. --- clippy_lints/src/non_copy_const.rs | 4 +-- clippy_lints/src/types/mod.rs | 2 +- clippy_utils/src/ast_utils/mod.rs | 28 +++++++++++-------- ...duplication_in_bounds_assoc_const_eq.fixed | 4 +-- ...it_duplication_in_bounds_assoc_const_eq.rs | 4 +-- 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index f99748127a8f..e09fc0a76366 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -739,7 +739,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { - if let TraitItemKind::Const(_, ct_rhs_opt) = item.kind + if let TraitItemKind::Const(_, ct_rhs_opt, _) = item.kind && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && match self.is_ty_freeze(cx.tcx, cx.typing_env(), ty) { IsFreeze::No => true, @@ -931,7 +931,7 @@ fn get_const_hir_value<'tcx>( { match tcx.hir_node(tcx.local_def_id_to_hir_id(did)) { Node::ImplItem(item) if let ImplItemKind::Const(.., ct_rhs) = item.kind => (did, ct_rhs), - Node::TraitItem(item) if let TraitItemKind::Const(.., Some(ct_rhs)) = item.kind => (did, ct_rhs), + Node::TraitItem(item) if let TraitItemKind::Const(_, Some(ct_rhs), _) = item.kind => (did, ct_rhs), _ => return None, } }, diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs index 7018146f184b..7d97ce97f487 100644 --- a/clippy_lints/src/types/mod.rs +++ b/clippy_lints/src/types/mod.rs @@ -514,7 +514,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { }; match item.kind { - TraitItemKind::Const(ty, _) | TraitItemKind::Type(_, Some(ty)) => { + TraitItemKind::Const(ty, _, _) | TraitItemKind::Type(_, Some(ty)) => { self.check_ty(cx, ty, context); }, TraitItemKind::Fn(ref sig, trait_method) => { diff --git a/clippy_utils/src/ast_utils/mod.rs b/clippy_utils/src/ast_utils/mod.rs index cf8716398efb..3b043f7565ef 100644 --- a/clippy_utils/src/ast_utils/mod.rs +++ b/clippy_utils/src/ast_utils/mod.rs @@ -355,7 +355,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { ident: li, generics: lg, ty: lt, - rhs: lb, + rhs_kind: lb, define_opaque: _, }), Const(box ConstItem { @@ -363,7 +363,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { ident: ri, generics: rg, ty: rt, - rhs: rb, + rhs_kind: rb, define_opaque: _, }), ) => { @@ -371,7 +371,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { && eq_id(*li, *ri) && eq_generics(lg, rg) && eq_ty(lt, rt) - && both(lb.as_ref(), rb.as_ref(), eq_const_item_rhs) + && both(Some(lb), Some(rb), eq_const_item_rhs) }, ( Fn(box ast::Fn { @@ -615,7 +615,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { ident: li, generics: lg, ty: lt, - rhs: lb, + rhs_kind: lb, define_opaque: _, }), Const(box ConstItem { @@ -623,7 +623,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { ident: ri, generics: rg, ty: rt, - rhs: rb, + rhs_kind: rb, define_opaque: _, }), ) => { @@ -631,7 +631,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { && eq_id(*li, *ri) && eq_generics(lg, rg) && eq_ty(lt, rt) - && both(lb.as_ref(), rb.as_ref(), eq_const_item_rhs) + && both(Some(lb), Some(rb), eq_const_item_rhs) }, ( Fn(box ast::Fn { @@ -791,12 +791,18 @@ pub fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool { eq_expr(&l.value, &r.value) } -pub fn eq_const_item_rhs(l: &ConstItemRhs, r: &ConstItemRhs) -> bool { - use ConstItemRhs::*; +pub fn eq_const_item_rhs(l: &ConstItemRhsKind, r: &ConstItemRhsKind) -> bool { + use ConstItemRhsKind::*; match (l, r) { - (TypeConst(l), TypeConst(r)) => eq_anon_const(l, r), - (Body(l), Body(r)) => eq_expr(l, r), - (TypeConst(..), Body(..)) | (Body(..), TypeConst(..)) => false, + (TypeConst { rhs: Some(l) }, TypeConst { rhs: Some(r) }) => eq_anon_const(l, r), + (TypeConst { rhs: None }, TypeConst { rhs: None }) => true, + (TypeConst { rhs: Some(..) }, TypeConst { rhs: None }) => false, + (TypeConst { rhs: None }, TypeConst { rhs: Some(..) }) => false, + (Body { rhs: Some(l) }, Body { rhs: Some(r) }) => eq_expr(l, r), + (Body { rhs: None }, Body { rhs: None }) => true, + (Body { rhs: None }, Body { rhs: Some(..) }) => false, + (Body { rhs: Some(..) }, Body { rhs: None }) => false, + (TypeConst {..}, Body { .. }) | ( Body { .. }, TypeConst { .. }) => false, } } diff --git a/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed b/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed index f8be3331317c..8d63fc44e7f8 100644 --- a/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed +++ b/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed @@ -3,8 +3,8 @@ #![feature(min_generic_const_args)] trait AssocConstTrait { - #[type_const] - const ASSOC: usize; + + type const ASSOC: usize; } fn assoc_const_args() where diff --git a/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs b/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs index a0d7a653993f..36a83619c0f9 100644 --- a/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs +++ b/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs @@ -3,8 +3,8 @@ #![feature(min_generic_const_args)] trait AssocConstTrait { - #[type_const] - const ASSOC: usize; + + type const ASSOC: usize; } fn assoc_const_args() where From 6546a98d90bf1a95a9d02432bab2d8550d4e980e Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 9 Feb 2026 18:00:54 +0100 Subject: [PATCH 762/978] Update books --- src/doc/book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/book b/src/doc/book index 39aeceaa3aea..05d114287b7d 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 39aeceaa3aeab845bc4517e7a44e48727d3b9dbe +Subproject commit 05d114287b7d6f6c9253d5242540f00fbd6172ab diff --git a/src/doc/nomicon b/src/doc/nomicon index 050c002a360f..b8f254a991b8 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 050c002a360fa45b701ea34feed7a860dc8a41bf +Subproject commit b8f254a991b8b7e8f704527f0d4f343a4697dfa9 diff --git a/src/doc/reference b/src/doc/reference index 990819b86c22..addd0602c819 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 990819b86c22bbf538c0526f0287670f3dc1a67a +Subproject commit addd0602c819b6526b9cc97653b0fadca395528c From 41e0e0690f74685f094d88ae2a0f05379e38873f Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 9 Feb 2026 19:12:13 +0100 Subject: [PATCH 763/978] Move `inline_fluent` to a proc macro --- compiler/rustc_macros/src/diagnostics/inline_fluent.rs | 10 ++++++++++ compiler/rustc_macros/src/diagnostics/mod.rs | 2 ++ compiler/rustc_macros/src/lib.rs | 9 +++++++++ 3 files changed, 21 insertions(+) create mode 100644 compiler/rustc_macros/src/diagnostics/inline_fluent.rs diff --git a/compiler/rustc_macros/src/diagnostics/inline_fluent.rs b/compiler/rustc_macros/src/diagnostics/inline_fluent.rs new file mode 100644 index 000000000000..ab0ed6aa6e0e --- /dev/null +++ b/compiler/rustc_macros/src/diagnostics/inline_fluent.rs @@ -0,0 +1,10 @@ +use syn::{LitStr, parse_macro_input}; + +use crate::diagnostics::message::Message; + +pub(crate) fn inline_fluent(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let inline = parse_macro_input!(input as LitStr); + let message = + Message { attr_span: inline.span(), message_span: inline.span(), value: inline.value() }; + message.diag_message(None).into() +} diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index 09f05ce972f1..d9168939dd48 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -1,11 +1,13 @@ mod diagnostic; mod diagnostic_builder; mod error; +mod inline_fluent; mod message; mod subdiagnostic; mod utils; use diagnostic::{DiagnosticDerive, LintDiagnosticDerive}; +pub(super) use inline_fluent::inline_fluent; use proc_macro2::TokenStream; use subdiagnostic::SubdiagnosticDerive; use synstructure::Structure; diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 8cd6c0264448..3d2111b86881 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -241,6 +241,15 @@ decl_derive!( applicability)] => diagnostics::subdiagnostic_derive ); +/// This macro creates a translatable `DiagMessage` from a fluent format string. +/// It should be used in places where a translatable message is needed, but struct diagnostics are undesired. +/// +/// This macro statically checks that the message is valid Fluent, but not that variables in the Fluent message actually exist. +#[proc_macro] +pub fn inline_fluent(input: TokenStream) -> TokenStream { + diagnostics::inline_fluent(input) +} + decl_derive! { [PrintAttribute] => /// Derives `PrintAttribute` for `AttributeKind`. From 6eb2a8fa9ef2b35d34b021550942cc327fa93b3a Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 9 Feb 2026 19:12:22 +0100 Subject: [PATCH 764/978] Reformat existing error messages --- .../src/const_eval/eval_queries.rs | 6 +- .../src/const_eval/machine.rs | 16 +- compiler/rustc_const_eval/src/errors.rs | 212 +++++++++--------- .../src/interpret/intrinsics.rs | 10 +- .../rustc_const_eval/src/interpret/memory.rs | 56 ++--- compiler/rustc_errors/src/diagnostic_impls.rs | 12 +- compiler/rustc_errors/src/lib.rs | 3 +- compiler/rustc_errors/src/translation.rs | 11 - .../rustc_lint/src/impl_trait_overcaptures.rs | 2 +- compiler/rustc_lint/src/lints.rs | 16 +- compiler/rustc_lint/src/non_fmt_panic.rs | 10 +- compiler/rustc_middle/src/middle/stability.rs | 28 ++- .../src/lint_tail_expr_drop_order.rs | 10 +- compiler/rustc_passes/src/errors.rs | 6 +- .../src/error_reporting/infer/region.rs | 10 +- compiler/rustc_trait_selection/src/errors.rs | 104 +++++---- .../src/errors/note_and_explain.rs | 62 ++--- 17 files changed, 299 insertions(+), 275 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 25da90298791..131e17ac3173 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -471,9 +471,9 @@ fn report_eval_error<'tcx>( span, inline_fluent!( "evaluation of `{$instance}` failed {$num_frames -> - [0] here - *[other] inside this call -}" + [0] here + *[other] inside this call + }" ), ); for frame in frames { diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index da4f97db1c59..8bc515a8b1b5 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -491,10 +491,10 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { Err(err) => throw_ub_custom!( inline_fluent!( "invalid align passed to `{$name}`: {$align} is {$err_kind -> - [not_power_of_two] not a power of 2 - [too_large] too large - *[other] {\"\"} -}" + [not_power_of_two] not a power of 2 + [too_large] too large + *[other] {\"\"} + }" ), name = "const_allocate", err_kind = err.diag_ident(), @@ -521,10 +521,10 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { Err(err) => throw_ub_custom!( inline_fluent!( "invalid align passed to `{$name}`: {$align} is {$err_kind -> - [not_power_of_two] not a power of 2 - [too_large] too large - *[other] {\"\"} -}" + [not_power_of_two] not a power of 2 + [too_large] too large + *[other] {\"\"} + }" ), name = "const_deallocate", err_kind = err.diag_ident(), diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index a673e0cb1efb..cba2c462bf22 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -393,16 +393,17 @@ impl Subdiagnostic for FrameNote { } let msg = diag.eagerly_translate(inline_fluent!( r#"{$times -> - [0] {const_eval_frame_note_inner} - *[other] [... {$times} additional calls {const_eval_frame_note_inner} ...] -} - -const_eval_frame_note_inner = inside {$where_ -> - [closure] closure - [instance] `{$instance}` - *[other] {""} -} -"# + [0] inside {$where_ -> + [closure] closure + [instance] `{$instance}` + *[other] {""} + } + *[other] [... {$times} additional calls inside {$where_ -> + [closure] closure + [instance] `{$instance}` + *[other] {""} + } ...] + }"# )); diag.remove_arg("times"); diag.remove_arg("where_"); @@ -663,89 +664,96 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { InvalidMeta(InvalidMetaKind::SliceTooBig) => "invalid metadata in wide pointer: slice is bigger than largest supported object".into(), InvalidMeta(InvalidMetaKind::TooBig) => "invalid metadata in wide pointer: total size is bigger than largest supported object".into(), UnterminatedCString(_) => "reading a null-terminated string starting at {$pointer} with no null found before end of allocation".into(), - PointerUseAfterFree(_, _) => inline_fluent!("{$operation -> - [MemoryAccess] memory access failed - [InboundsPointerArithmetic] in-bounds pointer arithmetic failed - *[Dereferenceable] pointer not dereferenceable -}: {$alloc_id} has been freed, so this pointer is dangling"), - PointerOutOfBounds { .. } => inline_fluent!("{$operation -> - [MemoryAccess] memory access failed - [InboundsPointerArithmetic] in-bounds pointer arithmetic failed - *[Dereferenceable] pointer not dereferenceable -}: {$operation -> - [MemoryAccess] attempting to access {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - *[Dereferenceable] pointer must {$inbounds_size -> - [0] point to some allocation - [1] be dereferenceable for 1 byte - *[x] be dereferenceable for {$inbounds_size} bytes - } -}, but got {$pointer} which {$ptr_offset_is_neg -> - [true] points to before the beginning of the allocation - *[false] {$inbounds_size_is_neg -> - [false] {$alloc_size_minus_ptr_offset -> - [0] is at or beyond the end of the allocation of size {$alloc_size -> - [1] 1 byte - *[x] {$alloc_size} bytes - } - [1] is only 1 byte from the end of the allocation - *[x] is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation - } - *[true] {$ptr_offset_abs -> - [0] is at the beginning of the allocation - *[other] is only {$ptr_offset_abs} bytes from the beginning of the allocation - } - } -} -"), - DanglingIntPointer { addr: 0, .. } => inline_fluent!("{$operation -> - [MemoryAccess] memory access failed - [InboundsPointerArithmetic] in-bounds pointer arithmetic failed - *[Dereferenceable] pointer not dereferenceable -}: {$operation -> - [MemoryAccess] attempting to access {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - *[Dereferenceable] pointer must {$inbounds_size -> - [0] point to some allocation - [1] be dereferenceable for 1 byte - *[x] be dereferenceable for {$inbounds_size} bytes - } -}, but got null pointer"), - DanglingIntPointer { .. } => inline_fluent!("{$operation -> - [MemoryAccess] memory access failed - [InboundsPointerArithmetic] in-bounds pointer arithmetic failed - *[Dereferenceable] pointer not dereferenceable -}: {$operation -> - [MemoryAccess] attempting to access {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - *[Dereferenceable] pointer must {$inbounds_size -> - [0] point to some allocation - [1] be dereferenceable for 1 byte - *[x] be dereferenceable for {$inbounds_size} bytes - } -}, but got {$pointer} which is a dangling pointer (it has no provenance)"), - AlignmentCheckFailed { .. } => inline_fluent!("{$msg -> - [AccessedPtr] accessing memory - *[other] accessing memory based on pointer -} with alignment {$has}, but alignment {$required} is required"), + PointerUseAfterFree(_, _) => inline_fluent!( + "{$operation -> + [MemoryAccess] memory access failed + [InboundsPointerArithmetic] in-bounds pointer arithmetic failed + *[Dereferenceable] pointer not dereferenceable + }: {$alloc_id} has been freed, so this pointer is dangling" + ), + PointerOutOfBounds { .. } => inline_fluent!( + "{$operation -> + [MemoryAccess] memory access failed + [InboundsPointerArithmetic] in-bounds pointer arithmetic failed + *[Dereferenceable] pointer not dereferenceable + }: {$operation -> + [MemoryAccess] attempting to access {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + *[Dereferenceable] pointer must {$inbounds_size -> + [0] point to some allocation + [1] be dereferenceable for 1 byte + *[x] be dereferenceable for {$inbounds_size} bytes + } + }, but got {$pointer} which {$ptr_offset_is_neg -> + [true] points to before the beginning of the allocation + *[false] {$inbounds_size_is_neg -> + [false] {$alloc_size_minus_ptr_offset -> + [0] is at or beyond the end of the allocation of size {$alloc_size -> + [1] 1 byte + *[x] {$alloc_size} bytes + } + [1] is only 1 byte from the end of the allocation + *[x] is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation + } + *[true] {$ptr_offset_abs -> + [0] is at the beginning of the allocation + *[other] is only {$ptr_offset_abs} bytes from the beginning of the allocation + } + } + }" + ), + DanglingIntPointer { addr: 0, .. } => inline_fluent!( + "{$operation -> + [MemoryAccess] memory access failed + [InboundsPointerArithmetic] in-bounds pointer arithmetic failed + *[Dereferenceable] pointer not dereferenceable + }: {$operation -> + [MemoryAccess] attempting to access {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + *[Dereferenceable] pointer must {$inbounds_size -> + [0] point to some allocation + [1] be dereferenceable for 1 byte + *[x] be dereferenceable for {$inbounds_size} bytes + } + }, but got null pointer"), + DanglingIntPointer { .. } => inline_fluent!( + "{$operation -> + [MemoryAccess] memory access failed + [InboundsPointerArithmetic] in-bounds pointer arithmetic failed + *[Dereferenceable] pointer not dereferenceable + }: {$operation -> + [MemoryAccess] attempting to access {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> + [1] 1 byte + *[x] {$inbounds_size} bytes + } + *[Dereferenceable] pointer must {$inbounds_size -> + [0] point to some allocation + [1] be dereferenceable for 1 byte + *[x] be dereferenceable for {$inbounds_size} bytes + } + }, but got {$pointer} which is a dangling pointer (it has no provenance)"), + AlignmentCheckFailed { .. } => inline_fluent!( + "{$msg -> + [AccessedPtr] accessing memory + *[other] accessing memory based on pointer + } with alignment {$has}, but alignment {$required} is required" + ), WriteToReadOnly(_) => inline_fluent!("writing to {$allocation} which is read-only"), DerefFunctionPointer(_) => inline_fluent!("accessing {$allocation} which contains a function"), DerefVTablePointer(_) => inline_fluent!("accessing {$allocation} which contains a vtable"), @@ -936,9 +944,9 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { NullFnPtr { .. } => { inline_fluent!( "{$front_matter}: encountered a {$maybe -> - [true] maybe-null - *[false] null -} function pointer" + [true] maybe-null + *[false] null + } function pointer" ) } NeverVal => { @@ -1021,17 +1029,17 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { NullPtr { ptr_kind: PointerKind::Box, .. } => { inline_fluent!( "{$front_matter}: encountered a {$maybe -> - [true] maybe-null - *[false] null -} box" + [true] maybe-null + *[false] null + } box" ) } NullPtr { ptr_kind: PointerKind::Ref(_), .. } => { inline_fluent!( "{$front_matter}: encountered a {$maybe -> - [true] maybe-null - *[false] null -} reference" + [true] maybe-null + *[false] null + } reference" ) } DanglingPtrNoProvenance { ptr_kind: PointerKind::Box, .. } => { diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 2ea5e4a25c11..7c49ba79a342 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -461,10 +461,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // a < b if intrinsic_name == sym::ptr_offset_from_unsigned { throw_ub_custom!( - inline_fluent!("`ptr_offset_from_unsigned` called when first pointer has smaller {$is_addr -> - [true] address - *[false] offset -} than second: {$a_offset} < {$b_offset}"), + inline_fluent!( + "`ptr_offset_from_unsigned` called when first pointer has smaller {$is_addr -> + [true] address + *[false] offset + } than second: {$a_offset} < {$b_offset}" + ), a_offset = a_offset, b_offset = b_offset, is_addr = is_addr, diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 28dae2ef3b8b..200155ab010e 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -293,10 +293,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { throw_ub_custom!( inline_fluent!( "{$kind -> - [dealloc] deallocating - [realloc] reallocating - *[other] {\"\"} -} {$ptr} which does not point to the beginning of an object" + [dealloc] deallocating + [realloc] reallocating + *[other] {\"\"} + } {$ptr} which does not point to the beginning of an object" ), ptr = format!("{ptr:?}"), kind = "realloc" @@ -379,10 +379,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { throw_ub_custom!( inline_fluent!( "{$kind -> - [dealloc] deallocating - [realloc] reallocating - *[other] {\"\"} -} {$ptr} which does not point to the beginning of an object" + [dealloc] deallocating + [realloc] reallocating + *[other] {\"\"} + } {$ptr} which does not point to the beginning of an object" ), ptr = format!("{ptr:?}"), kind = "dealloc", @@ -396,11 +396,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { err_ub_custom!( inline_fluent!( "deallocating {$alloc_id}, which is {$kind -> - [fn] a function - [vtable] a vtable - [static_mem] static memory - *[other] {\"\"} -}" + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} + }" ), alloc_id = alloc_id, kind = "fn", @@ -410,11 +410,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { err_ub_custom!( inline_fluent!( "deallocating {$alloc_id}, which is {$kind -> - [fn] a function - [vtable] a vtable - [static_mem] static memory - *[other] {\"\"} -}" + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} + }" ), alloc_id = alloc_id, kind = "vtable", @@ -424,11 +424,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { err_ub_custom!( inline_fluent!( "deallocating {$alloc_id}, which is {$kind -> - [fn] a function - [vtable] a vtable - [static_mem] static memory - *[other] {\"\"} -}" + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} + }" ), alloc_id = alloc_id, kind = "typeid", @@ -438,11 +438,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { err_ub_custom!( inline_fluent!( "deallocating {$alloc_id}, which is {$kind -> - [fn] a function - [vtable] a vtable - [static_mem] static memory - *[other] {\"\"} -}" + [fn] a function + [vtable] a vtable + [static_mem] static memory + *[other] {\"\"} + }" ), alloc_id = alloc_id, kind = "static_mem" diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index c36afc6fc889..ae3e33498ea1 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -60,11 +60,13 @@ impl Diagnostic<'_, G> for TargetDataLayoutErrors<'_> { .with_arg("cause", cause) } TargetDataLayoutErrors::InvalidAlignment { cause, err } => { - Diag::new(dcx, level, inline_fluent!("invalid alignment for `{$cause}` in \"data-layout\": `{$align}` is {$err_kind -> - [not_power_of_two] not a power of 2 - [too_large] too large - *[other] {\"\"} - }")) + Diag::new(dcx, level, inline_fluent!( + "invalid alignment for `{$cause}` in \"data-layout\": `{$align}` is {$err_kind -> + [not_power_of_two] not a power of 2 + [too_large] too large + *[other] {\"\"} + }" + )) .with_arg("cause", cause) .with_arg("err_kind", err.diag_ident()) .with_arg("align", err.align()) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 2e0afb8fc4c2..4eadb8249405 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -63,6 +63,7 @@ pub use rustc_error_messages::{ use rustc_hashes::Hash128; use rustc_lint_defs::LintExpectationId; pub use rustc_lint_defs::{Applicability, listify, pluralize}; +pub use rustc_macros::inline_fluent; use rustc_macros::{Decodable, Encodable}; pub use rustc_span::ErrorGuaranteed; pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker, catch_fatal_errors}; @@ -1562,7 +1563,7 @@ impl DelayedDiagInner { let msg = match self.note.status() { BacktraceStatus::Captured => inline_fluent!( "delayed at {$emitted_at} -{$note}" + {$note}" ), // Avoid the needless newline when no backtrace has been captured, // the display impl should just be a single line. diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index b5de3f87e9f3..c6d30032f1af 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -90,14 +90,3 @@ impl Translator { } } } - -/// This macro creates a translatable `DiagMessage` from a literal string. -/// It should be used in places where a translatable message is needed, but struct diagnostics are undesired. -/// -/// This is a macro because in the future we may want to globally register these messages. -#[macro_export] -macro_rules! inline_fluent { - ($inline: literal) => { - rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed($inline)) - }; -} diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 087403719968..aef0021d0660 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -446,7 +446,7 @@ impl<'a> LintDiagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> { "specifically, {$num_captured -> [one] this lifetime is *[other] these lifetimes are - } in scope but not mentioned in the type's bounds" + } in scope but not mentioned in the type's bounds" ), ) .note(inline_fluent!( diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 0aa5199cffc6..4ec59a3cb98f 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -353,8 +353,10 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { self.label, inline_fluent!("will not be checked at usage sites of the type alias"), ); - diag.note(inline_fluent!("this is a known limitation of the type checker that may be lifted in a future edition. - see issue #112792 for more information")); + diag.note(inline_fluent!( + "this is a known limitation of the type checker that may be lifted in a future edition. + see issue #112792 for more information" + )); if self.enable_feat_help { diag.help(inline_fluent!("add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics")); } @@ -1748,10 +1750,12 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { if doctest { diag.help(inline_fluent!(r#"remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}`"#)); } else { - diag.help(inline_fluent!("remove the `#[macro_export]` or move this `macro_rules!` outside the of the current {$body_kind_descr} {$depth -> - [one] `{$body_name}` - *[other] `{$body_name}` and up {$depth} bodies - }")); + diag.help(inline_fluent!( + "remove the `#[macro_export]` or move this `macro_rules!` outside the of the current {$body_kind_descr} {$depth -> + [one] `{$body_name}` + *[other] `{$body_name}` and up {$depth} bodies + }" + )); } diag.note(inline_fluent!("a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute")); diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index daf62277693a..10a37637400b 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -196,10 +196,12 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc if let Some((open, close, del)) = find_delimiters(cx, span) { lint.arg("already_suggested", suggest_display || suggest_debug); lint.multipart_suggestion( - inline_fluent!("{$already_suggested -> - [true] or use - *[false] use - } std::panic::panic_any instead"), + inline_fluent!( + "{$already_suggested -> + [true] or use + *[false] use + } std::panic::panic_any instead" + ), if del == '(' { vec![(span.until(open), "std::panic::panic_any".into())] } else { diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index fce0158aa511..903ef645207d 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -128,19 +128,25 @@ pub struct Deprecated { impl<'a, G: EmissionGuarantee> rustc_errors::LintDiagnostic<'a, G> for Deprecated { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) { diag.primary_message(match &self.since_kind { - DeprecatedSinceKind::InEffect => inline_fluent!("use of deprecated {$kind} `{$path}`{$has_note -> - [true] : {$note} - *[other] {\"\"} - }"), - DeprecatedSinceKind::InFuture => inline_fluent!("use of {$kind} `{$path}` that will be deprecated in a future Rust version{$has_note -> - [true] : {$note} - *[other] {\"\"} - }"), - DeprecatedSinceKind::InVersion(_) => { - inline_fluent!("use of {$kind} `{$path}` that will be deprecated in future version {$version}{$has_note -> + DeprecatedSinceKind::InEffect => inline_fluent!( + "use of deprecated {$kind} `{$path}`{$has_note -> [true] : {$note} *[other] {\"\"} - }") + }" + ), + DeprecatedSinceKind::InFuture => inline_fluent!( + "use of {$kind} `{$path}` that will be deprecated in a future Rust version{$has_note -> + [true] : {$note} + *[other] {\"\"} + }" + ), + DeprecatedSinceKind::InVersion(_) => { + inline_fluent!( + "use of {$kind} `{$path}` that will be deprecated in future version {$version}{$has_note -> + [true] : {$note} + *[other] {\"\"} + }" + ) } }); diag.arg("kind", self.kind); diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index 789398c58880..448ed78702b7 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -542,10 +542,12 @@ impl Subdiagnostic for LocalLabel<'_> { dtor.add_to_diag(diag); } let msg = - diag.eagerly_translate(inline_fluent!("{$is_dropped_first_edition_2024 -> - [true] up until Edition 2021 `{$name}` is dropped last but will be dropped earlier in Edition 2024 - *[false] `{$name}` will be dropped later as of Edition 2024 - }")); + diag.eagerly_translate(inline_fluent!( + "{$is_dropped_first_edition_2024 -> + [true] up until Edition 2021 `{$name}` is dropped last but will be dropped earlier in Edition 2024 + *[false] `{$name}` will be dropped later as of Edition 2024 + }" + )); diag.span_label(self.span, msg); } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index f420bba9b4e9..8a70302c4c4e 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -684,9 +684,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NoMainErr { // There were some functions named `main` though. Try to give the user a hint. inline_fluent!( "the main function must be defined at the crate level{$has_filename -> - [true] {\" \"}(in `{$filename}`) - *[false] {\"\"} - }" + [true] {\" \"}(in `{$filename}`) + *[false] {\"\"} + }" ) } else if self.has_filename { inline_fluent!("consider adding a `main` function to `{$filename}`") diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index d15fb40dd1cb..c99dde6d45b9 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -252,10 +252,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::RelateParamBound(span, ty, opt_span) => { RegionOriginNote::WithName { span, - msg: inline_fluent!("...so that the type `{$name}` will meet its required lifetime bounds{$continues -> -[true] ... -*[false] {\"\"} -}"), + msg: inline_fluent!( + "...so that the type `{$name}` will meet its required lifetime bounds{$continues -> + [true] ... + *[false] {\"\"} + }" + ), name: &self.ty_to_string(ty), continues: opt_span.is_some(), } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 013e4b522fb5..529a7fcf5f1c 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -102,10 +102,16 @@ pub struct NegativePositiveConflict<'tcx> { impl Diagnostic<'_, G> for NegativePositiveConflict<'_> { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, inline_fluent!("found both positive and negative implementation of trait `{$trait_desc}`{$self_desc -> -[none] {\"\"} -*[default] {\" \"}for type `{$self_desc}` -}:")); + let mut diag = Diag::new( + dcx, + level, + inline_fluent!( + "found both positive and negative implementation of trait `{$trait_desc}`{$self_desc -> + [none] {\"\"} + *[default] {\" \"}for type `{$self_desc}` + }:" + ), + ); diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string()); diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string())); diag.span(self.impl_span); @@ -157,9 +163,9 @@ impl Subdiagnostic for AdjustSignatureBorrow { diag.multipart_suggestion_verbose( inline_fluent!( "consider adjusting the signature so it borrows its {$borrow_len -> -[one] argument -*[other] arguments -}" + [one] argument + *[other] arguments + }" ), to_borrow, Applicability::MaybeIncorrect, @@ -170,9 +176,9 @@ impl Subdiagnostic for AdjustSignatureBorrow { diag.multipart_suggestion_verbose( inline_fluent!( "consider adjusting the signature so it does not borrow its {$remove_borrow_len -> -[one] argument -*[other] arguments -}" + [one] argument + *[other] arguments + }" ), remove_borrow, Applicability::MaybeIncorrect, @@ -505,18 +511,18 @@ impl Subdiagnostic for RegionOriginNote<'_> { span, inline_fluent!( "...so that the {$requirement -> -[method_compat] method type is compatible with trait -[type_compat] associated type is compatible with trait -[const_compat] const is compatible with trait -[expr_assignable] expression is assignable -[if_else_different] `if` and `else` have incompatible types -[no_else] `if` missing an `else` returns `()` -[fn_main_correct_type] `main` function has the correct type -[fn_lang_correct_type] lang item function has the correct type -[intrinsic_correct_type] intrinsic has the correct type -[method_correct_type] method receiver has the correct type -*[other] types are compatible -}" + [method_compat] method type is compatible with trait + [type_compat] associated type is compatible with trait + [const_compat] const is compatible with trait + [expr_assignable] expression is assignable + [if_else_different] `if` and `else` have incompatible types + [no_else] `if` missing an `else` returns `()` + [fn_main_correct_type] `main` function has the correct type + [fn_lang_correct_type] lang item function has the correct type + [intrinsic_correct_type] intrinsic has the correct type + [method_correct_type] method receiver has the correct type + *[other] types are compatible + }" ), ); diag.arg("requirement", requirement); @@ -531,18 +537,18 @@ impl Subdiagnostic for RegionOriginNote<'_> { span, inline_fluent!( "...so that {$requirement -> -[method_compat] method type is compatible with trait -[type_compat] associated type is compatible with trait -[const_compat] const is compatible with trait -[expr_assignable] expression is assignable -[if_else_different] `if` and `else` have incompatible types -[no_else] `if` missing an `else` returns `()` -[fn_main_correct_type] `main` function has the correct type -[fn_lang_correct_type] lang item function has the correct type -[intrinsic_correct_type] intrinsic has the correct type -[method_correct_type] method receiver has the correct type -*[other] types are compatible -}" + [method_compat] method type is compatible with trait + [type_compat] associated type is compatible with trait + [const_compat] const is compatible with trait + [expr_assignable] expression is assignable + [if_else_different] `if` and `else` have incompatible types + [no_else] `if` missing an `else` returns `()` + [fn_main_correct_type] `main` function has the correct type + [fn_lang_correct_type] lang item function has the correct type + [intrinsic_correct_type] intrinsic has the correct type + [method_correct_type] method receiver has the correct type + *[other] types are compatible + }" ), ); diag.arg("requirement", requirement); @@ -578,9 +584,9 @@ impl Subdiagnostic for LifetimeMismatchLabels { span, inline_fluent!( "...but data{$label_var1_exists -> -[true] {\" \"}from `{$label_var1}` -*[false] {\"\"} -} is returned here" + [true] {\" \"}from `{$label_var1}` + *[false] {\"\"} + } is returned here" ), ); diag.arg("label_var1_exists", label_var1.is_some()); @@ -614,12 +620,12 @@ impl Subdiagnostic for LifetimeMismatchLabels { span, inline_fluent!( "...but data{$label_var1_exists -> -[true] {\" \"}from `{$label_var1}` -*[false] {\"\"} -} flows{$label_var2_exists -> -[true] {\" \"}into `{$label_var2}` -*[false] {\"\"} -} here" + [true] {\" \"}from `{$label_var1}` + *[false] {\"\"} + } flows{$label_var2_exists -> + [true] {\" \"}into `{$label_var2}` + *[false] {\"\"} + } here" ), ); diag.arg("label_var1_exists", label_var1.is_some()); @@ -789,12 +795,12 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { diag.multipart_suggestion_verbose( inline_fluent!( "consider {$is_reuse -> -[true] reusing -*[false] introducing -} a named lifetime parameter{$is_impl -> -[true] {\" \"}and update trait if needed -*[false] {\"\"} -}" + [true] reusing + *[false] introducing + } a named lifetime parameter{$is_impl -> + [true] {\" \"}and update trait if needed + *[false] {\"\"} + }" ), visitor.suggestions, Applicability::MaybeIncorrect, diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs index 8e86b8fae157..6a7e1d252806 100644 --- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs @@ -171,37 +171,37 @@ impl Subdiagnostic for RegionExplanation<'_> { let msg = diag.eagerly_translate(inline_fluent!( "{$pref_kind -> -*[should_not_happen] [{$pref_kind}] -[ref_valid_for] ...the reference is valid for -[content_valid_for] ...but the borrowed content is only valid for -[type_obj_valid_for] object type is valid for -[source_pointer_valid_for] source pointer is only valid for -[type_satisfy] type must satisfy -[type_outlive] type must outlive -[lf_param_instantiated_with] lifetime parameter instantiated with -[lf_param_must_outlive] but lifetime parameter must outlive -[lf_instantiated_with] lifetime instantiated with -[lf_must_outlive] but lifetime must outlive -[pointer_valid_for] the pointer is valid for -[data_valid_for] but the referenced data is only valid for -[empty] {\"\"} -}{$pref_kind -> -[empty] {\"\"} -*[other] {\" \"} -}{$desc_kind -> -*[should_not_happen] [{$desc_kind}] -[restatic] the static lifetime -[revar] lifetime {$desc_arg} -[as_defined] the lifetime `{$desc_arg}` as defined here -[as_defined_anon] the anonymous lifetime as defined here -[defined_here] the anonymous lifetime defined here -[defined_here_reg] the lifetime `{$desc_arg}` as defined here -}{$suff_kind -> -*[should_not_happen] [{$suff_kind}] -[empty]{\"\"} -[continues] ... -[req_by_binding] {\" \"}as required by this binding -}" + *[should_not_happen] [{$pref_kind}] + [ref_valid_for] ...the reference is valid for + [content_valid_for] ...but the borrowed content is only valid for + [type_obj_valid_for] object type is valid for + [source_pointer_valid_for] source pointer is only valid for + [type_satisfy] type must satisfy + [type_outlive] type must outlive + [lf_param_instantiated_with] lifetime parameter instantiated with + [lf_param_must_outlive] but lifetime parameter must outlive + [lf_instantiated_with] lifetime instantiated with + [lf_must_outlive] but lifetime must outlive + [pointer_valid_for] the pointer is valid for + [data_valid_for] but the referenced data is only valid for + [empty] {\"\"} + }{$pref_kind -> + [empty] {\"\"} + *[other] {\" \"} + }{$desc_kind -> + *[should_not_happen] [{$desc_kind}] + [restatic] the static lifetime + [revar] lifetime {$desc_arg} + [as_defined] the lifetime `{$desc_arg}` as defined here + [as_defined_anon] the anonymous lifetime as defined here + [defined_here] the anonymous lifetime defined here + [defined_here_reg] the lifetime `{$desc_arg}` as defined here + }{$suff_kind -> + *[should_not_happen] [{$suff_kind}] + [empty]{\"\"} + [continues] ... + [req_by_binding] {\" \"}as required by this binding + }" )); diag.restore_args(); if let Some(span) = self.desc.span { From 61b5382ad8972cf0c218b2eb2ebc88a78b741d03 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 9 Feb 2026 16:16:31 +0100 Subject: [PATCH 765/978] Correctly check if a macro call is actually a macro call in rustdoc highlighter --- src/librustdoc/html/highlight.rs | 39 ++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index f70b350de283..1c162a79c4c4 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -1246,7 +1246,7 @@ impl<'src> Classifier<'src> { LiteralKind::Float { .. } | LiteralKind::Int { .. } => Class::Number, }, TokenKind::GuardedStrPrefix => return no_highlight(sink), - TokenKind::RawIdent if let Some((TokenKind::Bang, _)) = self.peek_non_trivia() => { + TokenKind::RawIdent if self.check_if_macro_call("") => { self.new_macro_span(text, sink, before, file_span); return; } @@ -1268,9 +1268,7 @@ impl<'src> Classifier<'src> { // So if it's not a keyword which can be followed by a value (like `if` or // `return`) and the next non-whitespace token is a `!`, then we consider // it's a macro. - if !NON_MACRO_KEYWORDS.contains(&text) - && matches!(self.peek_non_trivia(), Some((TokenKind::Bang, _))) - { + if !NON_MACRO_KEYWORDS.contains(&text) && self.check_if_macro_call(text) { self.new_macro_span(text, sink, before, file_span); return; } @@ -1278,7 +1276,7 @@ impl<'src> Classifier<'src> { } // If it's not a keyword and the next non whitespace token is a `!`, then // we consider it's a macro. - _ if matches!(self.peek_non_trivia(), Some((TokenKind::Bang, _))) => { + _ if self.check_if_macro_call(text) => { self.new_macro_span(text, sink, before, file_span); return; } @@ -1339,6 +1337,37 @@ impl<'src> Classifier<'src> { self.tokens.stop_peeking(); None } + + fn check_if_macro_call(&mut self, ident: &str) -> bool { + let mut has_bang = false; + let is_macro_rule_ident = ident == "macro_rules"; + + while let Some((kind, _)) = self.tokens.peek_next() { + if let TokenKind::Whitespace + | TokenKind::LineComment { doc_style: None } + | TokenKind::BlockComment { doc_style: None, .. } = kind + { + continue; + } + if !has_bang { + if kind != TokenKind::Bang { + break; + } + has_bang = true; + continue; + } + self.tokens.stop_peeking(); + if is_macro_rule_ident { + return matches!(kind, TokenKind::Ident | TokenKind::RawIdent); + } + return matches!( + kind, + TokenKind::OpenParen | TokenKind::OpenBracket | TokenKind::OpenBrace + ); + } + self.tokens.stop_peeking(); + false + } } fn is_keyword(symbol: Symbol) -> bool { From 31c4ad33cc3c4b56a63657408842af4f628bfa59 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 9 Feb 2026 16:17:09 +0100 Subject: [PATCH 766/978] Add regression test for macro call highlighting --- .../source-code-pages/macro-call.rs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tests/rustdoc-html/source-code-pages/macro-call.rs diff --git a/tests/rustdoc-html/source-code-pages/macro-call.rs b/tests/rustdoc-html/source-code-pages/macro-call.rs new file mode 100644 index 000000000000..df2d22aa9b60 --- /dev/null +++ b/tests/rustdoc-html/source-code-pages/macro-call.rs @@ -0,0 +1,29 @@ +// This is yet another test to ensure that only macro calls are considered as such +// by the rustdoc highlighter. +// This is a regression test for . + +#![crate_name = "foo"] + +//@ has src/foo/macro-call.rs.html +//@ count - '//code/span[@class="macro"]' 2 +//@ has - '//code/span[@class="macro"]' 'panic!' +//@ has - '//code/span[@class="macro"]' 'macro_rules!' + +pub struct Layout; + +impl Layout { + pub fn new() {} +} + +pub fn bar() { + let layout = Layout::new::(); + if layout != Layout::new::() { + panic!(); + } + let macro_rules = 3; + if macro_rules != 3 {} +} + +macro_rules! blob { + () => {} +} From aefb9a9ae261dae8d84b801c9396dd571a75339a Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Mon, 9 Feb 2026 14:07:30 -0500 Subject: [PATCH 767/978] tests: adapt align-offset.rs for InstCombine improvements in LLVM 23 Upstream has improved InstCombine so that it can shrink added constants using known zeroes, which caused a little bit of change in this test. As far as I can tell either output is fine, so we just accept both. --- tests/assembly-llvm/align_offset.rs | 8 ++++---- tests/codegen-llvm/align-offset.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/assembly-llvm/align_offset.rs b/tests/assembly-llvm/align_offset.rs index d9902ce336b0..5663dca30b25 100644 --- a/tests/assembly-llvm/align_offset.rs +++ b/tests/assembly-llvm/align_offset.rs @@ -4,7 +4,7 @@ #![crate_type = "rlib"] // CHECK-LABEL: align_offset_byte_ptr -// CHECK: leaq 31 +// CHECK: leaq {{31|28}} // CHECK: andq $-32 // CHECK: subq #[no_mangle] @@ -13,7 +13,7 @@ pub fn align_offset_byte_ptr(ptr: *const u8) -> usize { } // CHECK-LABEL: align_offset_byte_slice -// CHECK: leaq 31 +// CHECK: leaq {{31|28}} // CHECK: andq $-32 // CHECK: subq #[no_mangle] @@ -22,7 +22,7 @@ pub fn align_offset_byte_slice(slice: &[u8]) -> usize { } // CHECK-LABEL: align_offset_word_ptr -// CHECK: leaq 31 +// CHECK: leaq {{31|28}} // CHECK: andq $-32 // CHECK: subq // CHECK: shrq @@ -35,7 +35,7 @@ pub fn align_offset_word_ptr(ptr: *const u32) -> usize { } // CHECK-LABEL: align_offset_word_slice -// CHECK: leaq 31 +// CHECK: leaq {{31|28}} // CHECK: andq $-32 // CHECK: subq // CHECK: shrq diff --git a/tests/codegen-llvm/align-offset.rs b/tests/codegen-llvm/align-offset.rs index 21062cc0a914..383e9dd45dab 100644 --- a/tests/codegen-llvm/align-offset.rs +++ b/tests/codegen-llvm/align-offset.rs @@ -24,7 +24,7 @@ pub fn align_to4(x: &[u8]) -> bool { #[no_mangle] pub fn align_offset_byte_ptr(ptr: *const u8) -> usize { // CHECK: %[[ADDR:.+]] = ptrtoint ptr %ptr to [[USIZE:i[0-9]+]] - // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], 31 + // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], {{31|28}} // CHECK: %[[ALIGNED:.+]] = and [[USIZE]] %[[UP]], -32 // CHECK: %[[OFFSET:.+]] = sub [[USIZE]] %[[ALIGNED]], %[[ADDR]] @@ -41,7 +41,7 @@ pub fn align_offset_byte_ptr(ptr: *const u8) -> usize { #[no_mangle] pub fn align_offset_word_slice(slice: &[Align4]) -> usize { // CHECK: %[[ADDR:.+]] = ptrtoint ptr %slice.0 to [[USIZE]] - // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], 31 + // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], {{31|28}} // CHECK: %[[ALIGNED:.+]] = and [[USIZE]] %[[UP]], -32 // CHECK: %[[BOFFSET:.+]] = sub [[USIZE]] %[[ALIGNED]], %[[ADDR]] // CHECK: %[[OFFSET:.+]] = lshr exact [[USIZE]] %[[BOFFSET]], 2 @@ -57,7 +57,7 @@ pub fn align_offset_word_slice(slice: &[Align4]) -> usize { #[no_mangle] pub fn align_offset_word_ptr(ptr: *const Align4) -> usize { // CHECK: %[[ADDR:.+]] = ptrtoint ptr %ptr to [[USIZE]] - // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], 31 + // CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], {{31|28}} // CHECK: %[[ALIGNED:.+]] = and [[USIZE]] %[[UP]], -32 // CHECK: %[[BOFFSET:.+]] = sub [[USIZE]] %[[ALIGNED]], %[[ADDR]] From 34ed98677513c81efa3fa7cf5948a810ac4c9e48 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Mon, 9 Feb 2026 16:31:39 -0500 Subject: [PATCH 768/978] improve build docs --- src/doc/rustc-dev-guide/src/offload/internals.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/offload/internals.md b/src/doc/rustc-dev-guide/src/offload/internals.md index 520c48d95896..836fd7ad2670 100644 --- a/src/doc/rustc-dev-guide/src/offload/internals.md +++ b/src/doc/rustc-dev-guide/src/offload/internals.md @@ -8,9 +8,15 @@ also offer more advanced, possibly unsafe, interfaces which allow a higher degre The implementation is based on LLVM's "offload" project, which is already used by OpenMP to run Fortran or C++ code on GPUs. While the project is under development, users will need to call other compilers like clang to finish the compilation process. -## High-level design: +## High-level compilation design: We use a single-source, two-pass compilation approach. First we compile all functions that should be offloaded for the device (e.g nvptx64, amdgcn-amd-amdhsa, intel in the future). Currently we require cumbersome `#cfg(target_os="")` annotations, but we intend to recognize those in the future based on our offload intrinsic. +This first compilation currently does not leverage rustc's internal Query system, so it will always recompile your kernels at the moment. This should be easy to fix, but we prioritize features and runtime performance improvements at the moment. Please reach out if you want to implement it, though! We then compile the code for the host (e.g. x86-64), where most of the offloading logic happens. On the host side, we generate calls to the openmp offload runtime, to inform it about the layout of the types (a simplified version of the autodiff TypeTrees). We also use the type system to figure out whether kernel arguments have to be moved only to the device (e.g. `&[f32;1024]`), from the device, or both (e.g. `&mut [f64]`). We then launch the kernel, after which we inform the runtime to end this environment and move data back (as far as needed). + +The second pass for the host will load the kernel artifacts from the previous compilation. rustc in general may not "guess" or hardcode the build directory layout, and as such it must be told the path to the kernel artifacts in the second invocation. The logic for this could be integrated into cargo, but it also only requires a trivial cargo wrapper, which we could trivially provide via crates.io till we see larger adoption. + +It might seem tempting to think about a single-source, single pass compilation approach. However, a lot of the rustc frontend (e.g. AST) will drop any dead code (e.g. code behind an inactive `cfg`). Getting the frontend to expand and lower code for two targets naively will result in multiple definitions of the same symbol (and other issues). Trying to teach the whole rustc middle and backend to be aware that any symbol now might contain two implementations is a large undertaking, and it is questionable why we should make the whole compiler more complex, if the alternative is a ~5 line cargo wrapper. We still control the full compilation pipeline and have both host and device code available, therefore there shouldn't be a runtime performance difference between the two approaches. + From 90fd76845cc73288f680f0d14d55f511bfe41fac Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 4 Jan 2026 16:52:51 +1100 Subject: [PATCH 769/978] Make it clearer that `check_pat_lit` only handles literal patterns --- compiler/rustc_hir_typeck/src/pat.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index f054145dc7e9..13f87c092352 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -3,6 +3,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant}; use rustc_abi::FieldIdx; use rustc_ast as ast; +use rustc_data_structures::assert_matches; use rustc_data_structures::fx::FxHashMap; use rustc_errors::codes::*; use rustc_errors::{ @@ -24,7 +25,6 @@ use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; -use rustc_span::source_map::Spanned; use rustc_span::{BytePos, DUMMY_SP, Ident, Span, kw, sym}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode}; @@ -611,7 +611,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.write_ty(*hir_id, ty); ty } - PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, &pat_info.top_info), + PatKind::Expr(expr @ PatExpr { kind: PatExprKind::Lit { lit, .. }, .. }) => { + self.check_pat_lit(pat.span, expr, &lit.node, expected, &pat_info.top_info) + } PatKind::Range(lhs, rhs, _) => { self.check_pat_range(pat.span, lhs, rhs, expected, &pat_info.top_info) } @@ -938,23 +940,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_lit( &self, span: Span, - lt: &hir::PatExpr<'tcx>, + expr: &hir::PatExpr<'tcx>, + lit_kind: &ast::LitKind, expected: Ty<'tcx>, ti: &TopInfo<'tcx>, ) -> Ty<'tcx> { + assert_matches!(expr.kind, hir::PatExprKind::Lit { .. }); + // We've already computed the type above (when checking for a non-ref pat), // so avoid computing it again. - let ty = self.node_ty(lt.hir_id); + let ty = self.node_ty(expr.hir_id); // Byte string patterns behave the same way as array patterns // They can denote both statically and dynamically-sized byte arrays. // Additionally, when `deref_patterns` is enabled, byte string literal patterns may have // types `[u8]` or `[u8; N]`, in order to type, e.g., `deref!(b"..."): Vec`. let mut pat_ty = ty; - if let hir::PatExprKind::Lit { - lit: Spanned { node: ast::LitKind::ByteStr(..), .. }, .. - } = lt.kind - { + if matches!(lit_kind, ast::LitKind::ByteStr(..)) { let tcx = self.tcx; let expected = self.structurally_resolve_type(span, expected); match *expected.kind() { @@ -962,7 +964,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Ref(_, inner_ty, _) if self.try_structurally_resolve_type(span, inner_ty).is_slice() => { - trace!(?lt.hir_id.local_id, "polymorphic byte string lit"); + trace!(?expr.hir_id.local_id, "polymorphic byte string lit"); pat_ty = Ty::new_imm_ref( tcx, tcx.lifetimes.re_static, @@ -988,9 +990,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // When `deref_patterns` is enabled, in order to allow `deref!("..."): String`, we allow // string literal patterns to have type `str`. This is accounted for when lowering to MIR. if self.tcx.features().deref_patterns() - && let hir::PatExprKind::Lit { - lit: Spanned { node: ast::LitKind::Str(..), .. }, .. - } = lt.kind + && matches!(lit_kind, ast::LitKind::Str(..)) && self.try_structurally_resolve_type(span, expected).is_str() { pat_ty = self.tcx.types.str_; From 91d47a5c0d82cce04c1e4aef2eacad4f8c9b7e8b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 8 Feb 2026 13:40:20 +1100 Subject: [PATCH 770/978] Don't import `TyCtxt` from `crate::ty::context` --- .../rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs | 3 +-- compiler/rustc_middle/src/ty/inhabitedness/mod.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index d03e593e37b9..c935869b504c 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -2,8 +2,7 @@ use rustc_macros::HashStable; use smallvec::SmallVec; use tracing::instrument; -use crate::ty::context::TyCtxt; -use crate::ty::{self, DefId, OpaqueTypeKey, Ty, TypingEnv}; +use crate::ty::{self, DefId, OpaqueTypeKey, Ty, TyCtxt, TypingEnv}; /// Represents whether some type is inhabited in a given context. /// Examples of uninhabited types are `!`, `enum Void {}`, or a struct diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 7eb74b52b44c..5c4c1733be29 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -47,8 +47,7 @@ use rustc_type_ir::TyKind::*; use tracing::instrument; use crate::query::Providers; -use crate::ty::context::TyCtxt; -use crate::ty::{self, DefId, Ty, TypeVisitableExt, VariantDef, Visibility}; +use crate::ty::{self, DefId, Ty, TyCtxt, TypeVisitableExt, VariantDef, Visibility}; pub mod inhabited_predicate; From 4234d2dd72b38069981a6ba0c4c6befb22d3276b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 8 Feb 2026 13:40:20 +1100 Subject: [PATCH 771/978] Move `impl Interner for TyCtxt` to its own submodule --- compiler/rustc_middle/src/ty/context.rs | 808 +----------------- .../src/ty/context/impl_interner.rs | 804 +++++++++++++++++ 2 files changed, 815 insertions(+), 797 deletions(-) create mode 100644 compiler/rustc_middle/src/ty/context/impl_interner.rs diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1bb83530487d..fbb959ce710d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2,6 +2,7 @@ #![allow(rustc::usage_of_ty_tykind)] +mod impl_interner; pub mod tls; use std::borrow::{Borrow, Cow}; @@ -16,6 +17,7 @@ use std::{fmt, iter, mem}; use rustc_abi::{ExternAbi, FieldIdx, Layout, LayoutData, TargetDataLayout, VariantIdx}; use rustc_ast as ast; +use rustc_data_structures::defer; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::intern::Interned; @@ -27,12 +29,9 @@ use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{ self, DynSend, DynSync, FreezeReadGuard, Lock, RwLock, WorkerLocal, }; -use rustc_data_structures::{debug_assert_matches, defer}; -use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, LintDiagnostic, MultiSpan, -}; +use rustc_errors::{Applicability, Diag, DiagCtxtHandle, LintDiagnostic, MultiSpan}; use rustc_hir::attrs::AttributeKind; -use rustc_hir::def::{CtorKind, CtorOf, DefKind}; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState}; use rustc_hir::intravisit::VisitorExt; @@ -50,16 +49,13 @@ use rustc_session::lint::Lint; use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw}; use rustc_type_ir::TyKind::*; -use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem}; pub use rustc_type_ir::lift::Lift; -use rustc_type_ir::{ - CollectAndApply, Interner, TypeFlags, TypeFoldable, WithCachedTypeInfo, elaborate, search_graph, -}; +use rustc_type_ir::{CollectAndApply, TypeFlags, WithCachedTypeInfo, elaborate, search_graph}; use tracing::{debug, instrument}; use crate::arena::Arena; use crate::dep_graph::{DepGraph, DepKindVTable}; -use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarKind, CanonicalVarKinds}; +use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarKind}; use crate::lint::lint_level; use crate::metadata::ModChild; use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature}; @@ -70,798 +66,16 @@ use crate::query::plumbing::QuerySystem; use crate::query::{IntoQueryParam, LocalCrate, Providers, TyCtxtAt}; use crate::thir::Thir; use crate::traits; -use crate::traits::cache::WithDepNode; -use crate::traits::solve::{ - self, CanonicalInput, ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, - QueryResult, inspect, -}; +use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData, PredefinedOpaques}; use crate::ty::predicate::ExistentialPredicateStableCmpExt as _; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, GenericArg, GenericArgs, - GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, ParamConst, ParamTy, - Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, - PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, - ValTree, ValTreeKind, Visibility, + GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, ParamConst, Pattern, + PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity, + Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, ValTree, ValTreeKind, + Visibility, }; -#[allow(rustc::usage_of_ty_tykind)] -impl<'tcx> Interner for TyCtxt<'tcx> { - fn next_trait_solver_globally(self) -> bool { - self.next_trait_solver_globally() - } - - type DefId = DefId; - type LocalDefId = LocalDefId; - type TraitId = DefId; - type ForeignId = DefId; - type FunctionId = DefId; - type ClosureId = DefId; - type CoroutineClosureId = DefId; - type CoroutineId = DefId; - type AdtId = DefId; - type ImplId = DefId; - type UnevaluatedConstId = DefId; - type Span = Span; - - type GenericArgs = ty::GenericArgsRef<'tcx>; - - type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>]; - type GenericArg = ty::GenericArg<'tcx>; - type Term = ty::Term<'tcx>; - type BoundVarKinds = &'tcx List>; - - type PredefinedOpaques = solve::PredefinedOpaques<'tcx>; - - fn mk_predefined_opaques_in_body( - self, - data: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)], - ) -> Self::PredefinedOpaques { - self.mk_predefined_opaques_in_body(data) - } - type LocalDefIds = &'tcx ty::List; - type CanonicalVarKinds = CanonicalVarKinds<'tcx>; - fn mk_canonical_var_kinds( - self, - kinds: &[ty::CanonicalVarKind], - ) -> Self::CanonicalVarKinds { - self.mk_canonical_var_kinds(kinds) - } - - type ExternalConstraints = ExternalConstraints<'tcx>; - fn mk_external_constraints( - self, - data: ExternalConstraintsData, - ) -> ExternalConstraints<'tcx> { - self.mk_external_constraints(data) - } - type DepNodeIndex = DepNodeIndex; - fn with_cached_task(self, task: impl FnOnce() -> T) -> (T, DepNodeIndex) { - self.dep_graph.with_anon_task(self, crate::dep_graph::dep_kinds::TraitSelect, task) - } - type Ty = Ty<'tcx>; - type Tys = &'tcx List>; - - type FnInputTys = &'tcx [Ty<'tcx>]; - type ParamTy = ParamTy; - type Symbol = Symbol; - - type ErrorGuaranteed = ErrorGuaranteed; - type BoundExistentialPredicates = &'tcx List>; - - type AllocId = crate::mir::interpret::AllocId; - type Pat = Pattern<'tcx>; - type PatList = &'tcx List>; - type Safety = hir::Safety; - type Abi = ExternAbi; - type Const = ty::Const<'tcx>; - - type ParamConst = ty::ParamConst; - type ValueConst = ty::Value<'tcx>; - type ExprConst = ty::Expr<'tcx>; - type ValTree = ty::ValTree<'tcx>; - type ScalarInt = ty::ScalarInt; - - type Region = Region<'tcx>; - type EarlyParamRegion = ty::EarlyParamRegion; - type LateParamRegion = ty::LateParamRegion; - - type RegionAssumptions = &'tcx ty::List>; - - type ParamEnv = ty::ParamEnv<'tcx>; - type Predicate = Predicate<'tcx>; - - type Clause = Clause<'tcx>; - type Clauses = ty::Clauses<'tcx>; - - type Tracked = WithDepNode; - fn mk_tracked( - self, - data: T, - dep_node: DepNodeIndex, - ) -> Self::Tracked { - WithDepNode::new(dep_node, data) - } - fn get_tracked(self, tracked: &Self::Tracked) -> T { - tracked.get(self) - } - - fn with_global_cache(self, f: impl FnOnce(&mut search_graph::GlobalCache) -> R) -> R { - f(&mut *self.new_solver_evaluation_cache.lock()) - } - - fn canonical_param_env_cache_get_or_insert( - self, - param_env: ty::ParamEnv<'tcx>, - f: impl FnOnce() -> ty::CanonicalParamEnvCacheEntry, - from_entry: impl FnOnce(&ty::CanonicalParamEnvCacheEntry) -> R, - ) -> R { - let mut cache = self.new_solver_canonical_param_env_cache.lock(); - let entry = cache.entry(param_env).or_insert_with(f); - from_entry(entry) - } - - fn assert_evaluation_is_concurrent(&self) { - // Turns out, the assumption for this function isn't perfect. - // See trait-system-refactor-initiative#234. - } - - fn expand_abstract_consts>>(self, t: T) -> T { - self.expand_abstract_consts(t) - } - - type GenericsOf = &'tcx ty::Generics; - - fn generics_of(self, def_id: DefId) -> &'tcx ty::Generics { - self.generics_of(def_id) - } - - type VariancesOf = &'tcx [ty::Variance]; - - fn variances_of(self, def_id: DefId) -> Self::VariancesOf { - self.variances_of(def_id) - } - - fn opt_alias_variances( - self, - kind: impl Into, - def_id: DefId, - ) -> Option<&'tcx [ty::Variance]> { - self.opt_alias_variances(kind, def_id) - } - - fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { - self.type_of(def_id) - } - fn type_of_opaque_hir_typeck(self, def_id: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { - self.type_of_opaque_hir_typeck(def_id) - } - fn const_of_item(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Const<'tcx>> { - self.const_of_item(def_id) - } - fn anon_const_kind(self, def_id: DefId) -> ty::AnonConstKind { - self.anon_const_kind(def_id) - } - - type AdtDef = ty::AdtDef<'tcx>; - fn adt_def(self, adt_def_id: DefId) -> Self::AdtDef { - self.adt_def(adt_def_id) - } - - fn alias_ty_kind(self, alias: ty::AliasTy<'tcx>) -> ty::AliasTyKind { - match self.def_kind(alias.def_id) { - DefKind::AssocTy => { - if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id)) - { - ty::Inherent - } else { - ty::Projection - } - } - DefKind::OpaqueTy => ty::Opaque, - DefKind::TyAlias => ty::Free, - kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), - } - } - - fn alias_term_kind(self, alias: ty::AliasTerm<'tcx>) -> ty::AliasTermKind { - match self.def_kind(alias.def_id) { - DefKind::AssocTy => { - if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id)) - { - ty::AliasTermKind::InherentTy - } else { - ty::AliasTermKind::ProjectionTy - } - } - DefKind::AssocConst => { - if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id)) - { - ty::AliasTermKind::InherentConst - } else { - ty::AliasTermKind::ProjectionConst - } - } - DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy, - DefKind::TyAlias => ty::AliasTermKind::FreeTy, - DefKind::Const => ty::AliasTermKind::FreeConst, - DefKind::AnonConst | DefKind::Ctor(_, CtorKind::Const) => { - ty::AliasTermKind::UnevaluatedConst - } - kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), - } - } - - fn trait_ref_and_own_args_for_alias( - self, - def_id: DefId, - args: ty::GenericArgsRef<'tcx>, - ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) { - debug_assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst); - let trait_def_id = self.parent(def_id); - debug_assert_matches!(self.def_kind(trait_def_id), DefKind::Trait); - let trait_ref = ty::TraitRef::from_assoc(self, trait_def_id, args); - (trait_ref, &args[trait_ref.args.len()..]) - } - - fn mk_args(self, args: &[Self::GenericArg]) -> ty::GenericArgsRef<'tcx> { - self.mk_args(args) - } - - fn mk_args_from_iter(self, args: I) -> T::Output - where - I: Iterator, - T: CollectAndApply>, - { - self.mk_args_from_iter(args) - } - - fn check_args_compatible(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> bool { - self.check_args_compatible(def_id, args) - } - - fn debug_assert_args_compatible(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) { - self.debug_assert_args_compatible(def_id, args); - } - - /// Assert that the args from an `ExistentialTraitRef` or `ExistentialProjection` - /// are compatible with the `DefId`. Since we're missing a `Self` type, stick on - /// a dummy self type and forward to `debug_assert_args_compatible`. - fn debug_assert_existential_args_compatible( - self, - def_id: Self::DefId, - args: Self::GenericArgs, - ) { - // FIXME: We could perhaps add a `skip: usize` to `debug_assert_args_compatible` - // to avoid needing to reintern the set of args... - if cfg!(debug_assertions) { - self.debug_assert_args_compatible( - def_id, - self.mk_args_from_iter( - [self.types.trait_object_dummy_self.into()].into_iter().chain(args.iter()), - ), - ); - } - } - - fn mk_type_list_from_iter(self, args: I) -> T::Output - where - I: Iterator, - T: CollectAndApply, &'tcx List>>, - { - self.mk_type_list_from_iter(args) - } - - fn parent(self, def_id: DefId) -> DefId { - self.parent(def_id) - } - - fn recursion_limit(self) -> usize { - self.recursion_limit().0 - } - - type Features = &'tcx rustc_feature::Features; - - fn features(self) -> Self::Features { - self.features() - } - - fn coroutine_hidden_types( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes>>> { - self.coroutine_hidden_types(def_id) - } - - fn fn_sig(self, def_id: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> { - self.fn_sig(def_id) - } - - fn coroutine_movability(self, def_id: DefId) -> rustc_ast::Movability { - self.coroutine_movability(def_id) - } - - fn coroutine_for_closure(self, def_id: DefId) -> DefId { - self.coroutine_for_closure(def_id) - } - - fn generics_require_sized_self(self, def_id: DefId) -> bool { - self.generics_require_sized_self(def_id) - } - - fn item_bounds( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - self.item_bounds(def_id).map_bound(IntoIterator::into_iter) - } - - fn item_self_bounds( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - self.item_self_bounds(def_id).map_bound(IntoIterator::into_iter) - } - - fn item_non_self_bounds( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - self.item_non_self_bounds(def_id).map_bound(IntoIterator::into_iter) - } - - fn predicates_of( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - ty::EarlyBinder::bind( - self.predicates_of(def_id).instantiate_identity(self).predicates.into_iter(), - ) - } - - fn own_predicates_of( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - ty::EarlyBinder::bind( - self.predicates_of(def_id).instantiate_own_identity().map(|(clause, _)| clause), - ) - } - - fn explicit_super_predicates_of( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator, Span)>> { - self.explicit_super_predicates_of(def_id).map_bound(|preds| preds.into_iter().copied()) - } - - fn explicit_implied_predicates_of( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator, Span)>> { - self.explicit_implied_predicates_of(def_id).map_bound(|preds| preds.into_iter().copied()) - } - - fn impl_super_outlives( - self, - impl_def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - self.impl_super_outlives(impl_def_id) - } - - fn impl_is_const(self, def_id: DefId) -> bool { - debug_assert_matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true }); - self.is_conditionally_const(def_id) - } - - fn fn_is_const(self, def_id: DefId) -> bool { - debug_assert_matches!( - self.def_kind(def_id), - DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) - ); - self.is_conditionally_const(def_id) - } - - fn alias_has_const_conditions(self, def_id: DefId) -> bool { - debug_assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::OpaqueTy); - self.is_conditionally_const(def_id) - } - - fn const_conditions( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>>> { - ty::EarlyBinder::bind( - self.const_conditions(def_id).instantiate_identity(self).into_iter().map(|(c, _)| c), - ) - } - - fn explicit_implied_const_bounds( - self, - def_id: DefId, - ) -> ty::EarlyBinder<'tcx, impl IntoIterator>>> { - ty::EarlyBinder::bind( - self.explicit_implied_const_bounds(def_id).iter_identity_copied().map(|(c, _)| c), - ) - } - - fn impl_self_is_guaranteed_unsized(self, impl_def_id: DefId) -> bool { - self.impl_self_is_guaranteed_unsized(impl_def_id) - } - - fn has_target_features(self, def_id: DefId) -> bool { - !self.codegen_fn_attrs(def_id).target_features.is_empty() - } - - fn require_lang_item(self, lang_item: SolverLangItem) -> DefId { - self.require_lang_item(solver_lang_item_to_lang_item(lang_item), DUMMY_SP) - } - - fn require_trait_lang_item(self, lang_item: SolverTraitLangItem) -> DefId { - self.require_lang_item(solver_trait_lang_item_to_lang_item(lang_item), DUMMY_SP) - } - - fn require_adt_lang_item(self, lang_item: SolverAdtLangItem) -> DefId { - self.require_lang_item(solver_adt_lang_item_to_lang_item(lang_item), DUMMY_SP) - } - - fn is_lang_item(self, def_id: DefId, lang_item: SolverLangItem) -> bool { - self.is_lang_item(def_id, solver_lang_item_to_lang_item(lang_item)) - } - - fn is_trait_lang_item(self, def_id: DefId, lang_item: SolverTraitLangItem) -> bool { - self.is_lang_item(def_id, solver_trait_lang_item_to_lang_item(lang_item)) - } - - fn is_adt_lang_item(self, def_id: DefId, lang_item: SolverAdtLangItem) -> bool { - self.is_lang_item(def_id, solver_adt_lang_item_to_lang_item(lang_item)) - } - - fn is_default_trait(self, def_id: DefId) -> bool { - self.is_default_trait(def_id) - } - - fn is_sizedness_trait(self, def_id: DefId) -> bool { - self.is_sizedness_trait(def_id) - } - - fn as_lang_item(self, def_id: DefId) -> Option { - lang_item_to_solver_lang_item(self.lang_items().from_def_id(def_id)?) - } - - fn as_trait_lang_item(self, def_id: DefId) -> Option { - lang_item_to_solver_trait_lang_item(self.lang_items().from_def_id(def_id)?) - } - - fn as_adt_lang_item(self, def_id: DefId) -> Option { - lang_item_to_solver_adt_lang_item(self.lang_items().from_def_id(def_id)?) - } - - fn associated_type_def_ids(self, def_id: DefId) -> impl IntoIterator { - self.associated_items(def_id) - .in_definition_order() - .filter(|assoc_item| assoc_item.is_type()) - .map(|assoc_item| assoc_item.def_id) - } - - // This implementation is a bit different from `TyCtxt::for_each_relevant_impl`, - // since we want to skip over blanket impls for non-rigid aliases, and also we - // only want to consider types that *actually* unify with float/int vars. - fn for_each_relevant_impl( - self, - trait_def_id: DefId, - self_ty: Ty<'tcx>, - mut f: impl FnMut(DefId), - ) { - let tcx = self; - let trait_impls = tcx.trait_impls_of(trait_def_id); - let mut consider_impls_for_simplified_type = |simp| { - if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) { - for &impl_def_id in impls_for_type { - f(impl_def_id); - } - } - }; - - match self_ty.kind() { - ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Adt(_, _) - | ty::Foreign(_) - | ty::Str - | ty::Array(_, _) - | ty::Pat(_, _) - | ty::Slice(_) - | ty::RawPtr(_, _) - | ty::Ref(_, _, _) - | ty::FnDef(_, _) - | ty::FnPtr(..) - | ty::Dynamic(_, _) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Coroutine(_, _) - | ty::Never - | ty::Tuple(_) - | ty::UnsafeBinder(_) => { - if let Some(simp) = ty::fast_reject::simplify_type( - tcx, - self_ty, - ty::fast_reject::TreatParams::AsRigid, - ) { - consider_impls_for_simplified_type(simp); - } - } - - // HACK: For integer and float variables we have to manually look at all impls - // which have some integer or float as a self type. - ty::Infer(ty::IntVar(_)) => { - use ty::IntTy::*; - use ty::UintTy::*; - // This causes a compiler error if any new integer kinds are added. - let (I8 | I16 | I32 | I64 | I128 | Isize): ty::IntTy; - let (U8 | U16 | U32 | U64 | U128 | Usize): ty::UintTy; - let possible_integers = [ - // signed integers - ty::SimplifiedType::Int(I8), - ty::SimplifiedType::Int(I16), - ty::SimplifiedType::Int(I32), - ty::SimplifiedType::Int(I64), - ty::SimplifiedType::Int(I128), - ty::SimplifiedType::Int(Isize), - // unsigned integers - ty::SimplifiedType::Uint(U8), - ty::SimplifiedType::Uint(U16), - ty::SimplifiedType::Uint(U32), - ty::SimplifiedType::Uint(U64), - ty::SimplifiedType::Uint(U128), - ty::SimplifiedType::Uint(Usize), - ]; - for simp in possible_integers { - consider_impls_for_simplified_type(simp); - } - } - - ty::Infer(ty::FloatVar(_)) => { - // This causes a compiler error if any new float kinds are added. - let (ty::FloatTy::F16 | ty::FloatTy::F32 | ty::FloatTy::F64 | ty::FloatTy::F128); - let possible_floats = [ - ty::SimplifiedType::Float(ty::FloatTy::F16), - ty::SimplifiedType::Float(ty::FloatTy::F32), - ty::SimplifiedType::Float(ty::FloatTy::F64), - ty::SimplifiedType::Float(ty::FloatTy::F128), - ]; - - for simp in possible_floats { - consider_impls_for_simplified_type(simp); - } - } - - // The only traits applying to aliases and placeholders are blanket impls. - // - // Impls which apply to an alias after normalization are handled by - // `assemble_candidates_after_normalizing_self_ty`. - ty::Alias(_, _) | ty::Placeholder(..) | ty::Error(_) => (), - - // FIXME: These should ideally not exist as a self type. It would be nice for - // the builtin auto trait impls of coroutines to instead directly recurse - // into the witness. - ty::CoroutineWitness(..) => (), - - // These variants should not exist as a self type. - ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) - | ty::Param(_) - | ty::Bound(_, _) => bug!("unexpected self type: {self_ty}"), - } - - #[allow(rustc::usage_of_type_ir_traits)] - self.for_each_blanket_impl(trait_def_id, f) - } - fn for_each_blanket_impl(self, trait_def_id: DefId, mut f: impl FnMut(DefId)) { - let trait_impls = self.trait_impls_of(trait_def_id); - for &impl_def_id in trait_impls.blanket_impls() { - f(impl_def_id); - } - } - - fn has_item_definition(self, def_id: DefId) -> bool { - self.defaultness(def_id).has_value() - } - - fn impl_specializes(self, impl_def_id: Self::DefId, victim_def_id: Self::DefId) -> bool { - self.specializes((impl_def_id, victim_def_id)) - } - - fn impl_is_default(self, impl_def_id: DefId) -> bool { - self.defaultness(impl_def_id).is_default() - } - - fn impl_trait_ref(self, impl_def_id: DefId) -> ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>> { - self.impl_trait_ref(impl_def_id) - } - - fn impl_polarity(self, impl_def_id: DefId) -> ty::ImplPolarity { - self.impl_polarity(impl_def_id) - } - - fn trait_is_auto(self, trait_def_id: DefId) -> bool { - self.trait_is_auto(trait_def_id) - } - - fn trait_is_coinductive(self, trait_def_id: DefId) -> bool { - self.trait_is_coinductive(trait_def_id) - } - - fn trait_is_alias(self, trait_def_id: DefId) -> bool { - self.trait_is_alias(trait_def_id) - } - - fn trait_is_dyn_compatible(self, trait_def_id: DefId) -> bool { - self.is_dyn_compatible(trait_def_id) - } - - fn trait_is_fundamental(self, def_id: DefId) -> bool { - self.trait_def(def_id).is_fundamental - } - - fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool { - self.trait_def(trait_def_id).safety.is_unsafe() - } - - fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { - self.is_impl_trait_in_trait(def_id) - } - - fn delay_bug(self, msg: impl ToString) -> ErrorGuaranteed { - self.dcx().span_delayed_bug(DUMMY_SP, msg.to_string()) - } - - fn is_general_coroutine(self, coroutine_def_id: DefId) -> bool { - self.is_general_coroutine(coroutine_def_id) - } - - fn coroutine_is_async(self, coroutine_def_id: DefId) -> bool { - self.coroutine_is_async(coroutine_def_id) - } - - fn coroutine_is_gen(self, coroutine_def_id: DefId) -> bool { - self.coroutine_is_gen(coroutine_def_id) - } - - fn coroutine_is_async_gen(self, coroutine_def_id: DefId) -> bool { - self.coroutine_is_async_gen(coroutine_def_id) - } - - type UnsizingParams = &'tcx rustc_index::bit_set::DenseBitSet; - fn unsizing_params_for_adt(self, adt_def_id: DefId) -> Self::UnsizingParams { - self.unsizing_params_for_adt(adt_def_id) - } - - fn anonymize_bound_vars>>( - self, - binder: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { - self.anonymize_bound_vars(binder) - } - - fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::LocalDefIds { - self.opaque_types_defined_by(defining_anchor) - } - - fn opaque_types_and_coroutines_defined_by( - self, - defining_anchor: Self::LocalDefId, - ) -> Self::LocalDefIds { - let coroutines_defined_by = self - .nested_bodies_within(defining_anchor) - .iter() - .filter(|def_id| self.is_coroutine(def_id.to_def_id())); - self.mk_local_def_ids_from_iter( - self.opaque_types_defined_by(defining_anchor).iter().chain(coroutines_defined_by), - ) - } - - type Probe = &'tcx inspect::Probe>; - fn mk_probe(self, probe: inspect::Probe) -> &'tcx inspect::Probe> { - self.arena.alloc(probe) - } - fn evaluate_root_goal_for_proof_tree_raw( - self, - canonical_goal: CanonicalInput<'tcx>, - ) -> (QueryResult<'tcx>, &'tcx inspect::Probe>) { - self.evaluate_root_goal_for_proof_tree_raw(canonical_goal) - } - - fn item_name(self, id: DefId) -> Symbol { - let id = id.into_query_param(); - self.opt_item_name(id).unwrap_or_else(|| { - bug!("item_name: no name for {:?}", self.def_path(id)); - }) - } -} - -macro_rules! bidirectional_lang_item_map { - ( - $solver_ty:ident, $to_solver:ident, $from_solver:ident; - $($name:ident),+ $(,)? - ) => { - fn $from_solver(lang_item: $solver_ty) -> LangItem { - match lang_item { - $($solver_ty::$name => LangItem::$name,)+ - } - } - - fn $to_solver(lang_item: LangItem) -> Option<$solver_ty> { - Some(match lang_item { - $(LangItem::$name => $solver_ty::$name,)+ - _ => return None, - }) - } - } -} - -bidirectional_lang_item_map! { - SolverLangItem, lang_item_to_solver_lang_item, solver_lang_item_to_lang_item; - -// tidy-alphabetical-start - AsyncFnKindUpvars, - AsyncFnOnceOutput, - CallOnceFuture, - CallRefFuture, - CoroutineReturn, - CoroutineYield, - DynMetadata, - FutureOutput, - Metadata, -// tidy-alphabetical-end -} - -bidirectional_lang_item_map! { - SolverAdtLangItem, lang_item_to_solver_adt_lang_item, solver_adt_lang_item_to_lang_item; - -// tidy-alphabetical-start - Option, - Poll, -// tidy-alphabetical-end -} - -bidirectional_lang_item_map! { - SolverTraitLangItem, lang_item_to_solver_trait_lang_item, solver_trait_lang_item_to_lang_item; - -// tidy-alphabetical-start - AsyncFn, - AsyncFnKindHelper, - AsyncFnMut, - AsyncFnOnce, - AsyncFnOnceOutput, - AsyncIterator, - BikeshedGuaranteedNoDrop, - Clone, - Copy, - Coroutine, - Destruct, - DiscriminantKind, - Drop, - Fn, - FnMut, - FnOnce, - FnPtrTrait, - FusedIterator, - Future, - Iterator, - MetaSized, - PointeeSized, - PointeeTrait, - Sized, - TransmuteTrait, - TrivialClone, - Tuple, - Unpin, - Unsize, -// tidy-alphabetical-end -} - impl<'tcx> rustc_type_ir::inherent::DefId> for DefId { fn is_local(self) -> bool { self.is_local() diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs new file mode 100644 index 000000000000..c449f29634e2 --- /dev/null +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -0,0 +1,804 @@ +//! Implementation of [`rustc_type_ir::Interner`] for [`TyCtxt`]. + +use std::fmt; + +use rustc_abi::ExternAbi; +use rustc_data_structures::debug_assert_matches; +use rustc_errors::ErrorGuaranteed; +use rustc_hir::def::{CtorKind, CtorOf, DefKind}; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::lang_items::LangItem; +use rustc_hir::{self as hir}; +use rustc_query_system::dep_graph::DepNodeIndex; +use rustc_span::{DUMMY_SP, Span, Symbol}; +use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverLangItem, SolverTraitLangItem}; +use rustc_type_ir::{CollectAndApply, Interner, TypeFoldable, search_graph}; + +use crate::infer::canonical::CanonicalVarKinds; +use crate::query::IntoQueryParam; +use crate::traits::cache::WithDepNode; +use crate::traits::solve::{ + self, CanonicalInput, ExternalConstraints, ExternalConstraintsData, QueryResult, inspect, +}; +use crate::ty::{ + self, Clause, Const, List, ParamTy, Pattern, PolyExistentialPredicate, Predicate, Region, Ty, + TyCtxt, +}; + +#[allow(rustc::usage_of_ty_tykind)] +impl<'tcx> Interner for TyCtxt<'tcx> { + fn next_trait_solver_globally(self) -> bool { + self.next_trait_solver_globally() + } + + type DefId = DefId; + type LocalDefId = LocalDefId; + type TraitId = DefId; + type ForeignId = DefId; + type FunctionId = DefId; + type ClosureId = DefId; + type CoroutineClosureId = DefId; + type CoroutineId = DefId; + type AdtId = DefId; + type ImplId = DefId; + type UnevaluatedConstId = DefId; + type Span = Span; + + type GenericArgs = ty::GenericArgsRef<'tcx>; + + type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>]; + type GenericArg = ty::GenericArg<'tcx>; + type Term = ty::Term<'tcx>; + type BoundVarKinds = &'tcx List>; + + type PredefinedOpaques = solve::PredefinedOpaques<'tcx>; + + fn mk_predefined_opaques_in_body( + self, + data: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)], + ) -> Self::PredefinedOpaques { + self.mk_predefined_opaques_in_body(data) + } + type LocalDefIds = &'tcx ty::List; + type CanonicalVarKinds = CanonicalVarKinds<'tcx>; + fn mk_canonical_var_kinds( + self, + kinds: &[ty::CanonicalVarKind], + ) -> Self::CanonicalVarKinds { + self.mk_canonical_var_kinds(kinds) + } + + type ExternalConstraints = ExternalConstraints<'tcx>; + fn mk_external_constraints( + self, + data: ExternalConstraintsData, + ) -> ExternalConstraints<'tcx> { + self.mk_external_constraints(data) + } + type DepNodeIndex = DepNodeIndex; + fn with_cached_task(self, task: impl FnOnce() -> T) -> (T, DepNodeIndex) { + self.dep_graph.with_anon_task(self, crate::dep_graph::dep_kinds::TraitSelect, task) + } + type Ty = Ty<'tcx>; + type Tys = &'tcx List>; + + type FnInputTys = &'tcx [Ty<'tcx>]; + type ParamTy = ParamTy; + type Symbol = Symbol; + + type ErrorGuaranteed = ErrorGuaranteed; + type BoundExistentialPredicates = &'tcx List>; + + type AllocId = crate::mir::interpret::AllocId; + type Pat = Pattern<'tcx>; + type PatList = &'tcx List>; + type Safety = hir::Safety; + type Abi = ExternAbi; + type Const = ty::Const<'tcx>; + + type ParamConst = ty::ParamConst; + type ValueConst = ty::Value<'tcx>; + type ExprConst = ty::Expr<'tcx>; + type ValTree = ty::ValTree<'tcx>; + type ScalarInt = ty::ScalarInt; + + type Region = Region<'tcx>; + type EarlyParamRegion = ty::EarlyParamRegion; + type LateParamRegion = ty::LateParamRegion; + + type RegionAssumptions = &'tcx ty::List>; + + type ParamEnv = ty::ParamEnv<'tcx>; + type Predicate = Predicate<'tcx>; + + type Clause = Clause<'tcx>; + type Clauses = ty::Clauses<'tcx>; + + type Tracked = WithDepNode; + fn mk_tracked( + self, + data: T, + dep_node: DepNodeIndex, + ) -> Self::Tracked { + WithDepNode::new(dep_node, data) + } + fn get_tracked(self, tracked: &Self::Tracked) -> T { + tracked.get(self) + } + + fn with_global_cache(self, f: impl FnOnce(&mut search_graph::GlobalCache) -> R) -> R { + f(&mut *self.new_solver_evaluation_cache.lock()) + } + + fn canonical_param_env_cache_get_or_insert( + self, + param_env: ty::ParamEnv<'tcx>, + f: impl FnOnce() -> ty::CanonicalParamEnvCacheEntry, + from_entry: impl FnOnce(&ty::CanonicalParamEnvCacheEntry) -> R, + ) -> R { + let mut cache = self.new_solver_canonical_param_env_cache.lock(); + let entry = cache.entry(param_env).or_insert_with(f); + from_entry(entry) + } + + fn assert_evaluation_is_concurrent(&self) { + // Turns out, the assumption for this function isn't perfect. + // See trait-system-refactor-initiative#234. + } + + fn expand_abstract_consts>>(self, t: T) -> T { + self.expand_abstract_consts(t) + } + + type GenericsOf = &'tcx ty::Generics; + + fn generics_of(self, def_id: DefId) -> &'tcx ty::Generics { + self.generics_of(def_id) + } + + type VariancesOf = &'tcx [ty::Variance]; + + fn variances_of(self, def_id: DefId) -> Self::VariancesOf { + self.variances_of(def_id) + } + + fn opt_alias_variances( + self, + kind: impl Into, + def_id: DefId, + ) -> Option<&'tcx [ty::Variance]> { + self.opt_alias_variances(kind, def_id) + } + + fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { + self.type_of(def_id) + } + fn type_of_opaque_hir_typeck(self, def_id: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { + self.type_of_opaque_hir_typeck(def_id) + } + fn const_of_item(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Const<'tcx>> { + self.const_of_item(def_id) + } + fn anon_const_kind(self, def_id: DefId) -> ty::AnonConstKind { + self.anon_const_kind(def_id) + } + + type AdtDef = ty::AdtDef<'tcx>; + fn adt_def(self, adt_def_id: DefId) -> Self::AdtDef { + self.adt_def(adt_def_id) + } + + fn alias_ty_kind(self, alias: ty::AliasTy<'tcx>) -> ty::AliasTyKind { + match self.def_kind(alias.def_id) { + DefKind::AssocTy => { + if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id)) + { + ty::Inherent + } else { + ty::Projection + } + } + DefKind::OpaqueTy => ty::Opaque, + DefKind::TyAlias => ty::Free, + kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), + } + } + + fn alias_term_kind(self, alias: ty::AliasTerm<'tcx>) -> ty::AliasTermKind { + match self.def_kind(alias.def_id) { + DefKind::AssocTy => { + if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id)) + { + ty::AliasTermKind::InherentTy + } else { + ty::AliasTermKind::ProjectionTy + } + } + DefKind::AssocConst => { + if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id)) + { + ty::AliasTermKind::InherentConst + } else { + ty::AliasTermKind::ProjectionConst + } + } + DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy, + DefKind::TyAlias => ty::AliasTermKind::FreeTy, + DefKind::Const => ty::AliasTermKind::FreeConst, + DefKind::AnonConst | DefKind::Ctor(_, CtorKind::Const) => { + ty::AliasTermKind::UnevaluatedConst + } + kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), + } + } + + fn trait_ref_and_own_args_for_alias( + self, + def_id: DefId, + args: ty::GenericArgsRef<'tcx>, + ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) { + debug_assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst); + let trait_def_id = self.parent(def_id); + debug_assert_matches!(self.def_kind(trait_def_id), DefKind::Trait); + let trait_ref = ty::TraitRef::from_assoc(self, trait_def_id, args); + (trait_ref, &args[trait_ref.args.len()..]) + } + + fn mk_args(self, args: &[Self::GenericArg]) -> ty::GenericArgsRef<'tcx> { + self.mk_args(args) + } + + fn mk_args_from_iter(self, args: I) -> T::Output + where + I: Iterator, + T: CollectAndApply>, + { + self.mk_args_from_iter(args) + } + + fn check_args_compatible(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> bool { + self.check_args_compatible(def_id, args) + } + + fn debug_assert_args_compatible(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) { + self.debug_assert_args_compatible(def_id, args); + } + + /// Assert that the args from an `ExistentialTraitRef` or `ExistentialProjection` + /// are compatible with the `DefId`. Since we're missing a `Self` type, stick on + /// a dummy self type and forward to `debug_assert_args_compatible`. + fn debug_assert_existential_args_compatible( + self, + def_id: Self::DefId, + args: Self::GenericArgs, + ) { + // FIXME: We could perhaps add a `skip: usize` to `debug_assert_args_compatible` + // to avoid needing to reintern the set of args... + if cfg!(debug_assertions) { + self.debug_assert_args_compatible( + def_id, + self.mk_args_from_iter( + [self.types.trait_object_dummy_self.into()].into_iter().chain(args.iter()), + ), + ); + } + } + + fn mk_type_list_from_iter(self, args: I) -> T::Output + where + I: Iterator, + T: CollectAndApply, &'tcx List>>, + { + self.mk_type_list_from_iter(args) + } + + fn parent(self, def_id: DefId) -> DefId { + self.parent(def_id) + } + + fn recursion_limit(self) -> usize { + self.recursion_limit().0 + } + + type Features = &'tcx rustc_feature::Features; + + fn features(self) -> Self::Features { + self.features() + } + + fn coroutine_hidden_types( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes>>> { + self.coroutine_hidden_types(def_id) + } + + fn fn_sig(self, def_id: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> { + self.fn_sig(def_id) + } + + fn coroutine_movability(self, def_id: DefId) -> rustc_ast::Movability { + self.coroutine_movability(def_id) + } + + fn coroutine_for_closure(self, def_id: DefId) -> DefId { + self.coroutine_for_closure(def_id) + } + + fn generics_require_sized_self(self, def_id: DefId) -> bool { + self.generics_require_sized_self(def_id) + } + + fn item_bounds( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + self.item_bounds(def_id).map_bound(IntoIterator::into_iter) + } + + fn item_self_bounds( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + self.item_self_bounds(def_id).map_bound(IntoIterator::into_iter) + } + + fn item_non_self_bounds( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + self.item_non_self_bounds(def_id).map_bound(IntoIterator::into_iter) + } + + fn predicates_of( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + ty::EarlyBinder::bind( + self.predicates_of(def_id).instantiate_identity(self).predicates.into_iter(), + ) + } + + fn own_predicates_of( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + ty::EarlyBinder::bind( + self.predicates_of(def_id).instantiate_own_identity().map(|(clause, _)| clause), + ) + } + + fn explicit_super_predicates_of( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator, Span)>> { + self.explicit_super_predicates_of(def_id).map_bound(|preds| preds.into_iter().copied()) + } + + fn explicit_implied_predicates_of( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator, Span)>> { + self.explicit_implied_predicates_of(def_id).map_bound(|preds| preds.into_iter().copied()) + } + + fn impl_super_outlives( + self, + impl_def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + self.impl_super_outlives(impl_def_id) + } + + fn impl_is_const(self, def_id: DefId) -> bool { + debug_assert_matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true }); + self.is_conditionally_const(def_id) + } + + fn fn_is_const(self, def_id: DefId) -> bool { + debug_assert_matches!( + self.def_kind(def_id), + DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) + ); + self.is_conditionally_const(def_id) + } + + fn alias_has_const_conditions(self, def_id: DefId) -> bool { + debug_assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::OpaqueTy); + self.is_conditionally_const(def_id) + } + + fn const_conditions( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>>> { + ty::EarlyBinder::bind( + self.const_conditions(def_id).instantiate_identity(self).into_iter().map(|(c, _)| c), + ) + } + + fn explicit_implied_const_bounds( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>>> { + ty::EarlyBinder::bind( + self.explicit_implied_const_bounds(def_id).iter_identity_copied().map(|(c, _)| c), + ) + } + + fn impl_self_is_guaranteed_unsized(self, impl_def_id: DefId) -> bool { + self.impl_self_is_guaranteed_unsized(impl_def_id) + } + + fn has_target_features(self, def_id: DefId) -> bool { + !self.codegen_fn_attrs(def_id).target_features.is_empty() + } + + fn require_lang_item(self, lang_item: SolverLangItem) -> DefId { + self.require_lang_item(solver_lang_item_to_lang_item(lang_item), DUMMY_SP) + } + + fn require_trait_lang_item(self, lang_item: SolverTraitLangItem) -> DefId { + self.require_lang_item(solver_trait_lang_item_to_lang_item(lang_item), DUMMY_SP) + } + + fn require_adt_lang_item(self, lang_item: SolverAdtLangItem) -> DefId { + self.require_lang_item(solver_adt_lang_item_to_lang_item(lang_item), DUMMY_SP) + } + + fn is_lang_item(self, def_id: DefId, lang_item: SolverLangItem) -> bool { + self.is_lang_item(def_id, solver_lang_item_to_lang_item(lang_item)) + } + + fn is_trait_lang_item(self, def_id: DefId, lang_item: SolverTraitLangItem) -> bool { + self.is_lang_item(def_id, solver_trait_lang_item_to_lang_item(lang_item)) + } + + fn is_adt_lang_item(self, def_id: DefId, lang_item: SolverAdtLangItem) -> bool { + self.is_lang_item(def_id, solver_adt_lang_item_to_lang_item(lang_item)) + } + + fn is_default_trait(self, def_id: DefId) -> bool { + self.is_default_trait(def_id) + } + + fn is_sizedness_trait(self, def_id: DefId) -> bool { + self.is_sizedness_trait(def_id) + } + + fn as_lang_item(self, def_id: DefId) -> Option { + lang_item_to_solver_lang_item(self.lang_items().from_def_id(def_id)?) + } + + fn as_trait_lang_item(self, def_id: DefId) -> Option { + lang_item_to_solver_trait_lang_item(self.lang_items().from_def_id(def_id)?) + } + + fn as_adt_lang_item(self, def_id: DefId) -> Option { + lang_item_to_solver_adt_lang_item(self.lang_items().from_def_id(def_id)?) + } + + fn associated_type_def_ids(self, def_id: DefId) -> impl IntoIterator { + self.associated_items(def_id) + .in_definition_order() + .filter(|assoc_item| assoc_item.is_type()) + .map(|assoc_item| assoc_item.def_id) + } + + // This implementation is a bit different from `TyCtxt::for_each_relevant_impl`, + // since we want to skip over blanket impls for non-rigid aliases, and also we + // only want to consider types that *actually* unify with float/int vars. + fn for_each_relevant_impl( + self, + trait_def_id: DefId, + self_ty: Ty<'tcx>, + mut f: impl FnMut(DefId), + ) { + let tcx = self; + let trait_impls = tcx.trait_impls_of(trait_def_id); + let mut consider_impls_for_simplified_type = |simp| { + if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) { + for &impl_def_id in impls_for_type { + f(impl_def_id); + } + } + }; + + match self_ty.kind() { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Adt(_, _) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Pat(_, _) + | ty::Slice(_) + | ty::RawPtr(_, _) + | ty::Ref(_, _, _) + | ty::FnDef(_, _) + | ty::FnPtr(..) + | ty::Dynamic(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(_, _) + | ty::Never + | ty::Tuple(_) + | ty::UnsafeBinder(_) => { + if let Some(simp) = ty::fast_reject::simplify_type( + tcx, + self_ty, + ty::fast_reject::TreatParams::AsRigid, + ) { + consider_impls_for_simplified_type(simp); + } + } + + // HACK: For integer and float variables we have to manually look at all impls + // which have some integer or float as a self type. + ty::Infer(ty::IntVar(_)) => { + use ty::IntTy::*; + use ty::UintTy::*; + // This causes a compiler error if any new integer kinds are added. + let (I8 | I16 | I32 | I64 | I128 | Isize): ty::IntTy; + let (U8 | U16 | U32 | U64 | U128 | Usize): ty::UintTy; + let possible_integers = [ + // signed integers + ty::SimplifiedType::Int(I8), + ty::SimplifiedType::Int(I16), + ty::SimplifiedType::Int(I32), + ty::SimplifiedType::Int(I64), + ty::SimplifiedType::Int(I128), + ty::SimplifiedType::Int(Isize), + // unsigned integers + ty::SimplifiedType::Uint(U8), + ty::SimplifiedType::Uint(U16), + ty::SimplifiedType::Uint(U32), + ty::SimplifiedType::Uint(U64), + ty::SimplifiedType::Uint(U128), + ty::SimplifiedType::Uint(Usize), + ]; + for simp in possible_integers { + consider_impls_for_simplified_type(simp); + } + } + + ty::Infer(ty::FloatVar(_)) => { + // This causes a compiler error if any new float kinds are added. + let (ty::FloatTy::F16 | ty::FloatTy::F32 | ty::FloatTy::F64 | ty::FloatTy::F128); + let possible_floats = [ + ty::SimplifiedType::Float(ty::FloatTy::F16), + ty::SimplifiedType::Float(ty::FloatTy::F32), + ty::SimplifiedType::Float(ty::FloatTy::F64), + ty::SimplifiedType::Float(ty::FloatTy::F128), + ]; + + for simp in possible_floats { + consider_impls_for_simplified_type(simp); + } + } + + // The only traits applying to aliases and placeholders are blanket impls. + // + // Impls which apply to an alias after normalization are handled by + // `assemble_candidates_after_normalizing_self_ty`. + ty::Alias(_, _) | ty::Placeholder(..) | ty::Error(_) => (), + + // FIXME: These should ideally not exist as a self type. It would be nice for + // the builtin auto trait impls of coroutines to instead directly recurse + // into the witness. + ty::CoroutineWitness(..) => (), + + // These variants should not exist as a self type. + ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) + | ty::Param(_) + | ty::Bound(_, _) => bug!("unexpected self type: {self_ty}"), + } + + #[allow(rustc::usage_of_type_ir_traits)] + self.for_each_blanket_impl(trait_def_id, f) + } + fn for_each_blanket_impl(self, trait_def_id: DefId, mut f: impl FnMut(DefId)) { + let trait_impls = self.trait_impls_of(trait_def_id); + for &impl_def_id in trait_impls.blanket_impls() { + f(impl_def_id); + } + } + + fn has_item_definition(self, def_id: DefId) -> bool { + self.defaultness(def_id).has_value() + } + + fn impl_specializes(self, impl_def_id: Self::DefId, victim_def_id: Self::DefId) -> bool { + self.specializes((impl_def_id, victim_def_id)) + } + + fn impl_is_default(self, impl_def_id: DefId) -> bool { + self.defaultness(impl_def_id).is_default() + } + + fn impl_trait_ref(self, impl_def_id: DefId) -> ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>> { + self.impl_trait_ref(impl_def_id) + } + + fn impl_polarity(self, impl_def_id: DefId) -> ty::ImplPolarity { + self.impl_polarity(impl_def_id) + } + + fn trait_is_auto(self, trait_def_id: DefId) -> bool { + self.trait_is_auto(trait_def_id) + } + + fn trait_is_coinductive(self, trait_def_id: DefId) -> bool { + self.trait_is_coinductive(trait_def_id) + } + + fn trait_is_alias(self, trait_def_id: DefId) -> bool { + self.trait_is_alias(trait_def_id) + } + + fn trait_is_dyn_compatible(self, trait_def_id: DefId) -> bool { + self.is_dyn_compatible(trait_def_id) + } + + fn trait_is_fundamental(self, def_id: DefId) -> bool { + self.trait_def(def_id).is_fundamental + } + + fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool { + self.trait_def(trait_def_id).safety.is_unsafe() + } + + fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { + self.is_impl_trait_in_trait(def_id) + } + + fn delay_bug(self, msg: impl ToString) -> ErrorGuaranteed { + self.dcx().span_delayed_bug(DUMMY_SP, msg.to_string()) + } + + fn is_general_coroutine(self, coroutine_def_id: DefId) -> bool { + self.is_general_coroutine(coroutine_def_id) + } + + fn coroutine_is_async(self, coroutine_def_id: DefId) -> bool { + self.coroutine_is_async(coroutine_def_id) + } + + fn coroutine_is_gen(self, coroutine_def_id: DefId) -> bool { + self.coroutine_is_gen(coroutine_def_id) + } + + fn coroutine_is_async_gen(self, coroutine_def_id: DefId) -> bool { + self.coroutine_is_async_gen(coroutine_def_id) + } + + type UnsizingParams = &'tcx rustc_index::bit_set::DenseBitSet; + fn unsizing_params_for_adt(self, adt_def_id: DefId) -> Self::UnsizingParams { + self.unsizing_params_for_adt(adt_def_id) + } + + fn anonymize_bound_vars>>( + self, + binder: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { + self.anonymize_bound_vars(binder) + } + + fn opaque_types_defined_by(self, defining_anchor: LocalDefId) -> Self::LocalDefIds { + self.opaque_types_defined_by(defining_anchor) + } + + fn opaque_types_and_coroutines_defined_by( + self, + defining_anchor: Self::LocalDefId, + ) -> Self::LocalDefIds { + let coroutines_defined_by = self + .nested_bodies_within(defining_anchor) + .iter() + .filter(|def_id| self.is_coroutine(def_id.to_def_id())); + self.mk_local_def_ids_from_iter( + self.opaque_types_defined_by(defining_anchor).iter().chain(coroutines_defined_by), + ) + } + + type Probe = &'tcx inspect::Probe>; + fn mk_probe(self, probe: inspect::Probe) -> &'tcx inspect::Probe> { + self.arena.alloc(probe) + } + fn evaluate_root_goal_for_proof_tree_raw( + self, + canonical_goal: CanonicalInput<'tcx>, + ) -> (QueryResult<'tcx>, &'tcx inspect::Probe>) { + self.evaluate_root_goal_for_proof_tree_raw(canonical_goal) + } + + fn item_name(self, id: DefId) -> Symbol { + let id = id.into_query_param(); + self.opt_item_name(id).unwrap_or_else(|| { + bug!("item_name: no name for {:?}", self.def_path(id)); + }) + } +} + +macro_rules! bidirectional_lang_item_map { + ( + $solver_ty:ident, $to_solver:ident, $from_solver:ident; + $($name:ident),+ $(,)? + ) => { + fn $from_solver(lang_item: $solver_ty) -> LangItem { + match lang_item { + $($solver_ty::$name => LangItem::$name,)+ + } + } + + fn $to_solver(lang_item: LangItem) -> Option<$solver_ty> { + Some(match lang_item { + $(LangItem::$name => $solver_ty::$name,)+ + _ => return None, + }) + } + } +} + +bidirectional_lang_item_map! { + SolverLangItem, lang_item_to_solver_lang_item, solver_lang_item_to_lang_item; + +// tidy-alphabetical-start + AsyncFnKindUpvars, + AsyncFnOnceOutput, + CallOnceFuture, + CallRefFuture, + CoroutineReturn, + CoroutineYield, + DynMetadata, + FutureOutput, + Metadata, +// tidy-alphabetical-end +} + +bidirectional_lang_item_map! { + SolverAdtLangItem, lang_item_to_solver_adt_lang_item, solver_adt_lang_item_to_lang_item; + +// tidy-alphabetical-start + Option, + Poll, +// tidy-alphabetical-end +} + +bidirectional_lang_item_map! { + SolverTraitLangItem, lang_item_to_solver_trait_lang_item, solver_trait_lang_item_to_lang_item; + +// tidy-alphabetical-start + AsyncFn, + AsyncFnKindHelper, + AsyncFnMut, + AsyncFnOnce, + AsyncFnOnceOutput, + AsyncIterator, + BikeshedGuaranteedNoDrop, + Clone, + Copy, + Coroutine, + Destruct, + DiscriminantKind, + Drop, + Fn, + FnMut, + FnOnce, + FnPtrTrait, + FusedIterator, + Future, + Iterator, + MetaSized, + PointeeSized, + PointeeTrait, + Sized, + TransmuteTrait, + TrivialClone, + Tuple, + Unpin, + Unsize, +// tidy-alphabetical-end +} From b7bfb768d0f9da6a90c32ad596fd17f57935ae87 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 8 Feb 2026 13:40:20 +1100 Subject: [PATCH 772/978] Indicate that `bidirectional_lang_item_map!` declares functions Requiring `fn` in the macro syntax makes it a little more obvious that the macro declares functions with those names, and makes them easier to grep for. --- compiler/rustc_middle/src/ty/context/impl_interner.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index c449f29634e2..5a15d132048d 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -722,9 +722,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> { } } +/// Defines trivial conversion functions between the main [`LangItem`] enum, +/// and some other lang-item enum that is a subset of it. macro_rules! bidirectional_lang_item_map { ( - $solver_ty:ident, $to_solver:ident, $from_solver:ident; + $solver_ty:ident, fn $to_solver:ident, fn $from_solver:ident; $($name:ident),+ $(,)? ) => { fn $from_solver(lang_item: $solver_ty) -> LangItem { @@ -743,7 +745,7 @@ macro_rules! bidirectional_lang_item_map { } bidirectional_lang_item_map! { - SolverLangItem, lang_item_to_solver_lang_item, solver_lang_item_to_lang_item; + SolverLangItem, fn lang_item_to_solver_lang_item, fn solver_lang_item_to_lang_item; // tidy-alphabetical-start AsyncFnKindUpvars, @@ -759,7 +761,7 @@ bidirectional_lang_item_map! { } bidirectional_lang_item_map! { - SolverAdtLangItem, lang_item_to_solver_adt_lang_item, solver_adt_lang_item_to_lang_item; + SolverAdtLangItem, fn lang_item_to_solver_adt_lang_item, fn solver_adt_lang_item_to_lang_item; // tidy-alphabetical-start Option, @@ -768,7 +770,7 @@ bidirectional_lang_item_map! { } bidirectional_lang_item_map! { - SolverTraitLangItem, lang_item_to_solver_trait_lang_item, solver_trait_lang_item_to_lang_item; + SolverTraitLangItem, fn lang_item_to_solver_trait_lang_item, fn solver_trait_lang_item_to_lang_item; // tidy-alphabetical-start AsyncFn, From e1ed3bf01d602fefe6797fb56b52de5161fe64c4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 10 Feb 2026 12:22:40 +1100 Subject: [PATCH 773/978] Remove out-of-date comment. Keys and values now must be `Copy` due to erasing. --- compiler/rustc_query_system/src/query/caches.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs index eea1c5872290..c1f5e5b67085 100644 --- a/compiler/rustc_query_system/src/query/caches.rs +++ b/compiler/rustc_query_system/src/query/caches.rs @@ -21,9 +21,6 @@ pub trait QueryCacheKey = Hash + Eq + Copy + Debug + for<'a> HashStable Date: Tue, 10 Feb 2026 10:16:56 +1100 Subject: [PATCH 774/978] Derive `Clone` for `QueryLatch`. The derived version is equivalent to the hand-written version. --- compiler/rustc_query_system/src/query/job.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index bf7c480b05dd..c77ae38ba96f 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -181,17 +181,11 @@ struct QueryLatchInfo<'tcx> { waiters: Vec>>, } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct QueryLatch<'tcx> { info: Arc>>, } -impl<'tcx> Clone for QueryLatch<'tcx> { - fn clone(&self) -> Self { - Self { info: Arc::clone(&self.info) } - } -} - impl<'tcx> QueryLatch<'tcx> { fn new() -> Self { QueryLatch { From 4dc82e99efad0d0fbb91218b82394a48fcd0ed87 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 5 Feb 2026 18:21:27 +1100 Subject: [PATCH 775/978] Move the needs-drop check for `arena_cache` queries out of macro code --- compiler/rustc_middle/src/queries.rs | 1 - .../rustc_middle/src/query/arena_cached.rs | 33 +++++++++----- compiler/rustc_middle/src/query/plumbing.rs | 44 ++++++++----------- 3 files changed, 40 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index de2298914438..2fdc44ecd269 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -63,7 +63,6 @@ #![allow(unused_parens)] use std::ffi::OsStr; -use std::mem; use std::path::PathBuf; use std::sync::Arc; diff --git a/compiler/rustc_middle/src/query/arena_cached.rs b/compiler/rustc_middle/src/query/arena_cached.rs index ec6e466ff688..7c7ad1262260 100644 --- a/compiler/rustc_middle/src/query/arena_cached.rs +++ b/compiler/rustc_middle/src/query/arena_cached.rs @@ -1,3 +1,9 @@ +use std::mem; + +use rustc_arena::TypedArena; + +use crate::ty::TyCtxt; + /// Helper trait that allows `arena_cache` queries to return `Option<&T>` /// instead of `&Option`, and avoid allocating `None` in the arena. /// @@ -11,10 +17,11 @@ pub trait ArenaCached<'tcx>: Sized { /// Type that is stored in the arena. type Allocated: 'tcx; - /// Takes a provided value, and allocates it in the arena (if appropriate) - /// with the help of the given `arena_alloc` closure. + /// Takes a provided value, and allocates it in an appropriate arena, + /// unless the particular value doesn't need allocation (e.g. `None`). fn alloc_in_arena( - arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated, + tcx: TyCtxt<'tcx>, + typed_arena: &'tcx TypedArena, value: Self::Provided, ) -> Self; } @@ -23,12 +30,9 @@ impl<'tcx, T> ArenaCached<'tcx> for &'tcx T { type Provided = T; type Allocated = T; - fn alloc_in_arena( - arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated, - value: Self::Provided, - ) -> Self { + fn alloc_in_arena(tcx: TyCtxt<'tcx>, typed_arena: &'tcx TypedArena, value: T) -> Self { // Just allocate in the arena normally. - arena_alloc(value) + do_alloc(tcx, typed_arena, value) } } @@ -38,10 +42,17 @@ impl<'tcx, T> ArenaCached<'tcx> for Option<&'tcx T> { type Allocated = T; fn alloc_in_arena( - arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated, - value: Self::Provided, + tcx: TyCtxt<'tcx>, + typed_arena: &'tcx TypedArena, + value: Option, ) -> Self { // Don't store None in the arena, and wrap the allocated reference in Some. - value.map(arena_alloc) + try { do_alloc(tcx, typed_arena, value?) } } } + +/// Allocates a value in either its dedicated arena, or in the common dropless +/// arena, depending on whether it needs to be dropped. +fn do_alloc<'tcx, T>(tcx: TyCtxt<'tcx>, typed_arena: &'tcx TypedArena, value: T) -> &'tcx T { + if mem::needs_drop::() { typed_arena.alloc(value) } else { tcx.arena.dropless.alloc(value) } +} diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 04a3ceb0918a..b80f096ec993 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -295,36 +295,28 @@ macro_rules! define_callbacks { ($V) ); - /// This function takes `ProvidedValue` and converts it to an erased `Value` by - /// allocating it on an arena if the query has the `arena_cache` modifier. The - /// value is then erased and returned. This will happen when computing the query - /// using a provider or decoding a stored result. + /// This helper function takes a value returned by the query provider + /// (or loaded from disk, or supplied by query feeding), allocates + /// it in an arena if requested by the `arena_cache` modifier, and + /// then returns an erased copy of it. #[inline(always)] pub fn provided_to_erased<'tcx>( - _tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'tcx>, provided_value: ProvidedValue<'tcx>, ) -> Erased> { - // Store the provided value in an arena and get a reference - // to it, for queries with `arena_cache`. - let value: Value<'tcx> = query_if_arena!([$($modifiers)*] - { - use $crate::query::arena_cached::ArenaCached; - - if mem::needs_drop::<<$V as ArenaCached<'tcx>>::Allocated>() { - <$V as ArenaCached>::alloc_in_arena( - |v| _tcx.query_system.arenas.$name.alloc(v), - provided_value, - ) - } else { - <$V as ArenaCached>::alloc_in_arena( - |v| _tcx.arena.dropless.alloc(v), - provided_value, - ) - } - } - // Otherwise, the provided value is the value. - (provided_value) - ); + // For queries with the `arena_cache` modifier, store the + // provided value in an arena and get a reference to it. + let value: Value<'tcx> = query_if_arena!([$($modifiers)*] { + <$V as $crate::query::arena_cached::ArenaCached>::alloc_in_arena( + tcx, + &tcx.query_system.arenas.$name, + provided_value, + ) + } { + // Otherwise, the provided value is the value (and `tcx` is unused). + let _ = tcx; + provided_value + }); erase::erase_val(value) } From b6b6dc0b8260bacc01304c230e53b4328ae4ce23 Mon Sep 17 00:00:00 2001 From: zedddie Date: Thu, 5 Feb 2026 18:54:59 +0100 Subject: [PATCH 776/978] mGCA: add associated const type check in dyn arm --- .../rustc_trait_selection/src/traits/wf.rs | 28 +++++++++++++++++++ .../wf-mismatch-1.rs | 12 ++++++++ .../wf-mismatch-2.rs | 12 ++++++++ .../wf-mismatch-3.rs | 15 ++++++++++ 4 files changed, 67 insertions(+) create mode 100644 tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.rs create mode 100644 tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.rs create mode 100644 tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index d383cb9d91dd..358f14221a0d 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -951,6 +951,34 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { ty::Binder::dummy(ty::PredicateKind::DynCompatible(principal)), )); } + + if !t.has_escaping_bound_vars() { + for projection in data.projection_bounds() { + let pred_binder = projection + .with_self_ty(tcx, t) + .map_bound(|p| { + p.term.as_const().map(|ct| { + let assoc_const_ty = tcx + .type_of(p.projection_term.def_id) + .instantiate(tcx, p.projection_term.args); + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType( + ct, + assoc_const_ty, + )) + }) + }) + .transpose(); + if let Some(pred_binder) = pred_binder { + self.out.push(traits::Obligation::with_depth( + tcx, + self.cause(ObligationCauseCode::WellFormed(None)), + self.recursion_depth, + self.param_env, + pred_binder, + )); + } + } + } } // Inference variables are the complicated case, since we don't diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.rs b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.rs new file mode 100644 index 000000000000..319e3421a4cd --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.rs @@ -0,0 +1,12 @@ +//@ known-bug: unknown +//@ check-pass + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +trait Trait { #[type_const] const CT: bool; } + +// FIXME: this should yield a type mismatch (`bool` v `i32`) +fn f(_: impl Trait) {} + +fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.rs b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.rs new file mode 100644 index 000000000000..2adaaa3dd050 --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.rs @@ -0,0 +1,12 @@ +//@ known-bug: unknown +//@ check-pass + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +trait Trait { #[type_const] const CT: bool; } + +fn f() { + let _: dyn Trait; // FIXME: this should yield a type mismatch (`bool` v `i32`) +} +fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs new file mode 100644 index 000000000000..29d089bf9d2b --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs @@ -0,0 +1,15 @@ +//@ known-bug: unknown +//@ check-pass + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +trait Trait { #[type_const] const CT: bool; } + +trait Bound { #[type_const] const N: u32; } +impl Bound for () { #[type_const] const N: u32 = 0; } + +fn f() { let _: dyn Trait::N }>; } // FIXME +fn g(_: impl Trait::N }>) {} // FIXME + +fn main() {} From 963f82d3224ea0b1f7b1ca182b67af3e9293e89f Mon Sep 17 00:00:00 2001 From: zedddie Date: Sat, 7 Feb 2026 07:15:24 +0100 Subject: [PATCH 777/978] mGCA: add associated const obligations in wfck --- .../rustc_hir_analysis/src/check/wfcheck.rs | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index ceb0e138a0da..32af13b88a1a 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1569,11 +1569,40 @@ pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id: let predicates = predicates.instantiate_identity(tcx); + let assoc_const_obligations: Vec<_> = predicates + .predicates + .iter() + .copied() + .zip(predicates.spans.iter().copied()) + .filter_map(|(clause, sp)| { + let proj = clause.as_projection_clause()?; + let pred_binder = proj + .map_bound(|pred| { + pred.term.as_const().map(|ct| { + let assoc_const_ty = tcx + .type_of(pred.projection_term.def_id) + .instantiate(tcx, pred.projection_term.args); + ty::ClauseKind::ConstArgHasType(ct, assoc_const_ty) + }) + }) + .transpose(); + pred_binder.map(|pred_binder| { + let cause = traits::ObligationCause::new( + sp, + wfcx.body_def_id, + ObligationCauseCode::WhereClause(def_id.to_def_id(), sp), + ); + Obligation::new(tcx, cause, wfcx.param_env, pred_binder) + }) + }) + .collect(); + assert_eq!(predicates.predicates.len(), predicates.spans.len()); let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| { traits::wf::clause_obligations(infcx, wfcx.param_env, wfcx.body_def_id, p, sp) }); - let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect(); + let obligations: Vec<_> = + wf_obligations.chain(default_obligations).chain(assoc_const_obligations).collect(); wfcx.register_obligations(obligations); } From 20f65fc537e26bd92e0da4088c27e5905c3fc52a Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Tue, 10 Feb 2026 01:31:48 +0900 Subject: [PATCH 778/978] Uplift `Predicate::allow_normalization` to `rustc_type_ir` --- compiler/rustc_middle/src/ty/predicate.rs | 24 +--------------------- compiler/rustc_type_ir/src/inherent.rs | 25 ++++++++++++++++++++--- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 69dcca54f469..3baeb7141de5 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -49,10 +49,6 @@ impl<'tcx> rustc_type_ir::inherent::Predicate> for Predicate<'tcx> fn as_clause(self) -> Option> { self.as_clause() } - - fn allow_normalization(self) -> bool { - self.allow_normalization() - } } impl<'tcx> rustc_type_ir::inherent::IntoKind for Predicate<'tcx> { @@ -121,25 +117,7 @@ impl<'tcx> Predicate<'tcx> { /// unsoundly accept some programs. See #91068. #[inline] pub fn allow_normalization(self) -> bool { - match self.kind().skip_binder() { - PredicateKind::Clause(ClauseKind::WellFormed(_)) | PredicateKind::AliasRelate(..) => { - false - } - PredicateKind::Clause(ClauseKind::Trait(_)) - | PredicateKind::Clause(ClauseKind::HostEffect(..)) - | PredicateKind::Clause(ClauseKind::RegionOutlives(_)) - | PredicateKind::Clause(ClauseKind::TypeOutlives(_)) - | PredicateKind::Clause(ClauseKind::Projection(_)) - | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) - | PredicateKind::Clause(ClauseKind::UnstableFeature(_)) - | PredicateKind::DynCompatible(_) - | PredicateKind::Subtype(_) - | PredicateKind::Coerce(_) - | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_)) - | PredicateKind::ConstEquate(_, _) - | PredicateKind::NormalizesTo(..) - | PredicateKind::Ambiguous => true, - } + rustc_type_ir::inherent::Predicate::allow_normalization(self) } } diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 89cb236d38c6..c9580d589d21 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -13,7 +13,7 @@ use crate::fold::{TypeFoldable, TypeSuperFoldable}; use crate::relate::Relate; use crate::solve::{AdtDestructorKind, SizedTraitKind}; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; -use crate::{self as ty, CollectAndApply, Interner, UpcastFrom}; +use crate::{self as ty, ClauseKind, CollectAndApply, Interner, PredicateKind, UpcastFrom}; pub trait Ty>: Copy @@ -478,8 +478,27 @@ pub trait Predicate>: } } - // FIXME: Eventually uplift the impl out of rustc and make this defaulted. - fn allow_normalization(self) -> bool; + fn allow_normalization(self) -> bool { + match self.kind().skip_binder() { + PredicateKind::Clause(ClauseKind::WellFormed(_)) | PredicateKind::AliasRelate(..) => { + false + } + PredicateKind::Clause(ClauseKind::Trait(_)) + | PredicateKind::Clause(ClauseKind::HostEffect(..)) + | PredicateKind::Clause(ClauseKind::RegionOutlives(_)) + | PredicateKind::Clause(ClauseKind::TypeOutlives(_)) + | PredicateKind::Clause(ClauseKind::Projection(_)) + | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::Clause(ClauseKind::UnstableFeature(_)) + | PredicateKind::DynCompatible(_) + | PredicateKind::Subtype(_) + | PredicateKind::Coerce(_) + | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_)) + | PredicateKind::ConstEquate(_, _) + | PredicateKind::NormalizesTo(..) + | PredicateKind::Ambiguous => true, + } + } } pub trait Clause>: From ec03e39afd210cff8516b14b92dc259f61d303c5 Mon Sep 17 00:00:00 2001 From: zedddie Date: Mon, 9 Feb 2026 10:40:42 +0100 Subject: [PATCH 779/978] bless tests --- ...ection-behind-trait-alias-mentions-self.rs | 1 + ...on-behind-trait-alias-mentions-self.stderr | 16 +++++++++++++-- ...yn-const-projection-escaping-bound-vars.rs | 11 ++++++++++ .../wf-mismatch-1.rs | 9 ++++----- .../wf-mismatch-1.stderr | 14 +++++++++++++ .../wf-mismatch-2.rs | 9 +++++---- .../wf-mismatch-2.stderr | 8 ++++++++ .../wf-mismatch-3.rs | 16 ++++++++------- .../wf-mismatch-3.stderr | 20 +++++++++++++++++++ 9 files changed, 86 insertions(+), 18 deletions(-) create mode 100644 tests/ui/const-generics/associated-const-bindings/dyn-const-projection-escaping-bound-vars.rs create mode 100644 tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.stderr create mode 100644 tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.stderr create mode 100644 tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.stderr diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs index 415d7bda347b..9564903dce5b 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs @@ -15,6 +15,7 @@ trait Trait { struct Hold(T); trait Bound = Trait }>; +//~^ ERROR the constant `Hold::` is not of type `i32` fn main() { let _: dyn Bound; //~ ERROR associated constant binding in trait object type mentions `Self` diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.stderr index 576d4c3230ee..699b9192cf93 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.stderr @@ -1,5 +1,17 @@ +error: the constant `Hold::` is not of type `i32` + --> $DIR/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs:17:21 + | +LL | trait Bound = Trait }>; + | ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct constructor + | +note: required by a const generic parameter in `Bound` + --> $DIR/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs:17:21 + | +LL | trait Bound = Trait }>; + | ^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `Bound` + error: associated constant binding in trait object type mentions `Self` - --> $DIR/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs:20:12 + --> $DIR/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs:21:12 | LL | trait Bound = Trait }>; | -------------------- this binding mentions `Self` @@ -7,5 +19,5 @@ LL | trait Bound = Trait }>; LL | let _: dyn Bound; | ^^^^^^^^^ contains a mention of `Self` -error: aborting due to 1 previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-const-projection-escaping-bound-vars.rs b/tests/ui/const-generics/associated-const-bindings/dyn-const-projection-escaping-bound-vars.rs new file mode 100644 index 000000000000..c2ae86232a02 --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/dyn-const-projection-escaping-bound-vars.rs @@ -0,0 +1,11 @@ +//! Check associated const binding with escaping bound vars doesn't cause ICE +//! (#151642) +//@ check-pass + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +trait Trait2<'a> { type const ASSOC: i32; } +fn g(_: for<'a> fn(Box>)) {} + +fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.rs b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.rs index 319e3421a4cd..1beeb07e995a 100644 --- a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.rs +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.rs @@ -1,12 +1,11 @@ -//@ known-bug: unknown -//@ check-pass +//! Check that we correctly handle associated const bindings +//! in `impl Trait` where the RHS is a const param (#151642). #![feature(min_generic_const_args)] #![expect(incomplete_features)] -trait Trait { #[type_const] const CT: bool; } +trait Trait { type const CT: bool; } -// FIXME: this should yield a type mismatch (`bool` v `i32`) fn f(_: impl Trait) {} - +//~^ ERROR the constant `N` is not of type `bool` fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.stderr b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.stderr new file mode 100644 index 000000000000..56e01e640078 --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.stderr @@ -0,0 +1,14 @@ +error: the constant `N` is not of type `bool` + --> $DIR/wf-mismatch-1.rs:9:34 + | +LL | fn f(_: impl Trait) {} + | ^^^^^^^^^^ expected `bool`, found `i32` + | +note: required by a const generic parameter in `f` + --> $DIR/wf-mismatch-1.rs:9:34 + | +LL | fn f(_: impl Trait) {} + | ^^^^^^^^^^ required by this const generic parameter in `f` + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.rs b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.rs index 2adaaa3dd050..7a75b6da78c5 100644 --- a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.rs +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.rs @@ -1,12 +1,13 @@ -//@ known-bug: unknown -//@ check-pass +//! Check that we correctly handle associated const bindings +//! in `dyn Trait` where the RHS is a const param (#151642). #![feature(min_generic_const_args)] #![expect(incomplete_features)] -trait Trait { #[type_const] const CT: bool; } +trait Trait { type const CT: bool; } fn f() { - let _: dyn Trait; // FIXME: this should yield a type mismatch (`bool` v `i32`) + let _: dyn Trait; + //~^ ERROR the constant `N` is not of type `bool` } fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.stderr b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.stderr new file mode 100644 index 000000000000..8169cc07fc5f --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.stderr @@ -0,0 +1,8 @@ +error: the constant `N` is not of type `bool` + --> $DIR/wf-mismatch-2.rs:10:12 + | +LL | let _: dyn Trait; + | ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `i32` + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs index 29d089bf9d2b..3eeb7703aa2b 100644 --- a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs @@ -1,15 +1,17 @@ -//@ known-bug: unknown -//@ check-pass +//! Check that we correctly handle associated const bindings +//! where the RHS is a normalizable const projection (#151642). #![feature(min_generic_const_args)] #![expect(incomplete_features)] -trait Trait { #[type_const] const CT: bool; } +trait Trait { type const CT: bool; } -trait Bound { #[type_const] const N: u32; } -impl Bound for () { #[type_const] const N: u32 = 0; } +trait Bound { type const N: u32; } +impl Bound for () { type const N: u32 = 0; } -fn f() { let _: dyn Trait::N }>; } // FIXME -fn g(_: impl Trait::N }>) {} // FIXME +fn f() { let _: dyn Trait::N }>; } +//~^ ERROR the constant `0` is not of type `bool` +fn g(_: impl Trait::N }>) {} +//~^ ERROR the constant `0` is not of type `bool` fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.stderr b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.stderr new file mode 100644 index 000000000000..ac21527e04ed --- /dev/null +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.stderr @@ -0,0 +1,20 @@ +error: the constant `0` is not of type `bool` + --> $DIR/wf-mismatch-3.rs:14:20 + | +LL | fn g(_: impl Trait::N }>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `u32` + | +note: required by a const generic parameter in `g` + --> $DIR/wf-mismatch-3.rs:14:20 + | +LL | fn g(_: impl Trait::N }>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `g` + +error: the constant `0` is not of type `bool` + --> $DIR/wf-mismatch-3.rs:12:17 + | +LL | fn f() { let _: dyn Trait::N }>; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `u32` + +error: aborting due to 2 previous errors + From 066a935b0c25608db20da43951def47f3b1539e6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 10 Feb 2026 10:17:13 +1100 Subject: [PATCH 780/978] Move parts of `rustc_query_system::query::job` to `rustc_middle::job`. The latter is a new module. As well as the code motion, some other changes were required. - `QueryJobId` methods became free functions so they could move while `QueryJobId` itself stayed put. This was so `QueryMap` and `QueryJobInfo` could be moved. - Some visibilities in `rustc_query_system` required changing. - `collect_active_jobs_from_all_queries` is no longer required in `trait QueryContext`. --- Cargo.lock | 1 + compiler/rustc_interface/src/interface.rs | 3 +- compiler/rustc_interface/src/util.rs | 3 +- compiler/rustc_query_impl/Cargo.toml | 1 + compiler/rustc_query_impl/src/execution.rs | 9 +- compiler/rustc_query_impl/src/job.rs | 446 ++++++++++++++++++ compiler/rustc_query_impl/src/lib.rs | 4 +- compiler/rustc_query_impl/src/plumbing.rs | 59 +-- compiler/rustc_query_system/src/query/job.rs | 460 +------------------ compiler/rustc_query_system/src/query/mod.rs | 12 +- 10 files changed, 504 insertions(+), 494 deletions(-) create mode 100644 compiler/rustc_query_impl/src/job.rs diff --git a/Cargo.lock b/Cargo.lock index 545c776b4805..7230d633602d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4503,6 +4503,7 @@ dependencies = [ "rustc_query_system", "rustc_serialize", "rustc_span", + "rustc_thread_pool", "tracing", ] diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 72080c5f5369..6cbc184e8f1b 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -16,8 +16,7 @@ use rustc_parse::lexer::StripTokens; use rustc_parse::new_parser_from_source_str; use rustc_parse::parser::Recovery; use rustc_parse::parser::attr::AllowLeadingUnsafe; -use rustc_query_impl::QueryCtxt; -use rustc_query_system::query::print_query_stack; +use rustc_query_impl::{QueryCtxt, print_query_stack}; use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName}; use rustc_session::parse::ParseSess; use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, lint}; diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 458e7ad32143..59f0b67d6729 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -184,8 +184,7 @@ pub(crate) fn run_in_thread_pool_with_globals< use rustc_data_structures::defer; use rustc_data_structures::sync::FromDyn; use rustc_middle::ty::tls; - use rustc_query_impl::QueryCtxt; - use rustc_query_system::query::{QueryContext, break_query_cycles}; + use rustc_query_impl::{QueryCtxt, break_query_cycles}; let thread_stack_size = init_stack_size(thread_builder_diag); diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index d611629671a0..511337090d7f 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -16,5 +16,6 @@ rustc_middle = { path = "../rustc_middle" } rustc_query_system = { path = "../rustc_query_system" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } +rustc_thread_pool = { path = "../rustc_thread_pool" } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 88604c91d025..6f16932cb2eb 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -9,13 +9,14 @@ use rustc_middle::dep_graph::DepsType; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::{DepGraphData, DepNodeKey, HasDepContext}; use rustc_query_system::query::{ - ActiveKeyStatus, CycleError, CycleErrorHandling, QueryCache, QueryContext, QueryJob, - QueryJobId, QueryJobInfo, QueryLatch, QueryMap, QueryMode, QueryStackDeferred, QueryStackFrame, - QueryState, incremental_verify_ich, report_cycle, + ActiveKeyStatus, CycleError, CycleErrorHandling, QueryCache, QueryJob, QueryJobId, QueryLatch, + QueryMode, QueryStackDeferred, QueryStackFrame, QueryState, incremental_verify_ich, + report_cycle, }; use rustc_span::{DUMMY_SP, Span}; use crate::dep_graph::{DepContext, DepNode, DepNodeIndex}; +use crate::job::{QueryJobInfo, QueryMap, find_cycle_in_stack}; use crate::{QueryCtxt, QueryFlags, SemiDynamicQueryDispatcher}; #[inline] @@ -218,7 +219,7 @@ fn cycle_error<'tcx, C: QueryCache, const FLAGS: QueryFlags>( .ok() .expect("failed to collect active queries"); - let error = try_execute.find_cycle_in_stack(query_map, &qcx.current_query_job(), span); + let error = find_cycle_in_stack(try_execute, query_map, &qcx.current_query_job(), span); (mk_cycle(query, qcx, error.lift()), None) } diff --git a/compiler/rustc_query_impl/src/job.rs b/compiler/rustc_query_impl/src/job.rs new file mode 100644 index 000000000000..cb0a13d32ad2 --- /dev/null +++ b/compiler/rustc_query_impl/src/job.rs @@ -0,0 +1,446 @@ +use std::io::Write; +use std::iter; +use std::sync::Arc; + +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_errors::DiagCtxtHandle; +use rustc_query_system::query::{ + CycleError, QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryStackDeferred, QueryStackFrame, + QueryWaiter, +}; +use rustc_span::{DUMMY_SP, Span}; + +use crate::QueryCtxt; +use crate::dep_graph::DepContext; + +/// Map from query job IDs to job information collected by +/// `collect_active_jobs_from_all_queries`. +pub type QueryMap<'tcx> = FxHashMap>; + +fn query_job_id_frame<'a, 'tcx>( + id: QueryJobId, + map: &'a QueryMap<'tcx>, +) -> QueryStackFrame> { + map.get(&id).unwrap().frame.clone() +} + +fn query_job_id_span<'a, 'tcx>(id: QueryJobId, map: &'a QueryMap<'tcx>) -> Span { + map.get(&id).unwrap().job.span +} + +fn query_job_id_parent<'a, 'tcx>(id: QueryJobId, map: &'a QueryMap<'tcx>) -> Option { + map.get(&id).unwrap().job.parent +} + +fn query_job_id_latch<'a, 'tcx>( + id: QueryJobId, + map: &'a QueryMap<'tcx>, +) -> Option<&'a QueryLatch<'tcx>> { + map.get(&id).unwrap().job.latch.as_ref() +} + +#[derive(Clone, Debug)] +pub struct QueryJobInfo<'tcx> { + pub frame: QueryStackFrame>, + pub job: QueryJob<'tcx>, +} + +pub(crate) fn find_cycle_in_stack<'tcx>( + id: QueryJobId, + query_map: QueryMap<'tcx>, + current_job: &Option, + span: Span, +) -> CycleError> { + // Find the waitee amongst `current_job` parents + let mut cycle = Vec::new(); + let mut current_job = Option::clone(current_job); + + while let Some(job) = current_job { + let info = query_map.get(&job).unwrap(); + cycle.push(QueryInfo { span: info.job.span, frame: info.frame.clone() }); + + if job == id { + cycle.reverse(); + + // This is the end of the cycle + // The span entry we included was for the usage + // of the cycle itself, and not part of the cycle + // Replace it with the span which caused the cycle to form + cycle[0].span = span; + // Find out why the cycle itself was used + let usage = info + .job + .parent + .as_ref() + .map(|parent| (info.job.span, query_job_id_frame(*parent, &query_map))); + return CycleError { usage, cycle }; + } + + current_job = info.job.parent; + } + + panic!("did not find a cycle") +} + +#[cold] +#[inline(never)] +pub(crate) fn find_dep_kind_root<'tcx>( + id: QueryJobId, + query_map: QueryMap<'tcx>, +) -> (QueryJobInfo<'tcx>, usize) { + let mut depth = 1; + let info = query_map.get(&id).unwrap(); + let dep_kind = info.frame.dep_kind; + let mut current_id = info.job.parent; + let mut last_layout = (info.clone(), depth); + + while let Some(id) = current_id { + let info = query_map.get(&id).unwrap(); + if info.frame.dep_kind == dep_kind { + depth += 1; + last_layout = (info.clone(), depth); + } + current_id = info.job.parent; + } + last_layout +} + +/// A resumable waiter of a query. The usize is the index into waiters in the query's latch +type Waiter = (QueryJobId, usize); + +/// Visits all the non-resumable and resumable waiters of a query. +/// Only waiters in a query are visited. +/// `visit` is called for every waiter and is passed a query waiting on `query_ref` +/// and a span indicating the reason the query waited on `query_ref`. +/// If `visit` returns Some, this function returns. +/// For visits of non-resumable waiters it returns the return value of `visit`. +/// For visits of resumable waiters it returns Some(Some(Waiter)) which has the +/// required information to resume the waiter. +/// If all `visit` calls returns None, this function also returns None. +fn visit_waiters<'tcx, F>( + query_map: &QueryMap<'tcx>, + query: QueryJobId, + mut visit: F, +) -> Option> +where + F: FnMut(Span, QueryJobId) -> Option>, +{ + // Visit the parent query which is a non-resumable waiter since it's on the same stack + if let Some(parent) = query_job_id_parent(query, query_map) + && let Some(cycle) = visit(query_job_id_span(query, query_map), parent) + { + return Some(cycle); + } + + // Visit the explicit waiters which use condvars and are resumable + if let Some(latch) = query_job_id_latch(query, query_map) { + for (i, waiter) in latch.info.lock().waiters.iter().enumerate() { + if let Some(waiter_query) = waiter.query { + if visit(waiter.span, waiter_query).is_some() { + // Return a value which indicates that this waiter can be resumed + return Some(Some((query, i))); + } + } + } + } + + None +} + +/// Look for query cycles by doing a depth first search starting at `query`. +/// `span` is the reason for the `query` to execute. This is initially DUMMY_SP. +/// If a cycle is detected, this initial value is replaced with the span causing +/// the cycle. +fn cycle_check<'tcx>( + query_map: &QueryMap<'tcx>, + query: QueryJobId, + span: Span, + stack: &mut Vec<(Span, QueryJobId)>, + visited: &mut FxHashSet, +) -> Option> { + if !visited.insert(query) { + return if let Some(p) = stack.iter().position(|q| q.1 == query) { + // We detected a query cycle, fix up the initial span and return Some + + // Remove previous stack entries + stack.drain(0..p); + // Replace the span for the first query with the cycle cause + stack[0].0 = span; + Some(None) + } else { + None + }; + } + + // Query marked as visited is added it to the stack + stack.push((span, query)); + + // Visit all the waiters + let r = visit_waiters(query_map, query, |span, successor| { + cycle_check(query_map, successor, span, stack, visited) + }); + + // Remove the entry in our stack if we didn't find a cycle + if r.is_none() { + stack.pop(); + } + + r +} + +/// Finds out if there's a path to the compiler root (aka. code which isn't in a query) +/// from `query` without going through any of the queries in `visited`. +/// This is achieved with a depth first search. +fn connected_to_root<'tcx>( + query_map: &QueryMap<'tcx>, + query: QueryJobId, + visited: &mut FxHashSet, +) -> bool { + // We already visited this or we're deliberately ignoring it + if !visited.insert(query) { + return false; + } + + // This query is connected to the root (it has no query parent), return true + if query_job_id_parent(query, query_map).is_none() { + return true; + } + + visit_waiters(query_map, query, |_, successor| { + connected_to_root(query_map, successor, visited).then_some(None) + }) + .is_some() +} + +// Deterministically pick an query from a list +fn pick_query<'a, 'tcx, T, F>(query_map: &QueryMap<'tcx>, queries: &'a [T], f: F) -> &'a T +where + F: Fn(&T) -> (Span, QueryJobId), +{ + // Deterministically pick an entry point + // FIXME: Sort this instead + queries + .iter() + .min_by_key(|v| { + let (span, query) = f(v); + let hash = query_job_id_frame(query, query_map).hash; + // Prefer entry points which have valid spans for nicer error messages + // We add an integer to the tuple ensuring that entry points + // with valid spans are picked first + let span_cmp = if span == DUMMY_SP { 1 } else { 0 }; + (span_cmp, hash) + }) + .unwrap() +} + +/// Looks for query cycles starting from the last query in `jobs`. +/// If a cycle is found, all queries in the cycle is removed from `jobs` and +/// the function return true. +/// If a cycle was not found, the starting query is removed from `jobs` and +/// the function returns false. +fn remove_cycle<'tcx>( + query_map: &QueryMap<'tcx>, + jobs: &mut Vec, + wakelist: &mut Vec>>, +) -> bool { + let mut visited = FxHashSet::default(); + let mut stack = Vec::new(); + // Look for a cycle starting with the last query in `jobs` + if let Some(waiter) = + cycle_check(query_map, jobs.pop().unwrap(), DUMMY_SP, &mut stack, &mut visited) + { + // The stack is a vector of pairs of spans and queries; reverse it so that + // the earlier entries require later entries + let (mut spans, queries): (Vec<_>, Vec<_>) = stack.into_iter().rev().unzip(); + + // Shift the spans so that queries are matched with the span for their waitee + spans.rotate_right(1); + + // Zip them back together + let mut stack: Vec<_> = iter::zip(spans, queries).collect(); + + // Remove the queries in our cycle from the list of jobs to look at + for r in &stack { + if let Some(pos) = jobs.iter().position(|j| j == &r.1) { + jobs.remove(pos); + } + } + + // Find the queries in the cycle which are + // connected to queries outside the cycle + let entry_points = stack + .iter() + .filter_map(|&(span, query)| { + if query_job_id_parent(query, query_map).is_none() { + // This query is connected to the root (it has no query parent) + Some((span, query, None)) + } else { + let mut waiters = Vec::new(); + // Find all the direct waiters who lead to the root + visit_waiters(query_map, query, |span, waiter| { + // Mark all the other queries in the cycle as already visited + let mut visited = FxHashSet::from_iter(stack.iter().map(|q| q.1)); + + if connected_to_root(query_map, waiter, &mut visited) { + waiters.push((span, waiter)); + } + + None + }); + if waiters.is_empty() { + None + } else { + // Deterministically pick one of the waiters to show to the user + let waiter = *pick_query(query_map, &waiters, |s| *s); + Some((span, query, Some(waiter))) + } + } + }) + .collect::)>>(); + + // Deterministically pick an entry point + let (_, entry_point, usage) = pick_query(query_map, &entry_points, |e| (e.0, e.1)); + + // Shift the stack so that our entry point is first + let entry_point_pos = stack.iter().position(|(_, query)| query == entry_point); + if let Some(pos) = entry_point_pos { + stack.rotate_left(pos); + } + + let usage = + usage.as_ref().map(|(span, query)| (*span, query_job_id_frame(*query, query_map))); + + // Create the cycle error + let error = CycleError { + usage, + cycle: stack + .iter() + .map(|&(s, ref q)| QueryInfo { span: s, frame: query_job_id_frame(*q, query_map) }) + .collect(), + }; + + // We unwrap `waiter` here since there must always be one + // edge which is resumable / waited using a query latch + let (waitee_query, waiter_idx) = waiter.unwrap(); + + // Extract the waiter we want to resume + let waiter = + query_job_id_latch(waitee_query, query_map).unwrap().extract_waiter(waiter_idx); + + // Set the cycle error so it will be picked up when resumed + *waiter.cycle.lock() = Some(error); + + // Put the waiter on the list of things to resume + wakelist.push(waiter); + + true + } else { + false + } +} + +/// Detects query cycles by using depth first search over all active query jobs. +/// If a query cycle is found it will break the cycle by finding an edge which +/// uses a query latch and then resuming that waiter. +/// There may be multiple cycles involved in a deadlock, so this searches +/// all active queries for cycles before finally resuming all the waiters at once. +pub fn break_query_cycles<'tcx>(query_map: QueryMap<'tcx>, registry: &rustc_thread_pool::Registry) { + let mut wakelist = Vec::new(); + // It is OK per the comments: + // - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798854932 + // - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798866392 + #[allow(rustc::potential_query_instability)] + let mut jobs: Vec = query_map.keys().cloned().collect(); + + let mut found_cycle = false; + + while jobs.len() > 0 { + if remove_cycle(&query_map, &mut jobs, &mut wakelist) { + found_cycle = true; + } + } + + // Check that a cycle was found. It is possible for a deadlock to occur without + // a query cycle if a query which can be waited on uses Rayon to do multithreading + // internally. Such a query (X) may be executing on 2 threads (A and B) and A may + // wait using Rayon on B. Rayon may then switch to executing another query (Y) + // which in turn will wait on X causing a deadlock. We have a false dependency from + // X to Y due to Rayon waiting and a true dependency from Y to X. The algorithm here + // only considers the true dependency and won't detect a cycle. + if !found_cycle { + panic!( + "deadlock detected as we're unable to find a query cycle to break\n\ + current query map:\n{:#?}", + query_map + ); + } + + // Mark all the thread we're about to wake up as unblocked. This needs to be done before + // we wake the threads up as otherwise Rayon could detect a deadlock if a thread we + // resumed fell asleep and this thread had yet to mark the remaining threads as unblocked. + for _ in 0..wakelist.len() { + rustc_thread_pool::mark_unblocked(registry); + } + + for waiter in wakelist.into_iter() { + waiter.condvar.notify_one(); + } +} + +pub fn print_query_stack<'tcx>( + qcx: QueryCtxt<'tcx>, + mut current_query: Option, + dcx: DiagCtxtHandle<'_>, + limit_frames: Option, + mut file: Option, +) -> usize { + // Be careful relying on global state here: this code is called from + // a panic hook, which means that the global `DiagCtxt` may be in a weird + // state if it was responsible for triggering the panic. + let mut count_printed = 0; + let mut count_total = 0; + + // Make use of a partial query map if we fail to take locks collecting active queries. + let query_map = match qcx.collect_active_jobs_from_all_queries(false) { + Ok(query_map) => query_map, + Err(query_map) => query_map, + }; + + if let Some(ref mut file) = file { + let _ = writeln!(file, "\n\nquery stack during panic:"); + } + while let Some(query) = current_query { + let Some(query_info) = query_map.get(&query) else { + break; + }; + let query_extra = query_info.frame.info.extract(); + if Some(count_printed) < limit_frames || limit_frames.is_none() { + // Only print to stderr as many stack frames as `num_frames` when present. + dcx.struct_failure_note(format!( + "#{} [{:?}] {}", + count_printed, query_info.frame.dep_kind, query_extra.description + )) + .with_span(query_info.job.span) + .emit(); + count_printed += 1; + } + + if let Some(ref mut file) = file { + let _ = writeln!( + file, + "#{} [{}] {}", + count_total, + qcx.tcx.dep_kind_vtable(query_info.frame.dep_kind).name, + query_extra.description + ); + } + + current_query = query_info.job.parent; + count_total += 1; + } + + if let Some(ref mut file) = file { + let _ = writeln!(file, "end of query stack"); + } + count_total +} diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index a33bdd22a797..c1ead8da344b 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -23,10 +23,11 @@ use rustc_middle::query::values::Value; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::SerializedDepNodeIndex; use rustc_query_system::query::{ - CycleError, CycleErrorHandling, QueryCache, QueryMap, QueryMode, QueryState, + CycleError, CycleErrorHandling, QueryCache, QueryMode, QueryState, }; use rustc_span::{ErrorGuaranteed, Span}; +pub use crate::job::{QueryMap, break_query_cycles, print_query_stack}; pub use crate::plumbing::{QueryCtxt, query_key_hash_verify_all}; use crate::plumbing::{encode_all_query_results, try_mark_green}; use crate::profiling_support::QueryKeyStringCache; @@ -34,6 +35,7 @@ pub use crate::profiling_support::alloc_self_profile_query_strings; mod error; mod execution; +mod job; #[macro_use] mod plumbing; mod profiling_support; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 776d720f500b..5fba9dd4a68a 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -28,14 +28,15 @@ use rustc_middle::ty::tls::{self, ImplicitCtxt}; use rustc_middle::ty::{self, TyCtxt}; use rustc_query_system::dep_graph::{DepNodeKey, FingerprintStyle, HasDepContext}; use rustc_query_system::query::{ - QueryCache, QueryContext, QueryJobId, QueryMap, QuerySideEffect, QueryStackDeferred, - QueryStackFrame, QueryStackFrameExtra, + QueryCache, QueryContext, QueryJobId, QuerySideEffect, QueryStackDeferred, QueryStackFrame, + QueryStackFrameExtra, }; use rustc_serialize::{Decodable, Encodable}; use rustc_span::def_id::LOCAL_CRATE; use crate::error::{QueryOverflow, QueryOverflowNote}; use crate::execution::{all_inactive, force_query}; +use crate::job::{QueryMap, find_dep_kind_root}; use crate::{QueryDispatcherUnerased, QueryFlags, SemiDynamicQueryDispatcher}; /// Implements [`QueryContext`] for use by [`rustc_query_system`], since that @@ -55,7 +56,7 @@ impl<'tcx> QueryCtxt<'tcx> { let query_map = self .collect_active_jobs_from_all_queries(true) .expect("failed to collect active queries"); - let (info, depth) = job.find_dep_kind_root(query_map); + let (info, depth) = find_dep_kind_root(job, query_map); let suggested_limit = match self.tcx.recursion_limit() { Limit(0) => Limit(2), @@ -116,6 +117,32 @@ impl<'tcx> QueryCtxt<'tcx> { tls::enter_context(&new_icx, compute) }) } + + /// Returns a map of currently active query jobs, collected from all queries. + /// + /// If `require_complete` is `true`, this function locks all shards of the + /// query results to produce a complete map, which always returns `Ok`. + /// Otherwise, it may return an incomplete map as an error if any shard + /// lock cannot be acquired. + /// + /// Prefer passing `false` to `require_complete` to avoid potential deadlocks, + /// especially when called from within a deadlock handler, unless a + /// complete map is needed and no deadlock is possible at this call site. + pub fn collect_active_jobs_from_all_queries( + self, + require_complete: bool, + ) -> Result, QueryMap<'tcx>> { + let mut jobs = QueryMap::default(); + let mut complete = true; + + for gather_fn in crate::PER_QUERY_GATHER_ACTIVE_JOBS_FNS.iter() { + if gather_fn(self.tcx, &mut jobs, require_complete).is_none() { + complete = false; + } + } + + if complete { Ok(jobs) } else { Err(jobs) } + } } impl<'tcx> HasDepContext for QueryCtxt<'tcx> { @@ -134,32 +161,6 @@ impl<'tcx> QueryContext<'tcx> for QueryCtxt<'tcx> { &self.tcx.jobserver_proxy } - /// Returns a map of currently active query jobs, collected from all queries. - /// - /// If `require_complete` is `true`, this function locks all shards of the - /// query results to produce a complete map, which always returns `Ok`. - /// Otherwise, it may return an incomplete map as an error if any shard - /// lock cannot be acquired. - /// - /// Prefer passing `false` to `require_complete` to avoid potential deadlocks, - /// especially when called from within a deadlock handler, unless a - /// complete map is needed and no deadlock is possible at this call site. - fn collect_active_jobs_from_all_queries( - self, - require_complete: bool, - ) -> Result, QueryMap<'tcx>> { - let mut jobs = QueryMap::default(); - let mut complete = true; - - for gather_fn in crate::PER_QUERY_GATHER_ACTIVE_JOBS_FNS.iter() { - if gather_fn(self.tcx, &mut jobs, require_complete).is_none() { - complete = false; - } - } - - if complete { Ok(jobs) } else { Err(jobs) } - } - // Interactions with on_disk_cache fn load_side_effect( self, diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index c77ae38ba96f..e8acb8064f7e 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -1,19 +1,15 @@ use std::fmt::Debug; use std::hash::Hash; -use std::io::Write; -use std::iter; use std::num::NonZero; use std::sync::Arc; use parking_lot::{Condvar, Mutex}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{Diag, DiagCtxtHandle}; +use rustc_errors::Diag; use rustc_hir::def::DefKind; use rustc_session::Session; -use rustc_span::{DUMMY_SP, Span}; +use rustc_span::Span; use super::{QueryStackDeferred, QueryStackFrameExtra}; -use crate::dep_graph::DepContext; use crate::error::CycleStack; use crate::query::plumbing::CycleError; use crate::query::{QueryContext, QueryStackFrame}; @@ -32,38 +28,10 @@ impl<'tcx> QueryInfo> { } } -/// Map from query job IDs to job information collected by -/// [`QueryContext::collect_active_jobs_from_all_queries`]. -pub type QueryMap<'tcx> = FxHashMap>; - /// A value uniquely identifying an active query job. #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct QueryJobId(pub NonZero); -impl QueryJobId { - fn frame<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> QueryStackFrame> { - map.get(&self).unwrap().frame.clone() - } - - fn span<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> Span { - map.get(&self).unwrap().job.span - } - - fn parent<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> Option { - map.get(&self).unwrap().job.parent - } - - fn latch<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> Option<&'a QueryLatch<'tcx>> { - map.get(&self).unwrap().job.latch.as_ref() - } -} - -#[derive(Clone, Debug)] -pub struct QueryJobInfo<'tcx> { - pub frame: QueryStackFrame>, - pub job: QueryJob<'tcx>, -} - /// Represents an active query job. #[derive(Clone, Debug)] pub struct QueryJob<'tcx> { @@ -76,7 +44,7 @@ pub struct QueryJob<'tcx> { pub parent: Option, /// The latch that is used to wait on this job. - latch: Option>, + pub latch: Option>, } impl<'tcx> QueryJob<'tcx> { @@ -105,85 +73,23 @@ impl<'tcx> QueryJob<'tcx> { } } -impl QueryJobId { - pub fn find_cycle_in_stack<'tcx>( - &self, - query_map: QueryMap<'tcx>, - current_job: &Option, - span: Span, - ) -> CycleError> { - // Find the waitee amongst `current_job` parents - let mut cycle = Vec::new(); - let mut current_job = Option::clone(current_job); - - while let Some(job) = current_job { - let info = query_map.get(&job).unwrap(); - cycle.push(QueryInfo { span: info.job.span, frame: info.frame.clone() }); - - if job == *self { - cycle.reverse(); - - // This is the end of the cycle - // The span entry we included was for the usage - // of the cycle itself, and not part of the cycle - // Replace it with the span which caused the cycle to form - cycle[0].span = span; - // Find out why the cycle itself was used - let usage = info - .job - .parent - .as_ref() - .map(|parent| (info.job.span, parent.frame(&query_map))); - return CycleError { usage, cycle }; - } - - current_job = info.job.parent; - } - - panic!("did not find a cycle") - } - - #[cold] - #[inline(never)] - pub fn find_dep_kind_root<'tcx>( - &self, - query_map: QueryMap<'tcx>, - ) -> (QueryJobInfo<'tcx>, usize) { - let mut depth = 1; - let info = query_map.get(&self).unwrap(); - let dep_kind = info.frame.dep_kind; - let mut current_id = info.job.parent; - let mut last_layout = (info.clone(), depth); - - while let Some(id) = current_id { - let info = query_map.get(&id).unwrap(); - if info.frame.dep_kind == dep_kind { - depth += 1; - last_layout = (info.clone(), depth); - } - current_id = info.job.parent; - } - last_layout - } +#[derive(Debug)] +pub struct QueryWaiter<'tcx> { + pub query: Option, + pub condvar: Condvar, + pub span: Span, + pub cycle: Mutex>>>, } #[derive(Debug)] -struct QueryWaiter<'tcx> { - query: Option, - condvar: Condvar, - span: Span, - cycle: Mutex>>>, -} - -#[derive(Debug)] -struct QueryLatchInfo<'tcx> { - complete: bool, - waiters: Vec>>, +pub struct QueryLatchInfo<'tcx> { + pub complete: bool, + pub waiters: Vec>>, } #[derive(Clone, Debug)] pub struct QueryLatch<'tcx> { - info: Arc>>, + pub info: Arc>>, } impl<'tcx> QueryLatch<'tcx> { @@ -250,7 +156,7 @@ impl<'tcx> QueryLatch<'tcx> { /// Removes a single waiter from the list of waiters. /// This is used to break query cycles. - fn extract_waiter(&self, waiter: usize) -> Arc> { + pub fn extract_waiter(&self, waiter: usize) -> Arc> { let mut info = self.info.lock(); debug_assert!(!info.complete); // Remove the waiter from the list of waiters @@ -258,286 +164,6 @@ impl<'tcx> QueryLatch<'tcx> { } } -/// A resumable waiter of a query. The usize is the index into waiters in the query's latch -type Waiter = (QueryJobId, usize); - -/// Visits all the non-resumable and resumable waiters of a query. -/// Only waiters in a query are visited. -/// `visit` is called for every waiter and is passed a query waiting on `query_ref` -/// and a span indicating the reason the query waited on `query_ref`. -/// If `visit` returns Some, this function returns. -/// For visits of non-resumable waiters it returns the return value of `visit`. -/// For visits of resumable waiters it returns Some(Some(Waiter)) which has the -/// required information to resume the waiter. -/// If all `visit` calls returns None, this function also returns None. -fn visit_waiters<'tcx, F>( - query_map: &QueryMap<'tcx>, - query: QueryJobId, - mut visit: F, -) -> Option> -where - F: FnMut(Span, QueryJobId) -> Option>, -{ - // Visit the parent query which is a non-resumable waiter since it's on the same stack - if let Some(parent) = query.parent(query_map) - && let Some(cycle) = visit(query.span(query_map), parent) - { - return Some(cycle); - } - - // Visit the explicit waiters which use condvars and are resumable - if let Some(latch) = query.latch(query_map) { - for (i, waiter) in latch.info.lock().waiters.iter().enumerate() { - if let Some(waiter_query) = waiter.query { - if visit(waiter.span, waiter_query).is_some() { - // Return a value which indicates that this waiter can be resumed - return Some(Some((query, i))); - } - } - } - } - - None -} - -/// Look for query cycles by doing a depth first search starting at `query`. -/// `span` is the reason for the `query` to execute. This is initially DUMMY_SP. -/// If a cycle is detected, this initial value is replaced with the span causing -/// the cycle. -fn cycle_check<'tcx>( - query_map: &QueryMap<'tcx>, - query: QueryJobId, - span: Span, - stack: &mut Vec<(Span, QueryJobId)>, - visited: &mut FxHashSet, -) -> Option> { - if !visited.insert(query) { - return if let Some(p) = stack.iter().position(|q| q.1 == query) { - // We detected a query cycle, fix up the initial span and return Some - - // Remove previous stack entries - stack.drain(0..p); - // Replace the span for the first query with the cycle cause - stack[0].0 = span; - Some(None) - } else { - None - }; - } - - // Query marked as visited is added it to the stack - stack.push((span, query)); - - // Visit all the waiters - let r = visit_waiters(query_map, query, |span, successor| { - cycle_check(query_map, successor, span, stack, visited) - }); - - // Remove the entry in our stack if we didn't find a cycle - if r.is_none() { - stack.pop(); - } - - r -} - -/// Finds out if there's a path to the compiler root (aka. code which isn't in a query) -/// from `query` without going through any of the queries in `visited`. -/// This is achieved with a depth first search. -fn connected_to_root<'tcx>( - query_map: &QueryMap<'tcx>, - query: QueryJobId, - visited: &mut FxHashSet, -) -> bool { - // We already visited this or we're deliberately ignoring it - if !visited.insert(query) { - return false; - } - - // This query is connected to the root (it has no query parent), return true - if query.parent(query_map).is_none() { - return true; - } - - visit_waiters(query_map, query, |_, successor| { - connected_to_root(query_map, successor, visited).then_some(None) - }) - .is_some() -} - -// Deterministically pick an query from a list -fn pick_query<'a, 'tcx, T, F>(query_map: &QueryMap<'tcx>, queries: &'a [T], f: F) -> &'a T -where - F: Fn(&T) -> (Span, QueryJobId), -{ - // Deterministically pick an entry point - // FIXME: Sort this instead - queries - .iter() - .min_by_key(|v| { - let (span, query) = f(v); - let hash = query.frame(query_map).hash; - // Prefer entry points which have valid spans for nicer error messages - // We add an integer to the tuple ensuring that entry points - // with valid spans are picked first - let span_cmp = if span == DUMMY_SP { 1 } else { 0 }; - (span_cmp, hash) - }) - .unwrap() -} - -/// Looks for query cycles starting from the last query in `jobs`. -/// If a cycle is found, all queries in the cycle is removed from `jobs` and -/// the function return true. -/// If a cycle was not found, the starting query is removed from `jobs` and -/// the function returns false. -fn remove_cycle<'tcx>( - query_map: &QueryMap<'tcx>, - jobs: &mut Vec, - wakelist: &mut Vec>>, -) -> bool { - let mut visited = FxHashSet::default(); - let mut stack = Vec::new(); - // Look for a cycle starting with the last query in `jobs` - if let Some(waiter) = - cycle_check(query_map, jobs.pop().unwrap(), DUMMY_SP, &mut stack, &mut visited) - { - // The stack is a vector of pairs of spans and queries; reverse it so that - // the earlier entries require later entries - let (mut spans, queries): (Vec<_>, Vec<_>) = stack.into_iter().rev().unzip(); - - // Shift the spans so that queries are matched with the span for their waitee - spans.rotate_right(1); - - // Zip them back together - let mut stack: Vec<_> = iter::zip(spans, queries).collect(); - - // Remove the queries in our cycle from the list of jobs to look at - for r in &stack { - if let Some(pos) = jobs.iter().position(|j| j == &r.1) { - jobs.remove(pos); - } - } - - // Find the queries in the cycle which are - // connected to queries outside the cycle - let entry_points = stack - .iter() - .filter_map(|&(span, query)| { - if query.parent(query_map).is_none() { - // This query is connected to the root (it has no query parent) - Some((span, query, None)) - } else { - let mut waiters = Vec::new(); - // Find all the direct waiters who lead to the root - visit_waiters(query_map, query, |span, waiter| { - // Mark all the other queries in the cycle as already visited - let mut visited = FxHashSet::from_iter(stack.iter().map(|q| q.1)); - - if connected_to_root(query_map, waiter, &mut visited) { - waiters.push((span, waiter)); - } - - None - }); - if waiters.is_empty() { - None - } else { - // Deterministically pick one of the waiters to show to the user - let waiter = *pick_query(query_map, &waiters, |s| *s); - Some((span, query, Some(waiter))) - } - } - }) - .collect::)>>(); - - // Deterministically pick an entry point - let (_, entry_point, usage) = pick_query(query_map, &entry_points, |e| (e.0, e.1)); - - // Shift the stack so that our entry point is first - let entry_point_pos = stack.iter().position(|(_, query)| query == entry_point); - if let Some(pos) = entry_point_pos { - stack.rotate_left(pos); - } - - let usage = usage.as_ref().map(|(span, query)| (*span, query.frame(query_map))); - - // Create the cycle error - let error = CycleError { - usage, - cycle: stack - .iter() - .map(|&(s, ref q)| QueryInfo { span: s, frame: q.frame(query_map) }) - .collect(), - }; - - // We unwrap `waiter` here since there must always be one - // edge which is resumable / waited using a query latch - let (waitee_query, waiter_idx) = waiter.unwrap(); - - // Extract the waiter we want to resume - let waiter = waitee_query.latch(query_map).unwrap().extract_waiter(waiter_idx); - - // Set the cycle error so it will be picked up when resumed - *waiter.cycle.lock() = Some(error); - - // Put the waiter on the list of things to resume - wakelist.push(waiter); - - true - } else { - false - } -} - -/// Detects query cycles by using depth first search over all active query jobs. -/// If a query cycle is found it will break the cycle by finding an edge which -/// uses a query latch and then resuming that waiter. -/// There may be multiple cycles involved in a deadlock, so this searches -/// all active queries for cycles before finally resuming all the waiters at once. -pub fn break_query_cycles<'tcx>(query_map: QueryMap<'tcx>, registry: &rustc_thread_pool::Registry) { - let mut wakelist = Vec::new(); - // It is OK per the comments: - // - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798854932 - // - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798866392 - #[allow(rustc::potential_query_instability)] - let mut jobs: Vec = query_map.keys().cloned().collect(); - - let mut found_cycle = false; - - while jobs.len() > 0 { - if remove_cycle(&query_map, &mut jobs, &mut wakelist) { - found_cycle = true; - } - } - - // Check that a cycle was found. It is possible for a deadlock to occur without - // a query cycle if a query which can be waited on uses Rayon to do multithreading - // internally. Such a query (X) may be executing on 2 threads (A and B) and A may - // wait using Rayon on B. Rayon may then switch to executing another query (Y) - // which in turn will wait on X causing a deadlock. We have a false dependency from - // X to Y due to Rayon waiting and a true dependency from Y to X. The algorithm here - // only considers the true dependency and won't detect a cycle. - if !found_cycle { - panic!( - "deadlock detected as we're unable to find a query cycle to break\n\ - current query map:\n{:#?}", - query_map - ); - } - - // Mark all the thread we're about to wake up as unblocked. This needs to be done before - // we wake the threads up as otherwise Rayon could detect a deadlock if a thread we - // resumed fell asleep and this thread had yet to mark the remaining threads as unblocked. - for _ in 0..wakelist.len() { - rustc_thread_pool::mark_unblocked(registry); - } - - for waiter in wakelist.into_iter() { - waiter.condvar.notify_one(); - } -} - #[inline(never)] #[cold] pub fn report_cycle<'a>( @@ -588,61 +214,3 @@ pub fn report_cycle<'a>( sess.dcx().create_err(cycle_diag) } - -pub fn print_query_stack<'tcx, Qcx: QueryContext<'tcx>>( - qcx: Qcx, - mut current_query: Option, - dcx: DiagCtxtHandle<'_>, - limit_frames: Option, - mut file: Option, -) -> usize { - // Be careful relying on global state here: this code is called from - // a panic hook, which means that the global `DiagCtxt` may be in a weird - // state if it was responsible for triggering the panic. - let mut count_printed = 0; - let mut count_total = 0; - - // Make use of a partial query map if we fail to take locks collecting active queries. - let query_map = match qcx.collect_active_jobs_from_all_queries(false) { - Ok(query_map) => query_map, - Err(query_map) => query_map, - }; - - if let Some(ref mut file) = file { - let _ = writeln!(file, "\n\nquery stack during panic:"); - } - while let Some(query) = current_query { - let Some(query_info) = query_map.get(&query) else { - break; - }; - let query_extra = query_info.frame.info.extract(); - if Some(count_printed) < limit_frames || limit_frames.is_none() { - // Only print to stderr as many stack frames as `num_frames` when present. - dcx.struct_failure_note(format!( - "#{} [{:?}] {}", - count_printed, query_info.frame.dep_kind, query_extra.description - )) - .with_span(query_info.job.span) - .emit(); - count_printed += 1; - } - - if let Some(ref mut file) = file { - let _ = writeln!( - file, - "#{} [{}] {}", - count_total, - qcx.dep_context().dep_kind_vtable(query_info.frame.dep_kind).name, - query_extra.description - ); - } - - current_query = query_info.job.parent; - count_total += 1; - } - - if let Some(ref mut file) = file { - let _ = writeln!(file, "end of query stack"); - } - count_total -} diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index f4a3fda7e372..6067f7dafd5c 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -15,10 +15,7 @@ use rustc_span::def_id::DefId; pub use self::caches::{ DefIdCache, DefaultCache, QueryCache, QueryCacheKey, SingleCache, VecCache, }; -pub use self::job::{ - QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, QueryMap, break_query_cycles, - print_query_stack, report_cycle, -}; +pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter, report_cycle}; pub use self::plumbing::*; use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; @@ -52,7 +49,7 @@ pub struct QueryStackFrame { pub dep_kind: DepKind, /// This hash is used to deterministically pick /// a query to remove cycles in the parallel compiler. - hash: Hash64, + pub hash: Hash64, pub def_id: Option, /// A def-id that is extracted from a `Ty` in a query key pub def_id_for_ty_in_cycle: Option, @@ -161,11 +158,6 @@ pub trait QueryContext<'tcx>: HasDepContext { /// a token while waiting on a query. fn jobserver_proxy(&self) -> &Proxy; - fn collect_active_jobs_from_all_queries( - self, - require_complete: bool, - ) -> Result, QueryMap<'tcx>>; - /// Load a side effect associated to the node in the previous session. fn load_side_effect( self, From c750a1f5c49ba99f15de43fb651c7958012a12f2 Mon Sep 17 00:00:00 2001 From: AprilNEA Date: Mon, 9 Feb 2026 19:31:25 +0000 Subject: [PATCH 781/978] Add regression test for type_const with unit struct ctor under mGCA Unit struct constructors used as the RHS of a `type const` associated const used to ICE during normalization because they were lowered as `Const::new_unevaluated` with a Ctor def_id. The compiler now properly constructs a concrete ValTree value for const constructors. --- .../mgca/type-const-ctor-148953.rs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/ui/const-generics/mgca/type-const-ctor-148953.rs diff --git a/tests/ui/const-generics/mgca/type-const-ctor-148953.rs b/tests/ui/const-generics/mgca/type-const-ctor-148953.rs new file mode 100644 index 000000000000..bdd3dcf8618f --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-ctor-148953.rs @@ -0,0 +1,31 @@ +//! Regression test for +//! +//! Unit struct constructors used as the RHS of a `type const` associated +//! const used to ICE during normalization because they were lowered as +//! `Const::new_unevaluated` with a Ctor def_id. Fixed by adding proper const +//! constructor support that produces a concrete ValTree value instead. + +//@ check-pass + +#![feature(min_generic_const_args, adt_const_params)] +#![expect(incomplete_features)] + +use std::marker::ConstParamTy; + +#[derive(ConstParamTy, PartialEq, Eq)] +struct S; + +impl S { + type const N: S = S; +} + +#[derive(ConstParamTy, PartialEq, Eq)] +enum E { + V, +} + +impl E { + type const M: E = { E::V }; +} + +fn main() {} From 923de04f6a032ccd475dd271287db8faebf42c3f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 10 Feb 2026 11:53:47 +1100 Subject: [PATCH 782/978] Move `rustc_middle::query::values` to `rustc_query_impl`. Because all uses are now in `rustc_query_impl`. This was made possible by the previous commit. Less code in `rustc_middle`, hooray. --- Cargo.lock | 1 + compiler/rustc_middle/src/query/mod.rs | 1 - compiler/rustc_query_impl/Cargo.toml | 1 + compiler/rustc_query_impl/src/lib.rs | 3 ++- .../src/query => rustc_query_impl/src}/values.rs | 10 +++++----- 5 files changed, 9 insertions(+), 7 deletions(-) rename compiler/{rustc_middle/src/query => rustc_query_impl/src}/values.rs (98%) diff --git a/Cargo.lock b/Cargo.lock index 7230d633602d..741c51dcb3e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4493,6 +4493,7 @@ name = "rustc_query_impl" version = "0.0.0" dependencies = [ "measureme", + "rustc_abi", "rustc_data_structures", "rustc_errors", "rustc_hashes", diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index a7707cf48c49..24a38e70ff6f 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -13,7 +13,6 @@ mod keys; pub mod on_disk_cache; #[macro_use] pub mod plumbing; -pub mod values; pub fn describe_as_module(def_id: impl Into, tcx: TyCtxt<'_>) -> String { let def_id = def_id.into(); diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 511337090d7f..ee50ec073bc8 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -6,6 +6,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start measureme = "12.0.1" +rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hashes = { path = "../rustc_hashes" } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index c1ead8da344b..2241c3f44087 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -19,7 +19,6 @@ use rustc_middle::queries::{ use rustc_middle::query::AsLocalKey; use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; use rustc_middle::query::plumbing::{HashResult, QuerySystem, QuerySystemFns, QueryVTable}; -use rustc_middle::query::values::Value; use rustc_middle::ty::TyCtxt; use rustc_query_system::dep_graph::SerializedDepNodeIndex; use rustc_query_system::query::{ @@ -32,6 +31,7 @@ pub use crate::plumbing::{QueryCtxt, query_key_hash_verify_all}; use crate::plumbing::{encode_all_query_results, try_mark_green}; use crate::profiling_support::QueryKeyStringCache; pub use crate::profiling_support::alloc_self_profile_query_strings; +use crate::values::Value; mod error; mod execution; @@ -39,6 +39,7 @@ mod job; #[macro_use] mod plumbing; mod profiling_support; +mod values; #[derive(ConstParamTy)] // Allow this struct to be used for const-generic values. #[derive(Clone, Copy, Debug, PartialEq, Eq)] diff --git a/compiler/rustc_middle/src/query/values.rs b/compiler/rustc_query_impl/src/values.rs similarity index 98% rename from compiler/rustc_middle/src/query/values.rs rename to compiler/rustc_query_impl/src/values.rs index 0828758cc94e..2fe3808f3d6e 100644 --- a/compiler/rustc_middle/src/query/values.rs +++ b/compiler/rustc_query_impl/src/values.rs @@ -7,15 +7,15 @@ use rustc_errors::codes::*; use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; +use rustc_middle::dep_graph::dep_kinds; +use rustc_middle::query::plumbing::CyclePlaceholder; +use rustc_middle::ty::{self, Representability, Ty, TyCtxt}; +use rustc_middle::{bug, span_bug}; use rustc_query_system::query::{CycleError, report_cycle}; use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span}; -use crate::dep_graph::dep_kinds; -use crate::query::plumbing::CyclePlaceholder; -use crate::ty::{self, Representability, Ty, TyCtxt}; - -pub trait Value<'tcx>: Sized { +pub(crate) trait Value<'tcx>: Sized { fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed) -> Self; } From a34317e5a5641385706926b109bd259cbc8ec9b7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 10 Feb 2026 14:05:13 +1100 Subject: [PATCH 783/978] Move `report_cycle`. From `rustc_query_system::query::job` to `rustc_query_impl::job`. --- Cargo.lock | 1 + compiler/rustc_query_impl/Cargo.toml | 1 + compiler/rustc_query_impl/src/error.rs | 57 +++++++++++++++++++ compiler/rustc_query_impl/src/execution.rs | 3 +- compiler/rustc_query_impl/src/job.rs | 56 +++++++++++++++++- compiler/rustc_query_impl/src/values.rs | 4 +- compiler/rustc_query_system/src/error.rs | 60 +------------------- compiler/rustc_query_system/src/query/job.rs | 55 ------------------ compiler/rustc_query_system/src/query/mod.rs | 2 +- 9 files changed, 120 insertions(+), 119 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 741c51dcb3e7..3019ff581f37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4503,6 +4503,7 @@ dependencies = [ "rustc_middle", "rustc_query_system", "rustc_serialize", + "rustc_session", "rustc_span", "rustc_thread_pool", "tracing", diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index ee50ec073bc8..a8edc1129481 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -16,6 +16,7 @@ rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_query_system = { path = "../rustc_query_system" } rustc_serialize = { path = "../rustc_serialize" } +rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_thread_pool = { path = "../rustc_thread_pool" } tracing = "0.1" diff --git a/compiler/rustc_query_impl/src/error.rs b/compiler/rustc_query_impl/src/error.rs index b109172d8e49..6d3eb2950982 100644 --- a/compiler/rustc_query_impl/src/error.rs +++ b/compiler/rustc_query_impl/src/error.rs @@ -1,3 +1,4 @@ +use rustc_errors::codes::*; use rustc_hir::limit::Limit; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; @@ -22,3 +23,59 @@ pub(crate) struct QueryOverflowNote { pub desc: String, pub depth: usize, } + +#[derive(Subdiagnostic)] +#[note("...which requires {$desc}...")] +pub(crate) struct CycleStack { + #[primary_span] + pub span: Span, + pub desc: String, +} + +#[derive(Subdiagnostic)] +pub(crate) enum StackCount { + #[note("...which immediately requires {$stack_bottom} again")] + Single, + #[note("...which again requires {$stack_bottom}, completing the cycle")] + Multiple, +} + +#[derive(Subdiagnostic)] +pub(crate) enum Alias { + #[note("type aliases cannot be recursive")] + #[help("consider using a struct, enum, or union instead to break the cycle")] + #[help( + "see for more information" + )] + Ty, + #[note("trait aliases cannot be recursive")] + Trait, +} + +#[derive(Subdiagnostic)] +#[note("cycle used when {$usage}")] +pub(crate) struct CycleUsage { + #[primary_span] + pub span: Span, + pub usage: String, +} + +#[derive(Diagnostic)] +#[diag("cycle detected when {$stack_bottom}", code = E0391)] +pub(crate) struct Cycle { + #[primary_span] + pub span: Span, + pub stack_bottom: String, + #[subdiagnostic] + pub cycle_stack: Vec, + #[subdiagnostic] + pub stack_count: StackCount, + #[subdiagnostic] + pub alias: Option, + #[subdiagnostic] + pub cycle_usage: Option, + #[note( + "see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information" + )] + pub note_span: (), +} diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 6f16932cb2eb..d7e95d43ecaa 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -11,12 +11,11 @@ use rustc_query_system::dep_graph::{DepGraphData, DepNodeKey, HasDepContext}; use rustc_query_system::query::{ ActiveKeyStatus, CycleError, CycleErrorHandling, QueryCache, QueryJob, QueryJobId, QueryLatch, QueryMode, QueryStackDeferred, QueryStackFrame, QueryState, incremental_verify_ich, - report_cycle, }; use rustc_span::{DUMMY_SP, Span}; use crate::dep_graph::{DepContext, DepNode, DepNodeIndex}; -use crate::job::{QueryJobInfo, QueryMap, find_cycle_in_stack}; +use crate::job::{QueryJobInfo, QueryMap, find_cycle_in_stack, report_cycle}; use crate::{QueryCtxt, QueryFlags, SemiDynamicQueryDispatcher}; #[inline] diff --git a/compiler/rustc_query_impl/src/job.rs b/compiler/rustc_query_impl/src/job.rs index cb0a13d32ad2..f1eba0f76d17 100644 --- a/compiler/rustc_query_impl/src/job.rs +++ b/compiler/rustc_query_impl/src/job.rs @@ -3,11 +3,13 @@ use std::iter; use std::sync::Arc; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::DiagCtxtHandle; +use rustc_errors::{Diag, DiagCtxtHandle}; +use rustc_hir::def::DefKind; use rustc_query_system::query::{ CycleError, QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryStackDeferred, QueryStackFrame, QueryWaiter, }; +use rustc_session::Session; use rustc_span::{DUMMY_SP, Span}; use crate::QueryCtxt; @@ -444,3 +446,55 @@ pub fn print_query_stack<'tcx>( } count_total } + +#[inline(never)] +#[cold] +pub(crate) fn report_cycle<'a>( + sess: &'a Session, + CycleError { usage, cycle: stack }: &CycleError, +) -> Diag<'a> { + assert!(!stack.is_empty()); + + let span = stack[0].frame.info.default_span(stack[1 % stack.len()].span); + + let mut cycle_stack = Vec::new(); + + use crate::error::StackCount; + let stack_count = if stack.len() == 1 { StackCount::Single } else { StackCount::Multiple }; + + for i in 1..stack.len() { + let frame = &stack[i].frame; + let span = frame.info.default_span(stack[(i + 1) % stack.len()].span); + cycle_stack + .push(crate::error::CycleStack { span, desc: frame.info.description.to_owned() }); + } + + let mut cycle_usage = None; + if let Some((span, ref query)) = *usage { + cycle_usage = Some(crate::error::CycleUsage { + span: query.info.default_span(span), + usage: query.info.description.to_string(), + }); + } + + let alias = + if stack.iter().all(|entry| matches!(entry.frame.info.def_kind, Some(DefKind::TyAlias))) { + Some(crate::error::Alias::Ty) + } else if stack.iter().all(|entry| entry.frame.info.def_kind == Some(DefKind::TraitAlias)) { + Some(crate::error::Alias::Trait) + } else { + None + }; + + let cycle_diag = crate::error::Cycle { + span, + cycle_stack, + stack_bottom: stack[0].frame.info.description.to_owned(), + alias, + cycle_usage, + stack_count, + note_span: (), + }; + + sess.dcx().create_err(cycle_diag) +} diff --git a/compiler/rustc_query_impl/src/values.rs b/compiler/rustc_query_impl/src/values.rs index 2fe3808f3d6e..783e7a10d12a 100644 --- a/compiler/rustc_query_impl/src/values.rs +++ b/compiler/rustc_query_impl/src/values.rs @@ -11,10 +11,12 @@ use rustc_middle::dep_graph::dep_kinds; use rustc_middle::query::plumbing::CyclePlaceholder; use rustc_middle::ty::{self, Representability, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; -use rustc_query_system::query::{CycleError, report_cycle}; +use rustc_query_system::query::CycleError; use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span}; +use crate::job::report_cycle; + pub(crate) trait Value<'tcx>: Sized { fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed) -> Self; diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs index adce85bf31be..f48afe6f75fa 100644 --- a/compiler/rustc_query_system/src/error.rs +++ b/compiler/rustc_query_system/src/error.rs @@ -1,62 +1,4 @@ -use rustc_errors::codes::*; -use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_span::Span; - -#[derive(Subdiagnostic)] -#[note("...which requires {$desc}...")] -pub(crate) struct CycleStack { - #[primary_span] - pub span: Span, - pub desc: String, -} - -#[derive(Subdiagnostic)] -pub(crate) enum StackCount { - #[note("...which immediately requires {$stack_bottom} again")] - Single, - #[note("...which again requires {$stack_bottom}, completing the cycle")] - Multiple, -} - -#[derive(Subdiagnostic)] -pub(crate) enum Alias { - #[note("type aliases cannot be recursive")] - #[help("consider using a struct, enum, or union instead to break the cycle")] - #[help( - "see for more information" - )] - Ty, - #[note("trait aliases cannot be recursive")] - Trait, -} - -#[derive(Subdiagnostic)] -#[note("cycle used when {$usage}")] -pub(crate) struct CycleUsage { - #[primary_span] - pub span: Span, - pub usage: String, -} - -#[derive(Diagnostic)] -#[diag("cycle detected when {$stack_bottom}", code = E0391)] -pub(crate) struct Cycle { - #[primary_span] - pub span: Span, - pub stack_bottom: String, - #[subdiagnostic] - pub cycle_stack: Vec, - #[subdiagnostic] - pub stack_count: StackCount, - #[subdiagnostic] - pub alias: Option, - #[subdiagnostic] - pub cycle_usage: Option, - #[note( - "see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information" - )] - pub note_span: (), -} +use rustc_macros::Diagnostic; #[derive(Diagnostic)] #[diag("internal compiler error: reentrant incremental verify failure, suppressing message")] diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index e8acb8064f7e..7349fe223ef9 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -4,13 +4,9 @@ use std::num::NonZero; use std::sync::Arc; use parking_lot::{Condvar, Mutex}; -use rustc_errors::Diag; -use rustc_hir::def::DefKind; -use rustc_session::Session; use rustc_span::Span; use super::{QueryStackDeferred, QueryStackFrameExtra}; -use crate::error::CycleStack; use crate::query::plumbing::CycleError; use crate::query::{QueryContext, QueryStackFrame}; @@ -163,54 +159,3 @@ impl<'tcx> QueryLatch<'tcx> { info.waiters.remove(waiter) } } - -#[inline(never)] -#[cold] -pub fn report_cycle<'a>( - sess: &'a Session, - CycleError { usage, cycle: stack }: &CycleError, -) -> Diag<'a> { - assert!(!stack.is_empty()); - - let span = stack[0].frame.info.default_span(stack[1 % stack.len()].span); - - let mut cycle_stack = Vec::new(); - - use crate::error::StackCount; - let stack_count = if stack.len() == 1 { StackCount::Single } else { StackCount::Multiple }; - - for i in 1..stack.len() { - let frame = &stack[i].frame; - let span = frame.info.default_span(stack[(i + 1) % stack.len()].span); - cycle_stack.push(CycleStack { span, desc: frame.info.description.to_owned() }); - } - - let mut cycle_usage = None; - if let Some((span, ref query)) = *usage { - cycle_usage = Some(crate::error::CycleUsage { - span: query.info.default_span(span), - usage: query.info.description.to_string(), - }); - } - - let alias = - if stack.iter().all(|entry| matches!(entry.frame.info.def_kind, Some(DefKind::TyAlias))) { - Some(crate::error::Alias::Ty) - } else if stack.iter().all(|entry| entry.frame.info.def_kind == Some(DefKind::TraitAlias)) { - Some(crate::error::Alias::Trait) - } else { - None - }; - - let cycle_diag = crate::error::Cycle { - span, - cycle_stack, - stack_bottom: stack[0].frame.info.description.to_owned(), - alias, - cycle_usage, - stack_count, - note_span: (), - }; - - sess.dcx().create_err(cycle_diag) -} diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 6067f7dafd5c..c33af941f802 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -15,7 +15,7 @@ use rustc_span::def_id::DefId; pub use self::caches::{ DefIdCache, DefaultCache, QueryCache, QueryCacheKey, SingleCache, VecCache, }; -pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter, report_cycle}; +pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter}; pub use self::plumbing::*; use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; From 0ebd56ebbbf3e392c4fc81865ce89fc6f765a885 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 4 Dec 2025 11:49:56 +0000 Subject: [PATCH 784/978] Remove accidental const stability marker on a struct --- library/core/src/array/drain.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/array/drain.rs b/library/core/src/array/drain.rs index 1c6137191324..17792dca583d 100644 --- a/library/core/src/array/drain.rs +++ b/library/core/src/array/drain.rs @@ -31,7 +31,6 @@ impl<'l, 'f, T, U, const N: usize, F: FnMut(T) -> U> Drain<'l, 'f, T, N, F> { } /// See [`Drain::new`]; this is our fake iterator. -#[rustc_const_unstable(feature = "array_try_map", issue = "79711")] #[unstable(feature = "array_try_map", issue = "79711")] pub(super) struct Drain<'l, 'f, T, const N: usize, F> { // FIXME(const-hack): This is essentially a slice::IterMut<'static>, replace when possible. From 00fef81964699283c09a244c6fb53840eada28e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sat, 7 Feb 2026 17:57:43 +0100 Subject: [PATCH 785/978] Port `rustc_expected_cgu_reuse` to the new attribute parser --- Cargo.lock | 1 - .../src/attributes/rustc_internal.rs | 145 +++++++++++++++- compiler/rustc_attr_parsing/src/context.rs | 1 + .../src/session_diagnostics.rs | 9 + compiler/rustc_codegen_ssa/Cargo.toml | 1 - .../src/assert_module_sources.rs | 160 ++++++++---------- compiler/rustc_codegen_ssa/src/errors.rs | 30 +--- .../rustc_hir/src/attrs/data_structures.rs | 16 ++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 4 +- 10 files changed, 244 insertions(+), 124 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 545c776b4805..1a930b64f458 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3687,7 +3687,6 @@ dependencies = [ "serde_json", "smallvec", "tempfile", - "thin-vec", "thorin-dwp", "tracing", "wasm-encoder 0.219.2", diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 0fd8c8a04a57..e5ea7fde3954 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -2,7 +2,8 @@ use std::path::PathBuf; use rustc_ast::{LitIntType, LitKind, MetaItemLit}; use rustc_hir::attrs::{ - BorrowckGraphvizFormatKind, RustcCleanAttribute, RustcCleanQueries, RustcLayoutType, + BorrowckGraphvizFormatKind, CguFields, CguKind, DivergingBlockBehavior, + DivergingFallbackBehavior, RustcCleanAttribute, RustcCleanQueries, RustcLayoutType, RustcMirKind, }; use rustc_session::errors; @@ -10,7 +11,9 @@ use rustc_span::Symbol; use super::prelude::*; use super::util::parse_single_integer; -use crate::session_diagnostics::{AttributeRequiresOpt, RustcScalableVectorCountOutOfRange}; +use crate::session_diagnostics::{ + AttributeRequiresOpt, CguFieldsMissing, RustcScalableVectorCountOutOfRange, +}; pub(crate) struct RustcMainParser; @@ -204,6 +207,144 @@ impl NoArgsAttributeParser for RustcLintOptTyParser { const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintOptTy; } +fn parse_cgu_fields( + cx: &mut AcceptContext<'_, '_, S>, + args: &ArgParser, + accepts_kind: bool, +) -> Option<(Symbol, Symbol, Option)> { + let Some(args) = args.list() else { + cx.expected_list(cx.attr_span, args); + return None; + }; + + let mut cfg = None::<(Symbol, Span)>; + let mut module = None::<(Symbol, Span)>; + let mut kind = None::<(Symbol, Span)>; + + for arg in args.mixed() { + let Some(arg) = arg.meta_item() else { + cx.expected_name_value(args.span, None); + continue; + }; + + let res = match arg.ident().map(|i| i.name) { + Some(sym::cfg) => &mut cfg, + Some(sym::module) => &mut module, + Some(sym::kind) if accepts_kind => &mut kind, + _ => { + cx.expected_specific_argument( + arg.path().span(), + if accepts_kind { + &[sym::cfg, sym::module, sym::kind] + } else { + &[sym::cfg, sym::module] + }, + ); + continue; + } + }; + + let Some(i) = arg.args().name_value() else { + cx.expected_name_value(arg.span(), None); + continue; + }; + + let Some(str) = i.value_as_str() else { + cx.expected_string_literal(i.value_span, Some(i.value_as_lit())); + continue; + }; + + if res.is_some() { + cx.duplicate_key(arg.span(), arg.ident().unwrap().name); + continue; + } + + *res = Some((str, i.value_span)); + } + + let Some((cfg, _)) = cfg else { + cx.emit_err(CguFieldsMissing { span: args.span, name: &cx.attr_path, field: sym::cfg }); + return None; + }; + let Some((module, _)) = module else { + cx.emit_err(CguFieldsMissing { span: args.span, name: &cx.attr_path, field: sym::module }); + return None; + }; + let kind = if let Some((kind, span)) = kind { + Some(match kind { + sym::no => CguKind::No, + sym::pre_dash_lto => CguKind::PreDashLto, + sym::post_dash_lto => CguKind::PostDashLto, + sym::any => CguKind::Any, + _ => { + cx.expected_specific_argument_strings( + span, + &[sym::no, sym::pre_dash_lto, sym::post_dash_lto, sym::any], + ); + return None; + } + }) + } else { + // return None so that an unwrap for the attributes that need it is ok. + if accepts_kind { + cx.emit_err(CguFieldsMissing { + span: args.span, + name: &cx.attr_path, + field: sym::kind, + }); + return None; + }; + + None + }; + + Some((cfg, module, kind)) +} + +#[derive(Default)] +pub(crate) struct RustcCguTestAttributeParser { + items: ThinVec<(Span, CguFields)>, +} + +impl AttributeParser for RustcCguTestAttributeParser { + const ATTRIBUTES: AcceptMapping = &[ + ( + &[sym::rustc_partition_reused], + template!(List: &[r#"cfg = "...", module = "...""#]), + |this, cx, args| { + this.items.extend(parse_cgu_fields(cx, args, false).map(|(cfg, module, _)| { + (cx.attr_span, CguFields::PartitionReused { cfg, module }) + })); + }, + ), + ( + &[sym::rustc_partition_codegened], + template!(List: &[r#"cfg = "...", module = "...""#]), + |this, cx, args| { + this.items.extend(parse_cgu_fields(cx, args, false).map(|(cfg, module, _)| { + (cx.attr_span, CguFields::PartitionCodegened { cfg, module }) + })); + }, + ), + ( + &[sym::rustc_expected_cgu_reuse], + template!(List: &[r#"cfg = "...", module = "...", kind = "...""#]), + |this, cx, args| { + this.items.extend(parse_cgu_fields(cx, args, true).map(|(cfg, module, kind)| { + // unwrap ok because if not given, we return None in `parse_cgu_fields`. + (cx.attr_span, CguFields::ExpectedCguReuse { cfg, module, kind: kind.unwrap() }) + })); + }, + ), + ]; + + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowList(&[Allow(Target::Mod), Allow(Target::Crate)]); + + fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option { + Some(AttributeKind::RustcCguTestAttr(self.items)) + } +} pub(crate) struct RustcLintQueryInstabilityParser; impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 412f960fb7cf..f53f48b337b5 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -149,6 +149,7 @@ attribute_parsers!( NakedParser, StabilityParser, UsedParser, + RustcCguTestAttributeParser, // tidy-alphabetical-end // tidy-alphabetical-start diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 6ca47e8d698b..2eb585671fff 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -45,6 +45,15 @@ pub(crate) struct DocAliasStartEnd<'a> { pub attr_str: &'a str, } +#[derive(Diagnostic)] +#[diag("`#[{$name})]` is missing a `{$field}` argument")] +pub(crate) struct CguFieldsMissing<'a> { + #[primary_span] + pub span: Span, + pub name: &'a AttrPath, + pub field: Symbol, +} + #[derive(Diagnostic)] #[diag("`#![doc({$attr_name} = \"...\")]` isn't allowed as a crate-level attribute")] pub(crate) struct DocAttrNotCrateLevel { diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 864220635120..c7d7b7429f34 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -36,7 +36,6 @@ rustc_trait_selection = { path = "../rustc_trait_selection" } serde_json = "1.0.59" smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tempfile = "3.2" -thin-vec = "0.2.12" thorin-dwp = "0.9" tracing = "0.1" wasm-encoder = "0.219" diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index 43e1e135a666..081fe0aa91aa 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -28,13 +28,13 @@ use std::fmt; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::{DiagArgValue, IntoDiagArg}; -use rustc_hir as hir; +use rustc_hir::attrs::{AttributeKind, CguFields, CguKind}; use rustc_hir::def_id::LOCAL_CRATE; +use rustc_hir::{self as hir, find_attr}; use rustc_middle::mir::mono::CodegenUnitNameBuilder; use rustc_middle::ty::TyCtxt; use rustc_session::Session; -use rustc_span::{Span, Symbol, sym}; -use thin_vec::ThinVec; +use rustc_span::{Span, Symbol}; use tracing::debug; use crate::errors; @@ -63,9 +63,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>, set_reuse: &dyn Fn(&mut CguReuseTr }, }; - for attr in tcx.hir_attrs(rustc_hir::CRATE_HIR_ID) { - ams.check_attr(attr); - } + ams.check_attrs(tcx.hir_attrs(rustc_hir::CRATE_HIR_ID)); set_reuse(&mut ams.cgu_reuse_tracker); @@ -89,109 +87,91 @@ struct AssertModuleSource<'tcx> { } impl<'tcx> AssertModuleSource<'tcx> { - fn check_attr(&mut self, attr: &hir::Attribute) { - let (expected_reuse, comp_kind) = if attr.has_name(sym::rustc_partition_reused) { - (CguReuse::PreLto, ComparisonKind::AtLeast) - } else if attr.has_name(sym::rustc_partition_codegened) { - (CguReuse::No, ComparisonKind::Exact) - } else if attr.has_name(sym::rustc_expected_cgu_reuse) { - match self.field(attr, sym::kind) { - sym::no => (CguReuse::No, ComparisonKind::Exact), - sym::pre_dash_lto => (CguReuse::PreLto, ComparisonKind::Exact), - sym::post_dash_lto => (CguReuse::PostLto, ComparisonKind::Exact), - sym::any => (CguReuse::PreLto, ComparisonKind::AtLeast), - other => { - self.tcx - .dcx() - .emit_fatal(errors::UnknownReuseKind { span: attr.span(), kind: other }); - } + fn check_attrs(&mut self, attrs: &[hir::Attribute]) { + for &(span, cgu_fields) in find_attr!(attrs, + AttributeKind::RustcCguTestAttr(e) => e) + .into_iter() + .flatten() + { + let (expected_reuse, comp_kind) = match cgu_fields { + CguFields::PartitionReused { .. } => (CguReuse::PreLto, ComparisonKind::AtLeast), + CguFields::PartitionCodegened { .. } => (CguReuse::No, ComparisonKind::Exact), + CguFields::ExpectedCguReuse { kind, .. } => match kind { + CguKind::No => (CguReuse::No, ComparisonKind::Exact), + CguKind::PreDashLto => (CguReuse::PreLto, ComparisonKind::Exact), + CguKind::PostDashLto => (CguReuse::PostLto, ComparisonKind::Exact), + CguKind::Any => (CguReuse::PreLto, ComparisonKind::AtLeast), + }, + }; + let (CguFields::ExpectedCguReuse { cfg, module, .. } + | CguFields::PartitionCodegened { cfg, module } + | CguFields::PartitionReused { cfg, module }) = cgu_fields; + + if !self.tcx.sess.opts.unstable_opts.query_dep_graph { + self.tcx.dcx().emit_fatal(errors::MissingQueryDepGraph { span }); } - } else { - return; - }; - if !self.tcx.sess.opts.unstable_opts.query_dep_graph { - self.tcx.dcx().emit_fatal(errors::MissingQueryDepGraph { span: attr.span() }); - } + if !self.check_config(cfg) { + debug!("check_attr: config does not match, ignoring attr"); + return; + } - if !self.check_config(attr) { - debug!("check_attr: config does not match, ignoring attr"); - return; - } + let user_path = module.as_str(); + let crate_name = self.tcx.crate_name(LOCAL_CRATE); + let crate_name = crate_name.as_str(); - let user_path = self.field(attr, sym::module).to_string(); - let crate_name = self.tcx.crate_name(LOCAL_CRATE).to_string(); + if !user_path.starts_with(&crate_name) { + self.tcx.dcx().emit_fatal(errors::MalformedCguName { span, user_path, crate_name }); + } - if !user_path.starts_with(&crate_name) { - self.tcx.dcx().emit_fatal(errors::MalformedCguName { - span: attr.span(), - user_path, - crate_name, - }); - } + // Split of the "special suffix" if there is one. + let (user_path, cgu_special_suffix) = if let Some(index) = user_path.rfind('.') { + (&user_path[..index], Some(&user_path[index + 1..])) + } else { + (&user_path[..], None) + }; - // Split of the "special suffix" if there is one. - let (user_path, cgu_special_suffix) = if let Some(index) = user_path.rfind('.') { - (&user_path[..index], Some(&user_path[index + 1..])) - } else { - (&user_path[..], None) - }; + let mut iter = user_path.split('-'); - let mut iter = user_path.split('-'); + // Remove the crate name + assert_eq!(iter.next().unwrap(), crate_name); - // Remove the crate name - assert_eq!(iter.next().unwrap(), crate_name); + let cgu_path_components = iter.collect::>(); - let cgu_path_components = iter.collect::>(); + let cgu_name_builder = &mut CodegenUnitNameBuilder::new(self.tcx); + let cgu_name = cgu_name_builder.build_cgu_name( + LOCAL_CRATE, + cgu_path_components, + cgu_special_suffix, + ); - let cgu_name_builder = &mut CodegenUnitNameBuilder::new(self.tcx); - let cgu_name = - cgu_name_builder.build_cgu_name(LOCAL_CRATE, cgu_path_components, cgu_special_suffix); + debug!("mapping '{user_path}' to cgu name '{cgu_name}'"); - debug!("mapping '{}' to cgu name '{}'", self.field(attr, sym::module), cgu_name); + if !self.available_cgus.contains(&cgu_name) { + let cgu_names: Vec<&str> = + self.available_cgus.items().map(|cgu| cgu.as_str()).into_sorted_stable_ord(); + self.tcx.dcx().emit_err(errors::NoModuleNamed { + span, + user_path, + cgu_name, + cgu_names: cgu_names.join(", "), + }); + } - if !self.available_cgus.contains(&cgu_name) { - let cgu_names: Vec<&str> = - self.available_cgus.items().map(|cgu| cgu.as_str()).into_sorted_stable_ord(); - self.tcx.dcx().emit_err(errors::NoModuleNamed { - span: attr.span(), - user_path, + self.cgu_reuse_tracker.set_expectation( cgu_name, - cgu_names: cgu_names.join(", "), - }); + user_path, + span, + expected_reuse, + comp_kind, + ); } - - self.cgu_reuse_tracker.set_expectation( - cgu_name, - user_path, - attr.span(), - expected_reuse, - comp_kind, - ); - } - - fn field(&self, attr: &hir::Attribute, name: Symbol) -> Symbol { - for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) { - if item.has_name(name) { - if let Some(value) = item.value_str() { - return value; - } else { - self.tcx.dcx().emit_fatal(errors::FieldAssociatedValueExpected { - span: item.span(), - name, - }); - } - } - } - - self.tcx.dcx().emit_fatal(errors::NoField { span: attr.span(), name }); } /// Scan for a `cfg="foo"` attribute and check whether we have a /// cfg flag called `foo`. - fn check_config(&self, attr: &hir::Attribute) -> bool { + fn check_config(&self, value: Symbol) -> bool { let config = &self.tcx.sess.psess.config; - let value = self.field(attr, sym::cfg); debug!("check_config(config={:?}, value={:?})", config, value); if config.iter().any(|&(name, _)| name == value) { debug!("check_config: matched"); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 82a6525adcc9..897b5f957e15 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -42,14 +42,6 @@ pub(crate) struct CguNotRecorded<'a> { pub cgu_name: &'a str, } -#[derive(Diagnostic)] -#[diag("unknown cgu-reuse-kind `{$kind}` specified")] -pub(crate) struct UnknownReuseKind { - #[primary_span] - pub span: Span, - pub kind: Symbol, -} - #[derive(Diagnostic)] #[diag("found CGU-reuse attribute but `-Zquery-dep-graph` was not specified")] pub(crate) struct MissingQueryDepGraph { @@ -61,11 +53,11 @@ pub(crate) struct MissingQueryDepGraph { #[diag( "found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case)" )] -pub(crate) struct MalformedCguName { +pub(crate) struct MalformedCguName<'a> { #[primary_span] pub span: Span, - pub user_path: String, - pub crate_name: String, + pub user_path: &'a str, + pub crate_name: &'a str, } #[derive(Diagnostic)] @@ -78,22 +70,6 @@ pub(crate) struct NoModuleNamed<'a> { pub cgu_names: String, } -#[derive(Diagnostic)] -#[diag("associated value expected for `{$name}`")] -pub(crate) struct FieldAssociatedValueExpected { - #[primary_span] - pub span: Span, - pub name: Symbol, -} - -#[derive(Diagnostic)] -#[diag("no field `{$name}`")] -pub(crate) struct NoField { - #[primary_span] - pub span: Span, - pub name: Symbol, -} - #[derive(Diagnostic)] #[diag("failed to write lib.def file: {$error}")] pub(crate) struct LibDefWriteFailure { diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 2d3825ccd024..982c69c38afb 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -50,6 +50,19 @@ pub struct EiiDecl { } #[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, PrintAttribute)] +pub enum CguKind { + No, + PreDashLto, + PostDashLto, + Any, +} + +#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, PrintAttribute)] +pub enum CguFields { + PartitionReused { cfg: Symbol, module: Symbol }, + PartitionCodegened { cfg: Symbol, module: Symbol }, + ExpectedCguReuse { cfg: Symbol, module: Symbol, kind: CguKind }, +} pub enum InlineAttr { None, Hint, @@ -1117,6 +1130,9 @@ pub enum AttributeKind { /// Represents `#[rustc_evaluate_where_clauses]` RustcEvaluateWhereClauses, + /// Represents `#[rustc_expected_cgu_reuse]`, `#[rustc_partition_codegened]` and `#[rustc_partition_reused]`. + RustcCguTestAttr(ThinVec<(Span, CguFields)>), + /// Represents `#[rustc_has_incoherent_inherent_impls]` RustcHasIncoherentInherentImpls, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index ac9ef79e9ab9..116cda09657a 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -146,6 +146,7 @@ impl AttributeKind { RustcOffloadKernel => Yes, RustcOutlives => No, RustcParenSugar(..) => No, + RustcCguTestAttr { .. } => No, RustcPassByValue(..) => Yes, RustcPassIndirectlyInNonRusticAbis(..) => No, RustcPreserveUbChecks => No, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 0ba4450b1722..c8047e517616 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -338,6 +338,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcOffloadKernel | AttributeKind::RustcOutlives | AttributeKind::RustcParenSugar(..) + | AttributeKind::RustcCguTestAttr(..) | AttributeKind::RustcPassByValue (..) | AttributeKind::RustcPassIndirectlyInNonRusticAbis(..) | AttributeKind::RustcPreserveUbChecks @@ -407,9 +408,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_autodiff | sym::rustc_capture_analysis | sym::rustc_mir - | sym::rustc_partition_reused - | sym::rustc_partition_codegened - | sym::rustc_expected_cgu_reuse // crate-level attrs, are checked below | sym::feature | sym::register_tool From 9cc2924959717d5ef9db5c9cdb1060a6ac4cd9ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sat, 7 Feb 2026 17:57:43 +0100 Subject: [PATCH 786/978] Port `rustc_deprecated_safe_2024` to the new attribute parser --- .../src/attributes/rustc_internal.rs | 50 +++++++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + .../rustc_hir/src/attrs/data_structures.rs | 3 ++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + .../rustc_mir_build/src/check_unsafety.rs | 29 +++-------- compiler/rustc_passes/src/check_attr.rs | 2 +- 6 files changed, 63 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index e5ea7fde3954..96f386639803 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -345,6 +345,56 @@ impl AttributeParser for RustcCguTestAttributeParser { Some(AttributeKind::RustcCguTestAttr(self.items)) } } + +pub(crate) struct RustcDeprecatedSafe2024Parser; + +impl SingleAttributeParser for RustcDeprecatedSafe2024Parser { + const PATH: &[Symbol] = &[sym::rustc_deprecated_safe_2024]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; + const TEMPLATE: AttributeTemplate = template!(List: &[r#"audit_that = "...""#]); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(args) = args.list() else { + cx.expected_list(cx.attr_span, args); + return None; + }; + + let Some(single) = args.single() else { + cx.expected_single_argument(args.span); + return None; + }; + + let Some(arg) = single.meta_item() else { + cx.expected_name_value(args.span, None); + return None; + }; + + let Some(args) = arg.word_is(sym::audit_that) else { + cx.expected_specific_argument(arg.span(), &[sym::audit_that]); + return None; + }; + + let Some(nv) = args.name_value() else { + cx.expected_name_value(arg.span(), Some(sym::audit_that)); + return None; + }; + + let Some(suggestion) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + return None; + }; + + Some(AttributeKind::RustcDeprecatedSafe2024 { suggestion }) + } +} pub(crate) struct RustcLintQueryInstabilityParser; impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index f53f48b337b5..75f48bb39528 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -202,6 +202,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 982c69c38afb..d9da0633365e 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1103,6 +1103,9 @@ pub enum AttributeKind { /// Represents `#[rustc_deny_explicit_impl]`. RustcDenyExplicitImpl(Span), + /// Represents `#[rustc_deprecated_safe_2024]` + RustcDeprecatedSafe2024 { suggestion: Symbol }, + /// Represents `#[rustc_dummy]`. RustcDummy, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 116cda09657a..f26c5a07d430 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -108,6 +108,7 @@ impl AttributeKind { RustcDefPath(..) => No, RustcDelayedBugFromInsideQuery => No, RustcDenyExplicitImpl(..) => No, + RustcDeprecatedSafe2024 { .. } => Yes, RustcDummy => No, RustcDumpDefParents => No, RustcDumpItemBounds => No, diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 4a20b05d1fc2..7bced8168bd1 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::lint::Level; use rustc_session::lint::builtin::{DEPRECATED_SAFE_2024, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_span::def_id::{DefId, LocalDefId}; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Span, Symbol}; use crate::builder::ExprCategory; use crate::errors::*; @@ -98,29 +98,14 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { // from an edition before 2024. &UnsafeOpKind::CallToUnsafeFunction(Some(id)) if !span.at_least_rust_2024() - && let Some(attr) = self.tcx.get_attr(id, sym::rustc_deprecated_safe_2024) => + && let Some(suggestion) = find_attr!(self.tcx.get_all_attrs(id), AttributeKind::RustcDeprecatedSafe2024{suggestion} => suggestion) => { - let suggestion = attr - .meta_item_list() - .unwrap_or_default() - .into_iter() - .find(|item| item.has_name(sym::audit_that)) - .map(|item| { - item.value_str().expect( - "`#[rustc_deprecated_safe_2024(audit_that)]` must have a string value", - ) - }); - let sm = self.tcx.sess.source_map(); - let guarantee = suggestion - .as_ref() - .map(|suggestion| format!("that {}", suggestion)) - .unwrap_or_else(|| String::from("its unsafe preconditions")); - let suggestion = suggestion - .and_then(|suggestion| { - sm.indentation_before(span).map(|indent| { - format!("{}// TODO: Audit that {}.\n", indent, suggestion) // ignore-tidy-todo - }) + let guarantee = format!("that {}", suggestion); + let suggestion = sm + .indentation_before(span) + .map(|indent| { + format!("{}// TODO: Audit that {}.\n", indent, suggestion) // ignore-tidy-todo }) .unwrap_or_default(); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c8047e517616..738a8aaeaf7a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -303,6 +303,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcDefPath(..) | AttributeKind::RustcDelayedBugFromInsideQuery | AttributeKind::RustcDenyExplicitImpl(..) + | AttributeKind::RustcDeprecatedSafe2024 {..} | AttributeKind::RustcDummy | AttributeKind::RustcDumpDefParents | AttributeKind::RustcDumpItemBounds @@ -400,7 +401,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_do_not_const_check | sym::rustc_doc_primitive | sym::rustc_conversion_suggestion - | sym::rustc_deprecated_safe_2024 | sym::rustc_test_marker | sym::rustc_layout | sym::rustc_proc_macro_decls From 9d10b2ff370b0711bec5b542fa837a4f9f15400d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sat, 7 Feb 2026 17:57:43 +0100 Subject: [PATCH 787/978] Port `rustc_conversion_suggestion` to the new attribute parser --- .../src/attributes/rustc_internal.rs | 16 +++++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + .../rustc_hir/src/attrs/data_structures.rs | 3 +++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_hir_typeck/src/demand.rs | 27 +++++++++---------- compiler/rustc_passes/src/check_attr.rs | 2 +- 6 files changed, 35 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 96f386639803..73b8b2824b1a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -395,6 +395,22 @@ impl SingleAttributeParser for RustcDeprecatedSafe2024Parser { Some(AttributeKind::RustcDeprecatedSafe2024 { suggestion }) } } + +pub(crate) struct RustcConversionSuggestionParser; + +impl NoArgsAttributeParser for RustcConversionSuggestionParser { + const PATH: &[Symbol] = &[sym::rustc_conversion_suggestion]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcConversionSuggestion; +} + pub(crate) struct RustcLintQueryInstabilityParser; impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 75f48bb39528..c1889e9ec0e7 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -264,6 +264,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index d9da0633365e..0c5cb8e4ebff 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1091,6 +1091,9 @@ pub enum AttributeKind { /// Represents `#[rustc_const_stable_indirect]`. RustcConstStabilityIndirect, + /// Represents `#[rustc_conversion_suggestion]` + RustcConversionSuggestion, + /// Represents `#[rustc_deallocator]` RustcDeallocator, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index f26c5a07d430..3c81abdf3891 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -104,6 +104,7 @@ impl AttributeKind { RustcConfusables { .. } => Yes, RustcConstStability { .. } => Yes, RustcConstStabilityIndirect => No, + RustcConversionSuggestion => Yes, RustcDeallocator => No, RustcDefPath(..) => No, RustcDelayedBugFromInsideQuery => No, diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 84663ff884b4..68cbfa728058 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1,7 +1,8 @@ use rustc_errors::{Applicability, Diag, MultiSpan, listify}; -use rustc_hir as hir; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::Res; use rustc_hir::intravisit::Visitor; +use rustc_hir::{self as hir, find_attr}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_middle::bug; use rustc_middle::ty::adjustment::AllowTwoPhase; @@ -1081,19 +1082,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir_id, |m| { self.has_only_self_parameter(m) - && self - .tcx - // This special internal attribute is used to permit - // "identity-like" conversion methods to be suggested here. - // - // FIXME (#46459 and #46460): ideally - // `std::convert::Into::into` and `std::borrow:ToOwned` would - // also be `#[rustc_conversion_suggestion]`, if not for - // method-probing false-positives and -negatives (respectively). - // - // FIXME? Other potential candidate methods: `as_ref` and - // `as_mut`? - .has_attr(m.def_id, sym::rustc_conversion_suggestion) + // This special internal attribute is used to permit + // "identity-like" conversion methods to be suggested here. + // + // FIXME (#46459 and #46460): ideally + // `std::convert::Into::into` and `std::borrow:ToOwned` would + // also be `#[rustc_conversion_suggestion]`, if not for + // method-probing false-positives and -negatives (respectively). + // + // FIXME? Other potential candidate methods: `as_ref` and + // `as_mut`? + && find_attr!(self.tcx.get_all_attrs(m.def_id), AttributeKind::RustcConversionSuggestion) }, ); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 738a8aaeaf7a..8ca32179a445 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -299,6 +299,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcCoinductive(..) | AttributeKind::RustcConfusables { .. } | AttributeKind::RustcConstStabilityIndirect + | AttributeKind::RustcConversionSuggestion | AttributeKind::RustcDeallocator | AttributeKind::RustcDefPath(..) | AttributeKind::RustcDelayedBugFromInsideQuery @@ -400,7 +401,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_on_unimplemented | sym::rustc_do_not_const_check | sym::rustc_doc_primitive - | sym::rustc_conversion_suggestion | sym::rustc_test_marker | sym::rustc_layout | sym::rustc_proc_macro_decls From a17eb934db482303db43a78023e2e8e56e8e600b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sat, 7 Feb 2026 17:57:43 +0100 Subject: [PATCH 788/978] Port `rustc_capture_analysis` to the new attribute parser --- .../src/attributes/rustc_internal.rs | 9 +++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ compiler/rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_hir_typeck/src/upvar.rs | 10 +++++++--- compiler/rustc_passes/src/check_attr.rs | 1 + 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 73b8b2824b1a..52268def8718 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -411,6 +411,15 @@ impl NoArgsAttributeParser for RustcConversionSuggestionParser { const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcConversionSuggestion; } +pub(crate) struct RustcCaptureAnalysisParser; + +impl NoArgsAttributeParser for RustcCaptureAnalysisParser { + const PATH: &[Symbol] = &[sym::rustc_capture_analysis]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Closure)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCaptureAnalysis; +} + pub(crate) struct RustcLintQueryInstabilityParser; impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index c1889e9ec0e7..16e4a6452210 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -263,6 +263,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 0c5cb8e4ebff..09b51cef3c1a 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1066,6 +1066,9 @@ pub enum AttributeKind { /// Represents `#[rustc_builtin_macro]`. RustcBuiltinMacro { builtin_name: Option, helper_attrs: ThinVec, span: Span }, + /// Represents `#[rustc_capture_analysis]` + RustcCaptureAnalysis, + /// Represents `#[rustc_clean]` RustcClean(ThinVec), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 3c81abdf3891..4c68d51e6334 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -98,6 +98,7 @@ impl AttributeKind { RustcAsPtr(..) => Yes, RustcBodyStability { .. } => No, RustcBuiltinMacro { .. } => Yes, + RustcCaptureAnalysis => No, RustcClean { .. } => No, RustcCoherenceIsCore(..) => No, RustcCoinductive(..) => No, diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 1a2b76485f35..767913ba5261 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -36,10 +36,10 @@ use rustc_abi::FIRST_VARIANT; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::{ExtendUnord, UnordSet}; use rustc_errors::{Applicability, MultiSpan}; -use rustc_hir as hir; -use rustc_hir::HirId; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::{self as hir, HirId, find_attr}; use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind}; use rustc_middle::mir::FakeReadCause; use rustc_middle::traits::ObligationCauseCode; @@ -1743,7 +1743,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn should_log_capture_analysis(&self, closure_def_id: LocalDefId) -> bool { - self.has_rustc_attrs && self.tcx.has_attr(closure_def_id, sym::rustc_capture_analysis) + self.has_rustc_attrs + && find_attr!( + self.tcx.get_all_attrs(closure_def_id), + AttributeKind::RustcCaptureAnalysis + ) } fn log_capture_analysis_first_pass( diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 8ca32179a445..db5c33fcb17c 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -294,6 +294,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcAsPtr(..) | AttributeKind::RustcBodyStability { .. } | AttributeKind::RustcBuiltinMacro { .. } + | AttributeKind::RustcCaptureAnalysis | AttributeKind::RustcClean(..) | AttributeKind::RustcCoherenceIsCore(..) | AttributeKind::RustcCoinductive(..) From 1c45618335efce02aaf1bcc7235aedff7eae3629 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 10 Feb 2026 10:11:25 +0100 Subject: [PATCH 789/978] Update to LLVM 22 rc 3 --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 41256ab128f2..a306f6a8c534 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 41256ab128f2af613b4a16771cda6baa36b55f45 +Subproject commit a306f6a8c53494d32c171c346c6809c97124c697 From ea361287be9aa101d7ad50b81d216edc5222ce6f Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 10 Feb 2026 09:13:45 +0000 Subject: [PATCH 790/978] Remove SubdiagMessage in favour of the identical DiagMessage --- compiler/rustc_error_messages/src/lib.rs | 58 ---------- compiler/rustc_errors/src/diagnostic.rs | 108 ++++++------------ compiler/rustc_errors/src/lib.rs | 21 ++-- compiler/rustc_hir_typeck/src/method/mod.rs | 4 +- compiler/rustc_span/src/symbol.rs | 1 - .../src/diagnostics/translation.md | 12 +- .../clippy/clippy_utils/src/diagnostics.rs | 8 +- .../diagnostic-derive-doc-comment-field.rs | 2 +- .../diagnostic-derive-inline.rs | 2 +- .../subdiagnostic-derive-inline.rs | 2 +- 10 files changed, 56 insertions(+), 162 deletions(-) diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 916a370659aa..0b30102eb992 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -230,38 +230,6 @@ pub fn fallback_fluent_bundle( }))) } -/// Abstraction over a message in a subdiagnostic (i.e. label, note, help, etc) to support both -/// translatable and non-translatable diagnostic messages. -/// -/// Translatable messages for subdiagnostics are typically attributes attached to a larger Fluent -/// message so messages of this type must be combined with a `DiagMessage` (using -/// `DiagMessage::with_subdiagnostic_message`) before rendering. However, subdiagnostics from -/// the `Subdiagnostic` derive refer to Fluent identifiers directly. -#[rustc_diagnostic_item = "SubdiagMessage"] -pub enum SubdiagMessage { - /// Non-translatable diagnostic message. - Str(Cow<'static, str>), - /// An inline Fluent message. Instances of this variant are generated by the - /// `Subdiagnostic` derive. - Inline(Cow<'static, str>), -} - -impl From for SubdiagMessage { - fn from(s: String) -> Self { - SubdiagMessage::Str(Cow::Owned(s)) - } -} -impl From<&'static str> for SubdiagMessage { - fn from(s: &'static str) -> Self { - SubdiagMessage::Str(Cow::Borrowed(s)) - } -} -impl From> for SubdiagMessage { - fn from(s: Cow<'static, str>) -> Self { - SubdiagMessage::Str(s) - } -} - /// Abstraction over a message in a diagnostic to support both translatable and non-translatable /// diagnostic messages. /// @@ -281,18 +249,6 @@ pub enum DiagMessage { } impl DiagMessage { - /// Given a `SubdiagMessage` which may contain a Fluent attribute, create a new - /// `DiagMessage` that combines that attribute with the Fluent identifier of `self`. - /// - /// - If the `SubdiagMessage` is non-translatable then return the message as a `DiagMessage`. - /// - If `self` is non-translatable then return `self`'s message. - pub fn with_subdiagnostic_message(&self, sub: SubdiagMessage) -> Self { - match sub { - SubdiagMessage::Str(s) => DiagMessage::Str(s), - SubdiagMessage::Inline(s) => DiagMessage::Inline(s), - } - } - pub fn as_str(&self) -> Option<&str> { match self { DiagMessage::Str(s) => Some(s), @@ -317,20 +273,6 @@ impl From> for DiagMessage { } } -/// Translating *into* a subdiagnostic message from a diagnostic message is a little strange - but -/// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagMessage` and the -/// subdiagnostic derive refers to typed identifiers that are `DiagMessage`s, so need to be -/// able to convert between these, as much as they'll be converted back into `DiagMessage` -/// using `with_subdiagnostic_message` eventually. Don't use this other than for the derive. -impl From for SubdiagMessage { - fn from(val: DiagMessage) -> Self { - match val { - DiagMessage::Str(s) => SubdiagMessage::Str(s), - DiagMessage::Inline(s) => SubdiagMessage::Inline(s), - } - } -} - /// A span together with some additional data. #[derive(Clone, Debug)] pub struct SpanLabel { diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index a9e81354fc6a..087c5e700df0 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -17,8 +17,7 @@ use tracing::debug; use crate::{ CodeSuggestion, DiagCtxtHandle, DiagMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level, - MultiSpan, StashKey, Style, SubdiagMessage, Substitution, SubstitutionPart, SuggestionStyle, - Suggestions, + MultiSpan, StashKey, Style, Substitution, SubstitutionPart, SuggestionStyle, Suggestions, }; pub type DiagArgMap = FxIndexMap; @@ -325,30 +324,8 @@ impl DiagInner { } } - // See comment on `Diag::subdiagnostic_message_to_diagnostic_message`. - pub(crate) fn subdiagnostic_message_to_diagnostic_message( - &self, - attr: impl Into, - ) -> DiagMessage { - let msg = - self.messages.iter().map(|(msg, _)| msg).next().expect("diagnostic with no messages"); - msg.with_subdiagnostic_message(attr.into()) - } - - pub(crate) fn sub( - &mut self, - level: Level, - message: impl Into, - span: MultiSpan, - ) { - let sub = Subdiag { - level, - messages: vec![( - self.subdiagnostic_message_to_diagnostic_message(message), - Style::NoStyle, - )], - span, - }; + pub(crate) fn sub(&mut self, level: Level, message: impl Into, span: MultiSpan) { + let sub = Subdiag { level, messages: vec![(message.into(), Style::NoStyle)], span }; self.children.push(sub); } @@ -609,9 +586,8 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// the diagnostic was constructed. However, the label span is *not* considered a /// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is /// primary. - pub fn span_label(&mut self, span: Span, label: impl Into) -> &mut Self { - let msg = self.subdiagnostic_message_to_diagnostic_message(label); - self.span.push_span_label(span, msg); + pub fn span_label(&mut self, span: Span, label: impl Into) -> &mut Self { + self.span.push_span_label(span, label.into()); self } } @@ -713,7 +689,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_note, /// Add a note attached to this diagnostic. - pub fn note(&mut self, msg: impl Into) -> &mut Self { + pub fn note(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::Note, msg, MultiSpan::new()); self } } @@ -733,7 +709,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { } /// This is like [`Diag::note()`], but it's only printed once. - pub fn note_once(&mut self, msg: impl Into) -> &mut Self { + pub fn note_once(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::OnceNote, msg, MultiSpan::new()); self } @@ -744,7 +720,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_note( &mut self, sp: impl Into, - msg: impl Into, + msg: impl Into, ) -> &mut Self { self.sub(Level::Note, msg, sp.into()); self @@ -755,7 +731,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_note_once>( &mut self, sp: S, - msg: impl Into, + msg: impl Into, ) -> &mut Self { self.sub(Level::OnceNote, msg, sp.into()); self @@ -763,7 +739,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_warn, /// Add a warning attached to this diagnostic. - pub fn warn(&mut self, msg: impl Into) -> &mut Self { + pub fn warn(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::Warning, msg, MultiSpan::new()); self } } @@ -773,7 +749,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_warn>( &mut self, sp: S, - msg: impl Into, + msg: impl Into, ) -> &mut Self { self.sub(Level::Warning, msg, sp.into()); self @@ -781,13 +757,13 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { with_fn! { with_help, /// Add a help message attached to this diagnostic. - pub fn help(&mut self, msg: impl Into) -> &mut Self { + pub fn help(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::Help, msg, MultiSpan::new()); self } } /// This is like [`Diag::help()`], but it's only printed once. - pub fn help_once(&mut self, msg: impl Into) -> &mut Self { + pub fn help_once(&mut self, msg: impl Into) -> &mut Self { self.sub(Level::OnceHelp, msg, MultiSpan::new()); self } @@ -814,7 +790,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_help( &mut self, sp: impl Into, - msg: impl Into, + msg: impl Into, ) -> &mut Self { self.sub(Level::Help, msg, sp.into()); self @@ -866,7 +842,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// In other words, multiple changes need to be applied as part of this suggestion. pub fn multipart_suggestion( &mut self, - msg: impl Into, + msg: impl Into, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { @@ -882,7 +858,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// In other words, multiple changes need to be applied as part of this suggestion. pub fn multipart_suggestion_verbose( &mut self, - msg: impl Into, + msg: impl Into, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { @@ -897,7 +873,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// [`Diag::multipart_suggestion()`] but you can set the [`SuggestionStyle`]. pub fn multipart_suggestion_with_style( &mut self, - msg: impl Into, + msg: impl Into, mut suggestion: Vec<(Span, String)>, applicability: Applicability, style: SuggestionStyle, @@ -924,7 +900,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self.push_suggestion(CodeSuggestion { substitutions: vec![Substitution { parts }], - msg: self.subdiagnostic_message_to_diagnostic_message(msg), + msg: msg.into(), style, applicability, }); @@ -939,7 +915,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// improve understandability. pub fn tool_only_multipart_suggestion( &mut self, - msg: impl Into, + msg: impl Into, suggestion: Vec<(Span, String)>, applicability: Applicability, ) -> &mut Self { @@ -972,7 +948,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_suggestion( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -990,7 +966,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_suggestion_with_style( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, style: SuggestionStyle, @@ -1003,7 +979,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { substitutions: vec![Substitution { parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }], }], - msg: self.subdiagnostic_message_to_diagnostic_message(msg), + msg: msg.into(), style, applicability, }); @@ -1015,7 +991,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_suggestion_verbose( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -1035,7 +1011,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_suggestions( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestions: impl IntoIterator, applicability: Applicability, ) -> &mut Self { @@ -1051,7 +1027,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_suggestions_with_style( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestions: impl IntoIterator, applicability: Applicability, style: SuggestionStyle, @@ -1068,7 +1044,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { .collect(); self.push_suggestion(CodeSuggestion { substitutions, - msg: self.subdiagnostic_message_to_diagnostic_message(msg), + msg: msg.into(), style, applicability, }); @@ -1080,7 +1056,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// See also [`Diag::multipart_suggestion()`]. pub fn multipart_suggestions( &mut self, - msg: impl Into, + msg: impl Into, suggestions: impl IntoIterator>, applicability: Applicability, ) -> &mut Self { @@ -1112,7 +1088,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self.push_suggestion(CodeSuggestion { substitutions, - msg: self.subdiagnostic_message_to_diagnostic_message(msg), + msg: msg.into(), style: SuggestionStyle::ShowAlways, applicability, }); @@ -1127,7 +1103,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_suggestion_short( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -1150,7 +1126,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn span_suggestion_hidden( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -1172,7 +1148,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { pub fn tool_only_span_suggestion( &mut self, sp: Span, - msg: impl Into, + msg: impl Into, suggestion: impl ToString, applicability: Applicability, ) -> &mut Self { @@ -1200,10 +1176,9 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// one value will clobber the other. Eagerly translating the /// diagnostic uses the variables defined right then, before the /// clobbering occurs. - pub fn eagerly_translate(&self, msg: impl Into) -> SubdiagMessage { + pub fn eagerly_translate(&self, msg: impl Into) -> DiagMessage { let args = self.args.iter(); - let msg = self.subdiagnostic_message_to_diagnostic_message(msg.into()); - self.dcx.eagerly_translate(msg, args) + self.dcx.eagerly_translate(msg.into(), args) } with_fn! { with_span, @@ -1256,31 +1231,18 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } } - /// Helper function that takes a `SubdiagMessage` and returns a `DiagMessage` by - /// combining it with the primary message of the diagnostic (if translatable, otherwise it just - /// passes the user's string along). - pub(crate) fn subdiagnostic_message_to_diagnostic_message( - &self, - attr: impl Into, - ) -> DiagMessage { - self.deref().subdiagnostic_message_to_diagnostic_message(attr) - } - /// Convenience function for internal use, clients should use one of the /// public methods above. /// /// Used by `proc_macro_server` for implementing `server::Diagnostic`. - pub fn sub(&mut self, level: Level, message: impl Into, span: MultiSpan) { + pub fn sub(&mut self, level: Level, message: impl Into, span: MultiSpan) { self.deref_mut().sub(level, message, span); } /// Convenience function for internal use, clients should use one of the /// public methods above. fn sub_with_highlights(&mut self, level: Level, messages: Vec, span: MultiSpan) { - let messages = messages - .into_iter() - .map(|m| (self.subdiagnostic_message_to_diagnostic_message(m.content), m.style)) - .collect(); + let messages = messages.into_iter().map(|m| (m.content.into(), m.style)).collect(); let sub = Subdiag { level, messages, span }; self.children.push(sub); } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 2e0afb8fc4c2..c0398b3e8da0 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -57,8 +57,8 @@ use rustc_data_structures::sync::{DynSend, Lock}; use rustc_data_structures::{AtomicRef, assert_matches}; pub use rustc_error_messages::{ DiagArg, DiagArgFromDisplay, DiagArgName, DiagArgValue, DiagMessage, FluentBundle, IntoDiagArg, - LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage, - fallback_fluent_bundle, fluent_bundle, into_diag_arg_using_display, + LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, fallback_fluent_bundle, + fluent_bundle, into_diag_arg_using_display, }; use rustc_hashes::Hash128; use rustc_lint_defs::LintExpectationId; @@ -488,12 +488,12 @@ impl DiagCtxt { self.inner.borrow_mut().emitter = emitter; } - /// Translate `message` eagerly with `args` to `SubdiagMessage::Eager`. + /// Translate `message` eagerly with `args` to `DiagMessage::Eager`. pub fn eagerly_translate<'a>( &self, message: DiagMessage, args: impl Iterator>, - ) -> SubdiagMessage { + ) -> DiagMessage { let inner = self.inner.borrow(); inner.eagerly_translate(message, args) } @@ -1423,13 +1423,13 @@ impl DiagCtxtInner { self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied()) } - /// Translate `message` eagerly with `args` to `SubdiagMessage::Eager`. + /// Translate `message` eagerly with `args` to `DiagMessage::Eager`. fn eagerly_translate<'a>( &self, message: DiagMessage, args: impl Iterator>, - ) -> SubdiagMessage { - SubdiagMessage::Str(Cow::from(self.eagerly_translate_to_string(message, args))) + ) -> DiagMessage { + DiagMessage::Str(Cow::from(self.eagerly_translate_to_string(message, args))) } /// Translate `message` eagerly with `args` to `String`. @@ -1450,10 +1450,9 @@ impl DiagCtxtInner { fn eagerly_translate_for_subdiag( &self, diag: &DiagInner, - msg: impl Into, - ) -> SubdiagMessage { - let msg = diag.subdiagnostic_message_to_diagnostic_message(msg); - self.eagerly_translate(msg, diag.args.iter()) + msg: impl Into, + ) -> DiagMessage { + self.eagerly_translate(msg.into(), diag.args.iter()) } fn flush_delayed(&mut self) { diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index bf829c2d645d..746678e2865f 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -7,7 +7,7 @@ mod prelude_edition_lints; pub(crate) mod probe; mod suggest; -use rustc_errors::{Applicability, Diag, SubdiagMessage}; +use rustc_errors::{Applicability, Diag, DiagMessage}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace}; use rustc_hir::def_id::DefId; @@ -127,7 +127,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn suggest_method_call( &self, err: &mut Diag<'_>, - msg: impl Into + std::fmt::Debug, + msg: impl Into + std::fmt::Debug, method_name: Ident, self_ty: Ty<'tcx>, call_expr: &hir::Expr<'tcx>, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6aa2eae556e2..4b1faf718cd5 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -373,7 +373,6 @@ symbols! { Str, String, StructuralPartialEq, - SubdiagMessage, Subdiagnostic, SymbolIntern, Sync, diff --git a/src/doc/rustc-dev-guide/src/diagnostics/translation.md b/src/doc/rustc-dev-guide/src/diagnostics/translation.md index 58d75f54a005..e66c9430914a 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/translation.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/translation.md @@ -135,8 +135,7 @@ translation. ### Messages All of rustc's traditional diagnostic APIs (e.g. `struct_span_err` or `note`) -take any message that can be converted into a `DiagMessage` (or -`SubdiagMessage`). +take any message that can be converted into a `DiagMessage`. [`rustc_error_messages::DiagMessage`] can represent legacy non-translatable diagnostic messages and translatable messages. Non-translatable messages are @@ -149,14 +148,7 @@ with an attribute). Fluent resource (described in more detail below), or `DiagMessage`s will either be created in the macro-generated code of a diagnostic derive. -`rustc_error_messages::SubdiagMessage` is similar, it can correspond to a -legacy non-translatable diagnostic message or the name of an attribute to a -Fluent message. Translatable `SubdiagMessage`s must be combined with a -`DiagMessage` (using `DiagMessage::with_subdiagnostic_message`) to -be emitted (an attribute name on its own is meaningless without a corresponding -message identifier, which is what `DiagMessage` provides). - -Both `DiagMessage` and `SubdiagMessage` implement `Into` for any +`DiagMessage` implements `Into` for any type that can be converted into a string, and converts these into non-translatable diagnostics - this keeps all existing diagnostic calls working. diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index 8a19039a7fe7..4ba9af58f90a 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -8,7 +8,7 @@ //! Thank you! //! ~The `INTERNAL_METADATA_COLLECTOR` lint -use rustc_errors::{Applicability, Diag, DiagMessage, MultiSpan, SubdiagMessage}; +use rustc_errors::{Applicability, Diag, DiagMessage, MultiSpan}; #[cfg(debug_assertions)] use rustc_errors::{EmissionGuarantee, SubstitutionPart, Suggestions}; use rustc_hir::HirId; @@ -155,7 +155,7 @@ pub fn span_lint_and_help( span: impl Into, msg: impl Into, help_span: Option, - help: impl Into, + help: impl Into, ) { #[expect(clippy::disallowed_methods)] cx.span_lint(lint, span, |diag| { @@ -216,7 +216,7 @@ pub fn span_lint_and_note( span: impl Into, msg: impl Into, note_span: Option, - note: impl Into, + note: impl Into, ) { #[expect(clippy::disallowed_methods)] cx.span_lint(lint, span, |diag| { @@ -390,7 +390,7 @@ pub fn span_lint_and_sugg( lint: &'static Lint, sp: Span, msg: impl Into, - help: impl Into, + help: impl Into, sugg: String, applicability: Applicability, ) { diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs index e63ab03cda47..c1146de0fef1 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs @@ -19,7 +19,7 @@ extern crate rustc_session; extern crate rustc_span; extern crate core; -use rustc_errors::{Applicability, DiagMessage, SubdiagMessage}; +use rustc_errors::{Applicability, DiagMessage}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs index ca803d450b92..fa2b6e907a26 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs @@ -26,7 +26,7 @@ extern crate rustc_middle; use rustc_middle::ty::Ty; extern crate rustc_errors; -use rustc_errors::{Applicability, DiagMessage, ErrCode, MultiSpan, SubdiagMessage}; +use rustc_errors::{Applicability, DiagMessage, ErrCode, MultiSpan}; extern crate rustc_session; diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs index 99b2cba89da4..c7636bca80b5 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive-inline.rs @@ -17,7 +17,7 @@ extern crate rustc_session; extern crate rustc_span; extern crate core; -use rustc_errors::{Applicability, DiagMessage, SubdiagMessage}; +use rustc_errors::{Applicability, DiagMessage}; use rustc_macros::Subdiagnostic; use rustc_span::Span; From b1847b59cc0fecb8973d82366b72f994e8841331 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 10 Feb 2026 09:13:45 +0000 Subject: [PATCH 791/978] Remove SubdiagMessage in favour of the identical DiagMessage --- clippy_utils/src/diagnostics.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_utils/src/diagnostics.rs b/clippy_utils/src/diagnostics.rs index 8a19039a7fe7..4ba9af58f90a 100644 --- a/clippy_utils/src/diagnostics.rs +++ b/clippy_utils/src/diagnostics.rs @@ -8,7 +8,7 @@ //! Thank you! //! ~The `INTERNAL_METADATA_COLLECTOR` lint -use rustc_errors::{Applicability, Diag, DiagMessage, MultiSpan, SubdiagMessage}; +use rustc_errors::{Applicability, Diag, DiagMessage, MultiSpan}; #[cfg(debug_assertions)] use rustc_errors::{EmissionGuarantee, SubstitutionPart, Suggestions}; use rustc_hir::HirId; @@ -155,7 +155,7 @@ pub fn span_lint_and_help( span: impl Into, msg: impl Into, help_span: Option, - help: impl Into, + help: impl Into, ) { #[expect(clippy::disallowed_methods)] cx.span_lint(lint, span, |diag| { @@ -216,7 +216,7 @@ pub fn span_lint_and_note( span: impl Into, msg: impl Into, note_span: Option, - note: impl Into, + note: impl Into, ) { #[expect(clippy::disallowed_methods)] cx.span_lint(lint, span, |diag| { @@ -390,7 +390,7 @@ pub fn span_lint_and_sugg( lint: &'static Lint, sp: Span, msg: impl Into, - help: impl Into, + help: impl Into, sugg: String, applicability: Applicability, ) { From 954f483557e24c8559bde3d4b2ef4c48f2b34651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sat, 7 Feb 2026 17:57:43 +0100 Subject: [PATCH 792/978] Port `rustc_never_type_options` to the new attribute parser --- .../src/attributes/rustc_internal.rs | 82 +++++++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 3 +- .../rustc_hir/src/attrs/data_structures.rs | 50 ++++++++++- .../rustc_hir/src/attrs/encode_cross_crate.rs | 3 +- compiler/rustc_hir_typeck/src/fallback.rs | 12 +-- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 24 +----- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 55 +------------ compiler/rustc_passes/src/check_attr.rs | 4 +- .../malformed-never-type-options.rs | 2 +- .../malformed-never-type-options.stderr | 12 +-- 10 files changed, 148 insertions(+), 99 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 52268def8718..218488898e4b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -420,6 +420,88 @@ impl NoArgsAttributeParser for RustcCaptureAnalysisParser { const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCaptureAnalysis; } +pub(crate) struct RustcNeverTypeOptionsParser; + +impl SingleAttributeParser for RustcNeverTypeOptionsParser { + const PATH: &[Symbol] = &[sym::rustc_never_type_options]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; + const TEMPLATE: AttributeTemplate = template!(List: &[ + r#"fallback = "unit", "never", "no""#, + r#"diverging_block_default = "unit", "never""#, + ]); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(list) = args.list() else { + cx.expected_list(cx.attr_span, args); + return None; + }; + + let mut fallback = None::; + let mut diverging_block_default = None::; + + for arg in list.mixed() { + let Some(meta) = arg.meta_item() else { + cx.expected_name_value(arg.span(), None); + continue; + }; + + let res = match meta.ident().map(|i| i.name) { + Some(sym::fallback) => &mut fallback, + Some(sym::diverging_block_default) => &mut diverging_block_default, + _ => { + cx.expected_specific_argument( + meta.path().span(), + &[sym::fallback, sym::diverging_block_default], + ); + continue; + } + }; + + let Some(nv) = meta.args().name_value() else { + cx.expected_name_value(meta.span(), None); + continue; + }; + + let Some(field) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + continue; + }; + + if res.is_some() { + cx.duplicate_key(meta.span(), meta.ident().unwrap().name); + continue; + } + + *res = Some(Ident { name: field, span: nv.value_span }); + } + + let fallback = match fallback { + None => None, + Some(Ident { name: sym::unit, .. }) => Some(DivergingFallbackBehavior::ToUnit), + Some(Ident { name: sym::never, .. }) => Some(DivergingFallbackBehavior::ToNever), + Some(Ident { name: sym::no, .. }) => Some(DivergingFallbackBehavior::NoFallback), + Some(Ident { span, .. }) => { + cx.expected_specific_argument_strings(span, &[sym::unit, sym::never, sym::no]); + return None; + } + }; + + let diverging_block_default = match diverging_block_default { + None => None, + Some(Ident { name: sym::unit, .. }) => Some(DivergingBlockBehavior::Unit), + Some(Ident { name: sym::never, .. }) => Some(DivergingBlockBehavior::Never), + Some(Ident { span, .. }) => { + cx.expected_specific_argument_strings(span, &[sym::unit, sym::no]); + return None; + } + }; + + Some(AttributeKind::RustcNeverTypeOptions { fallback, diverging_block_default }) + } +} + pub(crate) struct RustcLintQueryInstabilityParser; impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 16e4a6452210..4d7dc41f1546 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -147,9 +147,9 @@ attribute_parsers!( DocParser, MacroUseParser, NakedParser, + RustcCguTestAttributeParser, StabilityParser, UsedParser, - RustcCguTestAttributeParser, // tidy-alphabetical-end // tidy-alphabetical-start @@ -210,6 +210,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 09b51cef3c1a..e5f45928fe7b 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -63,6 +63,44 @@ pub enum CguFields { PartitionCodegened { cfg: Symbol, module: Symbol }, ExpectedCguReuse { cfg: Symbol, module: Symbol, kind: CguKind }, } + +#[derive(Copy, Clone, PartialEq, Debug, PrintAttribute)] +#[derive(HashStable_Generic, Encodable, Decodable)] +pub enum DivergingFallbackBehavior { + /// Always fallback to `()` (aka "always spontaneous decay") + ToUnit, + /// Always fallback to `!` (which should be equivalent to never falling back + not making + /// never-to-any coercions unless necessary) + ToNever, + /// Don't fallback at all + NoFallback, +} + +#[derive(Copy, Clone, PartialEq, Debug, PrintAttribute, Default)] +#[derive(HashStable_Generic, Encodable, Decodable)] +pub enum DivergingBlockBehavior { + /// This is the current stable behavior: + /// + /// ```rust + /// { + /// return; + /// } // block has type = !, even though we are supposedly dropping it with `;` + /// ``` + #[default] + Never, + + /// Alternative behavior: + /// + /// ```ignore (very-unstable-new-attribute) + /// #![rustc_never_type_options(diverging_block_default = "unit")] + /// { + /// return; + /// } // block has type = (), since we are dropping `!` from `return` with `;` + /// ``` + Unit, +} + +#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, PrintAttribute)] pub enum InlineAttr { None, Hint, @@ -1069,6 +1107,9 @@ pub enum AttributeKind { /// Represents `#[rustc_capture_analysis]` RustcCaptureAnalysis, + /// Represents `#[rustc_expected_cgu_reuse]`, `#[rustc_partition_codegened]` and `#[rustc_partition_reused]`. + RustcCguTestAttr(ThinVec<(Span, CguFields)>), + /// Represents `#[rustc_clean]` RustcClean(ThinVec), @@ -1139,9 +1180,6 @@ pub enum AttributeKind { /// Represents `#[rustc_evaluate_where_clauses]` RustcEvaluateWhereClauses, - /// Represents `#[rustc_expected_cgu_reuse]`, `#[rustc_partition_codegened]` and `#[rustc_partition_reused]`. - RustcCguTestAttr(ThinVec<(Span, CguFields)>), - /// Represents `#[rustc_has_incoherent_inherent_impls]` RustcHasIncoherentInherentImpls, @@ -1199,6 +1237,12 @@ pub enum AttributeKind { /// Represents `#[rustc_never_returns_null_ptr]` RustcNeverReturnsNullPointer, + /// Represents `#[rustc_never_type_options]`. + RustcNeverTypeOptions { + fallback: Option, + diverging_block_default: Option, + }, + /// Represents `#[rustc_no_implicit_autorefs]` RustcNoImplicitAutorefs, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 4c68d51e6334..5384a12a0ffb 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -99,6 +99,7 @@ impl AttributeKind { RustcBodyStability { .. } => No, RustcBuiltinMacro { .. } => Yes, RustcCaptureAnalysis => No, + RustcCguTestAttr { .. } => No, RustcClean { .. } => No, RustcCoherenceIsCore(..) => No, RustcCoinductive(..) => No, @@ -139,6 +140,7 @@ impl AttributeKind { RustcMir(..) => Yes, RustcMustImplementOneOf { .. } => No, RustcNeverReturnsNullPointer => Yes, + RustcNeverTypeOptions { .. } => No, RustcNoImplicitAutorefs => Yes, RustcNoImplicitBounds => No, RustcNonConstTraitMethod => No, // should be reported via other queries like `constness` @@ -149,7 +151,6 @@ impl AttributeKind { RustcOffloadKernel => Yes, RustcOutlives => No, RustcParenSugar(..) => No, - RustcCguTestAttr { .. } => No, RustcPassByValue(..) => Yes, RustcPassIndirectlyInNonRusticAbis(..) => No, RustcPreserveUbChecks => No, diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 727666de3c47..2e421c610e7a 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -7,6 +7,7 @@ use rustc_data_structures::graph::{self}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir as hir; use rustc_hir::HirId; +use rustc_hir::attrs::DivergingFallbackBehavior; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{InferKind, Visitor}; @@ -19,17 +20,6 @@ use tracing::debug; use crate::{FnCtxt, errors}; -#[derive(Copy, Clone)] -pub(crate) enum DivergingFallbackBehavior { - /// Always fallback to `()` (aka "always spontaneous decay") - ToUnit, - /// Always fallback to `!` (which should be equivalent to never falling back + not making - /// never-to-any coercions unless necessary) - ToNever, - /// Don't fallback at all - NoFallback, -} - impl<'tcx> FnCtxt<'_, 'tcx> { /// Performs type inference fallback, setting [`FnCtxt::diverging_fallback_has_occurred`] /// if the never type fallback has occurred. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 2e85410c8960..54d8306936dd 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -5,6 +5,7 @@ use itertools::Itertools; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, a_or_an, listify, pluralize}; +use rustc_hir::attrs::DivergingBlockBehavior; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; @@ -47,29 +48,6 @@ rustc_index::newtype_index! { pub(crate) struct GenericIdx {} } -#[derive(Clone, Copy, Default)] -pub(crate) enum DivergingBlockBehavior { - /// This is the current stable behavior: - /// - /// ```rust - /// { - /// return; - /// } // block has type = !, even though we are supposedly dropping it with `;` - /// ``` - #[default] - Never, - - /// Alternative behavior: - /// - /// ```ignore (very-unstable-new-attribute) - /// #![rustc_never_type_options(diverging_block_default = "unit")] - /// { - /// return; - /// } // block has type = (), since we are dropping `!` from `return` with `;` - /// ``` - Unit, -} - impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn check_casts(&mut self) { let mut deferred_cast_checks = self.root_ctxt.deferred_cast_checks.borrow_mut(); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index c875e2e50d70..412df9162e9f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -10,8 +10,9 @@ use std::ops::Deref; use hir::def_id::CRATE_DEF_ID; use rustc_errors::DiagCtxtHandle; +use rustc_hir::attrs::{AttributeKind, DivergingBlockBehavior, DivergingFallbackBehavior}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, HirId, ItemLocalMap}; +use rustc_hir::{self as hir, HirId, ItemLocalMap, find_attr}; use rustc_hir_analysis::hir_ty_lowering::{ HirTyLowerer, InherentAssocCandidate, RegionInferReason, }; @@ -19,15 +20,13 @@ use rustc_infer::infer::{self, RegionVariableOrigin}; use rustc_infer::traits::{DynCompatibilityViolation, Obligation}; use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::Session; -use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span, sym}; +use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span}; use rustc_trait_selection::error_reporting::TypeErrCtxt; use rustc_trait_selection::traits::{ self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, }; use crate::coercion::CoerceMany; -use crate::fallback::DivergingFallbackBehavior; -use crate::fn_ctxt::checks::DivergingBlockBehavior; use crate::{CoroutineTypes, Diverges, EnclosingBreakables, TypeckRootCtxt}; /// The `FnCtxt` stores type-checking context needed to type-check bodies of @@ -517,51 +516,5 @@ fn parse_never_type_options_attr( // Error handling is dubious here (unwraps), but that's probably fine for an internal attribute. // Just don't write incorrect attributes <3 - let mut fallback = None; - let mut block = None; - - let items = if tcx.features().rustc_attrs() { - tcx.get_attr(CRATE_DEF_ID, sym::rustc_never_type_options) - .map(|attr| attr.meta_item_list().unwrap()) - } else { - None - }; - let items = items.unwrap_or_default(); - - for item in items { - if item.has_name(sym::fallback) && fallback.is_none() { - let mode = item.value_str().unwrap(); - match mode { - sym::unit => fallback = Some(DivergingFallbackBehavior::ToUnit), - sym::never => fallback = Some(DivergingFallbackBehavior::ToNever), - sym::no => fallback = Some(DivergingFallbackBehavior::NoFallback), - _ => { - tcx.dcx().span_err(item.span(), format!("unknown never type fallback mode: `{mode}` (supported: `unit`, `niko`, `never` and `no`)")); - } - }; - continue; - } - - if item.has_name(sym::diverging_block_default) && block.is_none() { - let default = item.value_str().unwrap(); - match default { - sym::unit => block = Some(DivergingBlockBehavior::Unit), - sym::never => block = Some(DivergingBlockBehavior::Never), - _ => { - tcx.dcx().span_err(item.span(), format!("unknown diverging block default: `{default}` (supported: `unit` and `never`)")); - } - }; - continue; - } - - tcx.dcx().span_err( - item.span(), - format!( - "unknown or duplicate never type option: `{}` (supported: `fallback`, `diverging_block_default`)", - item.name().unwrap() - ), - ); - } - - (fallback, block) + find_attr!(tcx.get_all_attrs(CRATE_DEF_ID), AttributeKind::RustcNeverTypeOptions {fallback, diverging_block_default} => (*fallback, *diverging_block_default)).unwrap_or_default() } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index db5c33fcb17c..4f29b5e715d6 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -295,6 +295,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcBodyStability { .. } | AttributeKind::RustcBuiltinMacro { .. } | AttributeKind::RustcCaptureAnalysis + | AttributeKind::RustcCguTestAttr(..) | AttributeKind::RustcClean(..) | AttributeKind::RustcCoherenceIsCore(..) | AttributeKind::RustcCoinductive(..) @@ -332,6 +333,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcMain | AttributeKind::RustcMir(_) | AttributeKind::RustcNeverReturnsNullPointer + | AttributeKind::RustcNeverTypeOptions {..} | AttributeKind::RustcNoImplicitAutorefs | AttributeKind::RustcNoImplicitBounds | AttributeKind::RustcNonConstTraitMethod @@ -341,7 +343,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcOffloadKernel | AttributeKind::RustcOutlives | AttributeKind::RustcParenSugar(..) - | AttributeKind::RustcCguTestAttr(..) | AttributeKind::RustcPassByValue (..) | AttributeKind::RustcPassIndirectlyInNonRusticAbis(..) | AttributeKind::RustcPreserveUbChecks @@ -405,7 +406,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_test_marker | sym::rustc_layout | sym::rustc_proc_macro_decls - | sym::rustc_never_type_options | sym::rustc_autodiff | sym::rustc_capture_analysis | sym::rustc_mir diff --git a/tests/ui/attributes/malformed-never-type-options.rs b/tests/ui/attributes/malformed-never-type-options.rs index 0c384be0e226..7dd7a854ed2e 100644 --- a/tests/ui/attributes/malformed-never-type-options.rs +++ b/tests/ui/attributes/malformed-never-type-options.rs @@ -2,7 +2,7 @@ //! The `rustc_*` attribute is malformed, but ICEing without a `feature(rustc_attrs)` is still bad. #![rustc_never_type_options(: Unsize = "hi")] -//~^ ERROR expected unsuffixed literal, found `:` +//~^ ERROR expected a literal //~| ERROR use of an internal attribute fn main() {} diff --git a/tests/ui/attributes/malformed-never-type-options.stderr b/tests/ui/attributes/malformed-never-type-options.stderr index 0d2ff4881f2a..98870c8bdded 100644 --- a/tests/ui/attributes/malformed-never-type-options.stderr +++ b/tests/ui/attributes/malformed-never-type-options.stderr @@ -1,9 +1,3 @@ -error: expected unsuffixed literal, found `:` - --> $DIR/malformed-never-type-options.rs:4:29 - | -LL | #![rustc_never_type_options(: Unsize = "hi")] - | ^ - error[E0658]: use of an internal attribute --> $DIR/malformed-never-type-options.rs:4:1 | @@ -14,6 +8,12 @@ LL | #![rustc_never_type_options(: Unsize = "hi")] = note: the `#[rustc_never_type_options]` attribute is an internal implementation detail that will never be stable = note: `rustc_never_type_options` is used to experiment with never type fallback and work on never type stabilization +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `:` + --> $DIR/malformed-never-type-options.rs:4:29 + | +LL | #![rustc_never_type_options(: Unsize = "hi")] + | ^ + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. From 2377d355ad61ce1bf5cb33632e101d3016cf152e Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 10 Feb 2026 10:17:59 +0100 Subject: [PATCH 793/978] Update documentation of rustc_macros --- compiler/rustc_macros/src/diagnostics/mod.rs | 115 ++++++------------- 1 file changed, 35 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index 09f05ce972f1..a036e61c3789 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -21,36 +21,25 @@ use synstructure::Structure; /// # extern crate rust_middle; /// # use rustc_middle::ty::Ty; /// #[derive(Diagnostic)] -/// #[diag(borrowck_move_out_of_borrow, code = E0505)] -/// pub struct MoveOutOfBorrowError<'tcx> { +/// #[diag("this is an example message", code = E0123)] +/// pub(crate) struct ExampleError<'tcx> { /// pub name: Ident, /// pub ty: Ty<'tcx>, /// #[primary_span] -/// #[label] +/// #[label("with a label")] /// pub span: Span, -/// #[label(first_borrow_label)] -/// pub first_borrow_span: Span, -/// #[suggestion(code = "{name}.clone()")] -/// pub clone_sugg: Option<(Span, Applicability)> +/// #[label("with a label")] +/// pub other_span: Span, +/// #[suggestion("with a suggestion", code = "{name}.clone()")] +/// pub opt_sugg: Option<(Span, Applicability)>, /// } /// ``` /// -/// ```fluent -/// move_out_of_borrow = cannot move out of {$name} because it is borrowed -/// .label = cannot move out of borrow -/// .first_borrow_label = `{$ty}` first borrowed here -/// .suggestion = consider cloning here -/// ``` -/// /// Then, later, to emit the error: /// /// ```ignore (rust) -/// sess.emit_err(MoveOutOfBorrowError { -/// expected, -/// actual, -/// span, -/// first_borrow_span, -/// clone_sugg: Some(suggestion, Applicability::MachineApplicable), +/// sess.emit_err(ExampleError { +/// name, ty, span, other_span, opt_sugg /// }); /// ``` /// @@ -65,38 +54,24 @@ pub(super) fn diagnostic_derive(s: Structure<'_>) -> TokenStream { /// /// ```ignore (rust) /// #[derive(LintDiagnostic)] -/// #[diag(lint_atomic_ordering_invalid_fail_success)] -/// pub struct AtomicOrderingInvalidLint { -/// method: Symbol, -/// success_ordering: Symbol, -/// fail_ordering: Symbol, -/// #[label(fail_label)] -/// fail_order_arg_span: Span, -/// #[label(success_label)] -/// #[suggestion( -/// code = "std::sync::atomic::Ordering::{success_suggestion}", -/// applicability = "maybe-incorrect" +/// #[diag("unused attribute")] +/// pub(crate) struct UnusedAttribute { +/// #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] +/// pub this: Span, +/// #[note("attribute also specified here")] +/// pub other: Span, +/// #[warning( +/// "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" /// )] -/// success_order_arg_span: Span, +/// pub warning: bool, /// } /// ``` /// -/// ```fluent -/// lint_atomic_ordering_invalid_fail_success = `{$method}`'s success ordering must be at least as strong as its failure ordering -/// .fail_label = `{$fail_ordering}` failure ordering -/// .success_label = `{$success_ordering}` success ordering -/// .suggestion = consider using `{$success_suggestion}` success ordering instead -/// ``` -/// /// Then, later, to emit the error: /// /// ```ignore (rust) -/// cx.emit_span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg_span, AtomicOrderingInvalidLint { -/// method, -/// success_ordering, -/// fail_ordering, -/// fail_order_arg_span, -/// success_order_arg_span, +/// cx.emit_span_lint(UNUSED_ATTRIBUTES, span, UnusedAttribute { +/// ... /// }); /// ``` /// @@ -112,45 +87,25 @@ pub(super) fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream { /// /// ```ignore (rust) /// #[derive(Subdiagnostic)] -/// pub enum ExpectedIdentifierLabel<'tcx> { -/// #[label(expected_identifier)] -/// WithoutFound { -/// #[primary_span] -/// span: Span, -/// } -/// #[label(expected_identifier_found)] -/// WithFound { -/// #[primary_span] -/// span: Span, -/// found: String, -/// } -/// } -/// -/// #[derive(Subdiagnostic)] -/// #[suggestion(style = "verbose",parser::raw_identifier)] -/// pub struct RawIdentifierSuggestion<'tcx> { -/// #[primary_span] -/// span: Span, -/// #[applicability] -/// applicability: Applicability, -/// ident: Ident, +/// pub(crate) enum BuiltinUnusedDocCommentSub { +/// #[help("use `//` for a plain comment")] +/// PlainHelp, +/// #[help("use `/* */` for a plain comment")] +/// BlockHelp, /// } /// ``` -/// -/// ```fluent -/// parser_expected_identifier = expected identifier -/// -/// parser_expected_identifier_found = expected identifier, found {$found} -/// -/// parser_raw_identifier = escape `{$ident}` to use it as an identifier -/// ``` -/// -/// Then, later, to add the subdiagnostic: +/// Then, later, use the subdiagnostic in a diagnostic: /// /// ```ignore (rust) -/// diag.subdiagnostic(ExpectedIdentifierLabel::WithoutFound { span }); -/// -/// diag.subdiagnostic(RawIdentifierSuggestion { span, applicability, ident }); +/// #[derive(LintDiagnostic)] +/// #[diag("unused doc comment")] +/// pub(crate) struct BuiltinUnusedDocComment<'a> { +/// pub kind: &'a str, +/// #[label("rustdoc does not generate documentation for {$kind}")] +/// pub label: Span, +/// #[subdiagnostic] +/// pub sub: BuiltinUnusedDocCommentSub, +/// } /// ``` pub(super) fn subdiagnostic_derive(s: Structure<'_>) -> TokenStream { SubdiagnosticDerive::new().into_tokens(s) From f4c135f91bfd13920faf671f044ea037ab7f7ea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sat, 7 Feb 2026 17:57:43 +0100 Subject: [PATCH 794/978] Port `rustc_trivial_field_reads` to the new attribute parser --- .../src/attributes/rustc_internal.rs | 9 +++++ compiler/rustc_attr_parsing/src/context.rs | 36 ++++++++++++++----- .../rustc_hir/src/attrs/data_structures.rs | 3 ++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_passes/src/dead.rs | 8 +++-- 6 files changed, 48 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 218488898e4b..09d0cffe3966 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -502,6 +502,15 @@ impl SingleAttributeParser for RustcNeverTypeOptionsParser { } } +pub(crate) struct RustcTrivialFieldReadsParser; + +impl NoArgsAttributeParser for RustcTrivialFieldReadsParser { + const PATH: &[Symbol] = &[sym::rustc_trivial_field_reads]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcTrivialFieldReads; +} + pub(crate) struct RustcLintQueryInstabilityParser; impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 4d7dc41f1546..c42a9c6031b4 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -169,6 +169,32 @@ attribute_parsers!( // tidy-alphabetical-end // tidy-alphabetical-start +%%%%%%% Changes from base to side #1 +%%%%%%%%%%% Changes from base to side #1 + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, ++ Single>, ++++++++ Contents of side #2 + Single>, ++++++++++++ Contents of side #2 +- Single>, + Single>, +<<<<<<< Conflict 1 of 1 +<<<<<<<<<<< Conflict 2 of 2 +>>>>>>> Conflict 1 of 1 ends + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, Single, Single, Single, @@ -213,6 +239,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, @@ -297,14 +324,7 @@ attribute_parsers!( Single>, Single>, Single>, - Single>, - Single>, - Single>, - Single>, - Single>, - Single>, - Single>, - Single>, +>>>>>>>>>>> Conflict 2 of 2 ends // tidy-alphabetical-end ]; ); diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index e5f45928fe7b..123a38131ecd 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1326,6 +1326,9 @@ pub enum AttributeKind { /// Represents `#[rustc_then_this_would_need]` RustcThenThisWouldNeed(Span, ThinVec), + /// Represents `#[rustc_trivial_field_reads]` + RustcTrivialFieldReads, + /// Represents `#[rustc_unsafe_specialization_marker]`. RustcUnsafeSpecializationMarker(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 5384a12a0ffb..9d7483dab125 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -167,6 +167,7 @@ impl AttributeKind { RustcStrictCoherence(..) => Yes, RustcSymbolName(..) => Yes, RustcThenThisWouldNeed(..) => No, + RustcTrivialFieldReads => Yes, RustcUnsafeSpecializationMarker(..) => No, RustcVariance => No, RustcVarianceOfOpaques => No, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4f29b5e715d6..a9d044ec9ecc 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -358,6 +358,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcStrictCoherence(..) | AttributeKind::RustcSymbolName(..) | AttributeKind::RustcThenThisWouldNeed(..) + | AttributeKind::RustcTrivialFieldReads | AttributeKind::RustcUnsafeSpecializationMarker(..) | AttributeKind::RustcVariance | AttributeKind::RustcVarianceOfOpaques @@ -399,7 +400,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_no_mir_inline | sym::rustc_nonnull_optimization_guaranteed | sym::rustc_inherit_overflow_checks - | sym::rustc_trivial_field_reads | sym::rustc_on_unimplemented | sym::rustc_do_not_const_check | sym::rustc_doc_primitive diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 3294b6802a71..75bac9eff2c7 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -10,10 +10,11 @@ use hir::def_id::{LocalDefIdMap, LocalDefIdSet}; use rustc_abi::FieldIdx; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ErrorGuaranteed, MultiSpan}; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, Node, PatKind, QPath}; +use rustc_hir::{self as hir, Node, PatKind, QPath, find_attr}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; @@ -380,7 +381,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { && let impl_of = self.tcx.parent(impl_item.owner_id.to_def_id()) && self.tcx.is_automatically_derived(impl_of) && let trait_ref = self.tcx.impl_trait_ref(impl_of).instantiate_identity() - && self.tcx.has_attr(trait_ref.def_id, sym::rustc_trivial_field_reads) + && find_attr!( + self.tcx.get_all_attrs(trait_ref.def_id), + AttributeKind::RustcTrivialFieldReads + ) { if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind() && let Some(adt_def_id) = adt_def.did().as_local() From eab26e329b246f98f86f64f935c9ef49d85ade04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sat, 7 Feb 2026 17:57:43 +0100 Subject: [PATCH 795/978] Port `rustc_no_mir_inline` to the new attribute parser --- .../src/attributes/rustc_internal.rs | 15 ++++++ compiler/rustc_attr_parsing/src/context.rs | 47 ++++++++----------- .../rustc_hir/src/attrs/data_structures.rs | 3 ++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + .../rustc_mir_transform/src/check_inline.rs | 4 +- compiler/rustc_passes/src/check_attr.rs | 2 +- 6 files changed, 41 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 09d0cffe3966..d71fa791193f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -511,6 +511,21 @@ impl NoArgsAttributeParser for RustcTrivialFieldReadsParser { const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcTrivialFieldReads; } +pub(crate) struct RustcNoMirInlineParser; + +impl NoArgsAttributeParser for RustcNoMirInlineParser { + const PATH: &[Symbol] = &[sym::rustc_no_mir_inline]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoMirInline; +} + pub(crate) struct RustcLintQueryInstabilityParser; impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index c42a9c6031b4..d6e9caeafc8a 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -169,32 +169,6 @@ attribute_parsers!( // tidy-alphabetical-end // tidy-alphabetical-start -%%%%%%% Changes from base to side #1 -%%%%%%%%%%% Changes from base to side #1 - Single>, - Single>, - Single>, - Single>, - Single>, - Single>, - Single>, -+ Single>, -+++++++ Contents of side #2 - Single>, -+++++++++++ Contents of side #2 -- Single>, - Single>, -<<<<<<< Conflict 1 of 1 -<<<<<<<<<<< Conflict 2 of 2 ->>>>>>> Conflict 1 of 1 ends - Single>, - Single>, - Single>, - Single>, - Single>, - Single>, - Single>, - Single>, Single, Single, Single, @@ -237,9 +211,9 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, - Single, Single, Single, Single, @@ -315,6 +289,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, @@ -324,7 +299,23 @@ attribute_parsers!( Single>, Single>, Single>, ->>>>>>>>>>> Conflict 2 of 2 ends + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, + Single>, // tidy-alphabetical-end ]; ); diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 123a38131ecd..7050bb6ea70d 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1249,6 +1249,9 @@ pub enum AttributeKind { /// Represents `#[rustc_no_implicit_bounds]` RustcNoImplicitBounds, + /// Represents `#[rustc_no_mir_inline]` + RustcNoMirInline, + /// Represents `#[rustc_non_const_trait_method]`. RustcNonConstTraitMethod, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 9d7483dab125..73ac1533cef5 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -143,6 +143,7 @@ impl AttributeKind { RustcNeverTypeOptions { .. } => No, RustcNoImplicitAutorefs => Yes, RustcNoImplicitBounds => No, + RustcNoMirInline => Yes, RustcNonConstTraitMethod => No, // should be reported via other queries like `constness` RustcNounwind => No, RustcObjcClass { .. } => No, diff --git a/compiler/rustc_mir_transform/src/check_inline.rs b/compiler/rustc_mir_transform/src/check_inline.rs index 2d1876426727..1f65bd1ba69b 100644 --- a/compiler/rustc_mir_transform/src/check_inline.rs +++ b/compiler/rustc_mir_transform/src/check_inline.rs @@ -8,7 +8,6 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::{Body, TerminatorKind}; use rustc_middle::ty; use rustc_middle::ty::TyCtxt; -use rustc_span::sym; use crate::pass_manager::MirLint; @@ -42,7 +41,8 @@ pub(super) fn is_inline_valid_on_fn<'tcx>( def_id: DefId, ) -> Result<(), &'static str> { let codegen_attrs = tcx.codegen_fn_attrs(def_id); - if tcx.has_attr(def_id, sym::rustc_no_mir_inline) { + + if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcNoMirInline) { return Err("#[rustc_no_mir_inline]"); } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index a9d044ec9ecc..2287b8bf483f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -336,6 +336,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcNeverTypeOptions {..} | AttributeKind::RustcNoImplicitAutorefs | AttributeKind::RustcNoImplicitBounds + | AttributeKind::RustcNoMirInline | AttributeKind::RustcNonConstTraitMethod | AttributeKind::RustcNounwind | AttributeKind::RustcObjcClass { .. } @@ -397,7 +398,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::lang | sym::default_lib_allocator | sym::rustc_diagnostic_item - | sym::rustc_no_mir_inline | sym::rustc_nonnull_optimization_guaranteed | sym::rustc_inherit_overflow_checks | sym::rustc_on_unimplemented From fe7530cad2736e1cb841793c20a23a2d3d3ab2f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sat, 7 Feb 2026 17:57:43 +0100 Subject: [PATCH 796/978] Make `rustc_object_lifetime_default` use NoArgsAttributeParser --- .../src/attributes/rustc_internal.rs | 14 ++------------ compiler/rustc_attr_parsing/src/context.rs | 11 ++++++++++- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index d71fa791193f..fa1a43058561 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -575,21 +575,11 @@ impl NoArgsAttributeParser for RustcLintUntrackedQueryInformationPa pub(crate) struct RustcObjectLifetimeDefaultParser; -impl SingleAttributeParser for RustcObjectLifetimeDefaultParser { +impl NoArgsAttributeParser for RustcObjectLifetimeDefaultParser { const PATH: &[Symbol] = &[sym::rustc_object_lifetime_default]; - const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); - const TEMPLATE: AttributeTemplate = template!(Word); - - fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { - if let Err(span) = args.no_args() { - cx.expected_no_args(span); - return None; - } - - Some(AttributeKind::RustcObjectLifetimeDefault) - } + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcObjectLifetimeDefault; } pub(crate) struct RustcSimdMonomorphizeLaneLimitParser; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index d6e9caeafc8a..5906d7a4d513 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -212,7 +212,6 @@ attribute_parsers!( Single, Single, Single, - Single, Single, Single, Single, @@ -292,6 +291,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, @@ -301,19 +301,28 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, + Single>, Single>, Single>, Single>, + Single>, + Single>, Single>, Single>, Single>, Single>, + Single>, + Single>, Single>, Single>, Single>, Single>, + Single>, Single>, Single>, + Single>, + Single>, Single>, Single>, // tidy-alphabetical-end From 628c37afadaea6702f95fef3b086e99980afb7ce Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 4 Dec 2025 08:55:33 +0000 Subject: [PATCH 797/978] Restrict the set of things that const stability can be applied --- .../src/attributes/stability.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 1f01cadcb43e..fb204e77abc8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -244,7 +244,21 @@ impl AttributeParser for ConstStabilityParser { this.promotable = true; }), ]; - const ALLOWED_TARGETS: AllowedTargets = ALLOWED_TARGETS; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Impl { of_trait: true }), + Allow(Target::Use), // FIXME I don't think this does anything? + Allow(Target::Const), + Allow(Target::AssocConst), + Allow(Target::Trait), + Allow(Target::Static), + Allow(Target::Crate), + Allow(Target::MacroDef), // FIXME(oli-obk): remove this and eliminate the manual check for it + ]); fn finalize(mut self, cx: &FinalizeContext<'_, '_, S>) -> Option { if self.promotable { From 475b9d9819a092e1820a07c688fdc7cd7b26c6aa Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 10 Feb 2026 09:37:30 +0000 Subject: [PATCH 798/978] Prevent const stability attrs from being applied to macros via the normal attribute logic instead of special cased checks --- .../src/attributes/stability.rs | 1 - compiler/rustc_expand/src/base.rs | 9 --------- compiler/rustc_expand/src/errors.rs | 10 ---------- .../ui/attributes/const-stability-on-macro.rs | 6 +++--- .../const-stability-on-macro.stderr | 20 +++++++++---------- 5 files changed, 12 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index fb204e77abc8..a2be2d42b3e1 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -257,7 +257,6 @@ impl AttributeParser for ConstStabilityParser { Allow(Target::Trait), Allow(Target::Static), Allow(Target::Crate), - Allow(Target::MacroDef), // FIXME(oli-obk): remove this and eliminate the manual check for it ]); fn finalize(mut self, cx: &FinalizeContext<'_, '_, S>) -> Option { diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 6b3c7fe97932..91f98d475f00 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -962,15 +962,6 @@ impl SyntaxExtension { let stability = find_attr!(attrs, AttributeKind::Stability { stability, .. } => *stability); - // FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem - if let Some(sp) = - find_attr!(attrs, AttributeKind::RustcConstStability { span, .. } => *span) - { - sess.dcx().emit_err(errors::MacroConstStability { - span: sp, - head_span: sess.source_map().guess_head_span(span), - }); - } if let Some(sp) = find_attr!(attrs, AttributeKind::RustcBodyStability{ span, .. } => *span) { sess.dcx().emit_err(errors::MacroBodyStability { diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index e64bfc136d16..b6fcc13321ee 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -80,16 +80,6 @@ pub(crate) struct ResolveRelativePath { pub path: String, } -#[derive(Diagnostic)] -#[diag("macros cannot have const stability attributes")] -pub(crate) struct MacroConstStability { - #[primary_span] - #[label("invalid const stability attribute")] - pub span: Span, - #[label("const stability attribute affects this macro")] - pub head_span: Span, -} - #[derive(Diagnostic)] #[diag("macros cannot have body stability attributes")] pub(crate) struct MacroBodyStability { diff --git a/tests/ui/attributes/const-stability-on-macro.rs b/tests/ui/attributes/const-stability-on-macro.rs index af268ccd5366..4336370430d4 100644 --- a/tests/ui/attributes/const-stability-on-macro.rs +++ b/tests/ui/attributes/const-stability-on-macro.rs @@ -2,13 +2,13 @@ #![stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "foo", since = "3.3.3")] -//~^ ERROR macros cannot have const stability attributes +//~^ ERROR attribute cannot be used on macro defs macro_rules! foo { () => {}; } -#[rustc_const_unstable(feature = "bar", issue="none")] -//~^ ERROR macros cannot have const stability attributes +#[rustc_const_unstable(feature = "bar", issue = "none")] +//~^ ERROR attribute cannot be used on macro defs macro_rules! bar { () => {}; } diff --git a/tests/ui/attributes/const-stability-on-macro.stderr b/tests/ui/attributes/const-stability-on-macro.stderr index 28f31e3d4f61..a8b56edfa59d 100644 --- a/tests/ui/attributes/const-stability-on-macro.stderr +++ b/tests/ui/attributes/const-stability-on-macro.stderr @@ -1,20 +1,18 @@ -error: macros cannot have const stability attributes +error: `#[rustc_const_stable]` attribute cannot be used on macro defs --> $DIR/const-stability-on-macro.rs:4:1 | LL | #[rustc_const_stable(feature = "foo", since = "3.3.3")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid const stability attribute -LL | -LL | macro_rules! foo { - | ---------------- const stability attribute affects this macro + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_const_stable]` can be applied to associated consts, constants, crates, functions, impl blocks, statics, traits, and use statements -error: macros cannot have const stability attributes +error: `#[rustc_const_unstable]` attribute cannot be used on macro defs --> $DIR/const-stability-on-macro.rs:10:1 | -LL | #[rustc_const_unstable(feature = "bar", issue="none")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid const stability attribute -LL | -LL | macro_rules! bar { - | ---------------- const stability attribute affects this macro +LL | #[rustc_const_unstable(feature = "bar", issue = "none")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_const_unstable]` can be applied to associated consts, constants, crates, functions, impl blocks, statics, traits, and use statements error: aborting due to 2 previous errors From 12dbc1bc635f6b4c86e1316a2bf4ca59749f9f09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sun, 8 Feb 2026 22:14:00 +0100 Subject: [PATCH 799/978] remove 'static in many places --- .../src/attributes/allow_unstable.rs | 2 +- .../src/attributes/inline.rs | 4 ++-- .../rustc_attr_parsing/src/attributes/repr.rs | 4 ++-- .../src/attributes/rustc_internal.rs | 10 +++++----- compiler/rustc_attr_parsing/src/context.rs | 18 ------------------ 5 files changed, 10 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index d825d770fa35..4f1a8cd8b403 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -29,7 +29,7 @@ impl CombineAttributeParser for AllowInternalUnstableParser { pub(crate) struct UnstableFeatureBoundParser; impl CombineAttributeParser for UnstableFeatureBoundParser { - const PATH: &'static [rustc_span::Symbol] = &[sym::unstable_feature_bound]; + const PATH: &[rustc_span::Symbol] = &[sym::unstable_feature_bound]; type Item = (Symbol, Span); const CONVERT: ConvertFn = |items, _| AttributeKind::UnstableFeatureBound(items); const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs index f6aab9ea0ee2..767200bfa9bf 100644 --- a/compiler/rustc_attr_parsing/src/attributes/inline.rs +++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs @@ -10,7 +10,7 @@ use super::prelude::*; pub(crate) struct InlineParser; impl SingleAttributeParser for InlineParser { - const PATH: &'static [Symbol] = &[sym::inline]; + const PATH: &[Symbol] = &[sym::inline]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ @@ -67,7 +67,7 @@ impl SingleAttributeParser for InlineParser { pub(crate) struct RustcForceInlineParser; impl SingleAttributeParser for RustcForceInlineParser { - const PATH: &'static [Symbol] = &[sym::rustc_force_inline]; + const PATH: &[Symbol] = &[sym::rustc_force_inline]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 34d4957edc70..fb0b8df65284 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -272,7 +272,7 @@ fn parse_alignment(node: &LitKind) -> Result { pub(crate) struct AlignParser(Option<(Align, Span)>); impl AlignParser { - const PATH: &'static [Symbol] = &[sym::rustc_align]; + const PATH: &[Symbol] = &[sym::rustc_align]; const TEMPLATE: AttributeTemplate = template!(List: &[""]); fn parse(&mut self, cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) { @@ -329,7 +329,7 @@ impl AttributeParser for AlignParser { pub(crate) struct AlignStaticParser(AlignParser); impl AlignStaticParser { - const PATH: &'static [Symbol] = &[sym::rustc_align_static]; + const PATH: &[Symbol] = &[sym::rustc_align_static]; const TEMPLATE: AttributeTemplate = AlignParser::TEMPLATE; fn parse(&mut self, cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) { diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index fa1a43058561..0d19dc25d402 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -18,7 +18,7 @@ use crate::session_diagnostics::{ pub(crate) struct RustcMainParser; impl NoArgsAttributeParser for RustcMainParser { - const PATH: &'static [Symbol] = &[sym::rustc_main]; + const PATH: &[Symbol] = &[sym::rustc_main]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcMain; @@ -103,7 +103,7 @@ impl NoArgsAttributeParser for RustcNoImplicitAutorefsParser { pub(crate) struct RustcLayoutScalarValidRangeStartParser; impl SingleAttributeParser for RustcLayoutScalarValidRangeStartParser { - const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_start]; + const PATH: &[Symbol] = &[sym::rustc_layout_scalar_valid_range_start]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); @@ -118,7 +118,7 @@ impl SingleAttributeParser for RustcLayoutScalarValidRangeStartPars pub(crate) struct RustcLayoutScalarValidRangeEndParser; impl SingleAttributeParser for RustcLayoutScalarValidRangeEndParser { - const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_end]; + const PATH: &[Symbol] = &[sym::rustc_layout_scalar_valid_range_end]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); @@ -822,7 +822,7 @@ impl CombineAttributeParser for RustcMirParser { pub(crate) struct RustcNonConstTraitMethodParser; impl NoArgsAttributeParser for RustcNonConstTraitMethodParser { - const PATH: &'static [Symbol] = &[sym::rustc_non_const_trait_method]; + const PATH: &[Symbol] = &[sym::rustc_non_const_trait_method]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Method(MethodKind::Trait { body: true })), @@ -1067,7 +1067,7 @@ impl NoArgsAttributeParser for RustcInsignificantDtorParser { pub(crate) struct RustcEffectiveVisibilityParser; impl NoArgsAttributeParser for RustcEffectiveVisibilityParser { - const PATH: &'static [Symbol] = &[sym::rustc_effective_visibility]; + const PATH: &[Symbol] = &[sym::rustc_effective_visibility]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Use), diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 5906d7a4d513..47b988bcf338 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -211,7 +211,6 @@ attribute_parsers!( Single, Single, Single, - Single, Single, Single, Single, @@ -300,30 +299,13 @@ attribute_parsers!( Single>, Single>, Single>, - Single>, - Single>, - Single>, Single>, Single>, - Single>, - Single>, - Single>, - Single>, Single>, Single>, - Single>, - Single>, - Single>, - Single>, Single>, Single>, - Single>, - Single>, Single>, - Single>, - Single>, - Single>, - Single>, Single>, // tidy-alphabetical-end ]; From 32e49a8b4016265459a39ca0c7cf193a76dfe814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 10 Feb 2026 12:04:09 +0100 Subject: [PATCH 800/978] Reenable a GCI+mGCA+GCPT test case --- .../assoc-const-bindings.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tests/ui/generic-const-items/assoc-const-bindings.rs b/tests/ui/generic-const-items/assoc-const-bindings.rs index 2bf4bea16deb..c187c87c7763 100644 --- a/tests/ui/generic-const-items/assoc-const-bindings.rs +++ b/tests/ui/generic-const-items/assoc-const-bindings.rs @@ -1,35 +1,33 @@ //@ check-pass #![feature(generic_const_items, min_generic_const_args)] -#![feature(adt_const_params)] -#![allow(incomplete_features)] +#![feature(adt_const_params, unsized_const_params, generic_const_parameter_types)] +#![expect(incomplete_features)] + +use std::marker::{ConstParamTy, ConstParamTy_}; trait Owner { type const C: u32; type const K: u32; - // #[type_const] - // const Q: Maybe; + type const Q: Maybe; } impl Owner for () { type const C: u32 = N; type const K: u32 = const { 99 + 1 }; - // FIXME(mgca): re-enable once we properly support ctors and generics on paths - // #[type_const] - // const Q: Maybe = Maybe::Nothing; + type const Q: Maybe = Maybe::Nothing::; } fn take0(_: impl Owner = { N }>) {} fn take1(_: impl Owner = 100>) {} -// FIXME(mgca): re-enable once we properly support ctors and generics on paths -// fn take2(_: impl Owner = { Maybe::Just(()) }>) {} +fn take2(_: impl Owner = { Maybe::Just::<()>(()) }>) {} fn main() { take0::<128>(()); take1(()); } -#[derive(PartialEq, Eq, std::marker::ConstParamTy)] +#[derive(PartialEq, Eq, ConstParamTy)] enum Maybe { Nothing, Just(T), From 85e8282fabe0beb071aca75a2c3a51068eaa1c12 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 24 Jan 2025 15:57:13 +0000 Subject: [PATCH 801/978] Start using pattern types in libcore --- .../src/debuginfo/metadata.rs | 13 ++- .../rustc_const_eval/src/interpret/call.rs | 3 + library/core/src/num/niche_types.rs | 103 +++++++----------- src/bootstrap/src/core/build_steps/test.rs | 3 + .../cast_fn_ptr_invalid_callee_ret.stderr | 2 +- .../cast_fn_ptr_invalid_caller_arg.stderr | 2 +- .../consts/const-eval/raw-bytes.32bit.stderr | 4 +- .../consts/const-eval/raw-bytes.64bit.stderr | 4 +- tests/ui/consts/const-eval/ub-nonnull.stderr | 4 +- tests/ui/lint/invalid_value.stderr | 2 - 10 files changed, 65 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 1c674f0e8a85..c759d46b7d2f 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -479,7 +479,18 @@ pub(crate) fn spanned_type_di_node<'ll, 'tcx>( AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id, span), }, ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id), - _ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t), + ty::Pat(base, _) => return type_di_node(cx, base), + // FIXME(unsafe_binders): impl debug info + ty::UnsafeBinder(_) => unimplemented!(), + ty::Alias(..) + | ty::Param(_) + | ty::Bound(..) + | ty::Infer(_) + | ty::Placeholder(_) + | ty::CoroutineWitness(..) + | ty::Error(_) => { + bug!("debuginfo: unexpected type in type_di_node(): {:?}", t) + } }; { diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index c7ddcaa73157..ffa7b09205d5 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -91,6 +91,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let (_, field) = layout.non_1zst_field(self).unwrap(); self.unfold_transparent(field, may_unfold) } + ty::Pat(base, _) => self.layout_of(*base).expect( + "if the layout of a pattern type could be computed, so can the layout of its base", + ), // Not a transparent type, no further unfolding. _ => layout, } diff --git a/library/core/src/num/niche_types.rs b/library/core/src/num/niche_types.rs index 9ac0eb72bdcb..33b2a6741abd 100644 --- a/library/core/src/num/niche_types.rs +++ b/library/core/src/num/niche_types.rs @@ -5,45 +5,33 @@ )] use crate::cmp::Ordering; -use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::marker::StructuralPartialEq; +use crate::{fmt, pattern_type}; macro_rules! define_valid_range_type { ($( $(#[$m:meta])* - $vis:vis struct $name:ident($int:ident as $uint:ident in $low:literal..=$high:literal); + $vis:vis struct $name:ident($int:ident is $pat:pat); )+) => {$( - #[derive(Clone, Copy, Eq)] + #[derive(Clone, Copy)] #[repr(transparent)] - #[rustc_layout_scalar_valid_range_start($low)] - #[rustc_layout_scalar_valid_range_end($high)] $(#[$m])* - $vis struct $name($int); - - const _: () = { - // With the `valid_range` attributes, it's always specified as unsigned - assert!(<$uint>::MIN == 0); - let ulow: $uint = $low; - let uhigh: $uint = $high; - assert!(ulow <= uhigh); - - assert!(size_of::<$int>() == size_of::<$uint>()); - }; - + $vis struct $name(pattern_type!($int is $pat)); impl $name { #[inline] pub const fn new(val: $int) -> Option { - if (val as $uint) >= ($low as $uint) && (val as $uint) <= ($high as $uint) { - // SAFETY: just checked the inclusive range - Some(unsafe { $name(val) }) + #[allow(non_contiguous_range_endpoints)] + if let $pat = val { + // SAFETY: just checked that the value matches the pattern + Some(unsafe { $name(crate::mem::transmute(val)) }) } else { None } } /// Constructs an instance of this type from the underlying integer - /// primitive without checking whether its zero. + /// primitive without checking whether its valid. /// /// # Safety /// Immediate language UB if `val` is not within the valid range for this @@ -51,13 +39,13 @@ macro_rules! define_valid_range_type { #[inline] pub const unsafe fn new_unchecked(val: $int) -> Self { // SAFETY: Caller promised that `val` is within the valid range. - unsafe { $name(val) } + unsafe { crate::mem::transmute(val) } } #[inline] pub const fn as_inner(self) -> $int { - // SAFETY: This is a transparent wrapper, so unwrapping it is sound - // (Not using `.0` due to MCP#807.) + // SAFETY: pattern types are always legal values of their base type + // (Not using `.0` because that has perf regressions.) unsafe { crate::mem::transmute(self) } } } @@ -67,6 +55,8 @@ macro_rules! define_valid_range_type { // by . impl StructuralPartialEq for $name {} + impl Eq for $name {} + impl PartialEq for $name { #[inline] fn eq(&self, other: &Self) -> bool { @@ -104,7 +94,7 @@ macro_rules! define_valid_range_type { } define_valid_range_type! { - pub struct Nanoseconds(u32 as u32 in 0..=999_999_999); + pub struct Nanoseconds(u32 is 0..=999_999_999); } impl Nanoseconds { @@ -120,47 +110,32 @@ impl const Default for Nanoseconds { } } -define_valid_range_type! { - pub struct NonZeroU8Inner(u8 as u8 in 1..=0xff); - pub struct NonZeroU16Inner(u16 as u16 in 1..=0xff_ff); - pub struct NonZeroU32Inner(u32 as u32 in 1..=0xffff_ffff); - pub struct NonZeroU64Inner(u64 as u64 in 1..=0xffffffff_ffffffff); - pub struct NonZeroU128Inner(u128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff); - - pub struct NonZeroI8Inner(i8 as u8 in 1..=0xff); - pub struct NonZeroI16Inner(i16 as u16 in 1..=0xff_ff); - pub struct NonZeroI32Inner(i32 as u32 in 1..=0xffff_ffff); - pub struct NonZeroI64Inner(i64 as u64 in 1..=0xffffffff_ffffffff); - pub struct NonZeroI128Inner(i128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff); - - pub struct NonZeroCharInner(char as u32 in 1..=0x10ffff); -} - -#[cfg(target_pointer_width = "16")] -define_valid_range_type! { - pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff); - pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff); - pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff); -} -#[cfg(target_pointer_width = "32")] -define_valid_range_type! { - pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff); - pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff); - pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff); -} -#[cfg(target_pointer_width = "64")] -define_valid_range_type! { - pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff_ffff_ffff); - pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff_ffff_ffff); - pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff_ffff_ffff); -} +const HALF_USIZE: usize = usize::MAX >> 1; define_valid_range_type! { - pub struct U32NotAllOnes(u32 as u32 in 0..=0xffff_fffe); - pub struct I32NotAllOnes(i32 as u32 in 0..=0xffff_fffe); + pub struct NonZeroU8Inner(u8 is 1..); + pub struct NonZeroU16Inner(u16 is 1..); + pub struct NonZeroU32Inner(u32 is 1..); + pub struct NonZeroU64Inner(u64 is 1..); + pub struct NonZeroU128Inner(u128 is 1..); - pub struct U64NotAllOnes(u64 as u64 in 0..=0xffff_ffff_ffff_fffe); - pub struct I64NotAllOnes(i64 as u64 in 0..=0xffff_ffff_ffff_fffe); + pub struct NonZeroI8Inner(i8 is ..0 | 1..); + pub struct NonZeroI16Inner(i16 is ..0 | 1..); + pub struct NonZeroI32Inner(i32 is ..0 | 1..); + pub struct NonZeroI64Inner(i64 is ..0 | 1..); + pub struct NonZeroI128Inner(i128 is ..0 | 1..); + + pub struct UsizeNoHighBit(usize is 0..=HALF_USIZE); + pub struct NonZeroUsizeInner(usize is 1..); + pub struct NonZeroIsizeInner(isize is ..0 | 1..); + + pub struct U32NotAllOnes(u32 is 0..u32::MAX); + pub struct I32NotAllOnes(i32 is ..-1 | 0..); + + pub struct U64NotAllOnes(u64 is 0..u64::MAX); + pub struct I64NotAllOnes(i64 is ..-1 | 0..); + + pub struct NonZeroCharInner(char is '\u{1}' ..= '\u{10ffff}'); } pub trait NotAllOnesHelper { @@ -181,7 +156,7 @@ impl NotAllOnesHelper for i64 { } define_valid_range_type! { - pub struct CodePointInner(u32 as u32 in 0..=0x10ffff); + pub struct CodePointInner(u32 is 0..=0x10ffff); } impl CodePointInner { diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 1ab76ef8f91d..fda9f3bbba3a 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2184,6 +2184,9 @@ Please disable assertions with `rust.debug-assertions = false`. for flag in targetflags { cmd.arg("--target-rustcflags").arg(flag); } + if target.is_synthetic() { + cmd.arg("--target-rustcflags").arg("-Zunstable-options"); + } cmd.arg("--python").arg( builder.config.python.as_ref().expect("python is required for running rustdoc tests"), diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr index a00d167df2f7..6fc1bc01655c 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error: Undefined Behavior: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> tests/fail/validity/cast_fn_ptr_invalid_callee_ret.rs:LL:CC | LL | f(); 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 c2e647aa18fc..3b23a6cc4e85 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,4 +1,4 @@ -error: Undefined Behavior: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error: Undefined Behavior: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs:LL:CC | LL | Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue()) diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr index 2861f82ec53b..be3b539b269a 100644 --- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr @@ -64,7 +64,7 @@ LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; 00 00 00 00 │ .... } -error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> $DIR/raw-bytes.rs:61:1 | LL | const NULL_U8: NonZero = unsafe { mem::transmute(0u8) }; @@ -75,7 +75,7 @@ LL | const NULL_U8: NonZero = unsafe { mem::transmute(0u8) }; 00 │ . } -error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> $DIR/raw-bytes.rs:63:1 | LL | const NULL_USIZE: NonZero = unsafe { mem::transmute(0usize) }; diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr index 8e6dc66a40ee..9950ac726ca7 100644 --- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr @@ -64,7 +64,7 @@ LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; 00 00 00 00 00 00 00 00 │ ........ } -error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> $DIR/raw-bytes.rs:61:1 | LL | const NULL_U8: NonZero = unsafe { mem::transmute(0u8) }; @@ -75,7 +75,7 @@ LL | const NULL_U8: NonZero = unsafe { mem::transmute(0u8) }; 00 │ . } -error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> $DIR/raw-bytes.rs:63:1 | LL | const NULL_USIZE: NonZero = unsafe { mem::transmute(0usize) }; diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr index e4486e3c500b..be5c6f77a087 100644 --- a/tests/ui/consts/const-eval/ub-nonnull.stderr +++ b/tests/ui/consts/const-eval/ub-nonnull.stderr @@ -15,7 +15,7 @@ error[E0080]: in-bounds pointer arithmetic failed: attempting to offset pointer LL | let out_of_bounds_ptr = &ptr[255]; | ^^^^^^^^^ evaluation of `OUT_OF_BOUNDS_PTR` failed here -error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> $DIR/ub-nonnull.rs:26:1 | LL | const NULL_U8: NonZero = unsafe { mem::transmute(0u8) }; @@ -26,7 +26,7 @@ LL | const NULL_U8: NonZero = unsafe { mem::transmute(0u8) }; HEX_DUMP } -error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> $DIR/ub-nonnull.rs:28:1 | LL | const NULL_USIZE: NonZero = unsafe { mem::transmute(0usize) }; diff --git a/tests/ui/lint/invalid_value.stderr b/tests/ui/lint/invalid_value.stderr index cc6a2a1c8e53..3dd2a521ff2e 100644 --- a/tests/ui/lint/invalid_value.stderr +++ b/tests/ui/lint/invalid_value.stderr @@ -333,7 +333,6 @@ LL | let _val: (NonZero, i32) = mem::uninitialized(); | = note: `std::num::NonZero` must be non-null = note: because `core::num::niche_types::NonZeroU32Inner` must be non-null - = note: integers must be initialized error: the type `*const dyn Send` does not permit zero-initialization --> $DIR/invalid_value.rs:97:37 @@ -430,7 +429,6 @@ note: because `std::num::NonZero` must be non-null (in this field of the on LL | Banana(NonZero), | ^^^^^^^^^^^^ = note: because `core::num::niche_types::NonZeroU32Inner` must be non-null - = note: integers must be initialized error: the type `bool` does not permit being left uninitialized --> $DIR/invalid_value.rs:111:26 From c9b5c934ca7acc33ff4aebbe1630cb02bb4c0f1f Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 10 Feb 2026 11:39:06 +0100 Subject: [PATCH 802/978] Fix passing/returning structs with the 64-bit SPARC ABI Co-authored-by: beetrees --- compiler/rustc_abi/src/callconv/reg.rs | 1 + compiler/rustc_target/src/callconv/sparc64.rs | 342 +++++++++--------- tests/assembly-llvm/sparc-struct-abi.rs | 193 +++++++++- tests/codegen-llvm/cast-target-abi.rs | 16 +- 4 files changed, 366 insertions(+), 186 deletions(-) diff --git a/compiler/rustc_abi/src/callconv/reg.rs b/compiler/rustc_abi/src/callconv/reg.rs index 66c8056d0c2a..66d4dca00726 100644 --- a/compiler/rustc_abi/src/callconv/reg.rs +++ b/compiler/rustc_abi/src/callconv/reg.rs @@ -35,6 +35,7 @@ impl Reg { reg_ctor!(f32, Float, 32); reg_ctor!(f64, Float, 64); + reg_ctor!(f128, Float, 128); } impl Reg { diff --git a/compiler/rustc_target/src/callconv/sparc64.rs b/compiler/rustc_target/src/callconv/sparc64.rs index fc732170dcb7..f55d03d89e8f 100644 --- a/compiler/rustc_target/src/callconv/sparc64.rs +++ b/compiler/rustc_target/src/callconv/sparc64.rs @@ -1,214 +1,203 @@ -// FIXME: This needs an audit for correctness and completeness. - use rustc_abi::{ - BackendRepr, FieldsShape, Float, HasDataLayout, Primitive, Reg, Scalar, Size, TyAbiInterface, - TyAndLayout, + Align, BackendRepr, FieldsShape, Float, HasDataLayout, Primitive, Reg, Size, TyAbiInterface, + TyAndLayout, Variants, }; use crate::callconv::{ArgAbi, ArgAttribute, CastTarget, FnAbi, Uniform}; -use crate::spec::{Env, HasTargetSpec, Os}; +use crate::spec::{HasTargetSpec, Os}; -#[derive(Clone, Debug)] -struct Sdata { - pub prefix: [Option; 8], - pub prefix_index: usize, - pub last_offset: Size, - pub has_float: bool, - pub arg_attribute: ArgAttribute, +// NOTE: GCC and Clang/LLVM have disagreements that the ABI doesn't resolve, we match the +// Clang/LLVM behavior in these cases. + +#[derive(Copy, Clone)] +enum DoubleWord { + F64, + F128Start, + F128End, + Words([Word; 2]), } -fn arg_scalar(cx: &C, scalar: &Scalar, offset: Size, mut data: Sdata) -> Sdata -where - C: HasDataLayout, -{ - let dl = cx.data_layout(); - - if !matches!(scalar.primitive(), Primitive::Float(Float::F32 | Float::F64)) { - return data; - } - - data.has_float = true; - - if !data.last_offset.is_aligned(dl.f64_align) && data.last_offset < offset { - if data.prefix_index == data.prefix.len() { - return data; - } - data.prefix[data.prefix_index] = Some(Reg::i32()); - data.prefix_index += 1; - data.last_offset = data.last_offset + Reg::i32().size; - } - - for _ in 0..((offset - data.last_offset).bits() / 64) - .min((data.prefix.len() - data.prefix_index) as u64) - { - data.prefix[data.prefix_index] = Some(Reg::i64()); - data.prefix_index += 1; - data.last_offset = data.last_offset + Reg::i64().size; - } - - if data.last_offset < offset { - if data.prefix_index == data.prefix.len() { - return data; - } - data.prefix[data.prefix_index] = Some(Reg::i32()); - data.prefix_index += 1; - data.last_offset = data.last_offset + Reg::i32().size; - } - - if data.prefix_index == data.prefix.len() { - return data; - } - - if scalar.primitive() == Primitive::Float(Float::F32) { - data.arg_attribute = ArgAttribute::InReg; - data.prefix[data.prefix_index] = Some(Reg::f32()); - data.last_offset = offset + Reg::f32().size; - } else { - data.prefix[data.prefix_index] = Some(Reg::f64()); - data.last_offset = offset + Reg::f64().size; - } - data.prefix_index += 1; - data +#[derive(Copy, Clone)] +enum Word { + F32, + Integer, } -fn arg_scalar_pair( +fn classify<'a, Ty, C>( cx: &C, - scalar1: &Scalar, - scalar2: &Scalar, - mut offset: Size, - mut data: Sdata, -) -> Sdata -where - C: HasDataLayout, -{ - data = arg_scalar(cx, scalar1, offset, data); - match (scalar1.primitive(), scalar2.primitive()) { - (Primitive::Float(Float::F32), _) => offset += Reg::f32().size, - (_, Primitive::Float(Float::F64)) => offset += Reg::f64().size, - (Primitive::Int(i, _signed), _) => offset += i.size(), - (Primitive::Pointer(_), _) => offset += Reg::i64().size, - _ => {} - } - - if !offset.bytes().is_multiple_of(4) - && matches!(scalar2.primitive(), Primitive::Float(Float::F32 | Float::F64)) - { - offset += Size::from_bytes(4 - (offset.bytes() % 4)); - } - data = arg_scalar(cx, scalar2, offset, data); - data -} - -fn parse_structure<'a, Ty, C>( - cx: &C, - layout: TyAndLayout<'a, Ty>, - mut data: Sdata, - mut offset: Size, -) -> Sdata -where + arg_layout: &TyAndLayout<'a, Ty>, + offset: Size, + double_words: &mut [DoubleWord; 4], +) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, { - if let FieldsShape::Union(_) = layout.fields { - return data; - } + // If this function does not update the `double_words` array, the value will be passed via + // integer registers. The array is initialized with `DoubleWord::Words([Word::Integer; 2])`. - match layout.backend_repr { - BackendRepr::Scalar(scalar) => { - data = arg_scalar(cx, &scalar, offset, data); - } - BackendRepr::Memory { .. } => { - for i in 0..layout.fields.count() { - if offset < layout.fields.offset(i) { - offset = layout.fields.offset(i); + match arg_layout.backend_repr { + BackendRepr::Scalar(scalar) => match scalar.primitive() { + Primitive::Float(float) => { + if offset.is_aligned(Ord::min(*float.align(cx), Align::EIGHT)) { + let index = offset.bytes_usize() / 8; + match float { + Float::F128 => { + double_words[index] = DoubleWord::F128Start; + double_words[index + 1] = DoubleWord::F128End; + } + Float::F64 => { + double_words[index] = DoubleWord::F64; + } + Float::F32 => match &mut double_words[index] { + DoubleWord::Words(words) => { + words[(offset.bytes_usize() % 8) / 4] = Word::F32; + } + _ => unreachable!(), + }, + Float::F16 => { + // Match LLVM by passing `f16` in integer registers. + } + } + } else { + /* pass unaligned floats in integer registers */ } - data = parse_structure(cx, layout.field(cx, i), data.clone(), offset); } - } - _ => { - if let BackendRepr::ScalarPair(scalar1, scalar2) = &layout.backend_repr { - data = arg_scalar_pair(cx, scalar1, scalar2, offset, data); + Primitive::Int(_, _) | Primitive::Pointer(_) => { /* pass in integer registers */ } + }, + BackendRepr::SimdVector { .. } => {} + BackendRepr::ScalableVector { .. } => {} + BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => match arg_layout.fields { + FieldsShape::Primitive => { + unreachable!("aggregates can't have `FieldsShape::Primitive`") } - } + FieldsShape::Union(_) => { + if !arg_layout.is_zst() { + if arg_layout.is_transparent() { + let non_1zst_elem = arg_layout.non_1zst_field(cx).expect("not exactly one non-1-ZST field in non-ZST repr(transparent) union").1; + classify(cx, &non_1zst_elem, offset, double_words); + } + } + } + FieldsShape::Array { .. } => {} + FieldsShape::Arbitrary { .. } => match arg_layout.variants { + Variants::Multiple { .. } => {} + Variants::Single { .. } | Variants::Empty => { + // Match Clang by ignoring whether a struct is packed and just considering + // whether individual fields are aligned. GCC currently uses only integer + // registers when passing packed structs. + for i in arg_layout.fields.index_by_increasing_offset() { + classify( + cx, + &arg_layout.field(cx, i), + offset + arg_layout.fields.offset(i), + double_words, + ); + } + } + }, + }, } - - data } -fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, in_registers_max: Size) -where +fn classify_arg<'a, Ty, C>( + cx: &C, + arg: &mut ArgAbi<'a, Ty>, + in_registers_max: Size, + total_double_word_count: &mut usize, +) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, { + // 64-bit SPARC allocates argument stack space in 64-bit chunks (double words), some of which + // are promoted to registers based on their position on the stack. + + // Keep track of the total number of double words used by arguments so far. This allows padding + // arguments to be inserted where necessary to ensure that 16-aligned arguments are passed in an + // aligned set of registers. + + let pad = !total_double_word_count.is_multiple_of(2) && arg.layout.align.abi.bytes() == 16; + // The number of double words used by this argument. + let double_word_count = arg.layout.size.bytes_usize().div_ceil(8); + // The number of double words before this argument, including any padding. + let start_double_word_count = *total_double_word_count + usize::from(pad); + if arg.layout.pass_indirectly_in_non_rustic_abis(cx) { arg.make_indirect(); + *total_double_word_count += 1; return; } + if !arg.layout.is_aggregate() { arg.extend_integer_width_to(64); + *total_double_word_count = start_double_word_count + double_word_count; return; } let total = arg.layout.size; if total > in_registers_max { arg.make_indirect(); + *total_double_word_count += 1; return; } - match arg.layout.fields { - FieldsShape::Primitive => unreachable!(), - FieldsShape::Array { .. } => { - // Arrays are passed indirectly - arg.make_indirect(); - return; + *total_double_word_count = start_double_word_count + double_word_count; + + const ARGUMENT_REGISTERS: usize = 8; + + let mut double_words = [DoubleWord::Words([Word::Integer; 2]); ARGUMENT_REGISTERS / 2]; + classify(cx, &arg.layout, Size::ZERO, &mut double_words); + + let mut regs = [None; ARGUMENT_REGISTERS]; + let mut i = 0; + let mut push = |reg| { + regs[i] = Some(reg); + i += 1; + }; + let mut attrs = ArgAttribute::empty(); + + for (index, double_word) in double_words.into_iter().enumerate() { + if arg.layout.size.bytes_usize() <= index * 8 { + break; } - FieldsShape::Union(_) => { - // Unions and are always treated as a series of 64-bit integer chunks - } - FieldsShape::Arbitrary { .. } => { - // Structures with floating point numbers need special care. - - let mut data = parse_structure( - cx, - arg.layout, - Sdata { - prefix: [None; 8], - prefix_index: 0, - last_offset: Size::ZERO, - has_float: false, - arg_attribute: ArgAttribute::default(), - }, - Size::ZERO, - ); - - if data.has_float { - // Structure { float, int, int } doesn't like to be handled like - // { float, long int }. Other way around it doesn't mind. - if data.last_offset < arg.layout.size - && !data.last_offset.bytes().is_multiple_of(8) - && data.prefix_index < data.prefix.len() - { - data.prefix[data.prefix_index] = Some(Reg::i32()); - data.prefix_index += 1; - data.last_offset += Reg::i32().size; + match double_word { + // `f128` must be aligned to be assigned a float register. + DoubleWord::F128Start if (start_double_word_count + index).is_multiple_of(2) => { + push(Reg::f128()); + } + DoubleWord::F128Start => { + // Clang currently handles this case nonsensically, always returning a packed + // `struct { long double x; }` in an aligned quad floating-point register even when + // the `long double` isn't aligned on the stack, which also makes all future + // arguments get passed in the wrong registers. This passes the `f128` in integer + // registers when it is unaligned, same as with `f32` and `f64`. + push(Reg::i64()); + push(Reg::i64()); + } + DoubleWord::F128End => {} // Already handled by `F128Start` + DoubleWord::F64 => push(Reg::f64()), + DoubleWord::Words([Word::Integer, Word::Integer]) => push(Reg::i64()), + DoubleWord::Words(words) => { + attrs |= ArgAttribute::InReg; + for word in words { + match word { + Word::F32 => push(Reg::f32()), + Word::Integer => push(Reg::i32()), + } } - - let mut rest_size = arg.layout.size - data.last_offset; - if !rest_size.bytes().is_multiple_of(8) && data.prefix_index < data.prefix.len() { - data.prefix[data.prefix_index] = Some(Reg::i32()); - rest_size = rest_size - Reg::i32().size; - } - - arg.cast_to( - CastTarget::prefixed(data.prefix, Uniform::new(Reg::i64(), rest_size)) - .with_attrs(data.arg_attribute.into()), - ); - return; } } } - arg.cast_to(Uniform::new(Reg::i64(), total)); + let cast_target = match regs { + [Some(reg), None, rest @ ..] => { + // Just a single register is needed for this value. + debug_assert!(rest.iter().all(|x| x.is_none())); + CastTarget::from(reg) + } + _ => CastTarget::prefixed(regs, Uniform::new(Reg::i8(), Size::ZERO)), + }; + + arg.cast_to_and_pad_i32(cast_target.with_attrs(attrs.into()), pad); } pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) @@ -217,23 +206,26 @@ where C: HasDataLayout + HasTargetSpec, { if !fn_abi.ret.is_ignore() && fn_abi.ret.layout.is_sized() { - classify_arg(cx, &mut fn_abi.ret, Size::from_bytes(32)); + // A return value of 32 bytes or smaller is passed via registers. + classify_arg(cx, &mut fn_abi.ret, Size::from_bytes(32), &mut 0); } + // sparc64-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs. + let passes_zsts = matches!(cx.target_spec().os, Os::Linux); + + let mut double_word_count = 0; for arg in fn_abi.args.iter_mut() { if !arg.layout.is_sized() { continue; } if arg.is_ignore() { - // sparc64-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs. - if cx.target_spec().os == Os::Linux - && matches!(cx.target_spec().env, Env::Gnu | Env::Musl | Env::Uclibc) - && arg.layout.is_zst() - { + if passes_zsts && arg.layout.is_zst() { arg.make_indirect_from_ignore(); + double_word_count += 1; } - return; + continue; } - classify_arg(cx, arg, Size::from_bytes(16)); + // An argument of 16 bytes or smaller is passed via registers. + classify_arg(cx, arg, Size::from_bytes(16), &mut double_word_count); } } diff --git a/tests/assembly-llvm/sparc-struct-abi.rs b/tests/assembly-llvm/sparc-struct-abi.rs index c6e83b6f8dab..41ac2be09b65 100644 --- a/tests/assembly-llvm/sparc-struct-abi.rs +++ b/tests/assembly-llvm/sparc-struct-abi.rs @@ -9,6 +9,7 @@ #![crate_type = "lib"] #![feature(no_core, lang_items)] #![no_core] +#![feature(f128)] extern crate minicore; use minicore::*; @@ -21,8 +22,33 @@ pub struct Franta { d: f32, } +#[repr(C, packed)] +struct Misaligned(i32, f64); + +#[repr(C)] +struct AlignToMakeAssemblyShorter(T, f64); + +#[repr(C)] +pub struct Floats(i32, f32, f64, f128); + +#[repr(C)] +pub struct LessFloats(f32, i32, f64); + +#[repr(C)] +pub struct NotMisaligned(i32, Misaligned); + +#[repr(C, align(16))] +pub struct Align16(f64, i32, i32); + +impl Copy for Misaligned {} +impl Copy for AlignToMakeAssemblyShorter {} +impl Copy for Floats {} +impl Copy for LessFloats {} +impl Copy for NotMisaligned {} +impl Copy for Align16 {} + // NB: due to delay slots the `ld` following the call is actually executed before the call. -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn callee(arg: Franta) { // CHECK-LABEL: callee: // CHECK: st %f3, [[PLACE_D:.*]] @@ -54,7 +80,7 @@ extern "C" { fn tail_call_avoidance_fn(); } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn caller() { // CHECK-LABEL: caller: // CHECK: ld [{{.*}}], %f0 @@ -62,7 +88,168 @@ pub unsafe extern "C" fn caller() { // CHECK: ld [{{.*}}], %f2 // CHECK: ld [{{.*}}], %f3 // CHECK: call opaque_callee - // CHECK: mov 3, %o2 + // CHECK: mov 3, %o2 opaque_callee(Franta { a: 1.0, b: 2.0, c: 3.0, d: 4.0 }, 3); tail_call_avoidance_fn(); } + +// Check that misaligned floats aren't promoted to floating point registers. +// CHECK-LABEL: misaligned_arg: +#[unsafe(no_mangle)] +extern "C" fn misaligned_arg(x: &mut AlignToMakeAssemblyShorter, value: Misaligned) { + // CHECK: srlx %o2, 32, %o2 + // CHECK-NEXT: stx %o1, [%o0] + // CHECK-NEXT: retl + // CHECK-NEXT: st %o2, [%o0+8] + x.0 = value; +} + +// CHECK-LABEL: misaligned_ret: +#[unsafe(no_mangle)] +extern "C" fn misaligned_ret(x: &AlignToMakeAssemblyShorter) -> Misaligned { + // CHECK: ld [%o0+8], %o1 + // CHECK-NEXT: ldx [%o0], %o0 + // CHECK-NEXT: retl + // CHECK-NEXT: sllx %o1, 32, %o1 + x.0 +} + +// Check structs where 32 >= size > 16 are promoted to register only as an argument. +// Also check that the various floating-point types are promoted to the correct registers. +// CHECK-LABEL: floats_arg: +#[unsafe(no_mangle)] +extern "C" fn floats_arg(x: &mut Floats, value: Floats) { + // CHECK: ldx [%o1+24], %o2 + // CHECK-NEXT: ldx [%o1+16], %o3 + // CHECK-NEXT: ldx [%o1+8], %o4 + // CHECK-NEXT: ldx [%o1], %o1 + // CHECK-NEXT: stx %o2, [%o0+24] + // CHECK-NEXT: stx %o3, [%o0+16] + // CHECK-NEXT: stx %o4, [%o0+8] + // CHECK-NEXT: retl + // CHECK-NEXT: stx %o1, [%o0] + *x = value; +} + +// CHECK-LABEL: floats_ret: +#[unsafe(no_mangle)] +extern "C" fn floats_ret(x: &Floats) -> Floats { + // CHECK: ld [%o0+4], %f1 + // CHECK-NEXT: ldd [%o0+8], %f2 + // CHECK-NEXT: ldd [%o0+16], %f4 + // CHECK-NEXT: ld [%o0], %o1 + // CHECK-NEXT: ldd [%o0+24], %f6 + // CHECK-NEXT: retl + // CHECK-NEXT: sllx %o1, 32, %o0 + *x +} + +// Check float promotion when passing as an argument with a struct where size <= 16. +// CHECK-LABEL: less_floats_arg: +#[unsafe(no_mangle)] +extern "C" fn less_floats_arg(x: &mut LessFloats, value: LessFloats) { + // CHECK: st %f2, [%o0] + // CHECK-NEXT: st %o1, [%o0+4] + // CHECK-NEXT: retl + // CHECK-NEXT: std %f4, [%o0+8] + *x = value; +} + +// CHECK-LABEL: less_floats_ret: +#[unsafe(no_mangle)] +extern "C" fn less_floats_ret(x: &LessFloats) -> LessFloats { + // CHECK: ld [%o0], %f0 + // CHECK-NEXT: ldd [%o0+8], %f2 + // CHECK-NEXT: retl + // CHECK-NEXT: ld [%o0+4], %o0 + *x +} + +// Check fields are promoted if they are aligned in the overall structure. +// This matches Clang's behaviour but not GCC's. +// CHECK-LABEL: not_misaligned_arg: +#[unsafe(no_mangle)] +extern "C" fn not_misaligned_arg( + x: &mut AlignToMakeAssemblyShorter, + value: NotMisaligned, +) { + // CHECK: stx %o1, [%o0] + // CHECK-NEXT: retl + // CHECK-NEXT: std %f4, [%o0+8] + x.0 = value; +} + +// CHECK-LABEL: not_misaligned_ret: +#[unsafe(no_mangle)] +extern "C" fn not_misaligned_ret(x: &AlignToMakeAssemblyShorter) -> NotMisaligned { + // CHECK: ldx [%o0], %o1 + // CHECK-NEXT: ldd [%o0+8], %f2 + // CHECK-NEXT: retl + // CHECK-NEXT: mov %o1, %o0 + x.0 +} + +// Check that 16-aligned structs are allocated the correct registers. +// CHECK-LABEL: align_16_arg: +#[unsafe(no_mangle)] +extern "C" fn align_16_arg(x: &mut Align16, value: Align16) { + // CHECK: std %f4, [%o0] + // CHECK-NEXT: retl + // CHECK-NEXT: stx %o3, [%o0+8] + *x = value; +} + +// CHECK-LABEL: align_16_ret: +#[unsafe(no_mangle)] +extern "C" fn align_16_ret(x: &Align16) -> Align16 { + // CHECK: ldd [%o0], %f0 + // CHECK-NEXT: retl + // CHECK-NEXT: ldx [%o0+8], %o1 + *x +} + +// Check ZST args don't prevent further arguments from being processed. +// CHECK-LABEL: zst_arg: +#[unsafe(no_mangle)] +extern "C" fn zst_arg(_: (), value: LessFloats, x: &mut LessFloats) { + // CHECK: st %f0, [%o2] + // CHECK-NEXT: st %o0, [%o2+4] + // CHECK-NEXT: retl + // CHECK-NEXT: std %f2, [%o2+8] + *x = value; +} + +#[repr(C)] +struct I32F32Input { + a: i32, + b: f32, +} + +#[repr(C)] +struct I32F32Output { + b: f32, + a: i32, +} + +// The clang/LLVM implementation mentions that this case requires special handling. +// CHECK-LABEL: i32_f32: +#[unsafe(no_mangle)] +extern "C" fn i32_f32(input: I32F32Input) -> I32F32Output { + // CHECK: srlx %o0, 32, %o0 + // CHECK-NEXT: fmovs %f1, %f0 + // CHECK-NEXT: retl + // CHECK-NEXT: nop + I32F32Output { a: input.a, b: input.b } +} + +#[repr(C)] +pub struct C { + a: f64, + b: f32, +} + +// regression test for https://github.com/rust-lang/rust/issues/147883. +#[unsafe(no_mangle)] +pub extern "C" fn foo(c: C) -> C { + c +} diff --git a/tests/codegen-llvm/cast-target-abi.rs b/tests/codegen-llvm/cast-target-abi.rs index 101e73e33c91..6f1ab4572ee0 100644 --- a/tests/codegen-llvm/cast-target-abi.rs +++ b/tests/codegen-llvm/cast-target-abi.rs @@ -119,7 +119,7 @@ pub extern "C" fn returns_twou16s() -> TwoU16s { // aarch64-SAME: ([[ABI_TYPE:\[2 x i64\]]] {{.*}}[[ABI_VALUE:%.+]]) // loongarch64-SAME: ([[ABI_TYPE:\[2 x i64\]]] {{.*}}[[ABI_VALUE:%.+]]) // powerpc64-SAME: ([[ABI_TYPE:\[2 x i64\]]] {{.*}}[[ABI_VALUE:%.+]]) -// sparc64-SAME: ([[ABI_TYPE:\[2 x i64\]]] {{.*}}[[ABI_VALUE:%.+]]) +// sparc64-SAME: ([[ABI_TYPE:{ i64, i64 }]] {{.*}}[[ABI_VALUE:%.+]]) // x86_64-SAME: ([[ABI_TYPE:{ i64, i16 }]] {{.*}}[[ABI_VALUE:%.+]]) #[no_mangle] #[inline(never)] @@ -148,7 +148,7 @@ pub extern "C" fn returns_fiveu16s() -> FiveU16s { // aarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] - // sparc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // sparc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ i64, i64 }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // x86_64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ i64, i16 }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // aarch64: ret [[ABI_TYPE]] [[ABI_VALUE]] @@ -217,7 +217,7 @@ pub extern "C" fn returns_doubledouble() -> DoubleDouble { // aarch64-SAME: ([[ABI_TYPE:\[2 x i64\]]] {{.*}}[[ABI_VALUE:%.+]]) // loongarch64-SAME: ([[ABI_TYPE:\[2 x i64\]]] {{.*}}[[ABI_VALUE:%.+]]) // powerpc64-SAME: ([[ABI_TYPE:\[2 x i64\]]] {{.*}}[[ABI_VALUE:%.+]]) -// sparc64-SAME: ([[ABI_TYPE:\[2 x i64\]]] {{.*}}[[ABI_VALUE:%.+]]) +// sparc64-SAME: ([[ABI_TYPE:{ i64, i64 }]] {{.*}}[[ABI_VALUE:%.+]]) // x86_64-SAME: ([[ABI_TYPE:{ i64, i32 }]] {{.*}}[[ABI_VALUE:%.+]]) #[no_mangle] #[inline(never)] @@ -246,7 +246,7 @@ pub extern "C" fn returns_three32s() -> Three32s { // aarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] - // sparc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // sparc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ i64, i64 }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // x86_64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ i64, i32 }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // aarch64: ret [[ABI_TYPE]] [[ABI_VALUE]] @@ -399,7 +399,7 @@ pub fn call_fiveu16s() { // aarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // powerpc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] - // sparc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // sparc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ i64, i64 }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // x86_64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ i64, i16 }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // CHECK: call void @receives_fiveu16s([[ABI_TYPE]] [[ABI_VALUE]]) @@ -424,7 +424,7 @@ pub fn return_fiveu16s() -> FiveU16s { // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x i64\]]] @returns_fiveu16s() // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x i64\]]] @returns_fiveu16s() - // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x i64\]]] @returns_fiveu16s() + // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:{ i64, i64 }]] @returns_fiveu16s() // x86_64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:{ i64, i16 }]] @returns_fiveu16s() // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] @@ -595,7 +595,7 @@ pub fn call_three32s() { // aarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // powerpc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] - // sparc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // sparc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ i64, i64 }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // x86_64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ i64, i32 }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // CHECK: call void @receives_three32s([[ABI_TYPE]] [[ABI_VALUE]]) @@ -619,7 +619,7 @@ pub fn return_three32s() -> Three32s { // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x i64\]]] @returns_three32s() // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x i64\]]] @returns_three32s() - // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x i64\]]] @returns_three32s() + // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:{ i64, i64 }]] @returns_three32s() // x86_64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:{ i64, i32 }]] @returns_three32s() // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] From b23d30885308fadf851af7fc3134d129731b6417 Mon Sep 17 00:00:00 2001 From: Asuna Date: Wed, 14 Jan 2026 22:19:12 +0100 Subject: [PATCH 803/978] Support structs in type info reflection --- .../src/const_eval/type_info.rs | 177 ++++++++++++++---- compiler/rustc_span/src/symbol.rs | 2 + library/core/src/mem/type_info.rs | 15 ++ library/coretests/tests/mem/type_info.rs | 51 +++++ .../missing-trait-bounds/issue-69725.stderr | 8 +- tests/ui/reflection/dump.bit32.run.stdout | 55 +++++- tests/ui/reflection/dump.bit64.run.stdout | 55 +++++- tests/ui/reflection/dump.rs | 9 +- 8 files changed, 333 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index f8881f0968bb..5b96856b253f 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -1,18 +1,36 @@ -use rustc_abi::FieldIdx; +use std::borrow::Cow; + +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_ast::Mutability; use rustc_hir::LangItem; use rustc_middle::span_bug; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::ty::{self, Const, ScalarInt, Ty}; +use rustc_middle::ty::{self, AdtDef, AdtKind, Const, GenericArgs, ScalarInt, Ty, VariantDef}; use rustc_span::{Symbol, sym}; use crate::const_eval::CompileTimeMachine; use crate::interpret::{ - CtfeProvenance, Immediate, InterpCx, InterpResult, MPlaceTy, MemoryKind, Scalar, Writeable, - interp_ok, + CtfeProvenance, Immediate, InterpCx, InterpResult, MPlaceTy, MemoryKind, Projectable, Scalar, + Writeable, interp_ok, }; impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { + /// Equivalent to `project_downcast`, but identifies the variant by name instead of index. + fn downcast<'a>( + &self, + place: &(impl Writeable<'tcx, CtfeProvenance> + 'a), + name: Symbol, + ) -> InterpResult<'tcx, (VariantIdx, impl Writeable<'tcx, CtfeProvenance> + 'a)> { + let variants = place.layout().ty.ty_adt_def().unwrap().variants(); + let variant_idx = variants + .iter_enumerated() + .find(|(_idx, var)| var.name == name) + .unwrap_or_else(|| panic!("got {name} but expected one of {variants:#?}")) + .0; + + interp_ok((variant_idx, self.project_downcast(place, variant_idx)?)) + } + /// Writes a `core::mem::type_info::TypeInfo` for a given type, `ty` to the given place. pub(crate) fn write_type_info( &mut self, @@ -26,22 +44,13 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { // Fill all fields of the `TypeInfo` struct. for (idx, field) in ty_struct.fields.iter_enumerated() { let field_dest = self.project_field(dest, idx)?; - let downcast = |name: Symbol| { - let variants = field_dest.layout().ty.ty_adt_def().unwrap().variants(); - let variant_id = variants - .iter_enumerated() - .find(|(_idx, var)| var.name == name) - .unwrap_or_else(|| panic!("got {name} but expected one of {variants:#?}")) - .0; - - interp_ok((variant_id, self.project_downcast(&field_dest, variant_id)?)) - }; let ptr_bit_width = || self.tcx.data_layout.pointer_size().bits(); match field.name { sym::kind => { let variant_index = match ty.kind() { ty::Tuple(fields) => { - let (variant, variant_place) = downcast(sym::Tuple)?; + let (variant, variant_place) = + self.downcast(&field_dest, sym::Tuple)?; // project to the single tuple variant field of `type_info::Tuple` struct type let tuple_place = self.project_field(&variant_place, FieldIdx::ZERO)?; assert_eq!( @@ -59,7 +68,8 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { variant } ty::Array(ty, len) => { - let (variant, variant_place) = downcast(sym::Array)?; + let (variant, variant_place) = + self.downcast(&field_dest, sym::Array)?; let array_place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_array_type_info(array_place, *ty, *len)?; @@ -67,23 +77,38 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { variant } ty::Slice(ty) => { - let (variant, variant_place) = downcast(sym::Slice)?; + let (variant, variant_place) = + self.downcast(&field_dest, sym::Slice)?; let slice_place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_slice_type_info(slice_place, *ty)?; variant } + ty::Adt(adt_def, generics) => { + // TODO(type_info): Handle enum and union + if !adt_def.is_struct() { + self.downcast(&field_dest, sym::Other)?.0 + } else { + let (variant, variant_place) = + self.downcast(&field_dest, sym::Struct)?; + let place = self.project_field(&variant_place, FieldIdx::ZERO)?; + self.write_adt_type_info(place, (ty, *adt_def), generics)?; + variant + } + } ty::Bool => { - let (variant, _variant_place) = downcast(sym::Bool)?; + let (variant, _variant_place) = + self.downcast(&field_dest, sym::Bool)?; variant } ty::Char => { - let (variant, _variant_place) = downcast(sym::Char)?; + let (variant, _variant_place) = + self.downcast(&field_dest, sym::Char)?; variant } ty::Int(int_ty) => { - let (variant, variant_place) = downcast(sym::Int)?; + let (variant, variant_place) = self.downcast(&field_dest, sym::Int)?; let place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_int_type_info( place, @@ -93,7 +118,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { variant } ty::Uint(uint_ty) => { - let (variant, variant_place) = downcast(sym::Int)?; + let (variant, variant_place) = self.downcast(&field_dest, sym::Int)?; let place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_int_type_info( place, @@ -103,17 +128,19 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { variant } ty::Float(float_ty) => { - let (variant, variant_place) = downcast(sym::Float)?; + let (variant, variant_place) = + self.downcast(&field_dest, sym::Float)?; let place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_float_type_info(place, float_ty.bit_width())?; variant } ty::Str => { - let (variant, _variant_place) = downcast(sym::Str)?; + let (variant, _variant_place) = self.downcast(&field_dest, sym::Str)?; variant } ty::Ref(_, ty, mutability) => { - let (variant, variant_place) = downcast(sym::Reference)?; + let (variant, variant_place) = + self.downcast(&field_dest, sym::Reference)?; let reference_place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_reference_type_info(reference_place, *ty, *mutability)?; @@ -121,7 +148,8 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { variant } ty::RawPtr(ty, mutability) => { - let (variant, variant_place) = downcast(sym::Pointer)?; + let (variant, variant_place) = + self.downcast(&field_dest, sym::Pointer)?; let pointer_place = self.project_field(&variant_place, FieldIdx::ZERO)?; @@ -130,13 +158,13 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { variant } ty::Dynamic(predicates, region) => { - let (variant, variant_place) = downcast(sym::DynTrait)?; + let (variant, variant_place) = + self.downcast(&field_dest, sym::DynTrait)?; let dyn_place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_dyn_trait_type_info(dyn_place, *predicates, *region)?; variant } - ty::Adt(_, _) - | ty::Foreign(_) + ty::Foreign(_) | ty::Pat(_, _) | ty::FnDef(..) | ty::FnPtr(..) @@ -151,14 +179,14 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(..) - | ty::Error(_) => downcast(sym::Other)?.0, + | ty::Error(_) => self.downcast(&field_dest, sym::Other)?.0, }; self.write_discriminant(variant_index, &field_dest)? } sym::size => { let layout = self.layout_of(ty)?; let variant_index = if layout.is_sized() { - let (variant, variant_place) = downcast(sym::Some)?; + let (variant, variant_place) = self.downcast(&field_dest, sym::Some)?; let size_field_place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_scalar( @@ -168,7 +196,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { )?; variant } else { - downcast(sym::None)?.0 + self.downcast(&field_dest, sym::None)?.0 }; self.write_discriminant(variant_index, &field_dest)?; } @@ -204,7 +232,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { while let Some((i, place)) = fields_places.next(self)? { let field_ty = fields[i as usize]; - self.write_field(field_ty, place, tuple_layout, i)?; + self.write_field(field_ty, place, tuple_layout, None, i)?; } let fields_place = fields_place.map_provenance(CtfeProvenance::as_immutable); @@ -219,6 +247,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { field_ty: Ty<'tcx>, place: MPlaceTy<'tcx>, layout: TyAndLayout<'tcx>, + name: Option, idx: u64, ) -> InterpResult<'tcx> { for (field_idx, field_ty_field) in @@ -226,6 +255,15 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { { let field_place = self.project_field(&place, field_idx)?; match field_ty_field.name { + sym::name => { + let name = match name.as_ref() { + Some(name) => Cow::Borrowed(name.as_str()), + None => Cow::Owned(idx.to_string()), // For tuples + }; + let name_place = self.allocate_str_dedup(&name)?; + let ptr = self.mplace_to_ref(&name_place)?; + self.write_immediate(*ptr, &field_place)? + } sym::ty => self.write_type_id(field_ty, &field_place)?, sym::offset => { let offset = layout.fields.offset(idx as usize); @@ -287,6 +325,81 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { interp_ok(()) } + // FIXME(type_info): No semver considerations for now + pub(crate) fn write_adt_type_info( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + adt: (Ty<'tcx>, AdtDef<'tcx>), + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + let (adt_ty, adt_def) = adt; + match adt_def.adt_kind() { + AdtKind::Struct => self.write_struct_type_info( + place, + (adt_ty, adt_def.variant(VariantIdx::ZERO)), + generics, + ), + AdtKind::Union => todo!(), + AdtKind::Enum => todo!(), + } + } + + pub(crate) fn write_struct_type_info( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + struct_: (Ty<'tcx>, &'tcx VariantDef), + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + let (struct_ty, struct_def) = struct_; + let struct_layout = self.layout_of(struct_ty)?; + + for (field_idx, field) in + place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() + { + let field_place = self.project_field(&place, field_idx)?; + + match field.name { + sym::fields => { + let fields_slice_place = field_place; + let field_type = fields_slice_place + .layout() + .ty + .builtin_deref(false) + .unwrap() + .sequence_element_type(self.tcx.tcx); + let fields_layout = self.layout_of(Ty::new_array( + self.tcx.tcx, + field_type, + struct_def.fields.len() as u64, + ))?; + let fields_place = self.allocate(fields_layout, MemoryKind::Stack)?; + let mut fields_places = self.project_array_fields(&fields_place)?; + + for field_def in &struct_def.fields { + let (i, place) = fields_places.next(self)?.unwrap(); + let field_ty = field_def.ty(*self.tcx, generics); + self.write_field(field_ty, place, struct_layout, Some(field_def.name), i)?; + } + + let fields_place = fields_place.map_provenance(CtfeProvenance::as_immutable); + let ptr = Immediate::new_slice( + fields_place.ptr(), + struct_def.fields.len() as u64, + self, + ); + self.write_immediate(ptr, &fields_slice_place)? + } + sym::non_exhaustive => { + let is_non_exhaustive = struct_def.is_field_list_non_exhaustive(); + self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? + } + other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), + } + } + + interp_ok(()) + } + fn write_int_type_info( &mut self, place: impl Writeable<'tcx, CtfeProvenance>, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6aa2eae556e2..271124a4c372 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -372,6 +372,7 @@ symbols! { Stdin, Str, String, + Struct, StructuralPartialEq, SubdiagMessage, Subdiagnostic, @@ -1086,6 +1087,7 @@ symbols! { ffi_returns_twice, field, field_init_shorthand, + fields, file, file_options, flags, diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index 8b30803c97c9..0e87b9d9cbb7 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -49,6 +49,8 @@ pub enum TypeKind { Slice(Slice), /// Dynamic Traits. DynTrait(DynTrait), + /// Structs. + Struct(Struct), /// Primitive boolean type. Bool(Bool), /// Primitive character type. @@ -81,6 +83,8 @@ pub struct Tuple { #[non_exhaustive] #[unstable(feature = "type_info", issue = "146922")] pub struct Field { + /// The name of the field. + pub name: &'static str, /// The field's type. pub ty: TypeId, /// Offset in bytes from the parent type @@ -137,6 +141,17 @@ pub struct Trait { pub is_auto: bool, } +/// Compile-time type information about arrays. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct Struct { + /// All fields of the struct. + pub fields: &'static [Field], + /// Whether the struct field list is non-exhaustive. + pub non_exhaustive: bool, +} + /// Compile-time type information about `bool`. #[derive(Debug)] #[non_exhaustive] diff --git a/library/coretests/tests/mem/type_info.rs b/library/coretests/tests/mem/type_info.rs index 87f2d5dd8289..03ff5f55c4f7 100644 --- a/library/coretests/tests/mem/type_info.rs +++ b/library/coretests/tests/mem/type_info.rs @@ -1,4 +1,7 @@ +#![allow(dead_code)] + use std::any::{Any, TypeId}; +use std::mem::offset_of; use std::mem::type_info::{Type, TypeKind}; #[test] @@ -66,6 +69,54 @@ fn test_tuples() { } } +#[test] +fn test_structs() { + use TypeKind::*; + + const { + struct TestStruct { + first: u8, + second: u16, + reference: &'static u16, + } + + let Type { kind: Struct(ty), size, .. } = Type::of::() else { panic!() }; + assert!(size == Some(size_of::())); + assert!(!ty.non_exhaustive); + assert!(ty.fields.len() == 3); + assert!(ty.fields[0].name == "first"); + assert!(ty.fields[0].ty == TypeId::of::()); + assert!(ty.fields[0].offset == offset_of!(TestStruct, first)); + assert!(ty.fields[1].name == "second"); + assert!(ty.fields[1].ty == TypeId::of::()); + assert!(ty.fields[1].offset == offset_of!(TestStruct, second)); + assert!(ty.fields[2].name == "reference"); + assert!(ty.fields[2].ty != TypeId::of::<&'static u16>()); // FIXME(type_info): should be == + assert!(ty.fields[2].offset == offset_of!(TestStruct, reference)); + } + + const { + #[non_exhaustive] + struct NonExhaustive { + a: u8, + } + + let Type { kind: Struct(ty), .. } = Type::of::() else { panic!() }; + assert!(ty.non_exhaustive); + } + + const { + struct TupleStruct(u8, u16); + + let Type { kind: Struct(ty), .. } = Type::of::() else { panic!() }; + assert!(ty.fields.len() == 2); + assert!(ty.fields[0].name == "0"); + assert!(ty.fields[0].ty == TypeId::of::()); + assert!(ty.fields[1].name == "1"); + assert!(ty.fields[1].ty == TypeId::of::()); + } +} + #[test] fn test_primitives() { use TypeKind::*; diff --git a/tests/ui/missing-trait-bounds/issue-69725.stderr b/tests/ui/missing-trait-bounds/issue-69725.stderr index f483ea849b0e..20d2213f4f5f 100644 --- a/tests/ui/missing-trait-bounds/issue-69725.stderr +++ b/tests/ui/missing-trait-bounds/issue-69725.stderr @@ -1,17 +1,17 @@ -error[E0599]: the method `clone` exists for struct `Struct`, but its trait bounds were not satisfied +error[E0599]: the method `clone` exists for struct `issue_69725::Struct`, but its trait bounds were not satisfied --> $DIR/issue-69725.rs:9:32 | LL | let _ = Struct::::new().clone(); - | ^^^^^ method cannot be called on `Struct` due to unsatisfied trait bounds + | ^^^^^ method cannot be called on `issue_69725::Struct` due to unsatisfied trait bounds | ::: $DIR/auxiliary/issue-69725.rs:2:1 | LL | pub struct Struct(A); - | -------------------- doesn't satisfy `Struct: Clone` + | -------------------- doesn't satisfy `issue_69725::Struct: Clone` | = note: the following trait bounds were not satisfied: `A: Clone` - which is required by `Struct: Clone` + which is required by `issue_69725::Struct: Clone` help: consider restricting the type parameter to satisfy the trait bound | LL | fn crash() where A: Clone { diff --git a/tests/ui/reflection/dump.bit32.run.stdout b/tests/ui/reflection/dump.bit32.run.stdout index d15b46509ff2..feda3401e462 100644 --- a/tests/ui/reflection/dump.bit32.run.stdout +++ b/tests/ui/reflection/dump.bit32.run.stdout @@ -3,14 +3,17 @@ Type { Tuple { fields: [ Field { + name: "0", ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb), offset: 0, }, Field { + name: "1", ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb), offset: 1, }, Field { + name: "2", ty: TypeId(0x41223169ff28813ba79b7268a2a968d9), offset: 2, }, @@ -143,7 +146,18 @@ Type { ), } Type { - kind: Other, + kind: Struct( + Struct { + fields: [ + Field { + name: "a", + ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7), + offset: 0, + }, + ], + non_exhaustive: false, + }, + ), size: Some( 4, ), @@ -154,6 +168,45 @@ Type { 12, ), } +Type { + kind: Struct( + Struct { + fields: [ + Field { + name: "a", + ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7), + offset: 0, + }, + ], + non_exhaustive: true, + }, + ), + size: Some( + 4, + ), +} +Type { + kind: Struct( + Struct { + fields: [ + Field { + name: "0", + ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7), + offset: 8, + }, + Field { + name: "1", + ty: TypeId(0x9ed91be891e304132cb86891e578f4a5), + offset: 0, + }, + ], + non_exhaustive: false, + }, + ), + size: Some( + 12, + ), +} Type { kind: Reference( Reference { diff --git a/tests/ui/reflection/dump.bit64.run.stdout b/tests/ui/reflection/dump.bit64.run.stdout index efae22653951..d9fef71f619c 100644 --- a/tests/ui/reflection/dump.bit64.run.stdout +++ b/tests/ui/reflection/dump.bit64.run.stdout @@ -3,14 +3,17 @@ Type { Tuple { fields: [ Field { + name: "0", ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb), offset: 0, }, Field { + name: "1", ty: TypeId(0x0596b48cc04376e64d5c788c2aa46bdb), offset: 1, }, Field { + name: "2", ty: TypeId(0x41223169ff28813ba79b7268a2a968d9), offset: 2, }, @@ -143,7 +146,18 @@ Type { ), } Type { - kind: Other, + kind: Struct( + Struct { + fields: [ + Field { + name: "a", + ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7), + offset: 0, + }, + ], + non_exhaustive: false, + }, + ), size: Some( 4, ), @@ -154,6 +168,45 @@ Type { 24, ), } +Type { + kind: Struct( + Struct { + fields: [ + Field { + name: "a", + ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7), + offset: 0, + }, + ], + non_exhaustive: true, + }, + ), + size: Some( + 4, + ), +} +Type { + kind: Struct( + Struct { + fields: [ + Field { + name: "0", + ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7), + offset: 8, + }, + Field { + name: "1", + ty: TypeId(0x9ed91be891e304132cb86891e578f4a5), + offset: 0, + }, + ], + non_exhaustive: false, + }, + ), + size: Some( + 16, + ), +} Type { kind: Reference( Reference { diff --git a/tests/ui/reflection/dump.rs b/tests/ui/reflection/dump.rs index d42216a62fdc..fefaad325aea 100644 --- a/tests/ui/reflection/dump.rs +++ b/tests/ui/reflection/dump.rs @@ -14,6 +14,13 @@ struct Foo { a: u32, } +#[non_exhaustive] +struct NonExhaustiveStruct { + a: u32, +} + +struct TupleStruct(u32, u64); + enum Bar { Some(u32), None, @@ -37,7 +44,7 @@ fn main() { [u8; 2], i8, i32, i64, i128, isize, u8, u32, u64, u128, usize, - Foo, Bar, + Foo, Bar, NonExhaustiveStruct, TupleStruct, &Unsized, &str, &[u8], str, [u8], &u8, &mut u8, From 870fd9070b5d98422107b8c748f7c7d084d4d037 Mon Sep 17 00:00:00 2001 From: Asuna Date: Mon, 19 Jan 2026 01:07:51 +0100 Subject: [PATCH 804/978] Add generics info for structs in type info --- .../src/const_eval/type_info.rs | 153 ++++++++++++++---- compiler/rustc_span/src/symbol.rs | 4 + library/core/src/mem/type_info.rs | 41 +++++ library/coretests/tests/mem/type_info.rs | 20 ++- tests/ui/generics/wrong-number-of-args.rs | 2 +- tests/ui/generics/wrong-number-of-args.stderr | 2 +- tests/ui/reflection/dump.bit32.run.stdout | 50 ++++++ tests/ui/reflection/dump.bit64.run.stdout | 50 ++++++ tests/ui/reflection/dump.rs | 8 +- .../resolve/resolve-assoc-suggestions.stderr | 10 ++ 10 files changed, 304 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index 5b96856b253f..9fb01b1f5c5c 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -3,9 +3,12 @@ use std::borrow::Cow; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_ast::Mutability; use rustc_hir::LangItem; -use rustc_middle::span_bug; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::ty::{self, AdtDef, AdtKind, Const, GenericArgs, ScalarInt, Ty, VariantDef}; +use rustc_middle::ty::{ + self, AdtDef, AdtKind, Const, ConstKind, GenericArgKind, GenericArgs, Region, ScalarInt, Ty, + VariantDef, +}; +use rustc_middle::{bug, span_bug}; use rustc_span::{Symbol, sym}; use crate::const_eval::CompileTimeMachine; @@ -31,6 +34,37 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { interp_ok((variant_idx, self.project_downcast(place, variant_idx)?)) } + // A general method to write an array to a static slice place. + fn allocate_fill_and_write_slice_ptr( + &mut self, + slice_place: impl Writeable<'tcx, CtfeProvenance>, + len: u64, + writer: impl Fn(&mut Self, /* index */ u64, MPlaceTy<'tcx>) -> InterpResult<'tcx>, + ) -> InterpResult<'tcx> { + // Array element type + let field_ty = slice_place + .layout() + .ty + .builtin_deref(false) + .unwrap() + .sequence_element_type(self.tcx.tcx); + + // Allocate an array + let array_layout = self.layout_of(Ty::new_array(self.tcx.tcx, field_ty, len))?; + let array_place = self.allocate(array_layout, MemoryKind::Stack)?; + + // Fill the array fields + let mut field_places = self.project_array_fields(&array_place)?; + while let Some((i, place)) = field_places.next(self)? { + writer(self, i, place)?; + } + + // Write the slice pointing to the array + let array_place = array_place.map_provenance(CtfeProvenance::as_immutable); + let ptr = Immediate::new_slice(array_place.ptr(), len, self); + self.write_immediate(ptr, &slice_place) + } + /// Writes a `core::mem::type_info::TypeInfo` for a given type, `ty` to the given place. pub(crate) fn write_type_info( &mut self, @@ -207,6 +241,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { interp_ok(()) } + // TODO(type_info): Remove this method, use `allocate_fill_and_write_slice_ptr` as it's more general. pub(crate) fn write_tuple_fields( &mut self, tuple_place: impl Writeable<'tcx, CtfeProvenance>, @@ -359,36 +394,16 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { let field_place = self.project_field(&place, field_idx)?; match field.name { - sym::fields => { - let fields_slice_place = field_place; - let field_type = fields_slice_place - .layout() - .ty - .builtin_deref(false) - .unwrap() - .sequence_element_type(self.tcx.tcx); - let fields_layout = self.layout_of(Ty::new_array( - self.tcx.tcx, - field_type, - struct_def.fields.len() as u64, - ))?; - let fields_place = self.allocate(fields_layout, MemoryKind::Stack)?; - let mut fields_places = self.project_array_fields(&fields_place)?; - - for field_def in &struct_def.fields { - let (i, place) = fields_places.next(self)?.unwrap(); - let field_ty = field_def.ty(*self.tcx, generics); - self.write_field(field_ty, place, struct_layout, Some(field_def.name), i)?; - } - - let fields_place = fields_place.map_provenance(CtfeProvenance::as_immutable); - let ptr = Immediate::new_slice( - fields_place.ptr(), - struct_def.fields.len() as u64, - self, - ); - self.write_immediate(ptr, &fields_slice_place)? - } + sym::generics => self.write_generics(field_place, generics)?, + sym::fields => self.allocate_fill_and_write_slice_ptr( + field_place, + struct_def.fields.len() as u64, + |this, i, place| { + let field_def = &struct_def.fields[FieldIdx::from_usize(i as usize)]; + let field_ty = field_def.ty(*this.tcx, generics); + this.write_field(field_ty, place, struct_layout, Some(field_def.name), i) + }, + )?, sym::non_exhaustive => { let is_non_exhaustive = struct_def.is_field_list_non_exhaustive(); self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? @@ -400,6 +415,80 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { interp_ok(()) } + fn write_generics( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + self.allocate_fill_and_write_slice_ptr(place, generics.len() as u64, |this, i, place| { + match generics[i as usize].kind() { + GenericArgKind::Lifetime(region) => this.write_generic_lifetime(region, place), + GenericArgKind::Type(ty) => this.write_generic_type(ty, place), + GenericArgKind::Const(c) => this.write_generic_const(c, place), + } + }) + } + + fn write_generic_lifetime( + &mut self, + _region: Region<'tcx>, + place: MPlaceTy<'tcx>, + ) -> InterpResult<'tcx> { + let (variant_idx, _) = self.downcast(&place, sym::Lifetime)?; + self.write_discriminant(variant_idx, &place)?; + interp_ok(()) + } + + fn write_generic_type(&mut self, ty: Ty<'tcx>, place: MPlaceTy<'tcx>) -> InterpResult<'tcx> { + let (variant_idx, variant_place) = self.downcast(&place, sym::Type)?; + let generic_type_place = self.project_field(&variant_place, FieldIdx::ZERO)?; + + for (field_idx, field_def) in generic_type_place + .layout() + .ty + .ty_adt_def() + .unwrap() + .non_enum_variant() + .fields + .iter_enumerated() + { + let field_place = self.project_field(&generic_type_place, field_idx)?; + match field_def.name { + sym::ty => self.write_type_id(ty, &field_place)?, + other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"), + } + } + + self.write_discriminant(variant_idx, &place)?; + interp_ok(()) + } + + fn write_generic_const(&mut self, c: Const<'tcx>, place: MPlaceTy<'tcx>) -> InterpResult<'tcx> { + let ConstKind::Value(c) = c.kind() else { bug!("expected a computed const, got {c:?}") }; + + let (variant_idx, variant_place) = self.downcast(&place, sym::Const)?; + let const_place = self.project_field(&variant_place, FieldIdx::ZERO)?; + + for (field_idx, field_def) in const_place + .layout() + .ty + .ty_adt_def() + .unwrap() + .non_enum_variant() + .fields + .iter_enumerated() + { + let field_place = self.project_field(&const_place, field_idx)?; + match field_def.name { + sym::ty => self.write_type_id(c.ty, &field_place)?, + other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"), + } + } + + self.write_discriminant(variant_idx, &place)?; + interp_ok(()) + } + fn write_int_type_info( &mut self, place: impl Writeable<'tcx, CtfeProvenance>, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 271124a4c372..70f5c1d0c472 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -211,6 +211,7 @@ symbols! { CoercePointeeValidated, CoerceUnsized, Command, + Const, ConstParamTy, ConstParamTy_, Context, @@ -292,6 +293,7 @@ symbols! { IteratorMap, Layout, Left, + Lifetime, LinkedList, LintDiagnostic, LintPass, @@ -396,6 +398,7 @@ symbols! { Ty, TyCtxt, TyKind, + Type, Unknown, Unsize, UnsizedConstParamTy, @@ -1176,6 +1179,7 @@ symbols! { generic_const_parameter_types, generic_param_attrs, generic_pattern_types, + generics, get_context, global_alloc_ty, global_allocator, diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index 0e87b9d9cbb7..8b11e5bd7035 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -146,12 +146,53 @@ pub struct Trait { #[non_exhaustive] #[unstable(feature = "type_info", issue = "146922")] pub struct Struct { + /// Instantiated generics of the struct. + pub generics: &'static [Generic], /// All fields of the struct. pub fields: &'static [Field], /// Whether the struct field list is non-exhaustive. pub non_exhaustive: bool, } +/// Compile-time type information about instantiated generics of structs, enum and union variants. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub enum Generic { + /// Lifetimes. + Lifetime(Lifetime), + /// Types. + Type(GenericType), + /// Const parameters. + Const(Const), +} + +/// Compile-time type information about generic lifetimes. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct Lifetime { + // No additional information to provide for now. +} + +/// Compile-time type information about instantiated generic types. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct GenericType { + /// The type itself. + pub ty: TypeId, +} + +/// Compile-time type information about generic const parameters. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct Const { + /// The const's type. + pub ty: TypeId, +} + /// Compile-time type information about `bool`. #[derive(Debug)] #[non_exhaustive] diff --git a/library/coretests/tests/mem/type_info.rs b/library/coretests/tests/mem/type_info.rs index 03ff5f55c4f7..9daf31029af6 100644 --- a/library/coretests/tests/mem/type_info.rs +++ b/library/coretests/tests/mem/type_info.rs @@ -2,7 +2,7 @@ use std::any::{Any, TypeId}; use std::mem::offset_of; -use std::mem::type_info::{Type, TypeKind}; +use std::mem::type_info::{Const, Generic, GenericType, Type, TypeKind}; #[test] fn test_arrays() { @@ -115,6 +115,24 @@ fn test_structs() { assert!(ty.fields[1].name == "1"); assert!(ty.fields[1].ty == TypeId::of::()); } + + const { + struct Generics<'a, T, const C: u64> { + a: &'a T, + } + + let Type { kind: Struct(ty), .. } = Type::of::>() else { + panic!() + }; + assert!(ty.fields.len() == 1); + assert!(ty.generics.len() == 3); + + let Generic::Lifetime(_) = ty.generics[0] else { panic!() }; + let Generic::Type(GenericType { ty: generic_ty, .. }) = ty.generics[1] else { panic!() }; + assert!(generic_ty == TypeId::of::()); + let Generic::Const(Const { ty: const_ty, .. }) = ty.generics[2] else { panic!() }; + assert!(const_ty == TypeId::of::()); + } } #[test] diff --git a/tests/ui/generics/wrong-number-of-args.rs b/tests/ui/generics/wrong-number-of-args.rs index 8bc384a3d817..9af16567cd75 100644 --- a/tests/ui/generics/wrong-number-of-args.rs +++ b/tests/ui/generics/wrong-number-of-args.rs @@ -127,7 +127,7 @@ mod r#trait { //~| HELP remove type D = Box; - //~^ ERROR missing generics for trait `GenericType` + //~^ ERROR missing generics for trait `r#trait::GenericType` //~| HELP add missing type E = Box>; diff --git a/tests/ui/generics/wrong-number-of-args.stderr b/tests/ui/generics/wrong-number-of-args.stderr index bedeeb812fc9..554d017d67e3 100644 --- a/tests/ui/generics/wrong-number-of-args.stderr +++ b/tests/ui/generics/wrong-number-of-args.stderr @@ -469,7 +469,7 @@ note: trait defined here, with 1 lifetime parameter: `'a` LL | trait GenericLifetime<'a> { | ^^^^^^^^^^^^^^^ -- -error[E0107]: missing generics for trait `GenericType` +error[E0107]: missing generics for trait `r#trait::GenericType` --> $DIR/wrong-number-of-args.rs:129:22 | LL | type D = Box; diff --git a/tests/ui/reflection/dump.bit32.run.stdout b/tests/ui/reflection/dump.bit32.run.stdout index feda3401e462..e80cea8ece2f 100644 --- a/tests/ui/reflection/dump.bit32.run.stdout +++ b/tests/ui/reflection/dump.bit32.run.stdout @@ -148,6 +148,7 @@ Type { Type { kind: Struct( Struct { + generics: [], fields: [ Field { name: "a", @@ -171,6 +172,7 @@ Type { Type { kind: Struct( Struct { + generics: [], fields: [ Field { name: "a", @@ -188,6 +190,7 @@ Type { Type { kind: Struct( Struct { + generics: [], fields: [ Field { name: "0", @@ -207,6 +210,53 @@ Type { 12, ), } +Type { + kind: Struct( + Struct { + generics: [ + Lifetime( + Lifetime, + ), + Type( + GenericType { + ty: TypeId(0x56ced5e4a15bd89050bb9674fa2df013), + }, + ), + Type( + GenericType { + ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7), + }, + ), + Const( + Const { + ty: TypeId(0x9ed91be891e304132cb86891e578f4a5), + }, + ), + ], + fields: [ + Field { + name: "a", + ty: TypeId(0x56ced5e4a15bd89050bb9674fa2df013), + offset: 4, + }, + Field { + name: "b", + ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7), + offset: 8, + }, + Field { + name: "l", + ty: TypeId(0x5d686ae9be5f6232dca1f88c0b941fd9), + offset: 0, + }, + ], + non_exhaustive: false, + }, + ), + size: Some( + 12, + ), +} Type { kind: Reference( Reference { diff --git a/tests/ui/reflection/dump.bit64.run.stdout b/tests/ui/reflection/dump.bit64.run.stdout index d9fef71f619c..812a918e519d 100644 --- a/tests/ui/reflection/dump.bit64.run.stdout +++ b/tests/ui/reflection/dump.bit64.run.stdout @@ -148,6 +148,7 @@ Type { Type { kind: Struct( Struct { + generics: [], fields: [ Field { name: "a", @@ -171,6 +172,7 @@ Type { Type { kind: Struct( Struct { + generics: [], fields: [ Field { name: "a", @@ -188,6 +190,7 @@ Type { Type { kind: Struct( Struct { + generics: [], fields: [ Field { name: "0", @@ -207,6 +210,53 @@ Type { 16, ), } +Type { + kind: Struct( + Struct { + generics: [ + Lifetime( + Lifetime, + ), + Type( + GenericType { + ty: TypeId(0x56ced5e4a15bd89050bb9674fa2df013), + }, + ), + Type( + GenericType { + ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7), + }, + ), + Const( + Const { + ty: TypeId(0x9ed91be891e304132cb86891e578f4a5), + }, + ), + ], + fields: [ + Field { + name: "a", + ty: TypeId(0x56ced5e4a15bd89050bb9674fa2df013), + offset: 8, + }, + Field { + name: "b", + ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7), + offset: 12, + }, + Field { + name: "l", + ty: TypeId(0x5d686ae9be5f6232dca1f88c0b941fd9), + offset: 0, + }, + ], + non_exhaustive: false, + }, + ), + size: Some( + 16, + ), +} Type { kind: Reference( Reference { diff --git a/tests/ui/reflection/dump.rs b/tests/ui/reflection/dump.rs index fefaad325aea..d0da0582fb51 100644 --- a/tests/ui/reflection/dump.rs +++ b/tests/ui/reflection/dump.rs @@ -27,6 +27,12 @@ enum Bar { Foomp { a: (), b: &'static str }, } +struct Generics<'a, A, B, const C: u64> { + a: A, + b: B, + l: &'a (), +} + struct Unsized { x: u16, s: str, @@ -44,7 +50,7 @@ fn main() { [u8; 2], i8, i32, i64, i128, isize, u8, u32, u64, u128, usize, - Foo, Bar, NonExhaustiveStruct, TupleStruct, + Foo, Bar, NonExhaustiveStruct, TupleStruct, Generics, &Unsized, &str, &[u8], str, [u8], &u8, &mut u8, diff --git a/tests/ui/resolve/resolve-assoc-suggestions.stderr b/tests/ui/resolve/resolve-assoc-suggestions.stderr index 7d94fb5ca35f..e6311962884f 100644 --- a/tests/ui/resolve/resolve-assoc-suggestions.stderr +++ b/tests/ui/resolve/resolve-assoc-suggestions.stderr @@ -41,12 +41,22 @@ error[E0531]: cannot find tuple struct or tuple variant `Type` in this scope | LL | let Type(..); | ^^^^ not found in this scope + | +help: consider importing this tuple variant + | +LL + use std::mem::type_info::Generic::Type; + | error[E0425]: cannot find value `Type` in this scope --> $DIR/resolve-assoc-suggestions.rs:27:9 | LL | Type; | ^^^^ not found in this scope + | +help: consider importing this tuple variant + | +LL + use std::mem::type_info::Generic::Type; + | error[E0425]: cannot find type `method` in this scope --> $DIR/resolve-assoc-suggestions.rs:30:16 From e9037882c17d7ebd017c7403c934a5a5ef2d8488 Mon Sep 17 00:00:00 2001 From: Asuna Date: Tue, 20 Jan 2026 08:46:33 +0100 Subject: [PATCH 805/978] Support enums in type info reflection --- .../src/const_eval/type_info.rs | 142 ++++++++++++++---- compiler/rustc_span/src/symbol.rs | 2 + library/core/src/mem/type_info.rs | 28 ++++ library/coretests/tests/mem/type_info.rs | 42 ++++++ tests/ui/privacy/issue-79593.rs | 6 +- tests/ui/privacy/issue-79593.stderr | 6 +- tests/ui/reflection/dump.bit32.run.stdout | 41 ++++- tests/ui/reflection/dump.bit64.run.stdout | 41 ++++- tests/ui/reflection/dump.rs | 6 +- 9 files changed, 279 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index 9fb01b1f5c5c..701adc7f732b 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -120,15 +120,11 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { variant } ty::Adt(adt_def, generics) => { - // TODO(type_info): Handle enum and union - if !adt_def.is_struct() { + // TODO(type_info): Handle union + if !adt_def.is_struct() && !adt_def.is_enum() { self.downcast(&field_dest, sym::Other)?.0 } else { - let (variant, variant_place) = - self.downcast(&field_dest, sym::Struct)?; - let place = self.project_field(&variant_place, FieldIdx::ZERO)?; - self.write_adt_type_info(place, (ty, *adt_def), generics)?; - variant + self.write_adt_type_info(&field_dest, (ty, *adt_def), generics)? } } ty::Bool => { @@ -277,6 +273,25 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { self.write_immediate(ptr, &fields_slice_place) } + // Write fields for struct, enum variants + fn write_variant_fields( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + variant_def: &'tcx VariantDef, + variant_layout: TyAndLayout<'tcx>, + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + self.allocate_fill_and_write_slice_ptr( + place, + variant_def.fields.len() as u64, + |this, i, place| { + let field_def = &variant_def.fields[FieldIdx::from_usize(i as usize)]; + let field_ty = field_def.ty(*this.tcx, generics); + this.write_field(field_ty, place, variant_layout, Some(field_def.name), i) + }, + ) + } + fn write_field( &mut self, field_ty: Ty<'tcx>, @@ -363,20 +378,31 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { // FIXME(type_info): No semver considerations for now pub(crate) fn write_adt_type_info( &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, + place: &impl Writeable<'tcx, CtfeProvenance>, adt: (Ty<'tcx>, AdtDef<'tcx>), generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { + ) -> InterpResult<'tcx, VariantIdx> { let (adt_ty, adt_def) = adt; - match adt_def.adt_kind() { - AdtKind::Struct => self.write_struct_type_info( - place, - (adt_ty, adt_def.variant(VariantIdx::ZERO)), - generics, - ), + let variant_idx = match adt_def.adt_kind() { + AdtKind::Struct => { + let (variant, variant_place) = self.downcast(place, sym::Struct)?; + let place = self.project_field(&variant_place, FieldIdx::ZERO)?; + self.write_struct_type_info( + place, + (adt_ty, adt_def.variant(VariantIdx::ZERO)), + generics, + )?; + variant + } + AdtKind::Enum => { + let (variant, variant_place) = self.downcast(place, sym::Enum)?; + let place = self.project_field(&variant_place, FieldIdx::ZERO)?; + self.write_enum_type_info(place, adt, generics)?; + variant + } AdtKind::Union => todo!(), - AdtKind::Enum => todo!(), - } + }; + interp_ok(variant_idx) } pub(crate) fn write_struct_type_info( @@ -395,15 +421,9 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { match field.name { sym::generics => self.write_generics(field_place, generics)?, - sym::fields => self.allocate_fill_and_write_slice_ptr( - field_place, - struct_def.fields.len() as u64, - |this, i, place| { - let field_def = &struct_def.fields[FieldIdx::from_usize(i as usize)]; - let field_ty = field_def.ty(*this.tcx, generics); - this.write_field(field_ty, place, struct_layout, Some(field_def.name), i) - }, - )?, + sym::fields => { + self.write_variant_fields(field_place, struct_def, struct_layout, generics)? + } sym::non_exhaustive => { let is_non_exhaustive = struct_def.is_field_list_non_exhaustive(); self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? @@ -415,6 +435,76 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { interp_ok(()) } + pub(crate) fn write_enum_type_info( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + enum_: (Ty<'tcx>, AdtDef<'tcx>), + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + let (enum_ty, enum_def) = enum_; + let enum_layout = self.layout_of(enum_ty)?; + + for (field_idx, field) in + place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() + { + let field_place = self.project_field(&place, field_idx)?; + + match field.name { + sym::generics => self.write_generics(field_place, generics)?, + sym::variants => { + self.allocate_fill_and_write_slice_ptr( + field_place, + enum_def.variants().len() as u64, + |this, i, place| { + let variant_idx = VariantIdx::from_usize(i as usize); + let variant_def = &enum_def.variants()[variant_idx]; + let variant_layout = enum_layout.for_variant(this, variant_idx); + this.write_enum_variant(place, (variant_layout, &variant_def), generics) + }, + )?; + } + sym::non_exhaustive => { + let is_non_exhaustive = enum_def.is_variant_list_non_exhaustive(); + self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? + } + other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), + } + } + + interp_ok(()) + } + + fn write_enum_variant( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + variant: (TyAndLayout<'tcx>, &'tcx VariantDef), + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + let (variant_layout, variant_def) = variant; + + for (field_idx, field_def) in + place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() + { + let field_place = self.project_field(&place, field_idx)?; + match field_def.name { + sym::name => { + let name_place = self.allocate_str_dedup(variant_def.name.as_str())?; + let ptr = self.mplace_to_ref(&name_place)?; + self.write_immediate(*ptr, &field_place)? + } + sym::fields => { + self.write_variant_fields(field_place, &variant_def, variant_layout, generics)? + } + sym::non_exhaustive => { + let is_non_exhaustive = variant_def.is_field_list_non_exhaustive(); + self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? + } + other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"), + } + } + interp_ok(()) + } + fn write_generics( &mut self, place: impl Writeable<'tcx, CtfeProvenance>, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 70f5c1d0c472..a3576b9a4437 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -235,6 +235,7 @@ symbols! { DynTrait, Encodable, Encoder, + Enum, Enumerate, Eq, Equal, @@ -2480,6 +2481,7 @@ symbols! { values, var, variant_count, + variants, vec, vec_as_mut_slice, vec_as_slice, diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index 8b11e5bd7035..b66a836c4bd4 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -51,6 +51,8 @@ pub enum TypeKind { DynTrait(DynTrait), /// Structs. Struct(Struct), + /// Enums. + Enum(Enum), /// Primitive boolean type. Bool(Bool), /// Primitive character type. @@ -154,6 +156,32 @@ pub struct Struct { pub non_exhaustive: bool, } +/// Compile-time type information about enums. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct Enum { + /// Instantiated generics of the enum. + pub generics: &'static [Generic], + /// All variants of the enum. + pub variants: &'static [Variant], + /// Whether the enum variant list is non-exhaustive. + pub non_exhaustive: bool, +} + +/// Compile-time type information about variants of enums. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct Variant { + /// The name of the variant. + pub name: &'static str, + /// All fields of the variant. + pub fields: &'static [Field], + /// Whether the enum variant fields is non-exhaustive. + pub non_exhaustive: bool, +} + /// Compile-time type information about instantiated generics of structs, enum and union variants. #[derive(Debug)] #[non_exhaustive] diff --git a/library/coretests/tests/mem/type_info.rs b/library/coretests/tests/mem/type_info.rs index 9daf31029af6..09e3a50d374c 100644 --- a/library/coretests/tests/mem/type_info.rs +++ b/library/coretests/tests/mem/type_info.rs @@ -135,6 +135,48 @@ fn test_structs() { } } +#[test] +fn test_enums() { + use TypeKind::*; + + const { + enum E { + Some(u32), + None, + #[non_exhaustive] + Foomp { + a: (), + b: &'static str, + }, + } + + let Type { kind: Enum(ty), size, .. } = Type::of::() else { panic!() }; + assert!(size == Some(size_of::())); + assert!(ty.variants.len() == 3); + + assert!(ty.variants[0].name == "Some"); + assert!(!ty.variants[0].non_exhaustive); + assert!(ty.variants[0].fields.len() == 1); + + assert!(ty.variants[1].name == "None"); + assert!(!ty.variants[1].non_exhaustive); + assert!(ty.variants[1].fields.len() == 0); + + assert!(ty.variants[2].name == "Foomp"); + assert!(ty.variants[2].non_exhaustive); + assert!(ty.variants[2].fields.len() == 2); + } + + const { + let Type { kind: Enum(ty), size, .. } = Type::of::>() else { panic!() }; + assert!(size == Some(size_of::>())); + assert!(ty.variants.len() == 2); + assert!(ty.generics.len() == 1); + let Generic::Type(GenericType { ty: generic_ty, .. }) = ty.generics[0] else { panic!() }; + assert!(generic_ty == TypeId::of::()); + } +} + #[test] fn test_primitives() { use TypeKind::*; diff --git a/tests/ui/privacy/issue-79593.rs b/tests/ui/privacy/issue-79593.rs index 39c222f7c341..663dd67fcdb1 100644 --- a/tests/ui/privacy/issue-79593.rs +++ b/tests/ui/privacy/issue-79593.rs @@ -10,7 +10,7 @@ mod foo { Pub {}; //~^ ERROR missing field `private` in initializer of `Pub` Enum::Variant { x: () }; - //~^ ERROR missing field `y` in initializer of `Enum` + //~^ ERROR missing field `y` in initializer of `foo::Enum` } } @@ -21,9 +21,9 @@ fn correct() { fn wrong() { foo::Enum::Variant { x: () }; - //~^ ERROR missing field `y` in initializer of `Enum` + //~^ ERROR missing field `y` in initializer of `foo::Enum` foo::Enum::Variant { }; - //~^ ERROR missing fields `x` and `y` in initializer of `Enum` + //~^ ERROR missing fields `x` and `y` in initializer of `foo::Enum` } fn main() {} diff --git a/tests/ui/privacy/issue-79593.stderr b/tests/ui/privacy/issue-79593.stderr index 5bb69836f609..74fea1a3ab76 100644 --- a/tests/ui/privacy/issue-79593.stderr +++ b/tests/ui/privacy/issue-79593.stderr @@ -4,7 +4,7 @@ error[E0063]: missing field `private` in initializer of `Pub` LL | Pub {}; | ^^^ missing `private` -error[E0063]: missing field `y` in initializer of `Enum` +error[E0063]: missing field `y` in initializer of `foo::Enum` --> $DIR/issue-79593.rs:12:9 | LL | Enum::Variant { x: () }; @@ -18,13 +18,13 @@ LL | foo::Pub {}; | = note: private field `private` that was not provided -error[E0063]: missing field `y` in initializer of `Enum` +error[E0063]: missing field `y` in initializer of `foo::Enum` --> $DIR/issue-79593.rs:23:5 | LL | foo::Enum::Variant { x: () }; | ^^^^^^^^^^^^^^^^^^ missing `y` -error[E0063]: missing fields `x` and `y` in initializer of `Enum` +error[E0063]: missing fields `x` and `y` in initializer of `foo::Enum` --> $DIR/issue-79593.rs:25:5 | LL | foo::Enum::Variant { }; diff --git a/tests/ui/reflection/dump.bit32.run.stdout b/tests/ui/reflection/dump.bit32.run.stdout index e80cea8ece2f..a6ad84f5fef1 100644 --- a/tests/ui/reflection/dump.bit32.run.stdout +++ b/tests/ui/reflection/dump.bit32.run.stdout @@ -164,7 +164,46 @@ Type { ), } Type { - kind: Other, + kind: Enum( + Enum { + generics: [], + variants: [ + Variant { + name: "Some", + fields: [ + Field { + name: "0", + ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7), + offset: 4, + }, + ], + non_exhaustive: false, + }, + Variant { + name: "None", + fields: [], + non_exhaustive: false, + }, + Variant { + name: "Foomp", + fields: [ + Field { + name: "a", + ty: TypeId(0x41223169ff28813ba79b7268a2a968d9), + offset: 4, + }, + Field { + name: "b", + ty: TypeId(0xb98b1b7157a6417863eb502cd6cb5d6d), + offset: 4, + }, + ], + non_exhaustive: true, + }, + ], + non_exhaustive: false, + }, + ), size: Some( 12, ), diff --git a/tests/ui/reflection/dump.bit64.run.stdout b/tests/ui/reflection/dump.bit64.run.stdout index 812a918e519d..45f0a2e2f063 100644 --- a/tests/ui/reflection/dump.bit64.run.stdout +++ b/tests/ui/reflection/dump.bit64.run.stdout @@ -164,7 +164,46 @@ Type { ), } Type { - kind: Other, + kind: Enum( + Enum { + generics: [], + variants: [ + Variant { + name: "Some", + fields: [ + Field { + name: "0", + ty: TypeId(0x1378bb1c0a0202683eb65e7c11f2e4d7), + offset: 4, + }, + ], + non_exhaustive: false, + }, + Variant { + name: "None", + fields: [], + non_exhaustive: false, + }, + Variant { + name: "Foomp", + fields: [ + Field { + name: "a", + ty: TypeId(0x41223169ff28813ba79b7268a2a968d9), + offset: 4, + }, + Field { + name: "b", + ty: TypeId(0xb98b1b7157a6417863eb502cd6cb5d6d), + offset: 8, + }, + ], + non_exhaustive: true, + }, + ], + non_exhaustive: false, + }, + ), size: Some( 24, ), diff --git a/tests/ui/reflection/dump.rs b/tests/ui/reflection/dump.rs index d0da0582fb51..755f0c900e33 100644 --- a/tests/ui/reflection/dump.rs +++ b/tests/ui/reflection/dump.rs @@ -24,7 +24,11 @@ struct TupleStruct(u32, u64); enum Bar { Some(u32), None, - Foomp { a: (), b: &'static str }, + #[non_exhaustive] + Foomp { + a: (), + b: &'static str, + }, } struct Generics<'a, A, B, const C: u64> { From 98e0c34f7f5ba6d68a6e3506d1569939fbf14627 Mon Sep 17 00:00:00 2001 From: Asuna Date: Thu, 5 Feb 2026 19:28:55 +0100 Subject: [PATCH 806/978] Support unions in type info reflection --- .../src/const_eval/type_info.rs | 48 ++++++++++++++++--- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/mem/type_info.rs | 13 +++++ library/coretests/tests/mem/type_info.rs | 41 ++++++++++++++++ tests/ui/reflection/dump.bit32.run.stdout | 22 +++++++++ tests/ui/reflection/dump.bit64.run.stdout | 22 +++++++++ tests/ui/reflection/dump.rs | 7 ++- 7 files changed, 146 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index 701adc7f732b..0529d452626b 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -120,12 +120,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { variant } ty::Adt(adt_def, generics) => { - // TODO(type_info): Handle union - if !adt_def.is_struct() && !adt_def.is_enum() { - self.downcast(&field_dest, sym::Other)?.0 - } else { - self.write_adt_type_info(&field_dest, (ty, *adt_def), generics)? - } + self.write_adt_type_info(&field_dest, (ty, *adt_def), generics)? } ty::Bool => { let (variant, _variant_place) = @@ -394,13 +389,22 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { )?; variant } + AdtKind::Union => { + let (variant, variant_place) = self.downcast(place, sym::Union)?; + let place = self.project_field(&variant_place, FieldIdx::ZERO)?; + self.write_union_type_info( + place, + (adt_ty, adt_def.variant(VariantIdx::ZERO)), + generics, + )?; + variant + } AdtKind::Enum => { let (variant, variant_place) = self.downcast(place, sym::Enum)?; let place = self.project_field(&variant_place, FieldIdx::ZERO)?; self.write_enum_type_info(place, adt, generics)?; variant } - AdtKind::Union => todo!(), }; interp_ok(variant_idx) } @@ -435,6 +439,36 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { interp_ok(()) } + pub(crate) fn write_union_type_info( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + union_: (Ty<'tcx>, &'tcx VariantDef), + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + let (union_ty, union_def) = union_; + let union_layout = self.layout_of(union_ty)?; + + for (field_idx, field) in + place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() + { + let field_place = self.project_field(&place, field_idx)?; + + match field.name { + sym::generics => self.write_generics(field_place, generics)?, + sym::fields => { + self.write_variant_fields(field_place, union_def, union_layout, generics)? + } + sym::non_exhaustive => { + let is_non_exhaustive = union_def.is_field_list_non_exhaustive(); + self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? + } + other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), + } + } + + interp_ok(()) + } + pub(crate) fn write_enum_type_info( &mut self, place: impl Writeable<'tcx, CtfeProvenance>, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a3576b9a4437..1a099f0cd70f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -400,6 +400,7 @@ symbols! { TyCtxt, TyKind, Type, + Union, Unknown, Unsize, UnsizedConstParamTy, diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index b66a836c4bd4..c2b2cf2f270d 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -53,6 +53,8 @@ pub enum TypeKind { Struct(Struct), /// Enums. Enum(Enum), + /// Unions. + Union(Union), /// Primitive boolean type. Bool(Bool), /// Primitive character type. @@ -156,6 +158,17 @@ pub struct Struct { pub non_exhaustive: bool, } +/// Compile-time type information about unions. +#[derive(Debug)] +#[non_exhaustive] +#[unstable(feature = "type_info", issue = "146922")] +pub struct Union { + /// Instantiated generics of the union. + pub generics: &'static [Generic], + /// All fields of the union. + pub fields: &'static [Field], +} + /// Compile-time type information about enums. #[derive(Debug)] #[non_exhaustive] diff --git a/library/coretests/tests/mem/type_info.rs b/library/coretests/tests/mem/type_info.rs index 09e3a50d374c..808ef68783af 100644 --- a/library/coretests/tests/mem/type_info.rs +++ b/library/coretests/tests/mem/type_info.rs @@ -135,6 +135,47 @@ fn test_structs() { } } +#[test] +fn test_unions() { + use TypeKind::*; + + const { + union TestUnion { + first: i16, + second: u16, + } + + let Type { kind: Union(ty), size, .. } = Type::of::() else { panic!() }; + assert!(size == Some(size_of::())); + assert!(ty.fields.len() == 2); + assert!(ty.fields[0].name == "first"); + assert!(ty.fields[0].offset == offset_of!(TestUnion, first)); + assert!(ty.fields[1].name == "second"); + assert!(ty.fields[1].offset == offset_of!(TestUnion, second)); + } + + const { + union Generics<'a, T: Copy, const C: u64> { + a: T, + z: &'a (), + } + + let Type { kind: Union(ty), .. } = Type::of::>() else { + panic!() + }; + assert!(ty.fields.len() == 2); + assert!(ty.fields[0].offset == offset_of!(Generics<'static, i32, 1_u64>, a)); + assert!(ty.fields[1].offset == offset_of!(Generics<'static, i32, 1_u64>, z)); + + assert!(ty.generics.len() == 3); + let Generic::Lifetime(_) = ty.generics[0] else { panic!() }; + let Generic::Type(GenericType { ty: generic_ty, .. }) = ty.generics[1] else { panic!() }; + assert!(generic_ty == TypeId::of::()); + let Generic::Const(Const { ty: const_ty, .. }) = ty.generics[2] else { panic!() }; + assert!(const_ty == TypeId::of::()); + } +} + #[test] fn test_enums() { use TypeKind::*; diff --git a/tests/ui/reflection/dump.bit32.run.stdout b/tests/ui/reflection/dump.bit32.run.stdout index a6ad84f5fef1..24a467775725 100644 --- a/tests/ui/reflection/dump.bit32.run.stdout +++ b/tests/ui/reflection/dump.bit32.run.stdout @@ -296,6 +296,28 @@ Type { 12, ), } +Type { + kind: Union( + Union { + generics: [], + fields: [ + Field { + name: "first", + ty: TypeId(0xdeb66dd04fa9db03298cc77926096aae), + offset: 0, + }, + Field { + name: "second", + ty: TypeId(0xc50c4a8d8e150aa67101203f1fab1cd7), + offset: 0, + }, + ], + }, + ), + size: Some( + 2, + ), +} Type { kind: Reference( Reference { diff --git a/tests/ui/reflection/dump.bit64.run.stdout b/tests/ui/reflection/dump.bit64.run.stdout index 45f0a2e2f063..15f40d944173 100644 --- a/tests/ui/reflection/dump.bit64.run.stdout +++ b/tests/ui/reflection/dump.bit64.run.stdout @@ -296,6 +296,28 @@ Type { 16, ), } +Type { + kind: Union( + Union { + generics: [], + fields: [ + Field { + name: "first", + ty: TypeId(0xdeb66dd04fa9db03298cc77926096aae), + offset: 0, + }, + Field { + name: "second", + ty: TypeId(0xc50c4a8d8e150aa67101203f1fab1cd7), + offset: 0, + }, + ], + }, + ), + size: Some( + 2, + ), +} Type { kind: Reference( Reference { diff --git a/tests/ui/reflection/dump.rs b/tests/ui/reflection/dump.rs index 755f0c900e33..57669ca85f30 100644 --- a/tests/ui/reflection/dump.rs +++ b/tests/ui/reflection/dump.rs @@ -42,6 +42,11 @@ struct Unsized { s: str, } +union Union { + first: i16, + second: u16, +} + macro_rules! dump_types { ($($ty:ty),+ $(,)?) => { $(println!("{:#?}", const { Type::of::<$ty>() });)+ @@ -54,7 +59,7 @@ fn main() { [u8; 2], i8, i32, i64, i128, isize, u8, u32, u64, u128, usize, - Foo, Bar, NonExhaustiveStruct, TupleStruct, Generics, + Foo, Bar, NonExhaustiveStruct, TupleStruct, Generics, Union, &Unsized, &str, &[u8], str, [u8], &u8, &mut u8, From b410cb01fe86d992a97f6316a7265716d0e3f851 Mon Sep 17 00:00:00 2001 From: Asuna Date: Sat, 7 Feb 2026 19:03:34 +0100 Subject: [PATCH 807/978] Simplify the writing of tuple type info --- .../src/const_eval/type_info.rs | 56 +++++++------------ 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index 0529d452626b..97206e138697 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -98,7 +98,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { .fields .len() ); - self.write_tuple_fields(tuple_place, fields, ty)?; + self.write_tuple_type_info(tuple_place, fields, ty)?; variant } ty::Array(ty, len) => { @@ -232,42 +232,6 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { interp_ok(()) } - // TODO(type_info): Remove this method, use `allocate_fill_and_write_slice_ptr` as it's more general. - pub(crate) fn write_tuple_fields( - &mut self, - tuple_place: impl Writeable<'tcx, CtfeProvenance>, - fields: &[Ty<'tcx>], - tuple_ty: Ty<'tcx>, - ) -> InterpResult<'tcx> { - // project into the `type_info::Tuple::fields` field - let fields_slice_place = self.project_field(&tuple_place, FieldIdx::ZERO)?; - // get the `type_info::Field` type from `fields: &[Field]` - let field_type = fields_slice_place - .layout() - .ty - .builtin_deref(false) - .unwrap() - .sequence_element_type(self.tcx.tcx); - // Create an array with as many elements as the number of fields in the inspected tuple - let fields_layout = - self.layout_of(Ty::new_array(self.tcx.tcx, field_type, fields.len() as u64))?; - let fields_place = self.allocate(fields_layout, MemoryKind::Stack)?; - let mut fields_places = self.project_array_fields(&fields_place)?; - - let tuple_layout = self.layout_of(tuple_ty)?; - - while let Some((i, place)) = fields_places.next(self)? { - let field_ty = fields[i as usize]; - self.write_field(field_ty, place, tuple_layout, None, i)?; - } - - let fields_place = fields_place.map_provenance(CtfeProvenance::as_immutable); - - let ptr = Immediate::new_slice(fields_place.ptr(), fields.len() as u64, self); - - self.write_immediate(ptr, &fields_slice_place) - } - // Write fields for struct, enum variants fn write_variant_fields( &mut self, @@ -325,6 +289,24 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { interp_ok(()) } + pub(crate) fn write_tuple_type_info( + &mut self, + tuple_place: impl Writeable<'tcx, CtfeProvenance>, + fields: &[Ty<'tcx>], + tuple_ty: Ty<'tcx>, + ) -> InterpResult<'tcx> { + let tuple_layout = self.layout_of(tuple_ty)?; + let fields_slice_place = self.project_field(&tuple_place, FieldIdx::ZERO)?; + self.allocate_fill_and_write_slice_ptr( + fields_slice_place, + fields.len() as u64, + |this, i, place| { + let field_ty = fields[i as usize]; + this.write_field(field_ty, place, tuple_layout, None, i) + }, + ) + } + pub(crate) fn write_array_type_info( &mut self, place: impl Writeable<'tcx, CtfeProvenance>, From a575fe168f2293a9c8c2945f5c5795eaec2f4d34 Mon Sep 17 00:00:00 2001 From: Asuna Date: Tue, 10 Feb 2026 01:28:35 +0100 Subject: [PATCH 808/978] Erase type lifetime before writing type ID --- compiler/rustc_const_eval/src/const_eval/type_info.rs | 5 ++++- compiler/rustc_const_eval/src/interpret/intrinsics.rs | 7 ++++++- library/coretests/tests/mem/type_info.rs | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index 97206e138697..7741027981d0 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -273,7 +273,10 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { let ptr = self.mplace_to_ref(&name_place)?; self.write_immediate(*ptr, &field_place)? } - sym::ty => self.write_type_id(field_ty, &field_place)?, + sym::ty => { + let field_ty = self.tcx.erase_and_anonymize_regions(field_ty); + self.write_type_id(field_ty, &field_place)? + } sym::offset => { let offset = layout.fields.offset(idx as usize); self.write_scalar( diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 2ea5e4a25c11..49038315b546 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -13,7 +13,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, read_target_uint, write_target_uint}; use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic}; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::ty::{FloatTy, PolyExistentialPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{FloatTy, PolyExistentialPredicate, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::{bug, span_bug, ty}; use rustc_span::{Symbol, sym}; use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt}; @@ -73,6 +73,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ty: Ty<'tcx>, dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, ()> { + debug_assert!( + !ty.has_erasable_regions(), + "type {ty:?} has regions that need erasing before writing a TypeId", + ); + let tcx = self.tcx; let type_id_hash = tcx.type_id_hash(ty).as_u128(); let op = self.const_val_to_op( diff --git a/library/coretests/tests/mem/type_info.rs b/library/coretests/tests/mem/type_info.rs index 808ef68783af..2483b4c2aacd 100644 --- a/library/coretests/tests/mem/type_info.rs +++ b/library/coretests/tests/mem/type_info.rs @@ -91,7 +91,7 @@ fn test_structs() { assert!(ty.fields[1].ty == TypeId::of::()); assert!(ty.fields[1].offset == offset_of!(TestStruct, second)); assert!(ty.fields[2].name == "reference"); - assert!(ty.fields[2].ty != TypeId::of::<&'static u16>()); // FIXME(type_info): should be == + assert!(ty.fields[2].ty == TypeId::of::<&'static u16>()); assert!(ty.fields[2].offset == offset_of!(TestStruct, reference)); } From 6ab6734d4badb8fb8956873df1c3e2e2389a42f4 Mon Sep 17 00:00:00 2001 From: Asuna Date: Tue, 10 Feb 2026 02:09:07 +0100 Subject: [PATCH 809/978] Move ADT related code to a sub module for type info --- .../src/const_eval/type_info.rs | 271 +---------------- .../src/const_eval/type_info/adt.rs | 276 ++++++++++++++++++ 2 files changed, 280 insertions(+), 267 deletions(-) create mode 100644 compiler/rustc_const_eval/src/const_eval/type_info/adt.rs diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index 7741027981d0..0fd70d784d4f 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -1,14 +1,13 @@ +mod adt; + use std::borrow::Cow; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_ast::Mutability; use rustc_hir::LangItem; +use rustc_middle::span_bug; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::ty::{ - self, AdtDef, AdtKind, Const, ConstKind, GenericArgKind, GenericArgs, Region, ScalarInt, Ty, - VariantDef, -}; -use rustc_middle::{bug, span_bug}; +use rustc_middle::ty::{self, Const, ScalarInt, Ty}; use rustc_span::{Symbol, sym}; use crate::const_eval::CompileTimeMachine; @@ -232,25 +231,6 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { interp_ok(()) } - // Write fields for struct, enum variants - fn write_variant_fields( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - variant_def: &'tcx VariantDef, - variant_layout: TyAndLayout<'tcx>, - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - self.allocate_fill_and_write_slice_ptr( - place, - variant_def.fields.len() as u64, - |this, i, place| { - let field_def = &variant_def.fields[FieldIdx::from_usize(i as usize)]; - let field_ty = field_def.ty(*this.tcx, generics); - this.write_field(field_ty, place, variant_layout, Some(field_def.name), i) - }, - ) - } - fn write_field( &mut self, field_ty: Ty<'tcx>, @@ -355,249 +335,6 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { interp_ok(()) } - // FIXME(type_info): No semver considerations for now - pub(crate) fn write_adt_type_info( - &mut self, - place: &impl Writeable<'tcx, CtfeProvenance>, - adt: (Ty<'tcx>, AdtDef<'tcx>), - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx, VariantIdx> { - let (adt_ty, adt_def) = adt; - let variant_idx = match adt_def.adt_kind() { - AdtKind::Struct => { - let (variant, variant_place) = self.downcast(place, sym::Struct)?; - let place = self.project_field(&variant_place, FieldIdx::ZERO)?; - self.write_struct_type_info( - place, - (adt_ty, adt_def.variant(VariantIdx::ZERO)), - generics, - )?; - variant - } - AdtKind::Union => { - let (variant, variant_place) = self.downcast(place, sym::Union)?; - let place = self.project_field(&variant_place, FieldIdx::ZERO)?; - self.write_union_type_info( - place, - (adt_ty, adt_def.variant(VariantIdx::ZERO)), - generics, - )?; - variant - } - AdtKind::Enum => { - let (variant, variant_place) = self.downcast(place, sym::Enum)?; - let place = self.project_field(&variant_place, FieldIdx::ZERO)?; - self.write_enum_type_info(place, adt, generics)?; - variant - } - }; - interp_ok(variant_idx) - } - - pub(crate) fn write_struct_type_info( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - struct_: (Ty<'tcx>, &'tcx VariantDef), - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - let (struct_ty, struct_def) = struct_; - let struct_layout = self.layout_of(struct_ty)?; - - for (field_idx, field) in - place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() - { - let field_place = self.project_field(&place, field_idx)?; - - match field.name { - sym::generics => self.write_generics(field_place, generics)?, - sym::fields => { - self.write_variant_fields(field_place, struct_def, struct_layout, generics)? - } - sym::non_exhaustive => { - let is_non_exhaustive = struct_def.is_field_list_non_exhaustive(); - self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? - } - other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), - } - } - - interp_ok(()) - } - - pub(crate) fn write_union_type_info( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - union_: (Ty<'tcx>, &'tcx VariantDef), - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - let (union_ty, union_def) = union_; - let union_layout = self.layout_of(union_ty)?; - - for (field_idx, field) in - place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() - { - let field_place = self.project_field(&place, field_idx)?; - - match field.name { - sym::generics => self.write_generics(field_place, generics)?, - sym::fields => { - self.write_variant_fields(field_place, union_def, union_layout, generics)? - } - sym::non_exhaustive => { - let is_non_exhaustive = union_def.is_field_list_non_exhaustive(); - self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? - } - other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), - } - } - - interp_ok(()) - } - - pub(crate) fn write_enum_type_info( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - enum_: (Ty<'tcx>, AdtDef<'tcx>), - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - let (enum_ty, enum_def) = enum_; - let enum_layout = self.layout_of(enum_ty)?; - - for (field_idx, field) in - place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() - { - let field_place = self.project_field(&place, field_idx)?; - - match field.name { - sym::generics => self.write_generics(field_place, generics)?, - sym::variants => { - self.allocate_fill_and_write_slice_ptr( - field_place, - enum_def.variants().len() as u64, - |this, i, place| { - let variant_idx = VariantIdx::from_usize(i as usize); - let variant_def = &enum_def.variants()[variant_idx]; - let variant_layout = enum_layout.for_variant(this, variant_idx); - this.write_enum_variant(place, (variant_layout, &variant_def), generics) - }, - )?; - } - sym::non_exhaustive => { - let is_non_exhaustive = enum_def.is_variant_list_non_exhaustive(); - self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? - } - other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), - } - } - - interp_ok(()) - } - - fn write_enum_variant( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - variant: (TyAndLayout<'tcx>, &'tcx VariantDef), - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - let (variant_layout, variant_def) = variant; - - for (field_idx, field_def) in - place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() - { - let field_place = self.project_field(&place, field_idx)?; - match field_def.name { - sym::name => { - let name_place = self.allocate_str_dedup(variant_def.name.as_str())?; - let ptr = self.mplace_to_ref(&name_place)?; - self.write_immediate(*ptr, &field_place)? - } - sym::fields => { - self.write_variant_fields(field_place, &variant_def, variant_layout, generics)? - } - sym::non_exhaustive => { - let is_non_exhaustive = variant_def.is_field_list_non_exhaustive(); - self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? - } - other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"), - } - } - interp_ok(()) - } - - fn write_generics( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - self.allocate_fill_and_write_slice_ptr(place, generics.len() as u64, |this, i, place| { - match generics[i as usize].kind() { - GenericArgKind::Lifetime(region) => this.write_generic_lifetime(region, place), - GenericArgKind::Type(ty) => this.write_generic_type(ty, place), - GenericArgKind::Const(c) => this.write_generic_const(c, place), - } - }) - } - - fn write_generic_lifetime( - &mut self, - _region: Region<'tcx>, - place: MPlaceTy<'tcx>, - ) -> InterpResult<'tcx> { - let (variant_idx, _) = self.downcast(&place, sym::Lifetime)?; - self.write_discriminant(variant_idx, &place)?; - interp_ok(()) - } - - fn write_generic_type(&mut self, ty: Ty<'tcx>, place: MPlaceTy<'tcx>) -> InterpResult<'tcx> { - let (variant_idx, variant_place) = self.downcast(&place, sym::Type)?; - let generic_type_place = self.project_field(&variant_place, FieldIdx::ZERO)?; - - for (field_idx, field_def) in generic_type_place - .layout() - .ty - .ty_adt_def() - .unwrap() - .non_enum_variant() - .fields - .iter_enumerated() - { - let field_place = self.project_field(&generic_type_place, field_idx)?; - match field_def.name { - sym::ty => self.write_type_id(ty, &field_place)?, - other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"), - } - } - - self.write_discriminant(variant_idx, &place)?; - interp_ok(()) - } - - fn write_generic_const(&mut self, c: Const<'tcx>, place: MPlaceTy<'tcx>) -> InterpResult<'tcx> { - let ConstKind::Value(c) = c.kind() else { bug!("expected a computed const, got {c:?}") }; - - let (variant_idx, variant_place) = self.downcast(&place, sym::Const)?; - let const_place = self.project_field(&variant_place, FieldIdx::ZERO)?; - - for (field_idx, field_def) in const_place - .layout() - .ty - .ty_adt_def() - .unwrap() - .non_enum_variant() - .fields - .iter_enumerated() - { - let field_place = self.project_field(&const_place, field_idx)?; - match field_def.name { - sym::ty => self.write_type_id(c.ty, &field_place)?, - other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"), - } - } - - self.write_discriminant(variant_idx, &place)?; - interp_ok(()) - } - fn write_int_type_info( &mut self, place: impl Writeable<'tcx, CtfeProvenance>, diff --git a/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs b/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs new file mode 100644 index 000000000000..60f7b95e799a --- /dev/null +++ b/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs @@ -0,0 +1,276 @@ +use rustc_abi::{FieldIdx, VariantIdx}; +use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::{ + AdtDef, AdtKind, Const, ConstKind, GenericArgKind, GenericArgs, Region, Ty, VariantDef, +}; +use rustc_middle::{bug, span_bug}; +use rustc_span::sym; + +use crate::const_eval::CompileTimeMachine; +use crate::interpret::{ + CtfeProvenance, InterpCx, InterpResult, MPlaceTy, Projectable, Scalar, Writeable, interp_ok, +}; + +impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { + // FIXME(type_info): No semver considerations for now + pub(crate) fn write_adt_type_info( + &mut self, + place: &impl Writeable<'tcx, CtfeProvenance>, + adt: (Ty<'tcx>, AdtDef<'tcx>), + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx, VariantIdx> { + let (adt_ty, adt_def) = adt; + let variant_idx = match adt_def.adt_kind() { + AdtKind::Struct => { + let (variant, variant_place) = self.downcast(place, sym::Struct)?; + let place = self.project_field(&variant_place, FieldIdx::ZERO)?; + self.write_struct_type_info( + place, + (adt_ty, adt_def.variant(VariantIdx::ZERO)), + generics, + )?; + variant + } + AdtKind::Union => { + let (variant, variant_place) = self.downcast(place, sym::Union)?; + let place = self.project_field(&variant_place, FieldIdx::ZERO)?; + self.write_union_type_info( + place, + (adt_ty, adt_def.variant(VariantIdx::ZERO)), + generics, + )?; + variant + } + AdtKind::Enum => { + let (variant, variant_place) = self.downcast(place, sym::Enum)?; + let place = self.project_field(&variant_place, FieldIdx::ZERO)?; + self.write_enum_type_info(place, adt, generics)?; + variant + } + }; + interp_ok(variant_idx) + } + + pub(crate) fn write_struct_type_info( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + struct_: (Ty<'tcx>, &'tcx VariantDef), + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + let (struct_ty, struct_def) = struct_; + let struct_layout = self.layout_of(struct_ty)?; + + for (field_idx, field) in + place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() + { + let field_place = self.project_field(&place, field_idx)?; + + match field.name { + sym::generics => self.write_generics(field_place, generics)?, + sym::fields => { + self.write_variant_fields(field_place, struct_def, struct_layout, generics)? + } + sym::non_exhaustive => { + let is_non_exhaustive = struct_def.is_field_list_non_exhaustive(); + self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? + } + other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), + } + } + + interp_ok(()) + } + + pub(crate) fn write_union_type_info( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + union_: (Ty<'tcx>, &'tcx VariantDef), + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + let (union_ty, union_def) = union_; + let union_layout = self.layout_of(union_ty)?; + + for (field_idx, field) in + place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() + { + let field_place = self.project_field(&place, field_idx)?; + + match field.name { + sym::generics => self.write_generics(field_place, generics)?, + sym::fields => { + self.write_variant_fields(field_place, union_def, union_layout, generics)? + } + sym::non_exhaustive => { + let is_non_exhaustive = union_def.is_field_list_non_exhaustive(); + self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? + } + other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), + } + } + + interp_ok(()) + } + + pub(crate) fn write_enum_type_info( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + enum_: (Ty<'tcx>, AdtDef<'tcx>), + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + let (enum_ty, enum_def) = enum_; + let enum_layout = self.layout_of(enum_ty)?; + + for (field_idx, field) in + place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() + { + let field_place = self.project_field(&place, field_idx)?; + + match field.name { + sym::generics => self.write_generics(field_place, generics)?, + sym::variants => { + self.allocate_fill_and_write_slice_ptr( + field_place, + enum_def.variants().len() as u64, + |this, i, place| { + let variant_idx = VariantIdx::from_usize(i as usize); + let variant_def = &enum_def.variants()[variant_idx]; + let variant_layout = enum_layout.for_variant(this, variant_idx); + this.write_enum_variant(place, (variant_layout, &variant_def), generics) + }, + )?; + } + sym::non_exhaustive => { + let is_non_exhaustive = enum_def.is_variant_list_non_exhaustive(); + self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? + } + other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), + } + } + + interp_ok(()) + } + + fn write_enum_variant( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + variant: (TyAndLayout<'tcx>, &'tcx VariantDef), + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + let (variant_layout, variant_def) = variant; + + for (field_idx, field_def) in + place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() + { + let field_place = self.project_field(&place, field_idx)?; + match field_def.name { + sym::name => { + let name_place = self.allocate_str_dedup(variant_def.name.as_str())?; + let ptr = self.mplace_to_ref(&name_place)?; + self.write_immediate(*ptr, &field_place)? + } + sym::fields => { + self.write_variant_fields(field_place, &variant_def, variant_layout, generics)? + } + sym::non_exhaustive => { + let is_non_exhaustive = variant_def.is_field_list_non_exhaustive(); + self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? + } + other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"), + } + } + interp_ok(()) + } + + // Write fields for struct, enum variants + fn write_variant_fields( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + variant_def: &'tcx VariantDef, + variant_layout: TyAndLayout<'tcx>, + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + self.allocate_fill_and_write_slice_ptr( + place, + variant_def.fields.len() as u64, + |this, i, place| { + let field_def = &variant_def.fields[FieldIdx::from_usize(i as usize)]; + let field_ty = field_def.ty(*this.tcx, generics); + this.write_field(field_ty, place, variant_layout, Some(field_def.name), i) + }, + ) + } + + fn write_generics( + &mut self, + place: impl Writeable<'tcx, CtfeProvenance>, + generics: &'tcx GenericArgs<'tcx>, + ) -> InterpResult<'tcx> { + self.allocate_fill_and_write_slice_ptr(place, generics.len() as u64, |this, i, place| { + match generics[i as usize].kind() { + GenericArgKind::Lifetime(region) => this.write_generic_lifetime(region, place), + GenericArgKind::Type(ty) => this.write_generic_type(ty, place), + GenericArgKind::Const(c) => this.write_generic_const(c, place), + } + }) + } + + fn write_generic_lifetime( + &mut self, + _region: Region<'tcx>, + place: MPlaceTy<'tcx>, + ) -> InterpResult<'tcx> { + let (variant_idx, _) = self.downcast(&place, sym::Lifetime)?; + self.write_discriminant(variant_idx, &place)?; + interp_ok(()) + } + + fn write_generic_type(&mut self, ty: Ty<'tcx>, place: MPlaceTy<'tcx>) -> InterpResult<'tcx> { + let (variant_idx, variant_place) = self.downcast(&place, sym::Type)?; + let generic_type_place = self.project_field(&variant_place, FieldIdx::ZERO)?; + + for (field_idx, field_def) in generic_type_place + .layout() + .ty + .ty_adt_def() + .unwrap() + .non_enum_variant() + .fields + .iter_enumerated() + { + let field_place = self.project_field(&generic_type_place, field_idx)?; + match field_def.name { + sym::ty => self.write_type_id(ty, &field_place)?, + other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"), + } + } + + self.write_discriminant(variant_idx, &place)?; + interp_ok(()) + } + + fn write_generic_const(&mut self, c: Const<'tcx>, place: MPlaceTy<'tcx>) -> InterpResult<'tcx> { + let ConstKind::Value(c) = c.kind() else { bug!("expected a computed const, got {c:?}") }; + + let (variant_idx, variant_place) = self.downcast(&place, sym::Const)?; + let const_place = self.project_field(&variant_place, FieldIdx::ZERO)?; + + for (field_idx, field_def) in const_place + .layout() + .ty + .ty_adt_def() + .unwrap() + .non_enum_variant() + .fields + .iter_enumerated() + { + let field_place = self.project_field(&const_place, field_idx)?; + match field_def.name { + sym::ty => self.write_type_id(c.ty, &field_place)?, + other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"), + } + } + + self.write_discriminant(variant_idx, &place)?; + interp_ok(()) + } +} From 78dc744e93028188c66d92dc2064b2107dd9992c Mon Sep 17 00:00:00 2001 From: Lizan Zhou Date: Tue, 10 Feb 2026 22:20:02 +0900 Subject: [PATCH 810/978] unwind/wasm: fix compile error by wrapping wasm_throw in unsafe block --- library/unwind/src/wasm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/unwind/src/wasm.rs b/library/unwind/src/wasm.rs index 2bff306af293..cb6e90ba180b 100644 --- a/library/unwind/src/wasm.rs +++ b/library/unwind/src/wasm.rs @@ -73,7 +73,7 @@ pub unsafe fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwi // corresponds with llvm::WebAssembly::Tag::CPP_EXCEPTION // in llvm-project/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h const CPP_EXCEPTION_TAG: i32 = 0; - wasm_throw(CPP_EXCEPTION_TAG, exception.cast()) + unsafe { wasm_throw(CPP_EXCEPTION_TAG, exception.cast()) } } _ => { let _ = exception; From 11e4873b96961d14202a8c63d83a21be5b7f7b82 Mon Sep 17 00:00:00 2001 From: ron Date: Tue, 10 Feb 2026 10:22:05 -0500 Subject: [PATCH 811/978] Fix typos and grammar in compiler and build documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - compiler/rustc_codegen_llvm/src/debuginfo/doc.md: fix 5 issues (adaption → adaptation, "allow to" → "allow V-ing" x3, later → latter + plural) - compiler/rustc_thread_pool/src/sleep/README.md: fix 2 issues (idle → active per context, then → than) - src/bootstrap/README.md: fix 2 issues (rust → Rust, add missing article "the") - src/ci/docker/README.md: fix 2 issues ("come form" → "come from", grammar) --- compiler/rustc_codegen_llvm/src/debuginfo/doc.md | 10 +++++----- compiler/rustc_thread_pool/src/sleep/README.md | 4 ++-- src/bootstrap/README.md | 4 ++-- src/ci/docker/README.md | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/doc.md b/compiler/rustc_codegen_llvm/src/debuginfo/doc.md index aaec4e68c174..f5ea5ea77c4b 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/doc.md +++ b/compiler/rustc_codegen_llvm/src/debuginfo/doc.md @@ -16,7 +16,7 @@ module to generate correct metadata and insert it into the LLVM IR. As the exact format of metadata trees may change between different LLVM versions, we now use LLVM [DIBuilder](https://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) -to create metadata where possible. This will hopefully ease the adaption of +to create metadata where possible. This will hopefully ease the adaptation of this module to future LLVM versions. The public API of the module is a set of functions that will insert the @@ -87,19 +87,19 @@ describe the type anew. This behavior is encapsulated in the ## Source Locations and Line Information In addition to data type descriptions the debugging information must also -allow to map machine code locations back to source code locations in order +allow mapping machine code locations back to source code locations in order to be useful. This functionality is also handled in this module. The -following functions allow to control source mappings: +following functions allow controlling source mappings: + `set_source_location()` + `clear_source_location()` + `start_emitting_source_locations()` -`set_source_location()` allows to set the current source location. All IR +`set_source_location()` allows setting the current source location. All IR instructions created after a call to this function will be linked to the given source location, until another location is specified with `set_source_location()` or the source location is cleared with -`clear_source_location()`. In the later case, subsequent IR instruction +`clear_source_location()`. In the latter case, subsequent IR instructions will not be linked to any source location. As you can see, this is a stateful API (mimicking the one in LLVM), so be careful with source locations set by previous calls. It's probably best to not rely on any diff --git a/compiler/rustc_thread_pool/src/sleep/README.md b/compiler/rustc_thread_pool/src/sleep/README.md index 1e11da55f4a4..948c2922a434 100644 --- a/compiler/rustc_thread_pool/src/sleep/README.md +++ b/compiler/rustc_thread_pool/src/sleep/README.md @@ -32,7 +32,7 @@ There are three main thread states: waiting to be awoken. We sometimes refer to the final two states collectively as **inactive**. -Threads begin as idle but transition to idle and finally sleeping when +Threads begin as active but transition to idle and finally sleeping when they're unable to find work to do. ## Sleepy threads @@ -160,7 +160,7 @@ not complete. It is possible -- if unlikely -- that enough activity occurs for Thread A to observe the same JEC value that it saw when getting sleepy. If the new work being published came from *inside* the thread-pool, then this race condition isn't too harmful. It means that we have fewer workers processing the -work then we should, but we won't deadlock. This seems like an acceptable risk +work than we should, but we won't deadlock. This seems like an acceptable risk given that this is unlikely in practice. However, if the work was posted as an *external* job, that is a problem. In that diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index e46fed7c426a..ef2de9b37ed0 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -175,8 +175,8 @@ When you use bootstrap, you'll call it through the entry point script (`x`, `x.ps1`, or `x.py`). However, most of the code lives in `src/bootstrap`. `bootstrap` has a difficult problem: it is written in Rust, but yet it is run before the Rust compiler is built! To work around this, there are two components -of bootstrap: the main one written in rust, and `bootstrap.py`. `bootstrap.py` -is what gets run by entry point script. It takes care of downloading the prebuilt +of bootstrap: the main one written in Rust, and `bootstrap.py`. `bootstrap.py` +is what gets run by the entry point script. It takes care of downloading the prebuilt stage 0 compiler, std and Cargo binaries, which are then used to build the bootstrap binary. diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index 4ee02e9bf005..5d3a74edc995 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -48,7 +48,7 @@ Refer to the [dev guide](https://rustc-dev-guide.rust-lang.org/tests/docker.html ## Docker Toolbox on Windows For Windows before Windows 10, the docker images can be run on Windows via -[Docker Toolbox]. There are several preparation needs to be made before running +[Docker Toolbox]. There are several preparations that need to be made before running a Docker image. 1. Stop the virtual machine from the terminal with `docker-machine stop` @@ -92,7 +92,7 @@ To run the image, A number of these images take quite a long time to compile as they're building whole gcc toolchains to do cross builds with. Much of this is relatively self-explanatory but some images use [crosstool-ng] which isn't quite as self -explanatory. Below is a description of where these `*.defconfig` files come form, +explanatory. Below is a description of where these `*.defconfig` files come from, how to generate them, and how the existing ones were generated. [crosstool-ng]: https://github.com/crosstool-ng/crosstool-ng From da80677d6a84c1a3ea3e22785392c91ccae6a69b Mon Sep 17 00:00:00 2001 From: ron Date: Tue, 10 Feb 2026 10:22:19 -0500 Subject: [PATCH 812/978] Fix typos and grammar in top-level and src/doc documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CONTRIBUTING.md: add missing verb "is" - INSTALL.md: fix subject-verb agreement ("requires" → "require") - RELEASES.md: fix 4 issues (previous → previously, remove extra "is", add hyphen in Rust-for-Linux, results → result) - src/doc/not_found.md: fix misspelling ("Standary" → "Standard") - src/doc/index.md: fix awkward grammar in Embedded Rust Book description --- CONTRIBUTING.md | 2 +- INSTALL.md | 2 +- RELEASES.md | 8 ++++---- src/doc/index.md | 5 ++--- src/doc/not_found.md | 2 +- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2b5699dcd098..3f052eca48e6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ the Zulip stream is the best place to *ask* for help. Documentation for contributing to the compiler or tooling is located in the [Guide to Rustc Development][rustc-dev-guide], commonly known as the [rustc-dev-guide]. Documentation for the -standard library in the [Standard library developers Guide][std-dev-guide], commonly known as the [std-dev-guide]. +standard library is in the [Standard library developers Guide][std-dev-guide], commonly known as the [std-dev-guide]. ## Making changes to subtrees and submodules diff --git a/INSTALL.md b/INSTALL.md index dd6c64b3df5f..0e998101fcd1 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -233,7 +233,7 @@ itself back on after some time). ### MSVC -MSVC builds of Rust additionally requires an installation of: +MSVC builds of Rust additionally require an installation of: - Visual Studio 2022 (or later) build tools so `rustc` can use its linker. Older Visual Studio versions such as 2019 *may* work but aren't actively tested. diff --git a/RELEASES.md b/RELEASES.md index 424e12ceec05..3c0a95f8462b 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1546,7 +1546,7 @@ Compatibility Notes - [Check well-formedness of the source type's signature in fn pointer casts.](https://github.com/rust-lang/rust/pull/129021) This partly closes a soundness hole that comes when casting a function item to function pointer - [Use equality instead of subtyping when resolving type dependent paths.](https://github.com/rust-lang/rust/pull/129073) - Linking on macOS now correctly includes Rust's default deployment target. Due to a linker bug, you might have to pass `MACOSX_DEPLOYMENT_TARGET` or fix your `#[link]` attributes to point to the correct frameworks. See . -- [Rust will now correctly raise an error for `repr(Rust)` written on non-`struct`/`enum`/`union` items, since it previous did not have any effect.](https://github.com/rust-lang/rust/pull/129422) +- [Rust will now correctly raise an error for `repr(Rust)` written on non-`struct`/`enum`/`union` items, since it previously did not have any effect.](https://github.com/rust-lang/rust/pull/129422) - The future incompatibility lint `deprecated_cfg_attr_crate_type_name` [has been made into a hard error](https://github.com/rust-lang/rust/pull/129670). It was used to deny usage of `#![crate_type]` and `#![crate_name]` attributes in `#![cfg_attr]`, which required a hack in the compiler to be able to change the used crate type and crate name after cfg expansion. Users can use `--crate-type` instead of `#![cfg_attr(..., crate_type = "...")]` and `--crate-name` instead of `#![cfg_attr(..., crate_name = "...")]` when running `rustc`/`cargo rustc` on the command line. Use of those two attributes outside of `#![cfg_attr]` continue to be fully supported. @@ -1722,7 +1722,7 @@ Cargo Compatibility Notes ------------------- - We now [disallow setting some built-in cfgs via the command-line](https://github.com/rust-lang/rust/pull/126158) with the newly added [`explicit_builtin_cfgs_in_flags`](https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#explicit-builtin-cfgs-in-flags) lint in order to prevent incoherent state, eg. `windows` cfg active but target is Linux based. The appropriate [`rustc` flag](https://doc.rust-lang.org/rustc/command-line-arguments.html) should be used instead. -- The standard library has a new implementation of `binary_search` which is significantly improves performance ([#128254](https://github.com/rust-lang/rust/pull/128254)). However when a sorted slice has multiple values which compare equal, the new implementation may select a different value among the equal ones than the old implementation. +- The standard library has a new implementation of `binary_search` which significantly improves performance ([#128254](https://github.com/rust-lang/rust/pull/128254)). However when a sorted slice has multiple values which compare equal, the new implementation may select a different value among the equal ones than the old implementation. - [illumos/Solaris now sets `MSG_NOSIGNAL` when writing to sockets](https://github.com/rust-lang/rust/pull/128259). This avoids killing the process with SIGPIPE when writing to a closed socket, which matches the existing behavior on other UNIX targets. - [Removes a problematic hack that always passed the --whole-archive linker flag for tests, which may cause linker errors for code accidentally relying on it.](https://github.com/rust-lang/rust/pull/128400) - The WebAssembly target features `multivalue` and `reference-types` are now @@ -1872,7 +1872,7 @@ 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. -- [Add a Rust-for Linux `auto` CI job to check kernel builds.](https://github.com/rust-lang/rust/pull/125209/) +- [Add a Rust-for-Linux `auto` CI job to check kernel builds.](https://github.com/rust-lang/rust/pull/125209/) Version 1.80.1 (2024-08-08) =========================== @@ -4510,7 +4510,7 @@ Compatibility Notes saturating to `0` instead][89926]. In the real world the panic happened mostly on platforms with buggy monotonic clock implementations rather than catching programming errors like reversing the start and end times. Such programming - errors will now results in `0` rather than a panic. + errors will now result in `0` rather than a panic. - In a future release we're planning to increase the baseline requirements for the Linux kernel to version 3.2, and for glibc to version 2.17. We'd love your feedback in [PR #95026][95026]. diff --git a/src/doc/index.md b/src/doc/index.md index 892057a8f4db..418939353975 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -194,9 +194,8 @@ resources maintained by the [Embedded Working Group] useful. #### The Embedded Rust Book -[The Embedded Rust Book] is targeted at developers familiar with embedded -development and familiar with Rust, but have not used Rust for embedded -development. +[The Embedded Rust Book] is targeted at developers who are familiar with embedded +development and Rust, but who have not used Rust for embedded development. [The Embedded Rust Book]: embedded-book/index.html [Rust project]: https://www.rust-lang.org diff --git a/src/doc/not_found.md b/src/doc/not_found.md index 9552759d2b8b..69e6ae3e2d03 100644 --- a/src/doc/not_found.md +++ b/src/doc/not_found.md @@ -41,7 +41,7 @@ Some things that might be helpful to you though:

(&mut self, predicate: P) -> Option where P: FnMut(Self::Item) -> bool, @@ -3178,6 +3224,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn max(self) -> Option where Self: Sized, @@ -3214,6 +3261,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn min(self) -> Option where Self: Sized, @@ -3236,6 +3284,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] + #[rustc_non_const_trait_method] fn max_by_key(self, f: F) -> Option where Self: Sized, @@ -3269,6 +3318,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_max_by", since = "1.15.0")] + #[rustc_non_const_trait_method] fn max_by(self, compare: F) -> Option where Self: Sized, @@ -3296,6 +3346,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] + #[rustc_non_const_trait_method] fn min_by_key(self, f: F) -> Option where Self: Sized, @@ -3329,6 +3380,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_min_by", since = "1.15.0")] + #[rustc_non_const_trait_method] fn min_by(self, compare: F) -> Option where Self: Sized, @@ -3366,6 +3418,7 @@ pub trait Iterator { #[inline] #[doc(alias = "reverse")] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn rev(self) -> Rev where Self: Sized + DoubleEndedIterator, @@ -3402,6 +3455,7 @@ pub trait Iterator { /// assert_eq!(z, [3, 6]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_non_const_trait_method] fn unzip(self) -> (FromA, FromB) where FromA: Default + Extend, @@ -3433,6 +3487,7 @@ pub trait Iterator { /// ``` #[stable(feature = "iter_copied", since = "1.36.0")] #[rustc_diagnostic_item = "iter_copied"] + #[rustc_non_const_trait_method] fn copied<'a, T>(self) -> Copied where T: Copy + 'a, @@ -3481,6 +3536,7 @@ pub trait Iterator { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "iter_cloned"] + #[rustc_non_const_trait_method] fn cloned<'a, T>(self) -> Cloned where T: Clone + 'a, @@ -3512,6 +3568,7 @@ pub trait Iterator { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[rustc_non_const_trait_method] fn cycle(self) -> Cycle where Self: Sized + Clone, @@ -3555,6 +3612,7 @@ pub trait Iterator { /// ``` #[track_caller] #[unstable(feature = "iter_array_chunks", issue = "100450")] + #[rustc_non_const_trait_method] fn array_chunks(self) -> ArrayChunks where Self: Sized, @@ -3591,6 +3649,7 @@ pub trait Iterator { /// assert_eq!(sum, -0.0_f32); /// ``` #[stable(feature = "iter_arith", since = "1.11.0")] + #[rustc_non_const_trait_method] fn sum(self) -> S where Self: Sized, @@ -3623,6 +3682,7 @@ pub trait Iterator { /// assert_eq!(factorial(5), 120); /// ``` #[stable(feature = "iter_arith", since = "1.11.0")] + #[rustc_non_const_trait_method] fn product